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 <fcntl.h>
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <media/hardware/HardwareAPI.h>
55 #include <sys/eventfd.h>
56 #include <nativebase/nativebase.h>
57 
58 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
59 #include <sys/ioctl.h>
60 #include <sys/mman.h>
61 #endif
62 
63 #ifdef _ANDROID_
64 #include <cutils/properties.h>
65 #undef USE_EGL_IMAGE_GPU
66 
67 #ifdef _QUERY_DISP_RES_
68 #include "display_config.h"
69 #endif
70 #endif
71 
72 #ifdef _USE_GLIB_
73 #include <glib.h>
74 #define strlcpy g_strlcpy
75 #endif
76 
77 #include <qdMetaData.h>
78 #include <gralloc_priv.h>
79 
80 #ifdef ANDROID_JELLYBEAN_MR2
81 #include "QComOMXMetadata.h"
82 #endif
83 
84 #ifdef USE_EGL_IMAGE_GPU
85 #include <EGL/egl.h>
86 #include <EGL/eglQCOM.h>
87 #define EGL_BUFFER_HANDLE 0x4F00
88 #define EGL_BUFFER_OFFSET 0x4F01
89 #endif
90 
91 #define BUFFER_LOG_LOC "/data/vendor/media"
92 
93 #ifdef OUTPUT_EXTRADATA_LOG
94 FILE *outputExtradataFile;
95 char output_extradata_filename [] = "/data/vendor/media/extradata";
96 #endif
97 
98 #define DEFAULT_FPS 30
99 #define MAX_SUPPORTED_FPS 240
100 #define DEFAULT_WIDTH_ALIGNMENT 128
101 #define DEFAULT_HEIGHT_ALIGNMENT 32
102 
103 #define VC1_SP_MP_START_CODE        0xC5000000
104 #define VC1_SP_MP_START_CODE_MASK   0xFF000000
105 #define VC1_AP_SEQ_START_CODE       0x0F010000
106 #define VC1_STRUCT_C_PROFILE_MASK   0xF0
107 #define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
108 #define VC1_SIMPLE_PROFILE          0
109 #define VC1_MAIN_PROFILE            1
110 #define VC1_ADVANCE_PROFILE         3
111 #define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
112 #define VC1_SIMPLE_PROFILE_MED_LEVEL  2
113 #define VC1_STRUCT_C_LEN            4
114 #define VC1_STRUCT_C_POS            8
115 #define VC1_STRUCT_A_POS            12
116 #define VC1_STRUCT_B_POS            24
117 #define VC1_SEQ_LAYER_SIZE          36
118 #define POLL_TIMEOUT 0x7fffffff
119 
120 #define MEM_DEVICE "/dev/ion"
121 
122 #ifdef _ANDROID_
123 extern "C" {
124 #include<utils/Log.h>
125 }
126 #endif//_ANDROID_
127 
128 #define SZ_4K 0x1000
129 #define SZ_1M 0x100000
130 
131 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
132 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
133 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
134 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
135 
136 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
137                            | OMX_DISPLAY_INFO_EXTRADATA | OMX_HDR_COLOR_INFO_EXTRADATA)
138 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
139 
140 #ifndef ION_FLAG_CP_BITSTREAM
141 #define ION_FLAG_CP_BITSTREAM 0
142 #endif
143 
144 #ifndef ION_FLAG_CP_PIXEL
145 #define ION_FLAG_CP_PIXEL 0
146 #endif
147 
148 #ifdef MASTER_SIDE_CP
149 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
150 #define SECURE_ALIGN SZ_4K
151 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
152 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
153 #else //SLAVE_SIDE_CP
154 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
155 #define SECURE_ALIGN SZ_1M
156 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
157 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
158 #endif
159 
160 #define LUMINANCE_DIV_FACTOR 10000.0
161 
162 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
163 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
164 
165 static OMX_U32 maxSmoothStreamingWidth = 1920;
166 static OMX_U32 maxSmoothStreamingHeight = 1088;
167 
async_message_thread(void * input)168 void* async_message_thread (void *input)
169 {
170     OMX_BUFFERHEADERTYPE *buffer;
171     struct v4l2_plane plane[VIDEO_MAX_PLANES];
172     struct pollfd pfds[2];
173     struct v4l2_buffer v4l2_buf;
174     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
175     struct v4l2_event dqevent;
176     omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
177     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
178     pfds[1].events = POLLIN | POLLERR;
179     pfds[0].fd = omx->drv_ctx.video_driver_fd;
180     pfds[1].fd = omx->m_poll_efd;
181     int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
182     DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
183     prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
184     while (!omx->async_thread_force_stop) {
185         rc = poll(pfds, 2, POLL_TIMEOUT);
186         if (!rc) {
187             DEBUG_PRINT_ERROR("Poll timedout");
188             break;
189         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
190             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
191             break;
192         }
193         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
194             DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
195             break;
196         }
197         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
198             struct vdec_msginfo vdec_msg;
199             memset(&vdec_msg, 0, sizeof(vdec_msg));
200             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
201             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
202             v4l2_buf.length = omx->drv_ctx.num_planes;
203             v4l2_buf.m.planes = plane;
204             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
205                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
206                 vdec_msg.status_code=VDEC_S_SUCCESS;
207                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
208                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
209                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
210                 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
211                     (uint64_t)v4l2_buf.timestamp.tv_usec;
212 
213                 if (omx->async_message_process(input,&vdec_msg) < 0) {
214                     DEBUG_PRINT_HIGH("async_message_thread Exited");
215                     break;
216                 }
217             }
218         }
219         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
220             struct vdec_msginfo vdec_msg;
221             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
222             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
223             v4l2_buf.length = 1;
224             v4l2_buf.m.planes = plane;
225             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
226                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
227                 vdec_msg.status_code=VDEC_S_SUCCESS;
228                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
229                 if (omx->async_message_process(input,&vdec_msg) < 0) {
230                     DEBUG_PRINT_HIGH("async_message_thread Exited");
231                     break;
232                 }
233             }
234         }
235         if (pfds[0].revents & POLLPRI) {
236             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
237             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
238                 struct vdec_msginfo vdec_msg;
239                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
240 
241                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
242                 vdec_msg.status_code=VDEC_S_SUCCESS;
243                 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
244                 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
245                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
246                 if(ptr[2] & V4L2_EVENT_BITDEPTH_FLAG) {
247                     omx->dpb_bit_depth = ptr[3];
248                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", ptr[3]);
249                 }
250                 if(ptr[2] & V4L2_EVENT_PICSTRUCT_FLAG) {
251                     omx->m_progressive = ptr[4];
252                     DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct change - %d", ptr[4]);
253                 }
254                 if(ptr[2] & V4L2_EVENT_COLOUR_SPACE_FLAG) {
255                     if (ptr[5] == MSM_VIDC_BT2020) {
256                         omx->m_color_space = omx_vdec::BT2020;
257                     } else {
258                         omx->m_color_space = omx_vdec::EXCEPT_BT2020;
259                     }
260                     DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace change - %d", omx->m_color_space);
261                 }
262                 if (omx->async_message_process(input,&vdec_msg) < 0) {
263                     DEBUG_PRINT_HIGH("async_message_thread Exited");
264                     break;
265                 }
266             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
267                 struct vdec_msginfo vdec_msg;
268                 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
269                 // Old driver doesn't send flushType information.
270                 // To make this backward compatible fallback to old approach
271                 // if the flush_type is not present.
272                 vdec_msg.status_code=VDEC_S_SUCCESS;
273                 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
274                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
275                     DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
276                     if (omx->async_message_process(input,&vdec_msg) < 0) {
277                         DEBUG_PRINT_HIGH("async_message_thread Exited");
278                         break;
279                     }
280                 }
281 
282                 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
283                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
284                     DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
285                     if (omx->async_message_process(input,&vdec_msg) < 0) {
286                         DEBUG_PRINT_HIGH("async_message_thread Exited");
287                         break;
288                     }
289                 }
290             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
291                 struct vdec_msginfo vdec_msg;
292                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
293                 vdec_msg.status_code=VDEC_S_SUCCESS;
294                 DEBUG_PRINT_ERROR("HW Overload received");
295                 if (omx->async_message_process(input,&vdec_msg) < 0) {
296                     DEBUG_PRINT_HIGH("async_message_thread Exited");
297                     break;
298                 }
299             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
300                 struct vdec_msginfo vdec_msg;
301                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
302                 vdec_msg.status_code=VDEC_S_SUCCESS;
303                 DEBUG_PRINT_ERROR("HW Unsupported received");
304                 if (omx->async_message_process(input,&vdec_msg) < 0) {
305                     DEBUG_PRINT_HIGH("async_message_thread Exited");
306                     break;
307                 }
308             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
309                 struct vdec_msginfo vdec_msg;
310                 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
311                 vdec_msg.status_code = VDEC_S_SUCCESS;
312                 DEBUG_PRINT_HIGH("SYS Error Recieved");
313                 if (omx->async_message_process(input,&vdec_msg) < 0) {
314                     DEBUG_PRINT_HIGH("async_message_thread Exited");
315                     break;
316                 }
317             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
318                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
319 
320                 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
321             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
322                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
323                 struct vdec_msginfo vdec_msg;
324 
325                 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
326 
327                 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
328                 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
329                 v4l2_buf.length = omx->drv_ctx.num_planes;
330                 v4l2_buf.m.planes = plane;
331                 v4l2_buf.index = ptr[5];
332                 v4l2_buf.flags = 0;
333 
334                 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
335                 vdec_msg.status_code = VDEC_S_SUCCESS;
336                 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
337                 vdec_msg.msgdata.output_frame.len = 0;
338                 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
339                 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
340                     (uint64_t)ptr[4];
341                 if (omx->async_message_process(input,&vdec_msg) < 0) {
342                     DEBUG_PRINT_HIGH("async_message_thread Exitedn");
343                     break;
344                 }
345             } else {
346                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
347                 continue;
348             }
349         }
350     }
351     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
352     return NULL;
353 }
354 
message_thread_dec(void * input)355 void* message_thread_dec(void *input)
356 {
357     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
358     unsigned char id;
359     int n;
360 
361     fd_set readFds;
362     int res = 0;
363     struct timeval tv;
364 
365     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
366     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
367     while (!omx->message_thread_stop) {
368 
369         tv.tv_sec = 2;
370         tv.tv_usec = 0;
371 
372         FD_ZERO(&readFds);
373         FD_SET(omx->m_pipe_in, &readFds);
374 
375         res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
376         if (res < 0) {
377             DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
378             continue;
379         } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
380             continue;
381         }
382 
383         n = read(omx->m_pipe_in, &id, 1);
384 
385         if (0 == n) {
386             break;
387         }
388 
389         if (1 == n) {
390             omx->process_event_cb(omx, id);
391         }
392 
393         if ((n < 0) && (errno != EINTR)) {
394             DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
395             break;
396         }
397     }
398     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
399     return 0;
400 }
401 
post_message(omx_vdec * omx,unsigned char id)402 void post_message(omx_vdec *omx, unsigned char id)
403 {
404     int ret_value;
405     DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
406     ret_value = write(omx->m_pipe_out, &id, 1);
407     if (ret_value <= 0) {
408         DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
409     } else {
410         DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
411     }
412 }
413 
414 // omx_cmd_queue destructor
~omx_cmd_queue()415 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
416 {
417     // Nothing to do
418 }
419 
420 // omx cmd queue constructor
omx_cmd_queue()421 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
422 {
423     memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
424 }
425 
426 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)427 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
428 {
429     bool ret = true;
430     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
431         m_q[m_write].id       = id;
432         m_q[m_write].param1   = p1;
433         m_q[m_write].param2   = p2;
434         m_write++;
435         m_size ++;
436         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
437             m_write = 0;
438         }
439     } else {
440         ret = false;
441         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
442     }
443     return ret;
444 }
445 
446 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)447 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
448 {
449     bool ret = true;
450     if (m_size > 0) {
451         *id = m_q[m_read].id;
452         *p1 = m_q[m_read].param1;
453         *p2 = m_q[m_read].param2;
454         // Move the read pointer ahead
455         ++m_read;
456         --m_size;
457         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
458             m_read = 0;
459         }
460     } else {
461         ret = false;
462     }
463     return ret;
464 }
465 
466 // Retrieve the first mesg type in the queue
get_q_msg_type()467 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
468 {
469     return m_q[m_read].id;
470 }
471 
472 #ifdef _ANDROID_
ts_arr_list()473 omx_vdec::ts_arr_list::ts_arr_list()
474 {
475     //initialize timestamps array
476     memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
477 }
~ts_arr_list()478 omx_vdec::ts_arr_list::~ts_arr_list()
479 {
480     //free m_ts_arr_list?
481 }
482 
insert_ts(OMX_TICKS ts)483 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
484 {
485     bool ret = true;
486     bool duplicate_ts = false;
487     int idx = 0;
488 
489     //insert at the first available empty location
490     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
491         if (!m_ts_arr_list[idx].valid) {
492             //found invalid or empty entry, save timestamp
493             m_ts_arr_list[idx].valid = true;
494             m_ts_arr_list[idx].timestamp = ts;
495             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
496                     ts, idx);
497             break;
498         }
499     }
500 
501     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
502         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
503         ret = false;
504     }
505     return ret;
506 }
507 
pop_min_ts(OMX_TICKS & ts)508 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
509 {
510     bool ret = true;
511     int min_idx = -1;
512     OMX_TICKS min_ts = 0;
513     int idx = 0;
514 
515     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
516 
517         if (m_ts_arr_list[idx].valid) {
518             //found valid entry, save index
519             if (min_idx < 0) {
520                 //first valid entry
521                 min_ts = m_ts_arr_list[idx].timestamp;
522                 min_idx = idx;
523             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
524                 min_ts = m_ts_arr_list[idx].timestamp;
525                 min_idx = idx;
526             }
527         }
528 
529     }
530 
531     if (min_idx < 0) {
532         //no valid entries found
533         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
534         ts = 0;
535         ret = false;
536     } else {
537         ts = m_ts_arr_list[min_idx].timestamp;
538         m_ts_arr_list[min_idx].valid = false;
539         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
540                 ts, min_idx);
541     }
542 
543     return ret;
544 
545 }
546 
547 
reset_ts_list()548 bool omx_vdec::ts_arr_list::reset_ts_list()
549 {
550     bool ret = true;
551     int idx = 0;
552 
553     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
554     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
555         m_ts_arr_list[idx].valid = false;
556     }
557     return ret;
558 }
559 #endif
560 
561 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)562 void *get_omx_component_factory_fn(void)
563 {
564     return (new omx_vdec);
565 }
566 
is_platform_tp10capture_supported()567 bool is_platform_tp10capture_supported()
568 {
569     char platform_name[PROPERTY_VALUE_MAX] = {0};
570     property_get("ro.board.platform", platform_name, "0");
571     if (!strncmp(platform_name, "msm8998", 7)) {
572         DEBUG_PRINT_HIGH("TP10 on capture port is supported");
573         return true;
574     }
575     DEBUG_PRINT_HIGH("TP10 on capture port is not supported");
576     return false;
577 }
578 
579 /* ======================================================================
580    FUNCTION
581    omx_vdec::omx_vdec
582 
583    DESCRIPTION
584    Constructor
585 
586    PARAMETERS
587    None
588 
589    RETURN VALUE
590    None.
591    ========================================================================== */
omx_vdec()592 omx_vdec::omx_vdec(): m_error_propogated(false),
593     m_state(OMX_StateInvalid),
594     m_app_data(NULL),
595     m_inp_mem_ptr(NULL),
596     m_out_mem_ptr(NULL),
597     m_client_output_extradata_mem_ptr(NULL),
598     input_flush_progress (false),
599     output_flush_progress (false),
600     input_use_buffer (false),
601     output_use_buffer (false),
602     ouput_egl_buffers(false),
603     m_use_output_pmem(OMX_FALSE),
604     m_out_mem_region_smi(OMX_FALSE),
605     m_out_pvt_entry_pmem(OMX_FALSE),
606     pending_input_buffers(0),
607     pending_output_buffers(0),
608     m_out_bm_count(0),
609     m_inp_bm_count(0),
610     m_out_extradata_bm_count(0),
611     m_inp_bPopulated(OMX_FALSE),
612     m_out_bPopulated(OMX_FALSE),
613     m_flags(0),
614     m_inp_bEnabled(OMX_TRUE),
615     m_out_bEnabled(OMX_TRUE),
616     m_in_alloc_cnt(0),
617     m_platform_list(NULL),
618     m_platform_entry(NULL),
619     m_pmem_info(NULL),
620     h264_parser(NULL),
621     arbitrary_bytes (true),
622     psource_frame (NULL),
623     pdest_frame (NULL),
624     m_inp_heap_ptr (NULL),
625     m_phdr_pmem_ptr(NULL),
626     m_heap_inp_bm_count (0),
627     codec_type_parse ((codec_type)0),
628     first_frame_meta (true),
629     frame_count (0),
630     nal_count (0),
631     nal_length(0),
632     look_ahead_nal (false),
633     first_frame(0),
634     first_buffer(NULL),
635     first_frame_size (0),
636     m_device_file_ptr(NULL),
637     m_vc1_profile((vc1_profile_type)0),
638     h264_last_au_ts(LLONG_MAX),
639     h264_last_au_flags(0),
640     m_disp_hor_size(0),
641     m_disp_vert_size(0),
642     prev_ts(LLONG_MAX),
643     prev_ts_actual(LLONG_MAX),
644     rst_prev_ts(true),
645     frm_int(0),
646     m_fps_received(0),
647     m_fps_prev(0),
648     m_drc_enable(0),
649     in_reconfig(false),
650     m_display_id(NULL),
651     client_extradata(0),
652     m_reject_avc_1080p_mp (0),
653 #ifdef _ANDROID_
654     m_enable_android_native_buffers(OMX_FALSE),
655     m_use_android_native_buffers(OMX_FALSE),
656 #endif
657     m_desc_buffer_ptr(NULL),
658     secure_mode(false),
659     allocate_native_handle(false),
660     m_other_extradata(NULL),
661     m_profile(0),
662     m_need_turbo(0),
663     client_set_fps(false),
664     stereo_output_mode(HAL_NO_3D),
665     m_last_rendered_TS(-1),
666     m_queued_codec_config_count(0),
667     current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
668     secure_scaling_to_non_secure_opb(false),
669     m_force_compressed_for_dpb(true),
670     m_is_display_session(false),
671     m_buffer_error(false)
672 {
673     m_pipe_in = -1;
674     m_pipe_out = -1;
675     m_poll_efd = -1;
676     drv_ctx.video_driver_fd = -1;
677     drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
678     /* Assumption is that , to begin with , we have all the frames with decoder */
679     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
680     memset(&m_debug,0,sizeof(m_debug));
681 #ifdef _ANDROID_
682     char property_value[PROPERTY_VALUE_MAX] = {0};
683     property_get("vendor.vidc.debug.level", property_value, "1");
684     debug_level = strtoul(property_value, NULL, 16);
685     property_value[0] = '\0';
686 
687     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
688 
689     property_get("vendor.vidc.dec.debug.perf", property_value, "0");
690     perf_flag = atoi(property_value);
691     if (perf_flag) {
692         DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
693         dec_time.start();
694     }
695     proc_frms = latency = 0;
696     prev_n_filled_len = 0;
697     property_value[0] = '\0';
698     property_get("vendor.vidc.dec.debug.ts", property_value, "0");
699     m_debug_timestamp = atoi(property_value);
700     DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
701     if (m_debug_timestamp) {
702         time_stamp_dts.set_timestamp_reorder_mode(true);
703         time_stamp_dts.enable_debug_print(true);
704     }
705 
706     property_value[0] = '\0';
707     property_get("vendor.vidc.dec.debug.concealedmb", property_value, "0");
708     m_debug_concealedmb = atoi(property_value);
709     DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
710 
711     property_value[0] = '\0';
712     property_get("vendor.vidc.dec.profile.check", property_value, "0");
713     m_reject_avc_1080p_mp = atoi(property_value);
714     DEBUG_PRINT_HIGH("vendor.vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
715 
716     property_value[0] = '\0';
717     property_get("vendor.vidc.dec.log.in", property_value, "0");
718     m_debug.in_buffer_log = atoi(property_value);
719 
720     property_value[0] = '\0';
721     property_get("vendor.vidc.dec.log.out", property_value, "0");
722     m_debug.out_buffer_log = atoi(property_value);
723     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
724 
725     property_value[0] = '\0';
726     property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
727     m_debug.out_meta_buffer_log = atoi(property_value);
728     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
729 
730     property_value[0] = '\0';
731     property_get("vendor.vidc.log.loc", property_value, "");
732     if (*property_value)
733         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
734 
735     property_value[0] = '\0';
736     property_get("vendor.vidc.dec.120fps.enabled", property_value, "0");
737 
738     //if this feature is not enabled then reset this value -ve
739     if(atoi(property_value)) {
740         DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
741         m_last_rendered_TS = 0;
742     }
743 
744     property_value[0] = '\0';
745     property_get("vendor.vidc.dec.debug.dyn.disabled", property_value, "0");
746     m_disable_dynamic_buf_mode = atoi(property_value);
747     DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
748 
749     property_value[0] = '\0';
750     property_get("vendor.vidc.dec.drc.enable", property_value, "0");
751     if (atoi(property_value)) {
752         m_drc_enable = true;
753         DEBUG_PRINT_HIGH("DRC enabled");
754     }
755 
756 #ifdef _UBWC_
757     property_value[0] = '\0';
758     property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
759     m_disable_ubwc_mode = atoi(property_value);
760     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
761 #else
762     m_disable_ubwc_mode = true;
763 #endif
764 #endif
765     memset(&m_cmp,0,sizeof(m_cmp));
766     memset(&m_cb,0,sizeof(m_cb));
767     memset (&drv_ctx,0,sizeof(drv_ctx));
768     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
769     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
770     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
771     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
772     memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
773     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
774     memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
775     memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
776     memset(&m_color_mdata, 0, sizeof(ColorMetaData));
777     m_demux_entries = 0;
778     msg_thread_id = 0;
779     async_thread_id = 0;
780     msg_thread_created = false;
781     async_thread_created = false;
782     async_thread_force_stop = false;
783     message_thread_stop = false;
784 #ifdef _ANDROID_ICS_
785     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
786 #endif
787     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
788 
789     /* invalidate m_frame_pack_arrangement */
790     memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
791     m_frame_pack_arrangement.cancel_flag = 1;
792 
793     drv_ctx.timestamp_adjust = false;
794     m_vendor_config.pData = NULL;
795     pthread_mutex_init(&m_lock, NULL);
796     pthread_mutex_init(&c_lock, NULL);
797     pthread_mutex_init(&buf_lock, NULL);
798     sem_init(&m_cmd_lock,0,0);
799     sem_init(&m_safe_flush, 0, 0);
800     streaming[CAPTURE_PORT] =
801         streaming[OUTPUT_PORT] = false;
802 #ifdef _ANDROID_
803     char extradata_value[PROPERTY_VALUE_MAX] = {0};
804     property_get("vendor.vidc.dec.debug.extradata", extradata_value, "0");
805     m_debug_extradata = atoi(extradata_value);
806     DEBUG_PRINT_HIGH("vendor.vidc.dec.debug.extradata value is %d",m_debug_extradata);
807 #endif
808     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
809     client_buffers.set_vdec_client(this);
810     dynamic_buf_mode = false;
811     out_dynamic_list = NULL;
812     is_down_scalar_enabled = false;
813     m_enable_downscalar = 0;
814     m_downscalar_width = 0;
815     m_downscalar_height = 0;
816     m_force_down_scalar = 0;
817     m_reconfig_height = 0;
818     m_reconfig_width = 0;
819     m_smoothstreaming_mode = false;
820     m_smoothstreaming_width = 0;
821     m_smoothstreaming_height = 0;
822     m_decode_order_mode = false;
823     is_q6_platform = false;
824     m_perf_control.send_hint_to_mpctl(true);
825     m_input_pass_buffer_fd = false;
826     memset(&m_extradata_info, 0, sizeof(m_extradata_info));
827     m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
828     m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
829     m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
830     m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
831     m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
832 
833     m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
834     m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
835     m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
836     m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
837     m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
838     m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
839 
840     m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
841     m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
842     m_change_client_hdr_info = false;
843     pthread_mutex_init(&m_hdr_info_client_lock, NULL);
844 
845     char dither_value[PROPERTY_VALUE_MAX] = {0};
846     property_get("vendor.vidc.dec.dither", dither_value, "0");
847     if ((atoi(dither_value) > DITHER_ALL_COLORSPACE) ||
848         (atoi(dither_value) < DITHER_DISABLE)) {
849         m_dither_config = DITHER_ALL_COLORSPACE;
850     } else {
851         m_dither_config = is_platform_tp10capture_supported() ? (dither_type)atoi(dither_value) : DITHER_ALL_COLORSPACE;
852     }
853 
854     DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
855     m_color_space = EXCEPT_BT2020;
856 }
857 
858 static const int event_type[] = {
859     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
860     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
861     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
862     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
863     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
864     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
865     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
866     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
867     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
868 };
869 
subscribe_to_events(int fd)870 static OMX_ERRORTYPE subscribe_to_events(int fd)
871 {
872     OMX_ERRORTYPE eRet = OMX_ErrorNone;
873     struct v4l2_event_subscription sub;
874     int array_sz = sizeof(event_type)/sizeof(int);
875     int i,rc;
876     if (fd < 0) {
877         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
878         return OMX_ErrorBadParameter;
879     }
880 
881     for (i = 0; i < array_sz; ++i) {
882         memset(&sub, 0, sizeof(sub));
883         sub.type = event_type[i];
884         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
885         if (rc) {
886             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
887             break;
888         }
889     }
890     if (i < array_sz) {
891         for (--i; i >=0 ; i--) {
892             memset(&sub, 0, sizeof(sub));
893             sub.type = event_type[i];
894             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
895             if (rc)
896                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
897         }
898         eRet = OMX_ErrorNotImplemented;
899     }
900     return eRet;
901 }
902 
903 
unsubscribe_to_events(int fd)904 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
905 {
906     OMX_ERRORTYPE eRet = OMX_ErrorNone;
907     struct v4l2_event_subscription sub;
908     int array_sz = sizeof(event_type)/sizeof(int);
909     int i,rc;
910     if (fd < 0) {
911         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
912         return OMX_ErrorBadParameter;
913     }
914 
915     for (i = 0; i < array_sz; ++i) {
916         memset(&sub, 0, sizeof(sub));
917         sub.type = event_type[i];
918         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
919         if (rc) {
920             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
921             break;
922         }
923     }
924     return eRet;
925 }
926 
927 /* ======================================================================
928    FUNCTION
929    omx_vdec::~omx_vdec
930 
931    DESCRIPTION
932    Destructor
933 
934    PARAMETERS
935    None
936 
937    RETURN VALUE
938    None.
939    ========================================================================== */
~omx_vdec()940 omx_vdec::~omx_vdec()
941 {
942     m_pmem_info = NULL;
943     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
944     if (msg_thread_created) {
945         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
946         message_thread_stop = true;
947         post_message(this, OMX_COMPONENT_CLOSE_MSG);
948         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
949         pthread_join(msg_thread_id,NULL);
950     }
951     close(m_pipe_in);
952     close(m_pipe_out);
953     m_pipe_in = -1;
954     m_pipe_out = -1;
955     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
956     if(eventfd_write(m_poll_efd, 1)) {
957          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
958          async_thread_force_stop = true;
959     }
960 
961     if (async_thread_created)
962         pthread_join(async_thread_id,NULL);
963     unsubscribe_to_events(drv_ctx.video_driver_fd);
964     close(m_poll_efd);
965     close(drv_ctx.video_driver_fd);
966     pthread_mutex_destroy(&m_lock);
967     pthread_mutex_destroy(&c_lock);
968     pthread_mutex_destroy(&buf_lock);
969     sem_destroy(&m_cmd_lock);
970     pthread_mutex_destroy(&m_hdr_info_client_lock);
971     if (perf_flag) {
972         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
973         dec_time.end();
974     }
975     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
976     m_perf_control.send_hint_to_mpctl(false);
977 }
978 
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)979 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
980 {
981     struct v4l2_requestbuffers bufreq;
982     int rc = 0;
983     if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
984         bufreq.memory = V4L2_MEMORY_USERPTR;
985         bufreq.count = 0;
986         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
987         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
988     } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
989         bufreq.memory = V4L2_MEMORY_USERPTR;
990         bufreq.count = 0;
991         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
992         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
993     }
994     return rc;
995 }
996 
set_dpb(bool is_split_mode,int dpb_color_format)997 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
998 {
999     int rc = 0;
1000     struct v4l2_ext_control ctrl[2];
1001     struct v4l2_ext_controls controls;
1002 
1003     DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
1004          is_split_mode ? "split" : "combined",
1005          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
1006          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
1007          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
1008          "unknown",
1009          capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
1010          capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
1011          capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC ? "nv12_10bit_ubwc":
1012          "unknown");
1013 
1014     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1015     if (is_split_mode) {
1016         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1017     } else {
1018         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1019     }
1020 
1021     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
1022     ctrl[1].value = dpb_color_format;
1023 
1024     controls.count = 2;
1025     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1026     controls.controls = ctrl;
1027 
1028     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1029     if (rc) {
1030         DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1031         return OMX_ErrorUnsupportedSetting;
1032     }
1033     return OMX_ErrorNone;
1034 }
1035 
1036 
decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt)1037 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt)
1038 {
1039     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1040     struct v4l2_format fmt;
1041     int rc = 0;
1042     bool cpu_access = (capture_capability != V4L2_PIX_FMT_NV12_UBWC) &&
1043         capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC;
1044     bool tp10_enable = !drv_ctx.idr_only_decoding &&
1045         !client_buffers.is_color_conversion_enabled() &&
1046         dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10;
1047     bool dither_enable = true;
1048 
1049     switch (m_dither_config) {
1050     case DITHER_DISABLE:
1051         dither_enable = false;
1052         break;
1053     case DITHER_COLORSPACE_EXCEPTBT2020:
1054         dither_enable = (m_color_space == EXCEPT_BT2020);
1055         break;
1056     case DITHER_ALL_COLORSPACE:
1057         dither_enable = true;
1058         break;
1059     default:
1060         DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1061     }
1062 
1063     if (tp10_enable && !dither_enable) {
1064         drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1065         capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1066         cpu_access = false;
1067 
1068         memset(&fmt, 0x0, sizeof(struct v4l2_format));
1069         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1070         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1071         if (rc) {
1072             DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1073             return OMX_ErrorUnsupportedSetting;
1074         }
1075         fmt.fmt.pix_mp.pixelformat = capture_capability;
1076         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1077         if (rc) {
1078             DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1079             return OMX_ErrorUnsupportedSetting;
1080         }
1081     }
1082 
1083 
1084     if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1085         !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1086         DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1087         return eRet;
1088     }
1089 
1090 
1091     if (cpu_access) {
1092         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1093             /* Disabled split mode for VP9. In split mode the DPB buffers are part of the internal
1094              * scratch buffers and the driver does not does the reference buffer management for
1095              * scratch buffers. In case of VP9 with spatial scalability, when a sequence changed
1096              * event is received with the new resolution, and when a flush is sent by the driver, it
1097              * releases all the references of internal scratch buffers. However as per the VP9
1098              * spatial scalability, even after the flush, the buffers which have not yet received
1099              * release reference event should not be unmapped and freed. Currently in driver,
1100              * reference buffer management of the internal scratch buffer is not implemented
1101              * and hence the DPB buffers get unmapped. For other codecs it does not matter
1102              * as with the new SPS/PPS, the DPB is flushed.
1103              */
1104             bool is_not_vp9 = eCompressionFormat != OMX_VIDEO_CodingVP9;
1105             bool eligible_for_split_dpb_ubwc =
1106                m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE &&     //@ Due to Venus limitation for Interlaced, Split mode enabled only for Progressive.
1107                is_not_vp9                                       &&     //@ Split mode disabled for VP9.
1108                !drv_ctx.idr_only_decoding                       &&     //@ Split mode disabled for Thumbnail usecase.
1109                !m_disable_split_mode;                                  //@ Set prop to disable split mode
1110 
1111             //Since opb is linear, dpb should also be linear.
1112             if (split_opb_dpb_with_same_color_fmt) {
1113                 eligible_for_split_dpb_ubwc = false;
1114             }
1115 
1116             if (eligible_for_split_dpb_ubwc) {
1117                 //split DPB-OPB
1118                 //DPB -> UBWC , OPB -> Linear
1119                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1120             } else if (split_opb_dpb_with_same_color_fmt) {
1121                         //DPB -> Linear, OPB -> Linear
1122                         eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1123             } else {
1124                         //DPB-OPB combined linear
1125                         eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1126            }
1127         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1128             //split DPB-OPB
1129             //DPB -> UBWC, OPB -> Linear
1130             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1131         }
1132     } else { //no cpu access
1133         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1134             if (split_opb_dpb_with_same_color_fmt) {
1135                 //split DPB-OPB
1136                 //DPB -> UBWC, OPB -> UBWC
1137                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1138             } else {
1139                 //DPB-OPB combined UBWC
1140                 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1141             }
1142         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1143             if (dither_enable) {
1144                 //split DPB-OPB
1145                 //DPB -> TP10UBWC, OPB -> UBWC
1146                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1147             } else {
1148                 //combined DPB-OPB
1149                 //DPB -> TP10UBWC, OPB -> TP10UBWC
1150                 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1151             }
1152         }
1153     }
1154     if (eRet) {
1155         DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1156     }
1157 
1158 
1159 
1160     return eRet;
1161 }
1162 
enable_downscalar()1163 int omx_vdec::enable_downscalar()
1164 {
1165     int rc = 0;
1166     struct v4l2_control control;
1167     struct v4l2_format fmt;
1168 
1169     if (is_down_scalar_enabled) {
1170         DEBUG_PRINT_LOW("%s: already enabled", __func__);
1171         return 0;
1172     }
1173 
1174     DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1175     rc = decide_dpb_buffer_mode(true);
1176     if (rc) {
1177         DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1178         return rc;
1179     }
1180     is_down_scalar_enabled = true;
1181 
1182     memset(&control, 0x0, sizeof(struct v4l2_control));
1183     control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1184     control.value = 1;
1185     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1186     if (rc) {
1187         DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1188         return rc;
1189     }
1190 
1191     return 0;
1192 }
1193 
disable_downscalar()1194 int omx_vdec::disable_downscalar()
1195 {
1196     int rc = 0;
1197     struct v4l2_control control;
1198 
1199     if (!is_down_scalar_enabled) {
1200         DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1201         return 0;
1202     }
1203 
1204     rc = decide_dpb_buffer_mode(false);
1205     if (rc < 0) {
1206         DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1207         return rc;
1208     }
1209     is_down_scalar_enabled = false;
1210 
1211     return rc;
1212 }
1213 
decide_downscalar()1214 int omx_vdec::decide_downscalar()
1215 {
1216     int rc = 0;
1217     struct v4l2_format fmt;
1218     enum color_fmts color_format;
1219     OMX_U32 width, height;
1220     OMX_BOOL isPortraitVideo = OMX_FALSE;
1221 
1222     if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1223         rc = disable_downscalar();
1224         if (rc) {
1225             DEBUG_PRINT_ERROR("Disable downscalar failed!");
1226             return rc;
1227         }
1228         return 0;
1229     }
1230 
1231     if  (!m_enable_downscalar) {
1232         DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1233         return 0;
1234     }
1235 
1236 #ifdef _QUERY_DISP_RES_
1237     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1238     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1239     fmt.fmt.pix_mp.pixelformat = capture_capability;
1240     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1241     if (rc < 0) {
1242        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1243        return rc;
1244     }
1245     isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
1246     if (!m_downscalar_width || !m_downscalar_height) {
1247         qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
1248         int prim_config, ext_config, virt_config;
1249 
1250         prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
1251         dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
1252         DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d  dpa.yres=%d   dpa.xdpi = %f  dpa.ydpi = %f ",
1253             __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
1254 
1255         ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
1256         dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
1257         DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d  dsa.yres = %d   dsa.xdpi = %f  dsa.ydpi = %f ",
1258             __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
1259 
1260         virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
1261         dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
1262         DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d  dva.yres = %d   dva.xdpi = %f  dva.ydpi = %f ",
1263             __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
1264 
1265         /* Below logic takes care of following conditions:
1266          *   1. Choose display resolution as maximum resolution of all the connected
1267          *      displays (secondary, primary, virtual), so that we do not downscale
1268          *      unnecessarily which might be supported on one of the display losing quality.
1269          *   2. Displays connected might be in landscape or portrait mode, so the xres might
1270          *      be smaller or greater than the yres. So we first take the max of the two
1271          *      in width and min of two in height and then rotate it if below point is true.
1272          *   3. Video might also be in portrait mode, so invert the downscalar width and
1273          *      height for such cases.
1274          */
1275         if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
1276             m_downscalar_width = MAX(dsa.xres, dsa.yres);
1277             m_downscalar_height = MIN(dsa.xres, dsa.yres);
1278         } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
1279             m_downscalar_width = MAX(dva.xres, dva.yres);
1280             m_downscalar_height = MIN(dva.xres, dva.yres);
1281 
1282         } else {
1283             m_downscalar_width = MAX(dpa.xres, dpa.yres);
1284             m_downscalar_height = MIN(dpa.xres, dpa.yres);
1285         }
1286         if (isPortraitVideo) {
1287             // Swap width and height
1288             m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1289             m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
1290             m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1291         }
1292     }
1293     m_downscalar_width = ALIGN(m_downscalar_width, 128);
1294     m_downscalar_height = ALIGN(m_downscalar_height, 32);
1295 #endif
1296 
1297     if (!m_downscalar_width || !m_downscalar_height) {
1298         DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
1299         return 0;
1300     }
1301 
1302     if (m_force_down_scalar) {
1303         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1304         return 0;
1305     }
1306 
1307     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1308     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1309     fmt.fmt.pix_mp.pixelformat = capture_capability;
1310     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1311     if (rc < 0) {
1312        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1313        return rc;
1314     }
1315 
1316     height = fmt.fmt.pix_mp.height;
1317     width = fmt.fmt.pix_mp.width;
1318 
1319     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
1320         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
1321 
1322     if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
1323          m_is_display_session) {
1324         rc = enable_downscalar();
1325         if (rc < 0) {
1326             DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1327             return rc;
1328         }
1329 
1330         width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1331                             fmt.fmt.pix_mp.width : m_downscalar_width;
1332         height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1333                             fmt.fmt.pix_mp.height : m_downscalar_height;
1334         switch (capture_capability) {
1335             case V4L2_PIX_FMT_NV12:
1336                 color_format = COLOR_FMT_NV12;
1337                 break;
1338             case V4L2_PIX_FMT_NV12_UBWC:
1339                 color_format = COLOR_FMT_NV12_UBWC;
1340                 break;
1341             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1342                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1343                 break;
1344             default:
1345                 DEBUG_PRINT_ERROR("Color format not recognized\n");
1346                 rc = OMX_ErrorUndefined;
1347                 return rc;
1348         }
1349     } else {
1350 
1351         rc = disable_downscalar();
1352         if (rc < 0) {
1353             DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1354             return rc;
1355         }
1356     }
1357 
1358     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1359     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1360     fmt.fmt.pix_mp.height = height;
1361     fmt.fmt.pix_mp.width = width;
1362     fmt.fmt.pix_mp.pixelformat = capture_capability;
1363     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1364     if (rc) {
1365         DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1366         return rc;
1367     }
1368 
1369     rc = get_buffer_req(&drv_ctx.op_buf);
1370     if (rc) {
1371         DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1372         return rc;
1373     }
1374 
1375     return rc;
1376 }
1377 
1378 /* ======================================================================
1379    FUNCTION
1380    omx_vdec::OMXCntrlProcessMsgCb
1381 
1382    DESCRIPTION
1383    IL Client callbacks are generated through this routine. The decoder
1384    provides the thread context for this routine.
1385 
1386    PARAMETERS
1387    ctxt -- Context information related to the self.
1388    id   -- Event identifier. This could be any of the following:
1389    1. Command completion event
1390    2. Buffer done callback event
1391    3. Frame done callback event
1392 
1393    RETURN VALUE
1394    None.
1395 
1396    ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1397 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1398 {
1399     unsigned long p1; // Parameter - 1
1400     unsigned long p2; // Parameter - 2
1401     unsigned long ident;
1402     unsigned qsize=0; // qsize
1403     omx_vdec *pThis = (omx_vdec *) ctxt;
1404 
1405     if (!pThis) {
1406         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1407                 __func__);
1408         return;
1409     }
1410 
1411     // Protect the shared queue data structure
1412     do {
1413         /*Read the message id's from the queue*/
1414         pthread_mutex_lock(&pThis->m_lock);
1415         qsize = pThis->m_cmd_q.m_size;
1416         if (qsize) {
1417             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1418         }
1419 
1420         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1421             qsize = pThis->m_ftb_q.m_size;
1422             if (qsize) {
1423                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1424             }
1425         }
1426 
1427         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1428             qsize = pThis->m_etb_q.m_size;
1429             if (qsize) {
1430                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1431             }
1432         }
1433         pthread_mutex_unlock(&pThis->m_lock);
1434 
1435         /*process message if we have one*/
1436         if (qsize > 0) {
1437             id = ident;
1438             switch (id) {
1439                 case OMX_COMPONENT_GENERATE_EVENT:
1440                     if (pThis->m_cb.EventHandler) {
1441                         switch (p1) {
1442                             case OMX_CommandStateSet:
1443                                 pThis->m_state = (OMX_STATETYPE) p2;
1444                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1445                                         pThis->m_state);
1446                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1447                                         OMX_EventCmdComplete, p1, p2, NULL);
1448                                 break;
1449 
1450                             case OMX_EventError:
1451                                 if (p2 == OMX_StateInvalid) {
1452                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1453                                     pThis->m_state = (OMX_STATETYPE) p2;
1454                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1455                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1456                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1457                                     pThis->omx_report_error();
1458                                 } else {
1459                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1460                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
1461                                 }
1462                                 break;
1463 
1464                             case OMX_CommandPortDisable:
1465                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1466                                 if (BITMASK_PRESENT(&pThis->m_flags,
1467                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1468                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1469                                     break;
1470                                 }
1471                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1472                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1473                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1474                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1475                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
1476                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1477                                     if (eRet !=  OMX_ErrorNone) {
1478                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1479                                         pThis->omx_report_error();
1480                                         break;
1481                                     }
1482                                 }
1483                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1484                                         OMX_EventCmdComplete, p1, p2, NULL );
1485                                 break;
1486                             case OMX_CommandPortEnable:
1487                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1488                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1489                                         OMX_EventCmdComplete, p1, p2, NULL );
1490                                 pThis->in_reconfig = false;
1491                                 break;
1492 
1493                             default:
1494                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1495                                         OMX_EventCmdComplete, p1, p2, NULL );
1496                                 break;
1497 
1498                         }
1499                     } else {
1500                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1501                     }
1502                     break;
1503                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1504                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1505                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1506                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1507                         pThis->omx_report_error ();
1508                     }
1509                     break;
1510                 case OMX_COMPONENT_GENERATE_ETB: {
1511                         OMX_ERRORTYPE iret;
1512                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1513                         if (iret == OMX_ErrorInsufficientResources) {
1514                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1515                             pThis->omx_report_hw_overload ();
1516                         } else if (iret != OMX_ErrorNone) {
1517                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1518                             pThis->omx_report_error ();
1519                         }
1520                     }
1521                     break;
1522 
1523                 case OMX_COMPONENT_GENERATE_FTB:
1524                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1525                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1526                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1527                         pThis->omx_report_error ();
1528                     }
1529                     break;
1530 
1531                 case OMX_COMPONENT_GENERATE_COMMAND:
1532                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1533                             (OMX_U32)p2,(OMX_PTR)NULL);
1534                     break;
1535 
1536                 case OMX_COMPONENT_GENERATE_EBD:
1537 
1538                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1539                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1540                         pThis->omx_report_error ();
1541                     } else {
1542                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1543                             pThis->time_stamp_dts.remove_time_stamp(
1544                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1545                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1546                                     ?true:false);
1547                         }
1548 
1549                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1550                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1551                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1552                             pThis->omx_report_error ();
1553                         }
1554                     }
1555                     break;
1556                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1557                                             int64_t *timestamp = (int64_t *)(intptr_t)p1;
1558                                             if (p1) {
1559                                                 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1560                                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1561                                                         ?true:false);
1562                                                 free(timestamp);
1563                                             }
1564                                         }
1565                                         break;
1566                 case OMX_COMPONENT_GENERATE_FBD:
1567                                         if (p2 != VDEC_S_SUCCESS) {
1568                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1569                                             pThis->omx_report_error ();
1570                                         } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1571                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1572                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
1573                                             pThis->omx_report_error ();
1574                                         }
1575                                         break;
1576 
1577                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1578                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1579                                         if (!pThis->input_flush_progress) {
1580                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1581                                         } else {
1582                                             pThis->execute_input_flush();
1583                                             if (pThis->m_cb.EventHandler) {
1584                                                 if (p2 != VDEC_S_SUCCESS) {
1585                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1586                                                     pThis->omx_report_error ();
1587                                                 } else {
1588                                                     /*Check if we need generate event for Flush done*/
1589                                                     pThis->notify_flush_done(ctxt);
1590 
1591                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1592                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1593                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1594                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1595                                                             pThis->omx_report_error ();
1596                                                         } else {
1597                                                             pThis->streaming[OUTPUT_PORT] = false;
1598                                                         }
1599                                                         if (!pThis->output_flush_progress) {
1600                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1601                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1602                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1603                                                         }
1604                                                     }
1605                                                 }
1606                                             } else {
1607                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1608                                             }
1609                                         }
1610                                         break;
1611 
1612                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1613                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1614                                         if (!pThis->output_flush_progress) {
1615                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1616                                         } else {
1617                                             pThis->execute_output_flush();
1618                                             if (pThis->m_cb.EventHandler) {
1619                                                 if (p2 != VDEC_S_SUCCESS) {
1620                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1621                                                     pThis->omx_report_error ();
1622                                                 } else {
1623                                                     /*Check if we need generate event for Flush done*/
1624                                                     pThis->notify_flush_done(ctxt);
1625 
1626                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1627                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1628                                                         DEBUG_PRINT_LOW("Internal flush complete");
1629                                                         BITMASK_CLEAR (&pThis->m_flags,
1630                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1631                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1632                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1633                                                             pThis->post_event(OMX_CommandPortDisable,
1634                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1635                                                                     OMX_COMPONENT_GENERATE_EVENT);
1636                                                             BITMASK_CLEAR (&pThis->m_flags,
1637                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1638                                                             BITMASK_CLEAR (&pThis->m_flags,
1639                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1640 
1641                                                         }
1642                                                     }
1643 
1644                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1645                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1646                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1647                                                             pThis->omx_report_error ();
1648                                                             break;
1649                                                         }
1650                                                         pThis->streaming[CAPTURE_PORT] = false;
1651                                                         if (!pThis->input_flush_progress) {
1652                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1653                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1654                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1655                                                         }
1656                                                     }
1657                                                 }
1658                                             } else {
1659                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1660                                             }
1661                                         }
1662                                         break;
1663 
1664                 case OMX_COMPONENT_GENERATE_START_DONE:
1665                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1666 
1667                                         if (pThis->m_cb.EventHandler) {
1668                                             if (p2 != VDEC_S_SUCCESS) {
1669                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1670                                                 pThis->omx_report_error ();
1671                                             } else {
1672                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1673                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1674                                                     DEBUG_PRINT_LOW("Move to executing");
1675                                                     // Send the callback now
1676                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1677                                                     pThis->m_state = OMX_StateExecuting;
1678                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1679                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1680                                                             OMX_StateExecuting, NULL);
1681                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1682                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1683                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1684                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1685                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1686                                                         pThis->omx_report_error ();
1687                                                     }
1688                                                 }
1689                                             }
1690                                         } else {
1691                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1692                                         }
1693                                         break;
1694 
1695                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1696                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1697                                         if (pThis->m_cb.EventHandler) {
1698                                             if (p2 != VDEC_S_SUCCESS) {
1699                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1700                                                 pThis->omx_report_error ();
1701                                             } else {
1702                                                 pThis->complete_pending_buffer_done_cbs();
1703                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1704                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1705                                                     //Send the callback now
1706                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1707                                                     pThis->m_state = OMX_StatePause;
1708                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1709                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1710                                                             OMX_StatePause, NULL);
1711                                                 }
1712                                             }
1713                                         } else {
1714                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1715                                         }
1716 
1717                                         break;
1718 
1719                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1720                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1721                                         if (pThis->m_cb.EventHandler) {
1722                                             if (p2 != VDEC_S_SUCCESS) {
1723                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1724                                                 pThis->omx_report_error ();
1725                                             } else {
1726                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1727                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1728                                                     // Send the callback now
1729                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1730                                                     pThis->m_state = OMX_StateExecuting;
1731                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1732                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1733                                                             OMX_StateExecuting,NULL);
1734                                                 }
1735                                             }
1736                                         } else {
1737                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1738                                         }
1739 
1740                                         break;
1741 
1742                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1743                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1744                                         if (pThis->m_cb.EventHandler) {
1745                                             if (p2 != VDEC_S_SUCCESS) {
1746                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1747                                                 pThis->omx_report_error ();
1748                                             } else {
1749                                                 pThis->complete_pending_buffer_done_cbs();
1750                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1751                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1752                                                     // Send the callback now
1753                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1754                                                     pThis->m_state = OMX_StateIdle;
1755                                                     DEBUG_PRINT_LOW("Move to Idle State");
1756                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1757                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1758                                                             OMX_StateIdle,NULL);
1759                                                 }
1760                                             }
1761                                         } else {
1762                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1763                                         }
1764 
1765                                         break;
1766 
1767                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1768                                         if (p2 == OMX_IndexParamPortDefinition) {
1769                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1770                                             pThis->in_reconfig = true;
1771                                             pThis->m_need_turbo &= ~TURBO_MODE_HIGH_FPS;
1772                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1773                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1774 
1775                                             /* Check if resolution is changed in smooth streaming mode */
1776                                             if (pThis->m_smoothstreaming_mode &&
1777                                                 (pThis->framesize.nWidth !=
1778                                                     pThis->drv_ctx.video_resolution.frame_width) ||
1779                                                 (pThis->framesize.nHeight !=
1780                                                     pThis->drv_ctx.video_resolution.frame_height)) {
1781 
1782                                                 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1783                                                         pThis->framesize.nWidth,
1784                                                         pThis->framesize.nHeight,
1785                                                         pThis->drv_ctx.video_resolution.frame_width,
1786                                                         pThis->drv_ctx.video_resolution.frame_height);
1787 
1788                                                 /* Update new resolution */
1789                                                 pThis->framesize.nWidth =
1790                                                        pThis->drv_ctx.video_resolution.frame_width;
1791                                                 pThis->framesize.nHeight =
1792                                                        pThis->drv_ctx.video_resolution.frame_height;
1793 
1794                                                 /* Update C2D with new resolution */
1795                                                 if (!pThis->client_buffers.update_buffer_req()) {
1796                                                     DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1797                                                 }
1798                                             }
1799 
1800                                             /* Update new crop information */
1801                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1802                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1803                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1804                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1805 
1806                                             /* Validate the new crop information */
1807                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1808                                                 pThis->drv_ctx.video_resolution.frame_width) {
1809 
1810                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1811                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1812                                                         pThis->drv_ctx.video_resolution.frame_width);
1813                                                 pThis->rectangle.nLeft = 0;
1814 
1815                                                 if (pThis->rectangle.nWidth >
1816                                                     pThis->drv_ctx.video_resolution.frame_width) {
1817 
1818                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1819                                                             pThis->rectangle.nWidth,
1820                                                             pThis->drv_ctx.video_resolution.frame_width);
1821                                                     pThis->rectangle.nWidth =
1822                                                         pThis->drv_ctx.video_resolution.frame_width;
1823                                                 }
1824                                             }
1825                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1826                                                 pThis->drv_ctx.video_resolution.frame_height) {
1827 
1828                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1829                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1830                                                     pThis->drv_ctx.video_resolution.frame_height);
1831                                                 pThis->rectangle.nTop = 0;
1832 
1833                                                 if (pThis->rectangle.nHeight >
1834                                                     pThis->drv_ctx.video_resolution.frame_height) {
1835 
1836                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1837                                                         pThis->rectangle.nHeight,
1838                                                         pThis->drv_ctx.video_resolution.frame_height);
1839                                                     pThis->rectangle.nHeight =
1840                                                         pThis->drv_ctx.video_resolution.frame_height;
1841                                                 }
1842                                             }
1843                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1844                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1845                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1846                                         } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1847                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1848                                         } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1849                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1850                                         } else {
1851                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1852                                             break;
1853                                         }
1854                                         if (pThis->m_debug.outfile) {
1855                                             fclose(pThis->m_debug.outfile);
1856                                             pThis->m_debug.outfile = NULL;
1857                                         }
1858                                         if (pThis->m_debug.out_ymeta_file) {
1859                                             fclose(pThis->m_debug.out_ymeta_file);
1860                                             pThis->m_debug.out_ymeta_file = NULL;
1861                                         }
1862                                         if (pThis->m_debug.out_uvmeta_file) {
1863                                             fclose(pThis->m_debug.out_uvmeta_file);
1864                                             pThis->m_debug.out_uvmeta_file = NULL;
1865                                         }
1866 
1867                                         if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1868                                             pThis->prefetchNewBuffers();
1869                                         }
1870 
1871                                         if (pThis->m_cb.EventHandler) {
1872                                             uint32_t frame_data[7];
1873                                             frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1874                                                 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1875                                             frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1876                                                 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1877 
1878                                             frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ?
1879                                                 frame_data[0] : pThis->drv_ctx.video_resolution.frame_height;
1880 
1881                                             frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ?
1882                                                 frame_data[1] : pThis->drv_ctx.video_resolution.frame_width;
1883                                             frame_data[4] = pThis->dpb_bit_depth;
1884                                             frame_data[5] = pThis->m_color_space;
1885                                             frame_data[6] = pThis->m_dither_config;
1886 
1887                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1888                                                     OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1889                                         } else {
1890                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1891                                         }
1892                                         break;
1893 
1894                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1895                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1896                                         if (pThis->m_cb.EventHandler) {
1897                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1898                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1899                                         } else {
1900                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1901                                         }
1902                                         pThis->prev_ts = LLONG_MAX;
1903                                         pThis->rst_prev_ts = true;
1904                                         break;
1905 
1906                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1907                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1908                                         pThis->omx_report_error();
1909                                         break;
1910 
1911                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1912                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1913                                         pThis->omx_report_unsupported_setting();
1914                                         break;
1915 
1916                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1917                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1918                                         pThis->omx_report_hw_overload();
1919                                         break;
1920 
1921                 default:
1922                                         break;
1923             }
1924         }
1925         pthread_mutex_lock(&pThis->m_lock);
1926         qsize = pThis->m_cmd_q.m_size;
1927         if (pThis->m_state != OMX_StatePause)
1928             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1929         pthread_mutex_unlock(&pThis->m_lock);
1930     } while (qsize>0);
1931 
1932 }
1933 
update_resolution(int width,int height,int stride,int scan_lines)1934 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1935 {
1936     int format_changed = 0;
1937     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1938             (width != (int)drv_ctx.video_resolution.frame_width)) {
1939         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1940                 width, drv_ctx.video_resolution.frame_width,
1941                 height,drv_ctx.video_resolution.frame_height);
1942         format_changed = 1;
1943     }
1944     drv_ctx.video_resolution.frame_height = height;
1945     drv_ctx.video_resolution.frame_width = width;
1946     drv_ctx.video_resolution.scan_lines = scan_lines;
1947     drv_ctx.video_resolution.stride = stride;
1948 
1949     if (!is_down_scalar_enabled) {
1950         rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
1951         rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
1952         rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
1953         rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
1954     }
1955     return format_changed;
1956 }
1957 
is_video_session_supported()1958 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1959 {
1960     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1961                 OMX_MAX_STRINGNAME_SIZE) &&
1962             (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1963         m_decoder_capability.max_width = 1280;
1964         m_decoder_capability.max_height = 720;
1965         DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1966     }
1967 
1968     if ((drv_ctx.video_resolution.frame_width *
1969                 drv_ctx.video_resolution.frame_height >
1970                 m_decoder_capability.max_width *
1971                 m_decoder_capability.max_height) ||
1972             (drv_ctx.video_resolution.frame_width*
1973              drv_ctx.video_resolution.frame_height <
1974              m_decoder_capability.min_width *
1975              m_decoder_capability.min_height)) {
1976         DEBUG_PRINT_ERROR(
1977                 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1978                 drv_ctx.video_resolution.frame_width,
1979                 drv_ctx.video_resolution.frame_height,
1980                 m_decoder_capability.min_width,
1981                 m_decoder_capability.min_height,
1982                 m_decoder_capability.max_width,
1983                 m_decoder_capability.max_height);
1984         return OMX_ErrorUnsupportedSetting;
1985     }
1986     DEBUG_PRINT_HIGH("video session supported");
1987     return OMX_ErrorNone;
1988 }
1989 
log_input_buffers(const char * buffer_addr,int buffer_len)1990 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1991 {
1992     if (m_debug.in_buffer_log && !m_debug.infile) {
1993         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1994            snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1995                    m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1996         } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1997                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1998                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1999         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
2000                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
2001                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2002         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
2003                     !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2004                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
2005                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2006         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2007                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
2008                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2009         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
2010                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2011                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2012         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
2013                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2014                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2015         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
2016                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2017                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2018         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2019                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2020                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2021         } else {
2022                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
2023                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2024         }
2025         m_debug.infile = fopen (m_debug.infile_name, "ab");
2026         if (!m_debug.infile) {
2027             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
2028             m_debug.infile_name[0] = '\0';
2029             return -1;
2030         }
2031         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2032                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2033             struct ivf_file_header {
2034                 OMX_U8 signature[4]; //='DKIF';
2035                 OMX_U8 version         ; //= 0;
2036                 OMX_U8 headersize      ; //= 32;
2037                 OMX_U32 FourCC;
2038                 OMX_U8 width;
2039                 OMX_U8 height;
2040                 OMX_U32 rate;
2041                 OMX_U32 scale;
2042                 OMX_U32 length;
2043                 OMX_U8 unused[4];
2044             } file_header;
2045 
2046             memset((void *)&file_header,0,sizeof(file_header));
2047             file_header.signature[0] = 'D';
2048             file_header.signature[1] = 'K';
2049             file_header.signature[2] = 'I';
2050             file_header.signature[3] = 'F';
2051             file_header.version = 0;
2052             file_header.headersize = 32;
2053             switch (drv_ctx.decoder_format) {
2054                 case VDEC_CODECTYPE_VP8:
2055                     file_header.FourCC = 0x30385056;
2056                     break;
2057                 case VDEC_CODECTYPE_VP9:
2058                     file_header.FourCC = 0x30395056;
2059                     break;
2060                 default:
2061                     DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
2062                     break;
2063             }
2064             fwrite((const char *)&file_header,
2065                     sizeof(file_header),1,m_debug.infile);
2066          }
2067     }
2068     if (m_debug.infile && buffer_addr && buffer_len) {
2069         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2070                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2071             struct vpx_ivf_frame_header {
2072                 OMX_U32 framesize;
2073                 OMX_U32 timestamp_lo;
2074                 OMX_U32 timestamp_hi;
2075             } vpx_frame_header;
2076             vpx_frame_header.framesize = buffer_len;
2077             /* Currently FW doesn't use timestamp values */
2078             vpx_frame_header.timestamp_lo = 0;
2079             vpx_frame_header.timestamp_hi = 0;
2080             fwrite((const char *)&vpx_frame_header,
2081                     sizeof(vpx_frame_header),1,m_debug.infile);
2082         }
2083         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
2084     }
2085     return 0;
2086 }
2087 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2088 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2089     int buf_index = 0;
2090     char *temp = NULL;
2091 
2092     if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2093         return 0;
2094 
2095     if (m_debug.out_buffer_log && !m_debug.outfile) {
2096         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
2097                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2098         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2099         if (!m_debug.outfile) {
2100             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2101             m_debug.outfile_name[0] = '\0';
2102             return -1;
2103         }
2104     }
2105 
2106     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2107         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2108                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2109         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2110                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2111         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2112         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2113         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2114             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2115             m_debug.out_ymetafile_name[0] = '\0';
2116             m_debug.out_uvmetafile_name[0] = '\0';
2117             return -1;
2118         }
2119     }
2120 
2121     buf_index = buffer - m_out_mem_ptr;
2122     temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2123 
2124     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2125             drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2126         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2127             drv_ctx.video_resolution.frame_width,
2128             drv_ctx.video_resolution.frame_height);
2129 
2130         if (m_debug.outfile)
2131             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2132 
2133         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2134             unsigned int width = 0, height = 0;
2135             unsigned int y_plane, y_meta_plane;
2136             int y_stride = 0, y_sclines = 0;
2137             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2138             int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2139             int i;
2140             int bytes_written = 0;
2141 
2142             width = drv_ctx.video_resolution.frame_width;
2143             height = drv_ctx.video_resolution.frame_height;
2144             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2145             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2146             y_stride = VENUS_Y_STRIDE(color_fmt, width);
2147             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2148             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2149             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2150 
2151             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2152             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2153 
2154             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2155             for (i = 0; i < y_meta_scanlines; i++) {
2156                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2157                  temp += y_meta_stride;
2158             }
2159 
2160             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
2161             for(i = 0; i < uv_meta_scanlines; i++) {
2162                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2163                 temp += uv_meta_stride;
2164             }
2165         }
2166     } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2167         int stride = drv_ctx.video_resolution.stride;
2168         int scanlines = drv_ctx.video_resolution.scan_lines;
2169         if (m_smoothstreaming_mode) {
2170             stride = drv_ctx.video_resolution.frame_width;
2171             scanlines = drv_ctx.video_resolution.frame_height;
2172             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2173             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2174         }
2175         unsigned i;
2176         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2177             drv_ctx.video_resolution.frame_width,
2178             drv_ctx.video_resolution.frame_height, stride, scanlines);
2179         int bytes_written = 0;
2180         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2181              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2182              temp += stride;
2183         }
2184         temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
2185         int stride_c = stride;
2186         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2187             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2188             temp += stride_c;
2189         }
2190     }
2191     return 0;
2192 }
2193 
2194 /* ======================================================================
2195    FUNCTION
2196    omx_vdec::ComponentInit
2197 
2198    DESCRIPTION
2199    Initialize the component.
2200 
2201    PARAMETERS
2202    ctxt -- Context information related to the self.
2203    id   -- Event identifier. This could be any of the following:
2204    1. Command completion event
2205    2. Buffer done callback event
2206    3. Frame done callback event
2207 
2208    RETURN VALUE
2209    None.
2210 
2211    ========================================================================== */
component_init(OMX_STRING role)2212 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2213 {
2214 
2215     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2216     struct v4l2_fmtdesc fdesc;
2217     struct v4l2_format fmt;
2218     struct v4l2_requestbuffers bufreq;
2219     struct v4l2_control control;
2220     struct v4l2_frmsizeenum frmsize;
2221     unsigned int   alignment = 0,buffer_size = 0;
2222     int fds[2];
2223     int r,ret=0;
2224     bool codec_ambiguous = false;
2225     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2226     char property_value[PROPERTY_VALUE_MAX] = {0};
2227     FILE *soc_file = NULL;
2228     char buffer[10];
2229 
2230 #ifdef _ANDROID_
2231     char platform_name[PROPERTY_VALUE_MAX];
2232     property_get("ro.board.platform", platform_name, "0");
2233     if (!strncmp(platform_name, "msm8610", 7)) {
2234         device_name = (OMX_STRING)"/dev/video/q6_dec";
2235         is_q6_platform = true;
2236         maxSmoothStreamingWidth = 1280;
2237         maxSmoothStreamingHeight = 720;
2238     }
2239 #endif
2240 
2241     is_thulium_v1 = false;
2242     soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2243     if (soc_file) {
2244         fread(buffer, 1, 4, soc_file);
2245         fclose(soc_file);
2246         if (atoi(buffer) == 246) {
2247             soc_file = fopen("/sys/devices/soc0/revision", "r");
2248             if (soc_file) {
2249                 fread(buffer, 1, 4, soc_file);
2250                 fclose(soc_file);
2251                 if (atoi(buffer) == 1) {
2252                     is_thulium_v1 = true;
2253                     DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2254                 }
2255             }
2256         }
2257     }
2258 
2259 #ifdef _ANDROID_
2260     /*
2261      * turn off frame parsing for Android by default.
2262      * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2263      */
2264     arbitrary_bytes = false;
2265     property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2266     if (atoi(property_value)) {
2267         DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2268         arbitrary_bytes = true;
2269     }
2270 #endif
2271 
2272     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2273                 OMX_MAX_STRINGNAME_SIZE)) {
2274         secure_mode = true;
2275         arbitrary_bytes = false;
2276         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2277     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2278                 OMX_MAX_STRINGNAME_SIZE)) {
2279         secure_mode = true;
2280         arbitrary_bytes = false;
2281         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2282     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2283                 OMX_MAX_STRINGNAME_SIZE)) {
2284         secure_mode = true;
2285         arbitrary_bytes = false;
2286         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2287     } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2288                 OMX_MAX_STRINGNAME_SIZE)) {
2289         secure_mode = true;
2290         arbitrary_bytes = false;
2291         role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2292     } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2293                 OMX_MAX_STRINGNAME_SIZE)) {
2294         secure_mode = true;
2295         arbitrary_bytes = false;
2296         role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2297     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2298                 OMX_MAX_STRINGNAME_SIZE)) {
2299         secure_mode = true;
2300         arbitrary_bytes = false;
2301         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2302     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2303                 OMX_MAX_STRINGNAME_SIZE)) {
2304         secure_mode = true;
2305         arbitrary_bytes = false;
2306         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2307     }
2308     else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure",
2309                 OMX_MAX_STRINGNAME_SIZE)) {
2310         secure_mode = true;
2311         arbitrary_bytes = false;
2312         role = (OMX_STRING)"OMX.qcom.video.decoder.vp8";
2313     }
2314 
2315     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2316 
2317     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2318 
2319     if (drv_ctx.video_driver_fd < 0) {
2320         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2321         return OMX_ErrorInsufficientResources;
2322     }
2323     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2324     drv_ctx.frame_rate.fps_denominator = 1;
2325     operating_frame_rate = DEFAULT_FPS;
2326     m_poll_efd = eventfd(0, 0);
2327     if (m_poll_efd < 0) {
2328         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2329         return OMX_ErrorInsufficientResources;
2330     }
2331     ret = subscribe_to_events(drv_ctx.video_driver_fd);
2332     if (!ret) {
2333         async_thread_created = true;
2334         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2335     }
2336     if (ret) {
2337         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2338         async_thread_created = false;
2339         return OMX_ErrorInsufficientResources;
2340     }
2341 
2342 #ifdef OUTPUT_EXTRADATA_LOG
2343     outputExtradataFile = fopen (output_extradata_filename, "ab");
2344 #endif
2345 
2346     // Copy the role information which provides the decoder kind
2347     strlcpy(drv_ctx.kind,role,128);
2348 
2349     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2350                 OMX_MAX_STRINGNAME_SIZE)) {
2351         strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2352                 OMX_MAX_STRINGNAME_SIZE);
2353         drv_ctx.timestamp_adjust = true;
2354         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2355         eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2356         output_capability=V4L2_PIX_FMT_MPEG4;
2357         /*Initialize Start Code for MPEG4*/
2358         codec_type_parse = CODEC_TYPE_MPEG4;
2359         m_frame_parser.init_start_codes(codec_type_parse);
2360     } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2361                 OMX_MAX_STRINGNAME_SIZE)) {
2362         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2363                 OMX_MAX_STRINGNAME_SIZE);
2364         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2365         output_capability = V4L2_PIX_FMT_MPEG2;
2366         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2367         /*Initialize Start Code for MPEG2*/
2368         codec_type_parse = CODEC_TYPE_MPEG2;
2369         m_frame_parser.init_start_codes(codec_type_parse);
2370     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2371                 OMX_MAX_STRINGNAME_SIZE)) {
2372         strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2373         DEBUG_PRINT_LOW("H263 Decoder selected");
2374         drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2375         eCompressionFormat = OMX_VIDEO_CodingH263;
2376         output_capability = V4L2_PIX_FMT_H263;
2377         codec_type_parse = CODEC_TYPE_H263;
2378         m_frame_parser.init_start_codes(codec_type_parse);
2379     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2380                 OMX_MAX_STRINGNAME_SIZE)) {
2381         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2382         DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2383         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2384         output_capability = V4L2_PIX_FMT_DIVX_311;
2385         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2386         codec_type_parse = CODEC_TYPE_DIVX;
2387         m_frame_parser.init_start_codes(codec_type_parse);
2388 
2389     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2390                 OMX_MAX_STRINGNAME_SIZE)) {
2391         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2392         DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2393         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2394         output_capability = V4L2_PIX_FMT_DIVX;
2395         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2396         codec_type_parse = CODEC_TYPE_DIVX;
2397         codec_ambiguous = true;
2398         m_frame_parser.init_start_codes(codec_type_parse);
2399 
2400     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2401                 OMX_MAX_STRINGNAME_SIZE)) {
2402         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2403         DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2404         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2405         output_capability = V4L2_PIX_FMT_DIVX;
2406         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2407         codec_type_parse = CODEC_TYPE_DIVX;
2408         codec_ambiguous = true;
2409         m_frame_parser.init_start_codes(codec_type_parse);
2410 
2411     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2412                 OMX_MAX_STRINGNAME_SIZE)) {
2413         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2414         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2415         output_capability=V4L2_PIX_FMT_H264;
2416         eCompressionFormat = OMX_VIDEO_CodingAVC;
2417         codec_type_parse = CODEC_TYPE_H264;
2418         m_frame_parser.init_start_codes(codec_type_parse);
2419         m_frame_parser.init_nal_length(nal_length);
2420         if (is_thulium_v1) {
2421             arbitrary_bytes = true;
2422             DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2423         }
2424     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2425                 OMX_MAX_STRINGNAME_SIZE)) {
2426         strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2427         drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2428         output_capability = V4L2_PIX_FMT_H264_MVC;
2429         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2430         codec_type_parse = CODEC_TYPE_H264;
2431         m_frame_parser.init_start_codes(codec_type_parse);
2432         m_frame_parser.init_nal_length(nal_length);
2433     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2434                 OMX_MAX_STRINGNAME_SIZE)) {
2435         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2436         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2437         output_capability = V4L2_PIX_FMT_HEVC;
2438         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2439         codec_type_parse = CODEC_TYPE_HEVC;
2440         m_frame_parser.init_start_codes(codec_type_parse);
2441         m_frame_parser.init_nal_length(nal_length);
2442     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2443                 OMX_MAX_STRINGNAME_SIZE)) {
2444         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2445         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2446         eCompressionFormat = OMX_VIDEO_CodingWMV;
2447         codec_type_parse = CODEC_TYPE_VC1;
2448         output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2449         m_frame_parser.init_start_codes(codec_type_parse);
2450     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2451                 OMX_MAX_STRINGNAME_SIZE)) {
2452         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2453         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2454         eCompressionFormat = OMX_VIDEO_CodingWMV;
2455         codec_type_parse = CODEC_TYPE_VC1;
2456         output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2457         m_frame_parser.init_start_codes(codec_type_parse);
2458     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2459                 OMX_MAX_STRINGNAME_SIZE)) {
2460         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2461         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2462         output_capability = V4L2_PIX_FMT_VP8;
2463         eCompressionFormat = OMX_VIDEO_CodingVP8;
2464         codec_type_parse = CODEC_TYPE_VP8;
2465         arbitrary_bytes = false;
2466     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2467                 OMX_MAX_STRINGNAME_SIZE)) {
2468         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2469         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2470         output_capability = V4L2_PIX_FMT_VP9;
2471         eCompressionFormat = OMX_VIDEO_CodingVP9;
2472         codec_type_parse = CODEC_TYPE_VP9;
2473         arbitrary_bytes = false;
2474     } else {
2475         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2476         eRet = OMX_ErrorInvalidComponentName;
2477     }
2478 
2479     if (eRet == OMX_ErrorNone) {
2480         OMX_COLOR_FORMATTYPE dest_color_format;
2481         if (m_disable_ubwc_mode) {
2482             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2483         } else {
2484             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2485         }
2486         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2487             dest_color_format = (OMX_COLOR_FORMATTYPE)
2488                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2489         else
2490             dest_color_format = (OMX_COLOR_FORMATTYPE)
2491                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2492         if (!client_buffers.set_color_format(dest_color_format)) {
2493             DEBUG_PRINT_ERROR("Setting color format failed");
2494             eRet = OMX_ErrorInsufficientResources;
2495         }
2496 
2497         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2498         m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2499 
2500         if (m_disable_ubwc_mode) {
2501             capture_capability = V4L2_PIX_FMT_NV12;
2502         } else {
2503             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2504         }
2505 
2506         struct v4l2_capability cap;
2507         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2508         if (ret) {
2509             DEBUG_PRINT_ERROR("Failed to query capabilities");
2510             /*TODO: How to handle this case */
2511         } else {
2512             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2513                 " version = %d, capabilities = %x", cap.driver, cap.card,
2514                 cap.bus_info, cap.version, cap.capabilities);
2515         }
2516         ret=0;
2517         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2518         fdesc.index=0;
2519         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2520             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2521                     fdesc.pixelformat, fdesc.flags);
2522             fdesc.index++;
2523         }
2524         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2525         fdesc.index=0;
2526         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2527 
2528             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2529                     fdesc.pixelformat, fdesc.flags);
2530             fdesc.index++;
2531         }
2532         m_extradata_info.output_crop_rect.nLeft = 0;
2533         m_extradata_info.output_crop_rect.nTop = 0;
2534         m_extradata_info.output_crop_rect.nWidth = 320;
2535         m_extradata_info.output_crop_rect.nHeight = 240;
2536         update_resolution(320, 240, 320, 240);
2537 
2538         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2539         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2540         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2541         fmt.fmt.pix_mp.pixelformat = output_capability;
2542         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2543         if (ret) {
2544             /*TODO: How to handle this case */
2545             DEBUG_PRINT_ERROR("Failed to set format on output port");
2546             return OMX_ErrorInsufficientResources;
2547         }
2548         DEBUG_PRINT_HIGH("Set Format was successful");
2549         if (codec_ambiguous) {
2550             if (output_capability == V4L2_PIX_FMT_DIVX) {
2551                 struct v4l2_control divx_ctrl;
2552 
2553                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2554                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2555                 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2556                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2557                 } else {
2558                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2559                 }
2560 
2561                 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2562                 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2563                 if (ret) {
2564                     DEBUG_PRINT_ERROR("Failed to set divx version");
2565                 }
2566             } else {
2567                 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2568             }
2569         }
2570 
2571         property_get("persist.vendor.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2572         m_conceal_color= atoi(property_value);
2573         DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2574         control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2575         control.value = m_conceal_color;
2576         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2577         if (ret) {
2578             DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2579         }
2580 
2581         //Get the hardware capabilities
2582         memset((void *)&frmsize,0,sizeof(frmsize));
2583         frmsize.index = 0;
2584         frmsize.pixel_format = output_capability;
2585         ret = ioctl(drv_ctx.video_driver_fd,
2586                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2587         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2588             DEBUG_PRINT_ERROR("Failed to get framesizes");
2589             return OMX_ErrorHardware;
2590         }
2591 
2592         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2593             m_decoder_capability.min_width = frmsize.stepwise.min_width;
2594             m_decoder_capability.max_width = frmsize.stepwise.max_width;
2595             m_decoder_capability.min_height = frmsize.stepwise.min_height;
2596             m_decoder_capability.max_height = frmsize.stepwise.max_height;
2597         }
2598 
2599         memset(&fmt, 0x0, sizeof(struct v4l2_format));
2600         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2601         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2602         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2603         fmt.fmt.pix_mp.pixelformat = capture_capability;
2604         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2605         if (ret) {
2606             /*TODO: How to handle this case */
2607             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2608         }
2609         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2610         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2611         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2612 
2613         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2614         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2615         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2616 
2617         DEBUG_PRINT_HIGH("Set Format was successful");
2618         if (secure_mode) {
2619             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2620             control.value = 1;
2621             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2622             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2623             if (ret) {
2624                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2625                 return OMX_ErrorInsufficientResources;
2626             }
2627         }
2628         if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2629             control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2630             control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2631             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2632             if (ret) {
2633                 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2634                 return OMX_ErrorInsufficientResources;
2635             }
2636         }
2637 
2638         if (is_thulium_v1) {
2639             eRet = enable_smoothstreaming();
2640             if (eRet != OMX_ErrorNone) {
2641                DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2642                return eRet;
2643             }
2644         }
2645 
2646         /*Get the Buffer requirements for input and output ports*/
2647         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2648         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2649 
2650         if (secure_mode) {
2651             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2652             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2653         } else {
2654             drv_ctx.op_buf.alignment = SZ_4K;
2655             drv_ctx.ip_buf.alignment = SZ_4K;
2656         }
2657 
2658         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2659         drv_ctx.extradata = 0;
2660         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2661         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2662         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2663         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2664         drv_ctx.idr_only_decoding = 0;
2665 
2666 #ifdef _ANDROID_
2667         property_get("vendor.vidc.dec.enable.downscalar",property_value,"0");
2668         if (atoi(property_value)) {
2669             m_enable_downscalar =  atoi(property_value);
2670             property_get("vendor.vidc.dec.downscalar_width",property_value,"0");
2671             if (atoi(property_value)) {
2672                 m_downscalar_width = atoi(property_value);
2673             }
2674             property_get("vendor.vidc.dec.downscalar_height",property_value,"0");
2675             if (atoi(property_value)) {
2676                 m_downscalar_height = atoi(property_value);
2677             }
2678 
2679             if (m_downscalar_width < m_decoder_capability.min_width ||
2680                 m_downscalar_height < m_decoder_capability.min_height) {
2681                 m_downscalar_width = 0;
2682                 m_downscalar_height = 0;
2683             }
2684 
2685             DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2686                 m_downscalar_width, m_downscalar_height);
2687         }
2688         property_get("vendor.vidc.disable.split.mode",property_value,"0");
2689         m_disable_split_mode = atoi(property_value);
2690         DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");
2691 #endif
2692         m_state = OMX_StateLoaded;
2693 #ifdef DEFAULT_EXTRADATA
2694         enable_extradata(DEFAULT_EXTRADATA, true, true);
2695 #endif
2696         eRet = get_buffer_req(&drv_ctx.ip_buf);
2697         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2698         get_buffer_req(&drv_ctx.op_buf);
2699         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2700                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2701                 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2702                     h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2703                     h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2704                     h264_scratch.nFilledLen = 0;
2705                     h264_scratch.nOffset = 0;
2706 
2707                     if (h264_scratch.pBuffer == NULL) {
2708                         DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2709                         return OMX_ErrorInsufficientResources;
2710                     }
2711         }
2712         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2713             drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2714             if (m_frame_parser.mutils == NULL) {
2715                 m_frame_parser.mutils = new H264_Utils();
2716                 if (m_frame_parser.mutils == NULL) {
2717                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2718                     eRet = OMX_ErrorInsufficientResources;
2719                 } else {
2720                     m_frame_parser.mutils->initialize_frame_checking_environment();
2721                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2722                 }
2723             }
2724 
2725             h264_parser = new h264_stream_parser();
2726             if (!h264_parser) {
2727                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2728                 eRet = OMX_ErrorInsufficientResources;
2729             }
2730         }
2731 
2732         if (pipe(fds)) {
2733             DEBUG_PRINT_ERROR("pipe creation failed");
2734             eRet = OMX_ErrorInsufficientResources;
2735         } else {
2736             m_pipe_in = fds[0];
2737             m_pipe_out = fds[1];
2738             msg_thread_created = true;
2739             r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2740 
2741             if (r < 0) {
2742                 DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2743                 msg_thread_created = false;
2744                 eRet = OMX_ErrorInsufficientResources;
2745             }
2746         }
2747     }
2748 
2749     {
2750         VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2751         init_vendor_extensions(*extStore);
2752         mVendorExtensionStore.dumpExtensions((const char *)role);
2753     }
2754 
2755     if (eRet != OMX_ErrorNone) {
2756         DEBUG_PRINT_ERROR("Component Init Failed");
2757     } else {
2758         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2759                 drv_ctx.video_driver_fd);
2760     }
2761     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2762     return eRet;
2763 }
2764 
2765 /* ======================================================================
2766    FUNCTION
2767    omx_vdec::GetComponentVersion
2768 
2769    DESCRIPTION
2770    Returns the component version.
2771 
2772    PARAMETERS
2773    TBD.
2774 
2775    RETURN VALUE
2776    OMX_ErrorNone.
2777 
2778    ========================================================================== */
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)2779 OMX_ERRORTYPE  omx_vdec::get_component_version
2780 (
2781  OMX_IN OMX_HANDLETYPE hComp,
2782  OMX_OUT OMX_STRING componentName,
2783  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2784  OMX_OUT OMX_VERSIONTYPE* specVersion,
2785  OMX_OUT OMX_UUIDTYPE* componentUUID
2786  )
2787 {
2788     (void) hComp;
2789     (void) componentName;
2790     (void) componentVersion;
2791     (void) componentUUID;
2792     if (m_state == OMX_StateInvalid) {
2793         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2794         return OMX_ErrorInvalidState;
2795     }
2796     /* TBD -- Return the proper version */
2797     if (specVersion) {
2798         specVersion->nVersion = OMX_SPEC_VERSION;
2799     }
2800     return OMX_ErrorNone;
2801 }
2802 /* ======================================================================
2803    FUNCTION
2804    omx_vdec::SendCommand
2805 
2806    DESCRIPTION
2807    Returns zero if all the buffers released..
2808 
2809    PARAMETERS
2810    None.
2811 
2812    RETURN VALUE
2813    true/false
2814 
2815    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2816 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2817         OMX_IN OMX_COMMANDTYPE cmd,
2818         OMX_IN OMX_U32 param1,
2819         OMX_IN OMX_PTR cmdData
2820         )
2821 {
2822     (void) hComp;
2823     (void) cmdData;
2824     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2825     if (m_state == OMX_StateInvalid) {
2826         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2827         return OMX_ErrorInvalidState;
2828     }
2829     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2830             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2831         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2832                 "to invalid port: %u", (unsigned int)param1);
2833         return OMX_ErrorBadPortIndex;
2834     }
2835 
2836     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2837     sem_wait(&m_cmd_lock);
2838     DEBUG_PRINT_LOW("send_command: Command Processed");
2839     return OMX_ErrorNone;
2840 }
2841 
2842 /* ======================================================================
2843    FUNCTION
2844    omx_vdec::SendCommand
2845 
2846    DESCRIPTION
2847    Returns zero if all the buffers released..
2848 
2849    PARAMETERS
2850    None.
2851 
2852    RETURN VALUE
2853    true/false
2854 
2855    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2856 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2857         OMX_IN OMX_COMMANDTYPE cmd,
2858         OMX_IN OMX_U32 param1,
2859         OMX_IN OMX_PTR cmdData
2860         )
2861 {
2862     (void) hComp;
2863     (void) cmdData;
2864     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2865     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2866     int bFlag = 1,sem_posted = 0,ret=0;
2867 
2868     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2869     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2870             m_state, eState);
2871 
2872     if (cmd == OMX_CommandStateSet) {
2873         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2874         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2875         /***************************/
2876         /* Current State is Loaded */
2877         /***************************/
2878         if (m_state == OMX_StateLoaded) {
2879             if (eState == OMX_StateIdle) {
2880                 //if all buffers are allocated or all ports disabled
2881                 if (allocate_done() ||
2882                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2883                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2884                 } else {
2885                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2886                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2887                     // Skip the event notification
2888                     bFlag = 0;
2889                 }
2890             }
2891             /* Requesting transition from Loaded to Loaded */
2892             else if (eState == OMX_StateLoaded) {
2893                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2894                 post_event(OMX_EventError,OMX_ErrorSameState,\
2895                         OMX_COMPONENT_GENERATE_EVENT);
2896                 eRet = OMX_ErrorSameState;
2897             }
2898             /* Requesting transition from Loaded to WaitForResources */
2899             else if (eState == OMX_StateWaitForResources) {
2900                 /* Since error is None , we will post an event
2901                    at the end of this function definition */
2902                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2903             }
2904             /* Requesting transition from Loaded to Executing */
2905             else if (eState == OMX_StateExecuting) {
2906                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2907                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2908                         OMX_COMPONENT_GENERATE_EVENT);
2909                 eRet = OMX_ErrorIncorrectStateTransition;
2910             }
2911             /* Requesting transition from Loaded to Pause */
2912             else if (eState == OMX_StatePause) {
2913                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2914                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2915                         OMX_COMPONENT_GENERATE_EVENT);
2916                 eRet = OMX_ErrorIncorrectStateTransition;
2917             }
2918             /* Requesting transition from Loaded to Invalid */
2919             else if (eState == OMX_StateInvalid) {
2920                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2921                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2922                 eRet = OMX_ErrorInvalidState;
2923             } else {
2924                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2925                         eState);
2926                 eRet = OMX_ErrorBadParameter;
2927             }
2928         }
2929 
2930         /***************************/
2931         /* Current State is IDLE */
2932         /***************************/
2933         else if (m_state == OMX_StateIdle) {
2934             if (eState == OMX_StateLoaded) {
2935                 if (release_done()) {
2936                     /*
2937                      * Since error is None , we will post an event at the end
2938                      * of this function definition
2939                      * Reset buffer requirements here to ensure setting buffer requirement
2940                      * when component move to executing state from loaded state via Idle.
2941                      */
2942                     drv_ctx.op_buf.buffer_size = 0;
2943                     drv_ctx.op_buf.actualcount = 0;
2944                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2945                 } else {
2946                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2947                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2948                     // Skip the event notification
2949                     bFlag = 0;
2950                 }
2951             }
2952             /* Requesting transition from Idle to Executing */
2953             else if (eState == OMX_StateExecuting) {
2954                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2955                 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2956                 bFlag = 1;
2957                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2958                 m_state=OMX_StateExecuting;
2959                 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2960             }
2961             /* Requesting transition from Idle to Idle */
2962             else if (eState == OMX_StateIdle) {
2963                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2964                 post_event(OMX_EventError,OMX_ErrorSameState,\
2965                         OMX_COMPONENT_GENERATE_EVENT);
2966                 eRet = OMX_ErrorSameState;
2967             }
2968             /* Requesting transition from Idle to WaitForResources */
2969             else if (eState == OMX_StateWaitForResources) {
2970                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2971                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2972                         OMX_COMPONENT_GENERATE_EVENT);
2973                 eRet = OMX_ErrorIncorrectStateTransition;
2974             }
2975             /* Requesting transition from Idle to Pause */
2976             else if (eState == OMX_StatePause) {
2977                 /*To pause the Video core we need to start the driver*/
2978                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2979                       NULL) < */0) {
2980                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2981                     omx_report_error ();
2982                     eRet = OMX_ErrorHardware;
2983                 } else {
2984                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2985                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2986                     bFlag = 0;
2987                 }
2988             }
2989             /* Requesting transition from Idle to Invalid */
2990             else if (eState == OMX_StateInvalid) {
2991                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2992                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2993                 eRet = OMX_ErrorInvalidState;
2994             } else {
2995                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2996                 eRet = OMX_ErrorBadParameter;
2997             }
2998         }
2999 
3000         /******************************/
3001         /* Current State is Executing */
3002         /******************************/
3003         else if (m_state == OMX_StateExecuting) {
3004             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
3005             /* Requesting transition from Executing to Idle */
3006             if (eState == OMX_StateIdle) {
3007                 /* Since error is None , we will post an event
3008                    at the end of this function definition
3009                  */
3010                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
3011                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3012                 if (!sem_posted) {
3013                     sem_posted = 1;
3014                     sem_post (&m_cmd_lock);
3015                     execute_omx_flush(OMX_ALL);
3016                 }
3017                 bFlag = 0;
3018             }
3019             /* Requesting transition from Executing to Paused */
3020             else if (eState == OMX_StatePause) {
3021                 DEBUG_PRINT_LOW("PAUSE Command Issued");
3022                 m_state = OMX_StatePause;
3023                 bFlag = 1;
3024             }
3025             /* Requesting transition from Executing to Loaded */
3026             else if (eState == OMX_StateLoaded) {
3027                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
3028                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3029                         OMX_COMPONENT_GENERATE_EVENT);
3030                 eRet = OMX_ErrorIncorrectStateTransition;
3031             }
3032             /* Requesting transition from Executing to WaitForResources */
3033             else if (eState == OMX_StateWaitForResources) {
3034                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
3035                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3036                         OMX_COMPONENT_GENERATE_EVENT);
3037                 eRet = OMX_ErrorIncorrectStateTransition;
3038             }
3039             /* Requesting transition from Executing to Executing */
3040             else if (eState == OMX_StateExecuting) {
3041                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
3042                 post_event(OMX_EventError,OMX_ErrorSameState,\
3043                         OMX_COMPONENT_GENERATE_EVENT);
3044                 eRet = OMX_ErrorSameState;
3045             }
3046             /* Requesting transition from Executing to Invalid */
3047             else if (eState == OMX_StateInvalid) {
3048                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
3049                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3050                 eRet = OMX_ErrorInvalidState;
3051             } else {
3052                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
3053                 eRet = OMX_ErrorBadParameter;
3054             }
3055         }
3056         /***************************/
3057         /* Current State is Pause  */
3058         /***************************/
3059         else if (m_state == OMX_StatePause) {
3060             /* Requesting transition from Pause to Executing */
3061             if (eState == OMX_StateExecuting) {
3062                 DEBUG_PRINT_LOW("Pause --> Executing");
3063                 m_state = OMX_StateExecuting;
3064                 bFlag = 1;
3065             }
3066             /* Requesting transition from Pause to Idle */
3067             else if (eState == OMX_StateIdle) {
3068                 /* Since error is None , we will post an event
3069                    at the end of this function definition */
3070                 DEBUG_PRINT_LOW("Pause --> Idle");
3071                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3072                 if (!sem_posted) {
3073                     sem_posted = 1;
3074                     sem_post (&m_cmd_lock);
3075                     execute_omx_flush(OMX_ALL);
3076                 }
3077                 bFlag = 0;
3078             }
3079             /* Requesting transition from Pause to loaded */
3080             else if (eState == OMX_StateLoaded) {
3081                 DEBUG_PRINT_ERROR("Pause --> loaded");
3082                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3083                         OMX_COMPONENT_GENERATE_EVENT);
3084                 eRet = OMX_ErrorIncorrectStateTransition;
3085             }
3086             /* Requesting transition from Pause to WaitForResources */
3087             else if (eState == OMX_StateWaitForResources) {
3088                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
3089                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3090                         OMX_COMPONENT_GENERATE_EVENT);
3091                 eRet = OMX_ErrorIncorrectStateTransition;
3092             }
3093             /* Requesting transition from Pause to Pause */
3094             else if (eState == OMX_StatePause) {
3095                 DEBUG_PRINT_ERROR("Pause --> Pause");
3096                 post_event(OMX_EventError,OMX_ErrorSameState,\
3097                         OMX_COMPONENT_GENERATE_EVENT);
3098                 eRet = OMX_ErrorSameState;
3099             }
3100             /* Requesting transition from Pause to Invalid */
3101             else if (eState == OMX_StateInvalid) {
3102                 DEBUG_PRINT_ERROR("Pause --> Invalid");
3103                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3104                 eRet = OMX_ErrorInvalidState;
3105             } else {
3106                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
3107                 eRet = OMX_ErrorBadParameter;
3108             }
3109         }
3110         /***************************/
3111         /* Current State is WaitForResources  */
3112         /***************************/
3113         else if (m_state == OMX_StateWaitForResources) {
3114             /* Requesting transition from WaitForResources to Loaded */
3115             if (eState == OMX_StateLoaded) {
3116                 /* Since error is None , we will post an event
3117                    at the end of this function definition */
3118                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
3119             }
3120             /* Requesting transition from WaitForResources to WaitForResources */
3121             else if (eState == OMX_StateWaitForResources) {
3122                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
3123                 post_event(OMX_EventError,OMX_ErrorSameState,
3124                         OMX_COMPONENT_GENERATE_EVENT);
3125                 eRet = OMX_ErrorSameState;
3126             }
3127             /* Requesting transition from WaitForResources to Executing */
3128             else if (eState == OMX_StateExecuting) {
3129                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
3130                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3131                         OMX_COMPONENT_GENERATE_EVENT);
3132                 eRet = OMX_ErrorIncorrectStateTransition;
3133             }
3134             /* Requesting transition from WaitForResources to Pause */
3135             else if (eState == OMX_StatePause) {
3136                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
3137                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3138                         OMX_COMPONENT_GENERATE_EVENT);
3139                 eRet = OMX_ErrorIncorrectStateTransition;
3140             }
3141             /* Requesting transition from WaitForResources to Invalid */
3142             else if (eState == OMX_StateInvalid) {
3143                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
3144                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3145                 eRet = OMX_ErrorInvalidState;
3146             }
3147             /* Requesting transition from WaitForResources to Loaded -
3148                is NOT tested by Khronos TS */
3149 
3150         } else {
3151             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
3152             eRet = OMX_ErrorBadParameter;
3153         }
3154     }
3155     /********************************/
3156     /* Current State is Invalid */
3157     /*******************************/
3158     else if (m_state == OMX_StateInvalid) {
3159         /* State Transition from Invalid to any state */
3160         if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
3161             eState == OMX_StateIdle || eState == OMX_StateExecuting ||
3162             eState == OMX_StatePause || eState == OMX_StateInvalid) {
3163             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
3164             post_event(OMX_EventError,OMX_ErrorInvalidState,\
3165                     OMX_COMPONENT_GENERATE_EVENT);
3166             eRet = OMX_ErrorInvalidState;
3167         }
3168     } else if (cmd == OMX_CommandFlush) {
3169         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
3170                 "with param1: %u", (unsigned int)param1);
3171 #ifdef _MSM8974_
3172         send_codec_config();
3173 #endif
3174         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3175                     param1 == OMX_ALL)) {
3176             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3177                struct timespec ts;
3178 
3179                clock_gettime(CLOCK_REALTIME, &ts);
3180                ts.tv_sec += 2;
3181                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3182                        m_queued_codec_config_count);
3183                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3184                if (sem_timedwait(&m_safe_flush, &ts)) {
3185                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3186                }
3187                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3188             }
3189         }
3190 
3191         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3192             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3193         }
3194         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3195             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3196         }
3197         if (!sem_posted) {
3198             sem_posted = 1;
3199             DEBUG_PRINT_LOW("Set the Semaphore");
3200             sem_post (&m_cmd_lock);
3201             execute_omx_flush(param1);
3202         }
3203         bFlag = 0;
3204     } else if ( cmd == OMX_CommandPortEnable) {
3205         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3206                 "with param1: %u", (unsigned int)param1);
3207         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3208             m_inp_bEnabled = OMX_TRUE;
3209 
3210             if ( (m_state == OMX_StateLoaded &&
3211                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3212                     || allocate_input_done()) {
3213                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3214                         OMX_COMPONENT_GENERATE_EVENT);
3215             } else {
3216                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3217                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3218                 // Skip the event notification
3219                 bFlag = 0;
3220             }
3221         }
3222         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3223             DEBUG_PRINT_LOW("Enable output Port command recieved");
3224             m_out_bEnabled = OMX_TRUE;
3225 
3226             if ( (m_state == OMX_StateLoaded &&
3227                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3228                     || (allocate_output_done())) {
3229                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3230                         OMX_COMPONENT_GENERATE_EVENT);
3231 
3232             } else {
3233                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3234                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3235                 // Skip the event notification
3236                 bFlag = 0;
3237                 /* enable/disable downscaling if required */
3238                 ret = decide_downscalar();
3239                 if (ret) {
3240                     DEBUG_PRINT_LOW("decide_downscalar failed\n");
3241                 }
3242             }
3243         }
3244     } else if (cmd == OMX_CommandPortDisable) {
3245         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3246                 "with param1: %u", (unsigned int)param1);
3247         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3248             codec_config_flag = false;
3249             m_inp_bEnabled = OMX_FALSE;
3250             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3251                     && release_input_done()) {
3252                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3253                         OMX_COMPONENT_GENERATE_EVENT);
3254             } else {
3255                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3256                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3257                     if (!sem_posted) {
3258                         sem_posted = 1;
3259                         sem_post (&m_cmd_lock);
3260                     }
3261                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3262                 }
3263 
3264                 // Skip the event notification
3265                 bFlag = 0;
3266             }
3267         }
3268         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3269             m_out_bEnabled = OMX_FALSE;
3270             DEBUG_PRINT_LOW("Disable output Port command recieved");
3271             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3272                     && release_output_done()) {
3273                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3274                         OMX_COMPONENT_GENERATE_EVENT);
3275             } else {
3276                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3277                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3278                     if (!sem_posted) {
3279                         sem_posted = 1;
3280                         sem_post (&m_cmd_lock);
3281                     }
3282                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3283                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3284                 }
3285                 // Skip the event notification
3286                 bFlag = 0;
3287 
3288             }
3289         }
3290     } else {
3291         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3292         eRet = OMX_ErrorNotImplemented;
3293     }
3294     if (eRet == OMX_ErrorNone && bFlag) {
3295         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3296     }
3297     if (!sem_posted) {
3298         sem_post(&m_cmd_lock);
3299     }
3300 
3301     return eRet;
3302 }
3303 
3304 /* ======================================================================
3305    FUNCTION
3306    omx_vdec::ExecuteOmxFlush
3307 
3308    DESCRIPTION
3309    Executes the OMX flush.
3310 
3311    PARAMETERS
3312    flushtype - input flush(1)/output flush(0)/ both.
3313 
3314    RETURN VALUE
3315    true/false
3316 
3317    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3318 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3319 {
3320     bool bRet = false;
3321     struct v4l2_plane plane;
3322     struct v4l2_buffer v4l2_buf;
3323     struct v4l2_decoder_cmd dec;
3324     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3325     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3326     dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3327 
3328     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3329 
3330     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3331         output_flush_progress = true;
3332         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3333     } else {
3334         /* XXX: The driver/hardware does not support flushing of individual ports
3335          * in all states. So we pretty much need to flush both ports internally,
3336          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3337          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3338          * we automatically omit sending the FLUSH done for the "opposite" port. */
3339         input_flush_progress = true;
3340         output_flush_progress = true;
3341         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3342         request_perf_level(VIDC_TURBO);
3343     }
3344 
3345     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3346         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3347         bRet = false;
3348     }
3349 
3350     return bRet;
3351 }
3352 /*=========================================================================
3353 FUNCTION : execute_output_flush
3354 
3355 DESCRIPTION
3356 Executes the OMX flush at OUTPUT PORT.
3357 
3358 PARAMETERS
3359 None.
3360 
3361 RETURN VALUE
3362 true/false
3363 ==========================================================================*/
execute_output_flush()3364 bool omx_vdec::execute_output_flush()
3365 {
3366     unsigned long p1 = 0; // Parameter - 1
3367     unsigned long p2 = 0; // Parameter - 2
3368     unsigned long ident = 0;
3369     bool bRet = true;
3370 
3371     /*Generate FBD for all Buffers in the FTBq*/
3372     pthread_mutex_lock(&m_lock);
3373     DEBUG_PRINT_LOW("Initiate Output Flush");
3374 
3375     //reset last render TS
3376     if(m_last_rendered_TS > 0) {
3377         m_last_rendered_TS = 0;
3378     }
3379 
3380     while (m_ftb_q.m_size) {
3381         DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3382                 m_ftb_q.m_size,pending_output_buffers);
3383         m_ftb_q.pop_entry(&p1,&p2,&ident);
3384         DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3385         if (ident == m_fill_output_msg ) {
3386             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3387         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3388             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3389         }
3390     }
3391     pthread_mutex_unlock(&m_lock);
3392     output_flush_progress = false;
3393 
3394     if (arbitrary_bytes) {
3395         prev_ts = LLONG_MAX;
3396         rst_prev_ts = true;
3397     }
3398     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3399     return bRet;
3400 }
3401 /*=========================================================================
3402 FUNCTION : execute_input_flush
3403 
3404 DESCRIPTION
3405 Executes the OMX flush at INPUT PORT.
3406 
3407 PARAMETERS
3408 None.
3409 
3410 RETURN VALUE
3411 true/false
3412 ==========================================================================*/
execute_input_flush()3413 bool omx_vdec::execute_input_flush()
3414 {
3415     unsigned       i =0;
3416     unsigned long p1 = 0; // Parameter - 1
3417     unsigned long p2 = 0; // Parameter - 2
3418     unsigned long ident = 0;
3419     bool bRet = true;
3420 
3421     /*Generate EBD for all Buffers in the ETBq*/
3422     DEBUG_PRINT_LOW("Initiate Input Flush");
3423 
3424     pthread_mutex_lock(&m_lock);
3425     DEBUG_PRINT_LOW("Check if the Queue is empty");
3426     while (m_etb_q.m_size) {
3427         m_etb_q.pop_entry(&p1,&p2,&ident);
3428 
3429         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3430             DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3431             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3432         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3433             pending_input_buffers++;
3434             VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3435             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3436                     (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3437             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3438         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3439             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3440                     (OMX_BUFFERHEADERTYPE *)p1);
3441             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3442         }
3443     }
3444     time_stamp_dts.flush_timestamp();
3445     /*Check if Heap Buffers are to be flushed*/
3446     if (arbitrary_bytes && !(codec_config_flag)) {
3447         DEBUG_PRINT_LOW("Reset all the variables before flusing");
3448         h264_scratch.nFilledLen = 0;
3449         nal_count = 0;
3450         look_ahead_nal = false;
3451         frame_count = 0;
3452         h264_last_au_ts = LLONG_MAX;
3453         h264_last_au_flags = 0;
3454         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3455         m_demux_entries = 0;
3456         DEBUG_PRINT_LOW("Initialize parser");
3457         if (m_frame_parser.mutils) {
3458             m_frame_parser.mutils->initialize_frame_checking_environment();
3459         }
3460 
3461         while (m_input_pending_q.m_size) {
3462             m_input_pending_q.pop_entry(&p1,&p2,&ident);
3463             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3464         }
3465 
3466         if (psource_frame) {
3467             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3468             psource_frame = NULL;
3469         }
3470 
3471         if (pdest_frame) {
3472             pdest_frame->nFilledLen = 0;
3473             m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3474                     (unsigned int)NULL);
3475             pdest_frame = NULL;
3476         }
3477         m_frame_parser.flush();
3478     } else if (codec_config_flag) {
3479         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3480                 "is not sent to the driver yet");
3481     }
3482     pthread_mutex_unlock(&m_lock);
3483     input_flush_progress = false;
3484     if (!arbitrary_bytes) {
3485         prev_ts = LLONG_MAX;
3486         rst_prev_ts = true;
3487     }
3488 #ifdef _ANDROID_
3489     if (m_debug_timestamp) {
3490         m_timestamp_list.reset_ts_list();
3491     }
3492 #endif
3493     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3494     return bRet;
3495 }
3496 
3497 /*=========================================================================
3498 FUNCTION : notify_flush_done
3499 
3500 DESCRIPTION
3501 Notifies flush done to the OMX Client.
3502 
3503 PARAMETERS
3504 ctxt -- Context information related to the self..
3505 
3506 RETURN VALUE
3507 NONE
3508 ==========================================================================*/
notify_flush_done(void * ctxt)3509 void omx_vdec::notify_flush_done(void *ctxt) {
3510 
3511     omx_vdec *pThis = (omx_vdec *) ctxt;
3512 
3513     if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3514         if (BITMASK_PRESENT(&pThis->m_flags,
3515                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3516             DEBUG_PRINT_LOW("Notify Output Flush done");
3517             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3518             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3519                 OMX_EventCmdComplete,OMX_CommandFlush,
3520                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3521         }
3522 
3523         if (BITMASK_PRESENT(&pThis->m_flags,
3524                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3525             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3526             DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3527             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3528                     OMX_EventCmdComplete,OMX_CommandFlush,
3529                     OMX_CORE_INPUT_PORT_INDEX,NULL );
3530         }
3531     }
3532 }
3533 
3534 /* ======================================================================
3535    FUNCTION
3536    omx_vdec::SendCommandEvent
3537 
3538    DESCRIPTION
3539    Send the event to decoder pipe.  This is needed to generate the callbacks
3540    in decoder thread context.
3541 
3542    PARAMETERS
3543    None.
3544 
3545    RETURN VALUE
3546    true/false
3547 
3548    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3549 bool omx_vdec::post_event(unsigned long p1,
3550         unsigned long p2,
3551         unsigned long id)
3552 {
3553     bool bRet = false;
3554 
3555     /* Just drop messages typically generated by hardware (w/o client request),
3556      * if we've reported an error to client. */
3557     if (m_error_propogated) {
3558         switch (id) {
3559             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3560             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3561                 DEBUG_PRINT_ERROR("Dropping message %lx "
3562                         "since client expected to be in error state", id);
3563                 return false;
3564             default:
3565                 /* whatever */
3566                 break;
3567         }
3568     }
3569 
3570     pthread_mutex_lock(&m_lock);
3571 
3572     if (id == m_fill_output_msg ||
3573             id == OMX_COMPONENT_GENERATE_FBD ||
3574             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3575             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3576         m_ftb_q.insert_entry(p1,p2,id);
3577     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3578             id == OMX_COMPONENT_GENERATE_EBD ||
3579             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3580             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3581         m_etb_q.insert_entry(p1,p2,id);
3582     } else {
3583         m_cmd_q.insert_entry(p1,p2,id);
3584     }
3585 
3586     bRet = true;
3587     DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3588     post_message(this, id);
3589 
3590     pthread_mutex_unlock(&m_lock);
3591 
3592     return bRet;
3593 }
3594 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3595 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3596 {
3597     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3598     if (!profileLevelType)
3599         return OMX_ErrorBadParameter;
3600 
3601     if (profileLevelType->nPortIndex == 0) {
3602         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3603             profileLevelType->eLevel = OMX_VIDEO_AVCLevel52;
3604             if (profileLevelType->nProfileIndex == 0) {
3605                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3606             } else if (profileLevelType->nProfileIndex == 1) {
3607                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3608             } else if (profileLevelType->nProfileIndex == 2) {
3609                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3610             } else if (profileLevelType->nProfileIndex == 3) {
3611                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
3612             } else if (profileLevelType->nProfileIndex == 4) {
3613                 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
3614             } else if (profileLevelType->nProfileIndex == 5) {
3615                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedHigh;
3616             } else if (profileLevelType->nProfileIndex == 6) {
3617                 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
3618             } else {
3619                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3620                         (unsigned int)profileLevelType->nProfileIndex);
3621                 eRet = OMX_ErrorNoMore;
3622             }
3623         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3624             if (profileLevelType->nProfileIndex == 0) {
3625                 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3626                 profileLevelType->eLevel   = QOMX_VIDEO_MVCLevel51;
3627             } else {
3628                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3629                                 (unsigned int)profileLevelType->nProfileIndex);
3630                 eRet = OMX_ErrorNoMore;
3631             }
3632         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3633             if (profileLevelType->nProfileIndex == 0) {
3634                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3635                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3636             } else if (profileLevelType->nProfileIndex == 1) {
3637                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3638                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3639             } else if (profileLevelType->nProfileIndex == 2) {
3640                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
3641                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3642             } else {
3643                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3644                         (unsigned int)profileLevelType->nProfileIndex);
3645                 eRet = OMX_ErrorNoMore;
3646             }
3647         } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3648             if (profileLevelType->nProfileIndex == 0) {
3649                 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3650                 profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
3651             } else {
3652                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3653                                 (unsigned int)profileLevelType->nProfileIndex);
3654                 eRet = OMX_ErrorNoMore;
3655             }
3656         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3657             if (profileLevelType->nProfileIndex == 0) {
3658                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3659                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3660             } else if (profileLevelType->nProfileIndex == 1) {
3661                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3662                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3663             } else {
3664                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3665                                 (unsigned int)profileLevelType->nProfileIndex);
3666                 eRet = OMX_ErrorNoMore;
3667             }
3668         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3669                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3670             eRet = OMX_ErrorNoMore;
3671         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3672             if (profileLevelType->nProfileIndex == 0) {
3673                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3674                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3675             } else if (profileLevelType->nProfileIndex == 1) {
3676                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3677                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3678             } else {
3679                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3680                                 (unsigned int)profileLevelType->nProfileIndex);
3681                 eRet = OMX_ErrorNoMore;
3682             }
3683         } else {
3684             DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3685             eRet = OMX_ErrorNoMore;
3686         }
3687     } else {
3688         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3689                           (unsigned int)profileLevelType->nPortIndex);
3690         eRet = OMX_ErrorBadPortIndex;
3691     }
3692     return eRet;
3693 }
3694 
3695 /* ======================================================================
3696    FUNCTION
3697    omx_vdec::GetParameter
3698 
3699    DESCRIPTION
3700    OMX Get Parameter method implementation
3701 
3702    PARAMETERS
3703    <TBD>.
3704 
3705    RETURN VALUE
3706    Error None if successful.
3707 
3708    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3709 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3710         OMX_IN OMX_INDEXTYPE paramIndex,
3711         OMX_INOUT OMX_PTR     paramData)
3712 {
3713     (void) hComp;
3714     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3715 
3716     DEBUG_PRINT_LOW("get_parameter:");
3717     if (m_state == OMX_StateInvalid) {
3718         DEBUG_PRINT_ERROR("Get Param in Invalid State");
3719         return OMX_ErrorInvalidState;
3720     }
3721     if (paramData == NULL) {
3722         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3723         return OMX_ErrorBadParameter;
3724     }
3725     switch ((unsigned long)paramIndex) {
3726         case OMX_IndexParamPortDefinition: {
3727                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3728                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3729                                    (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3730                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3731                                decide_dpb_buffer_mode(is_down_scalar_enabled);
3732                                eRet = update_portdef(portDefn);
3733                                if (eRet == OMX_ErrorNone)
3734                                    m_port_def = *portDefn;
3735                                break;
3736                            }
3737         case OMX_IndexParamVideoInit: {
3738                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3739                               OMX_PORT_PARAM_TYPE *portParamType =
3740                                   (OMX_PORT_PARAM_TYPE *) paramData;
3741                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3742 
3743                               portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3744                               portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3745                               portParamType->nPorts           = 2;
3746                               portParamType->nStartPortNumber = 0;
3747                               break;
3748                           }
3749         case OMX_IndexParamVideoPortFormat: {
3750                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3751                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3752                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3753                                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3754 
3755                                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3756                                 portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3757 
3758                                 if (0 == portFmt->nPortIndex) {
3759                                     if (0 == portFmt->nIndex) {
3760                                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3761                                         portFmt->eCompressionFormat = eCompressionFormat;
3762                                     } else {
3763                                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3764                                                 " NoMore compression formats");
3765                                         eRet =  OMX_ErrorNoMore;
3766                                     }
3767                                 } else if (1 == portFmt->nPortIndex) {
3768                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3769 
3770                                     // Distinguish non-surface mode from normal playback use-case based on
3771                                     // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3772                                     // For non-android, use the default list
3773                                     // Also use default format-list if FLEXIBLE YUV is supported,
3774                                     // as the client negotiates the standard color-format if it needs to
3775                                     bool useNonSurfaceMode = false;
3776 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3777                                     useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3778 #endif
3779                                     if (is_thulium_v1) {
3780                                         portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3781                                     } else {
3782                                         portFmt->eColorFormat = useNonSurfaceMode ?
3783                                             getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3784                                             getPreferredColorFormatDefaultMode(portFmt->nIndex);
3785                                     }
3786 
3787                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3788                                         eRet = OMX_ErrorNoMore;
3789                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3790                                                 " NoMore Color formats");
3791                                     }
3792                                     DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3793                                 } else {
3794                                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3795                                             (int)portFmt->nPortIndex);
3796                                     eRet = OMX_ErrorBadPortIndex;
3797                                 }
3798                                 break;
3799                             }
3800                             /*Component should support this port definition*/
3801         case OMX_IndexParamAudioInit: {
3802                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3803                               OMX_PORT_PARAM_TYPE *audioPortParamType =
3804                                   (OMX_PORT_PARAM_TYPE *) paramData;
3805                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3806                               audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3807                               audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3808                               audioPortParamType->nPorts           = 0;
3809                               audioPortParamType->nStartPortNumber = 0;
3810                               break;
3811                           }
3812                           /*Component should support this port definition*/
3813         case OMX_IndexParamImageInit: {
3814                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3815                               OMX_PORT_PARAM_TYPE *imagePortParamType =
3816                                   (OMX_PORT_PARAM_TYPE *) paramData;
3817                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3818                               imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3819                               imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3820                               imagePortParamType->nPorts           = 0;
3821                               imagePortParamType->nStartPortNumber = 0;
3822                               break;
3823 
3824                           }
3825                           /*Component should support this port definition*/
3826         case OMX_IndexParamOtherInit: {
3827                               DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3828                                       paramIndex);
3829                               eRet =OMX_ErrorUnsupportedIndex;
3830                               break;
3831                           }
3832         case OMX_IndexParamStandardComponentRole: {
3833                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3834                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
3835                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3836                                   comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3837                                   comp_role->nSize = sizeof(*comp_role);
3838 
3839                                   DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3840                                           paramIndex);
3841                                   strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3842                                           OMX_MAX_STRINGNAME_SIZE);
3843                                   break;
3844                               }
3845                               /* Added for parameter test */
3846         case OMX_IndexParamPriorityMgmt: {
3847                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3848                              OMX_PRIORITYMGMTTYPE *priorityMgmType =
3849                                  (OMX_PRIORITYMGMTTYPE *) paramData;
3850                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3851                              priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3852                              priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3853 
3854                              break;
3855                          }
3856                          /* Added for parameter test */
3857         case OMX_IndexParamCompBufferSupplier: {
3858                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3859                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3860                                        (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3861                                    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3862 
3863                                    bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3864                                    bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3865                                    if (0 == bufferSupplierType->nPortIndex)
3866                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3867                                    else if (1 == bufferSupplierType->nPortIndex)
3868                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3869                                    else
3870                                        eRet = OMX_ErrorBadPortIndex;
3871 
3872 
3873                                    break;
3874                                }
3875         case OMX_IndexParamVideoAvc: {
3876                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3877                                      paramIndex);
3878                              break;
3879                          }
3880         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3881                              DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3882                                      paramIndex);
3883                              break;
3884                          }
3885         case OMX_IndexParamVideoH263: {
3886                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3887                                       paramIndex);
3888                               break;
3889                           }
3890         case OMX_IndexParamVideoMpeg4: {
3891                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3892                                        paramIndex);
3893                                break;
3894                            }
3895         case OMX_IndexParamVideoMpeg2: {
3896                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3897                                        paramIndex);
3898                                break;
3899                            }
3900         case OMX_IndexParamVideoProfileLevelQuerySupported: {
3901                                         VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3902                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3903                                         OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3904                                             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3905                                         eRet = get_supported_profile_level(profileLevelType);
3906                                         break;
3907                                     }
3908 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3909         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3910                                         VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3911                                         DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3912                                         GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3913                                         if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3914 
3915                                             if (secure_mode && !secure_scaling_to_non_secure_opb) {
3916                                                 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3917                                                         GRALLOC_USAGE_PRIVATE_UNCACHED);
3918                                             } else {
3919                                                 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3920                                             }
3921                                         } else {
3922                                             DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3923                                             eRet = OMX_ErrorBadParameter;
3924                                         }
3925                                     }
3926                                     break;
3927 #endif
3928 
3929 #ifdef FLEXYUV_SUPPORTED
3930         case OMX_QcomIndexFlexibleYUVDescription: {
3931                 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3932                 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3933                 eRet = describeColorFormat(paramData);
3934                 break;
3935             }
3936 #endif
3937         case OMX_IndexParamVideoProfileLevelCurrent: {
3938              VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3939              OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3940              struct v4l2_control profile_control, level_control;
3941 
3942              switch (drv_ctx.decoder_format) {
3943                  case VDEC_CODECTYPE_H264:
3944                      profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3945                      level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3946                      break;
3947                  default:
3948                      DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3949                      eRet = OMX_ErrorNotImplemented;
3950                      break;
3951              }
3952 
3953              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3954                 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3955                     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3956                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3957                         pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3958                         break;
3959                     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3960                         pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3961                         break;
3962                     case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3963                         pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3964                         break;
3965                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3966                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3967                         break;
3968                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3969                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3970                         break;
3971                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3972                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3973                         break;
3974                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3975                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3976                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3977                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3978                     case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3979                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3980                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3981                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3982                     case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3983                     case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3984                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3985                         eRet = OMX_ErrorUnsupportedIndex;
3986                         break;
3987                 }
3988              } else {
3989                  eRet = OMX_ErrorUnsupportedIndex;
3990              }
3991 
3992 
3993              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3994                 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3995                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3996                         pParam->eLevel = OMX_VIDEO_AVCLevel1;
3997                         break;
3998                     case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3999                         pParam->eLevel = OMX_VIDEO_AVCLevel1b;
4000                         break;
4001                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
4002                         pParam->eLevel = OMX_VIDEO_AVCLevel11;
4003                         break;
4004                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
4005                         pParam->eLevel = OMX_VIDEO_AVCLevel12;
4006                         break;
4007                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
4008                         pParam->eLevel = OMX_VIDEO_AVCLevel13;
4009                         break;
4010                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
4011                         pParam->eLevel = OMX_VIDEO_AVCLevel2;
4012                         break;
4013                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
4014                         pParam->eLevel = OMX_VIDEO_AVCLevel21;
4015                         break;
4016                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
4017                         pParam->eLevel = OMX_VIDEO_AVCLevel22;
4018                         break;
4019                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4020                         pParam->eLevel = OMX_VIDEO_AVCLevel3;
4021                         break;
4022                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4023                         pParam->eLevel = OMX_VIDEO_AVCLevel31;
4024                         break;
4025                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4026                         pParam->eLevel = OMX_VIDEO_AVCLevel32;
4027                         break;
4028                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4029                         pParam->eLevel = OMX_VIDEO_AVCLevel4;
4030                         break;
4031                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4032                         pParam->eLevel = OMX_VIDEO_AVCLevel41;
4033                         break;
4034                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4035                         pParam->eLevel = OMX_VIDEO_AVCLevel42;
4036                         break;
4037                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4038                         pParam->eLevel = OMX_VIDEO_AVCLevel5;
4039                         break;
4040                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4041                         pParam->eLevel = OMX_VIDEO_AVCLevel51;
4042                         break;
4043                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4044                         pParam->eLevel = OMX_VIDEO_AVCLevel52;
4045                         break;
4046                 }
4047              } else {
4048                  eRet = OMX_ErrorUnsupportedIndex;
4049              }
4050 
4051              break;
4052 
4053          }
4054         case OMX_QTIIndexParamVideoClientExtradata:
4055         {
4056             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4057             DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
4058             QOMX_EXTRADATA_ENABLE *pParam =
4059                 (QOMX_EXTRADATA_ENABLE *)paramData;
4060             if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4061                 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE;
4062                 eRet = OMX_ErrorNone;
4063             } else {
4064                 eRet = OMX_ErrorUnsupportedIndex;
4065             }
4066             break;
4067         }
4068         case OMX_QTIIndexParamDitherControl:
4069         {
4070             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4071             DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
4072             QOMX_VIDEO_DITHER_CONTROL *pParam =
4073                 (QOMX_VIDEO_DITHER_CONTROL *) paramData;
4074             pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
4075             eRet = OMX_ErrorNone;
4076             break;
4077         }
4078         default: {
4079                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
4080                  eRet =OMX_ErrorUnsupportedIndex;
4081              }
4082 
4083     }
4084 
4085     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
4086             drv_ctx.video_resolution.frame_width,
4087             drv_ctx.video_resolution.frame_height,
4088             drv_ctx.video_resolution.stride,
4089             drv_ctx.video_resolution.scan_lines);
4090 
4091     return eRet;
4092 }
4093 
4094 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)4095 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
4096 {
4097     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
4098     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4099     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
4100 
4101     if ((params == NULL) ||
4102             (params->nativeBuffer == NULL) ||
4103             (params->nativeBuffer->handle == NULL) ||
4104             !m_enable_android_native_buffers)
4105         return OMX_ErrorBadParameter;
4106     m_use_android_native_buffers = OMX_TRUE;
4107     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4108     private_handle_t *handle = (private_handle_t *)nBuf->handle;
4109     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
4110         OMX_U8 *buffer = NULL;
4111         if (!secure_mode) {
4112             buffer = (OMX_U8*)mmap(0, handle->size,
4113                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4114             if (buffer == MAP_FAILED) {
4115                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4116                 return OMX_ErrorInsufficientResources;
4117             }
4118         }
4119         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
4120     } else {
4121         eRet = OMX_ErrorBadParameter;
4122     }
4123     return eRet;
4124 }
4125 #endif
4126 
enable_smoothstreaming()4127 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
4128     struct v4l2_control control;
4129     struct v4l2_format fmt;
4130     control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
4131     control.value = 1;
4132     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4133     if (rc < 0) {
4134         DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
4135         return OMX_ErrorHardware;
4136     }
4137     m_smoothstreaming_mode = true;
4138     return OMX_ErrorNone;
4139 }
4140 
4141 /* ======================================================================
4142    FUNCTION
4143    omx_vdec::Setparameter
4144 
4145    DESCRIPTION
4146    OMX Set Parameter method implementation.
4147 
4148    PARAMETERS
4149    <TBD>.
4150 
4151    RETURN VALUE
4152    OMX Error None if successful.
4153 
4154    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)4155 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
4156         OMX_IN OMX_INDEXTYPE paramIndex,
4157         OMX_IN OMX_PTR        paramData)
4158 {
4159     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4160     int ret=0;
4161     struct v4l2_format fmt;
4162 #ifdef _ANDROID_
4163     char property_value[PROPERTY_VALUE_MAX] = {0};
4164 #endif
4165     if (m_state == OMX_StateInvalid) {
4166         DEBUG_PRINT_ERROR("Set Param in Invalid State");
4167         return OMX_ErrorInvalidState;
4168     }
4169     if (paramData == NULL) {
4170         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4171         return OMX_ErrorBadParameter;
4172     }
4173     if ((m_state != OMX_StateLoaded) &&
4174             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4175             (m_out_bEnabled == OMX_TRUE) &&
4176             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4177             (m_inp_bEnabled == OMX_TRUE)) {
4178         DEBUG_PRINT_ERROR("Set Param in Invalid State");
4179         return OMX_ErrorIncorrectStateOperation;
4180     }
4181     switch ((unsigned long)paramIndex) {
4182         case OMX_IndexParamPortDefinition: {
4183                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4184                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4185                                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4186                                //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4187                                //been called.
4188                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
4189                                        (int)portDefn->format.video.nFrameHeight,
4190                                        (int)portDefn->format.video.nFrameWidth);
4191 
4192                                if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4193                                    DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4194                                                           portDefn->nBufferCountActual);
4195                                    eRet = OMX_ErrorBadParameter;
4196                                    break;
4197                                }
4198                                if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
4199                                    if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS ||
4200                                         portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
4201                                         DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
4202                                                           portDefn->nBufferCountActual, portDefn->nBufferSize);
4203                                         eRet = OMX_ErrorBadParameter;
4204                                         break;
4205                                    }
4206                                     m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
4207                                             portDefn->nBufferCountActual);
4208                                     break;
4209                                }
4210 
4211                                if (OMX_DirOutput == portDefn->eDir) {
4212                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4213                                    bool port_format_changed = false;
4214                                    m_display_id = portDefn->format.video.pNativeWindow;
4215                                    unsigned int buffer_size;
4216                                    /* update output port resolution with client supplied dimensions
4217                                       in case scaling is enabled, else it follows input resolution set
4218                                    */
4219                                    decide_dpb_buffer_mode(is_down_scalar_enabled);
4220                                    if (is_down_scalar_enabled) {
4221                                        DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4222                                                (unsigned int)portDefn->format.video.nFrameWidth,
4223                                                (unsigned int)portDefn->format.video.nFrameHeight);
4224                                        if (portDefn->format.video.nFrameHeight != 0x0 &&
4225                                                portDefn->format.video.nFrameWidth != 0x0) {
4226                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4227                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4228                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
4229                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4230                                            if (ret) {
4231                                                DEBUG_PRINT_ERROR("Get Resolution failed");
4232                                                eRet = OMX_ErrorHardware;
4233                                                break;
4234                                            }
4235                                            if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4236                                                (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4237                                                    port_format_changed = true;
4238                                            }
4239 
4240                                            /* set crop info */
4241                                            rectangle.nLeft = 0;
4242                                            rectangle.nTop = 0;
4243                                            rectangle.nWidth = portDefn->format.video.nFrameWidth;
4244                                            rectangle.nHeight = portDefn->format.video.nFrameHeight;
4245 
4246                                            m_extradata_info.output_crop_rect.nLeft = 0;
4247                                            m_extradata_info.output_crop_rect.nTop = 0;
4248                                            m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4249                                            m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4250 
4251                                            eRet = is_video_session_supported();
4252                                            if (eRet)
4253                                                break;
4254                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4255                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4256                                            fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4257                                            fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4258                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
4259                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4260                                                fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4261                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4262                                            if (ret) {
4263                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4264                                                eRet = OMX_ErrorUnsupportedSetting;
4265                                            } else
4266                                                eRet = get_buffer_req(&drv_ctx.op_buf);
4267                                        }
4268 
4269                                        if (eRet) {
4270                                            break;
4271                                        }
4272 
4273                                        if (secure_mode) {
4274                                            struct v4l2_control control;
4275                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
4276                                            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4277                                                DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
4278                                                eRet = OMX_ErrorHardware;
4279                                            } else {
4280                                                /* This is a workaround for a bug in fw which uses stride
4281                                                 * and slice instead of width and height to check against
4282                                                 * the threshold.
4283                                                 */
4284                                                OMX_U32 stride, slice;
4285                                                if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
4286                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
4287                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
4288                                                } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
4289                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
4290                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
4291                                                } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
4292                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameWidth);
4293                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameHeight);
4294                                                } else {
4295                                                    stride = portDefn->format.video.nFrameWidth;
4296                                                    slice = portDefn->format.video.nFrameHeight;
4297                                                }
4298 
4299                                                DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
4300                                                DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
4301 
4302                                                if (stride * slice <= (OMX_U32)control.value) {
4303                                                    secure_scaling_to_non_secure_opb = true;
4304                                                    DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
4305                                                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
4306                                                    control.value = 1;
4307                                                    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4308                                                        DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4309                                                        eRet = OMX_ErrorUnsupportedSetting;
4310                                                    }
4311                                                }
4312                                            }
4313                                        }
4314                                    }
4315 
4316                                    if (eRet) {
4317                                        break;
4318                                    }
4319 
4320                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4321                                        DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4322                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4323                                        eRet = OMX_ErrorBadParameter;
4324                                    } else if (!client_buffers.get_buffer_req(buffer_size)) {
4325                                        DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4326                                        eRet = OMX_ErrorBadParameter;
4327                                    } else if (!port_format_changed) {
4328 
4329                                        // Buffer count can change only when port is unallocated
4330                                        if (m_out_mem_ptr &&
4331                                                 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4332                                                 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4333 
4334                                            DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4335                                            eRet = OMX_ErrorInvalidState;
4336                                            break;
4337                                        }
4338 
4339                                        // route updating of buffer requirements via c2d proxy.
4340                                        // Based on whether c2d is enabled, requirements will be handed
4341                                        // to the vidc driver appropriately
4342                                        eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4343                                                 portDefn->nBufferCountActual);
4344                                        if (eRet == OMX_ErrorNone) {
4345                                            m_port_def = *portDefn;
4346                                        } else {
4347                                            DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4348                                                    drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4349                                                    (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4350                                            eRet = OMX_ErrorBadParameter;
4351                                        }
4352                                    }
4353                                } else if (OMX_DirInput == portDefn->eDir) {
4354                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4355                                    bool port_format_changed = false;
4356                                    if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4357                                            (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4358                                        // Frame rate only should be set if this is a "known value" or to
4359                                        // activate ts prediction logic (arbitrary mode only) sending input
4360                                        // timestamps with max value (LLONG_MAX).
4361                                        m_fps_received = portDefn->format.video.xFramerate;
4362                                        DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4363                                                (unsigned int)portDefn->format.video.xFramerate >> 16);
4364                                        Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4365                                                drv_ctx.frame_rate.fps_denominator);
4366                                        if (!drv_ctx.frame_rate.fps_numerator) {
4367                                            DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4368                                            drv_ctx.frame_rate.fps_numerator = 30;
4369                                        }
4370                                        if (drv_ctx.frame_rate.fps_denominator)
4371                                            drv_ctx.frame_rate.fps_numerator = (int)
4372                                                drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4373                                        drv_ctx.frame_rate.fps_denominator = 1;
4374                                        frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4375                                            drv_ctx.frame_rate.fps_numerator;
4376                                        DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4377                                                (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4378                                                (float)drv_ctx.frame_rate.fps_denominator);
4379 
4380                                        struct v4l2_outputparm oparm;
4381                                        /*XXX: we're providing timing info as seconds per frame rather than frames
4382                                         * per second.*/
4383                                        oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4384                                        oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4385 
4386                                        struct v4l2_streamparm sparm;
4387                                        sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4388                                        sparm.parm.output = oparm;
4389                                        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4390                                            DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4391                                            eRet = OMX_ErrorHardware;
4392                                            break;
4393                                        }
4394                                        m_perf_control.request_cores(frm_int);
4395                                    }
4396 
4397                                    if (drv_ctx.video_resolution.frame_height !=
4398                                            portDefn->format.video.nFrameHeight ||
4399                                            drv_ctx.video_resolution.frame_width  !=
4400                                            portDefn->format.video.nFrameWidth) {
4401                                        DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4402                                                (unsigned int)portDefn->format.video.nFrameWidth,
4403                                                (unsigned int)portDefn->format.video.nFrameHeight);
4404                                        port_format_changed = true;
4405                                        OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4406                                        OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4407                                        if (frameHeight != 0x0 && frameWidth != 0x0) {
4408                                            if (m_smoothstreaming_mode &&
4409                                                    ((frameWidth * frameHeight) <
4410                                                    (m_smoothstreaming_width * m_smoothstreaming_height))) {
4411                                                frameWidth = m_smoothstreaming_width;
4412                                                frameHeight = m_smoothstreaming_height;
4413                                                DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4414                                                        "for adaptive-playback/smooth-streaming",
4415                                                        (unsigned int)frameWidth, (unsigned int)frameHeight);
4416                                            }
4417 
4418                                            m_extradata_info.output_crop_rect.nLeft = 0;
4419                                            m_extradata_info.output_crop_rect.nTop = 0;
4420                                            m_extradata_info.output_crop_rect.nWidth = frameWidth;
4421                                            m_extradata_info.output_crop_rect.nHeight = frameHeight;
4422 
4423                                            update_resolution(frameWidth, frameHeight,
4424                                                    frameWidth, frameHeight);
4425                                            eRet = is_video_session_supported();
4426                                            if (eRet)
4427                                                break;
4428                                            if (is_down_scalar_enabled) {
4429                                                memset(&fmt, 0x0, sizeof(struct v4l2_format));
4430                                                fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4431                                                fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4432                                                fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4433                                                fmt.fmt.pix_mp.pixelformat = output_capability;
4434                                                DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4435                                                    fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4436                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4437                                            } else {
4438                                                memset(&fmt, 0x0, sizeof(struct v4l2_format));
4439                                                fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4440                                                fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4441                                                fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4442                                                fmt.fmt.pix_mp.pixelformat = output_capability;
4443                                                DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4444                                                    fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4445                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4446                                                fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4447                                                fmt.fmt.pix_mp.pixelformat = capture_capability;
4448                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4449                                            }
4450                                            if (ret) {
4451                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4452                                                eRet = OMX_ErrorUnsupportedSetting;
4453                                            } else {
4454                                                if (!is_down_scalar_enabled)
4455                                                    eRet = get_buffer_req(&drv_ctx.op_buf);
4456                                            }
4457                                        }
4458                                    }
4459                                    if (m_custom_buffersize.input_buffersize
4460                                         && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4461                                        DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4462                                                m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4463                                        eRet = OMX_ErrorBadParameter;
4464                                        break;
4465                                    }
4466                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4467                                        DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4468                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4469                                        eRet = OMX_ErrorBadParameter;
4470                                        break;
4471                                    }
4472                                    // Buffer count can change only when port is unallocated
4473                                    if (m_inp_mem_ptr &&
4474                                             (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4475                                             portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4476                                        DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4477                                        eRet = OMX_ErrorInvalidState;
4478                                        break;
4479                                    }
4480 
4481                                    if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4482                                            || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4483                                        port_format_changed = true;
4484                                        vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4485                                        drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4486                                        drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4487                                            (~(buffer_prop->alignment - 1));
4488                                        eRet = set_buffer_req(buffer_prop);
4489                                    }
4490                                    if (false == port_format_changed) {
4491                                        DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4492                                                drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4493                                                (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4494                                        eRet = OMX_ErrorBadParameter;
4495                                    }
4496                                } else if (portDefn->eDir ==  OMX_DirMax) {
4497                                    DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4498                                            (int)portDefn->nPortIndex);
4499                                    eRet = OMX_ErrorBadPortIndex;
4500                                }
4501                            }
4502                            break;
4503         case OMX_IndexParamVideoPortFormat: {
4504                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4505                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4506                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4507                                 int ret=0;
4508                                 struct v4l2_format fmt;
4509                                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4510                                         portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4511 
4512                                 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4513                                 if (1 == portFmt->nPortIndex) {
4514                                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4515                                     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4516                                     if (ret < 0) {
4517                                         DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4518                                         return OMX_ErrorBadParameter;
4519                                     }
4520                                     enum vdec_output_fromat op_format;
4521                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4522                                             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4523                                             portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4524                                             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4525                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4526                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4527                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4528                                     } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4529                                             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4530                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4531                                     } else
4532                                         eRet = OMX_ErrorBadParameter;
4533 
4534                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4535                                             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4536                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4537                                     } else {
4538                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4539                                     }
4540 
4541                                     if (eRet == OMX_ErrorNone) {
4542                                         drv_ctx.output_format = op_format;
4543                                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4544                                         if (ret) {
4545                                             DEBUG_PRINT_ERROR("Set output format failed");
4546                                             eRet = OMX_ErrorUnsupportedSetting;
4547                                             /*TODO: How to handle this case */
4548                                         } else {
4549                                             eRet = get_buffer_req(&drv_ctx.op_buf);
4550                                         }
4551                                     }
4552                                     if (eRet == OMX_ErrorNone) {
4553                                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4554                                             DEBUG_PRINT_ERROR("Set color format failed");
4555                                             eRet = OMX_ErrorBadParameter;
4556                                         }
4557                                     }
4558                                 }
4559                             }
4560                             break;
4561 
4562         case OMX_QcomIndexPortDefn: {
4563                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4564                             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4565                                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4566                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4567                                     (unsigned int)portFmt->nFramePackingFormat);
4568 
4569                             /* Input port */
4570                             if (portFmt->nPortIndex == 0) {
4571                                 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4572                                 //   - headers are allocated and
4573                                 //   - headers-indices are derived
4574                                 // Avoid changing arbitrary_bytes when the port is already allocated
4575                                 if (m_inp_mem_ptr) {
4576                                     DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4577                                     return OMX_ErrorUnsupportedSetting;
4578                                 }
4579                                 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4580                                     if (secure_mode || m_input_pass_buffer_fd) {
4581                                         arbitrary_bytes = false;
4582                                         DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4583                                         eRet = OMX_ErrorUnsupportedSetting;
4584                                     } else {
4585                                         arbitrary_bytes = true;
4586                                     }
4587                                 } else if (portFmt->nFramePackingFormat ==
4588                                         OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4589                                     arbitrary_bytes = false;
4590 #ifdef _ANDROID_
4591                                     property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4592                                     if (atoi(property_value)) {
4593                                         DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4594                                         arbitrary_bytes = true;
4595                                     }
4596 #endif
4597                                 } else {
4598                                     DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4599                                             (unsigned int)portFmt->nFramePackingFormat);
4600                                     eRet = OMX_ErrorUnsupportedSetting;
4601                                 }
4602                             } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4603                                 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4604                                 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4605                                             portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4606                                         portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4607                                     m_out_mem_region_smi = OMX_TRUE;
4608                                     if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4609                                         DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4610                                         m_use_output_pmem = OMX_TRUE;
4611                                     }
4612                                 }
4613                             }
4614                         }
4615                         if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4616                                     OMX_MAX_STRINGNAME_SIZE)) {
4617                             arbitrary_bytes = true;
4618                             DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4619                         }
4620                         break;
4621 
4622         case OMX_QTIIndexParamVideoClientExtradata: {
4623                                   VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4624                                   DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
4625                                   QOMX_EXTRADATA_ENABLE *pParam =
4626                                       (QOMX_EXTRADATA_ENABLE *)paramData;
4627 
4628                                   if (m_state != OMX_StateLoaded) {
4629                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
4630                                       return OMX_ErrorIncorrectStateOperation;
4631                                   }
4632 
4633                                   if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4634                                       m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
4635                                   } else {
4636                                       DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
4637                                       eRet = OMX_ErrorUnsupportedIndex;
4638                                   }
4639                                   break;
4640                               }
4641         case OMX_IndexParamStandardComponentRole: {
4642                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4643                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
4644                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4645                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4646                                           comp_role->cRole);
4647 
4648                                   if ((m_state == OMX_StateLoaded)&&
4649                                           !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4650                                       DEBUG_PRINT_LOW("Set Parameter called in valid state");
4651                                   } else {
4652                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4653                                       return OMX_ErrorIncorrectStateOperation;
4654                                   }
4655 
4656                                   if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4657                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4658                                           strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4659                                       } else {
4660                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4661                                           eRet =OMX_ErrorUnsupportedSetting;
4662                                       }
4663                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4664                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4665                                           strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4666                                       } else {
4667                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4668                                           eRet = OMX_ErrorUnsupportedSetting;
4669                                       }
4670                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4671                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4672                                           strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4673                                       } else {
4674                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4675                                           eRet = OMX_ErrorUnsupportedSetting;
4676                                       }
4677                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4678                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4679                                           strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4680                                       } else {
4681                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4682                                           eRet =OMX_ErrorUnsupportedSetting;
4683                                       }
4684                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4685                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4686                                           strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4687                                       } else {
4688                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4689                                           eRet = OMX_ErrorUnsupportedSetting;
4690                                       }
4691                                   } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4692                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4693                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4694                                         ) {
4695                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4696                                           strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4697                                       } else {
4698                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4699                                           eRet =OMX_ErrorUnsupportedSetting;
4700                                       }
4701                                   } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4702                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4703                                         ) {
4704                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4705                                           strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4706                                       } else {
4707                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4708                                           eRet =OMX_ErrorUnsupportedSetting;
4709                                       }
4710                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4711                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4712                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4713                                           strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4714                                       } else {
4715                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4716                                           eRet = OMX_ErrorUnsupportedSetting;
4717                                       }
4718                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4719                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4720                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4721                                           strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4722                                       } else {
4723                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4724                                           eRet = OMX_ErrorUnsupportedSetting;
4725                                       }
4726                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4727                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4728                                           strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4729                                       } else {
4730                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4731                                           eRet = OMX_ErrorUnsupportedSetting;
4732                                       }
4733                                   } else {
4734                                       DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4735                                       eRet = OMX_ErrorInvalidComponentName;
4736                                   }
4737                                   break;
4738                               }
4739 
4740         case OMX_IndexParamPriorityMgmt: {
4741                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4742                              if (m_state != OMX_StateLoaded) {
4743                                  DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4744                                  return OMX_ErrorIncorrectStateOperation;
4745                              }
4746                              OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4747                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4748                                      (unsigned int)priorityMgmtype->nGroupID);
4749 
4750                              DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4751                                      (unsigned int)priorityMgmtype->nGroupPriority);
4752 
4753                              m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4754                              m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4755 
4756                              break;
4757                          }
4758 
4759         case OMX_IndexParamCompBufferSupplier: {
4760                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4761                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4762                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4763                                            bufferSupplierType->eBufferSupplier);
4764                                    if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4765                                        m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4766 
4767                                    else
4768 
4769                                        eRet = OMX_ErrorBadPortIndex;
4770 
4771                                    break;
4772 
4773                                }
4774         case OMX_IndexParamVideoAvc: {
4775                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4776                                      paramIndex);
4777                              break;
4778                          }
4779         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4780                             DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4781                                      paramIndex);
4782                              break;
4783                         }
4784         case OMX_IndexParamVideoH263: {
4785                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4786                                       paramIndex);
4787                               break;
4788                           }
4789         case OMX_IndexParamVideoMpeg4: {
4790                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4791                                        paramIndex);
4792                                break;
4793                            }
4794         case OMX_IndexParamVideoMpeg2: {
4795                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4796                                        paramIndex);
4797                                break;
4798                            }
4799         case OMX_QTIIndexParamLowLatencyMode: {
4800                                struct v4l2_control control;
4801                                int rc = 0;
4802                                QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam =
4803                                    (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData;
4804                                if (pParam->bLowLatencyMode) {
4805                                    DEBUG_PRINT_HIGH("Enabling DECODE order");
4806                                    time_stamp_dts.set_timestamp_reorder_mode(false);
4807                                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4808                                    control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4809                                    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4810                                    if (rc) {
4811                                        DEBUG_PRINT_ERROR("Set picture order failed");
4812                                        eRet = OMX_ErrorUnsupportedSetting;
4813                                    }
4814                                }
4815                                break;
4816                            }
4817         case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4818                                      VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4819                                      QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4820                                          (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4821                                      struct v4l2_control control;
4822                                      int pic_order,rc=0;
4823                                      DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4824                                              pictureOrder->eOutputPictureOrder);
4825                                      if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4826                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4827                                      } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4828                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4829                                          time_stamp_dts.set_timestamp_reorder_mode(false);
4830                                      } else
4831                                          eRet = OMX_ErrorBadParameter;
4832                                      if (eRet == OMX_ErrorNone) {
4833                                          control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4834                                          control.value = pic_order;
4835                                          rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4836                                          if (rc) {
4837                                              DEBUG_PRINT_ERROR("Set picture order failed");
4838                                              eRet = OMX_ErrorUnsupportedSetting;
4839                                          }
4840                                      }
4841                                      m_decode_order_mode =
4842                                             pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4843                                      break;
4844                                  }
4845         case OMX_QcomIndexParamConcealMBMapExtraData:
4846                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4847                                eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4848                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4849                                break;
4850         case OMX_QcomIndexParamFrameInfoExtraData:
4851                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4852                                eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4853                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4854                                break;
4855         case OMX_ExtraDataFrameDimension:
4856                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4857                                eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4858                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4859                                break;
4860         case OMX_QcomIndexParamInterlaceExtraData:
4861                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4862                                eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4863                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4864                                break;
4865         case OMX_QcomIndexParamH264TimeInfo:
4866                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4867                                eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4868                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4869                                break;
4870         case OMX_QcomIndexParamVideoFramePackingExtradata:
4871                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4872                                eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4873                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4874                                break;
4875         case OMX_QcomIndexParamVideoQPExtraData:
4876                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4877                                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4878                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4879                                break;
4880         case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4881                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4882                                eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4883                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4884                                break;
4885         case OMX_QcomIndexEnableExtnUserData:
4886                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4887                                 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4888                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4889                                 break;
4890         case OMX_QTIIndexParamVQZipSEIExtraData:
4891                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4892                                 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4893                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4894                                 break;
4895         case OMX_QcomIndexParamVideoDivx: {
4896                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4897                           }
4898                           break;
4899         case OMX_QcomIndexPlatformPvt: {
4900                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4901                                DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4902                                OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4903                                if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4904                                    DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4905                                    eRet = OMX_ErrorUnsupportedSetting;
4906                                } else {
4907                                    m_out_pvt_entry_pmem = OMX_TRUE;
4908                                    if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4909                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4910                                        m_use_output_pmem = OMX_TRUE;
4911                                    }
4912                                }
4913 
4914                            }
4915                            break;
4916         case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4917                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4918                                        DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4919                                        struct v4l2_control control;
4920                                        int rc;
4921                                        drv_ctx.idr_only_decoding = 1;
4922                                        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4923                                        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4924                                        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4925                                        if (rc) {
4926                                            DEBUG_PRINT_ERROR("Set picture order failed");
4927                                            eRet = OMX_ErrorUnsupportedSetting;
4928                                        } else {
4929                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4930                                            control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4931                                            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4932                                            if (rc) {
4933                                                DEBUG_PRINT_ERROR("Sync frame setting failed");
4934                                                eRet = OMX_ErrorUnsupportedSetting;
4935                                            }
4936                                            /*Setting sync frame decoding on driver might change buffer
4937                                             * requirements so update them here*/
4938                                            if (get_buffer_req(&drv_ctx.ip_buf)) {
4939                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4940                                                eRet = OMX_ErrorUnsupportedSetting;
4941                                            }
4942                                            if (get_buffer_req(&drv_ctx.op_buf)) {
4943                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4944                                                eRet = OMX_ErrorUnsupportedSetting;
4945                                            }
4946                                        }
4947                                    }
4948                                    break;
4949 
4950         case OMX_QcomIndexParamIndexExtraDataType: {
4951                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4952                                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4953                                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4954                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4955                                             (extradataIndexType->nPortIndex == 1)) {
4956                                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4957                                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4958 
4959                                     }
4960                                 }
4961                                 break;
4962         case OMX_QcomIndexParamEnableSmoothStreaming: {
4963 #ifndef SMOOTH_STREAMING_DISABLED
4964                                       eRet = enable_smoothstreaming();
4965 #else
4966                                       eRet = OMX_ErrorUnsupportedSetting;
4967 #endif
4968                                   }
4969                                   break;
4970 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4971                                   /* Need to allow following two set_parameters even in Idle
4972                                    * state. This is ANDROID architecture which is not in sync
4973                                    * with openmax standard. */
4974         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4975                                            VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4976                                            EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4977                                            if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4978                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4979                                                 eRet = OMX_ErrorUnsupportedSetting;
4980                                                 break;
4981                                            } else if (m_out_mem_ptr) {
4982                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4983                                                 eRet = OMX_ErrorInvalidState;
4984                                                 break;
4985                                            }
4986                                            if (enableNativeBuffers) {
4987                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
4988                                            }
4989 #if !defined(FLEXYUV_SUPPORTED)
4990                                            if (m_enable_android_native_buffers) {
4991                                                // Use the most-preferred-native-color-format as surface-mode is hinted here
4992                                                if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4993                                                    DEBUG_PRINT_ERROR("Failed to set native color format!");
4994                                                    eRet = OMX_ErrorUnsupportedSetting;
4995                                                }
4996                                            }
4997 #endif
4998                                        }
4999                                        break;
5000         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
5001                                        VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
5002                                        eRet = use_android_native_buffer(hComp, paramData);
5003                                    }
5004                                    break;
5005 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5006         case OMX_GoogleAndroidIndexAllocateNativeHandle: {
5007 
5008                 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
5009                 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
5010 
5011                 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
5012                     DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
5013                     eRet = OMX_ErrorUnsupportedSetting;
5014                     break;
5015                 } else if (m_inp_mem_ptr) {
5016                     DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
5017                     eRet = OMX_ErrorInvalidState;
5018                     break;
5019                 }
5020 
5021                 if (allocateNativeHandleParams != NULL) {
5022                     allocate_native_handle = allocateNativeHandleParams->enable;
5023                 }
5024             }
5025             break;
5026 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5027 #endif
5028         case OMX_QcomIndexParamEnableTimeStampReorder: {
5029                                        VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
5030                                        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
5031                                        if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
5032                                            if (reorder->bEnable == OMX_TRUE) {
5033                                                frm_int =0;
5034                                                time_stamp_dts.set_timestamp_reorder_mode(true);
5035                                            } else
5036                                                time_stamp_dts.set_timestamp_reorder_mode(false);
5037                                        } else {
5038                                            time_stamp_dts.set_timestamp_reorder_mode(false);
5039                                            if (reorder->bEnable == OMX_TRUE) {
5040                                                eRet = OMX_ErrorUnsupportedSetting;
5041                                            }
5042                                        }
5043                                    }
5044                                    break;
5045         case OMX_IndexParamVideoProfileLevelCurrent: {
5046                                      VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
5047                                      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
5048                                          (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
5049                                      if (pParam) {
5050                                          m_profile_lvl.eProfile = pParam->eProfile;
5051                                          m_profile_lvl.eLevel = pParam->eLevel;
5052                                      }
5053                                      break;
5054 
5055                                  }
5056         case OMX_QcomIndexParamVideoMetaBufferMode:
5057         {
5058             VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
5059             StoreMetaDataInBuffersParams *metabuffer =
5060                 (StoreMetaDataInBuffersParams *)paramData;
5061             if (!metabuffer) {
5062                 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
5063                 eRet = OMX_ErrorBadParameter;
5064                 break;
5065             }
5066             if (m_disable_dynamic_buf_mode) {
5067                 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
5068                 eRet = OMX_ErrorUnsupportedSetting;
5069                 break;
5070             }
5071             if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5072 
5073                     if (m_out_mem_ptr) {
5074                         DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
5075                         eRet = OMX_ErrorInvalidState;
5076                         break;
5077                     }
5078                     //set property dynamic buffer mode to driver.
5079                     struct v4l2_control control;
5080                     struct v4l2_format fmt;
5081                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
5082                     if (metabuffer->bStoreMetaData == true) {
5083                         control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
5084                     } else {
5085                         control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
5086                     }
5087                     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
5088                     if (!rc) {
5089                         DEBUG_PRINT_HIGH("%s buffer mode",
5090                            (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
5091                     } else {
5092                         DEBUG_PRINT_ERROR("Failed to %s buffer mode",
5093                            (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
5094                     }
5095                     dynamic_buf_mode = metabuffer->bStoreMetaData;
5096                 } else {
5097                     DEBUG_PRINT_ERROR(
5098                        "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
5099                        (unsigned int)metabuffer->nPortIndex);
5100                     eRet = OMX_ErrorUnsupportedSetting;
5101                 }
5102                 break;
5103         }
5104         case OMX_QcomIndexParamVideoDownScalar:
5105         {
5106             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
5107             QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
5108             struct v4l2_control control;
5109             int rc;
5110             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
5111 
5112             if (pParam && pParam->bEnable) {
5113                 rc = enable_downscalar();
5114                 if (rc < 0) {
5115                     DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
5116                     return OMX_ErrorUnsupportedSetting;
5117                 }
5118                 m_force_down_scalar = pParam->bEnable;
5119             } else {
5120                 rc = disable_downscalar();
5121                 if (rc < 0) {
5122                     DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
5123                     return OMX_ErrorUnsupportedSetting;
5124                 }
5125                 m_force_down_scalar = pParam->bEnable;
5126             }
5127             break;
5128         }
5129 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5130         case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
5131         {
5132             VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
5133             DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
5134             PrepareForAdaptivePlaybackParams* pParams =
5135                     (PrepareForAdaptivePlaybackParams *) paramData;
5136             if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5137                 if (!pParams->bEnable) {
5138                     return OMX_ErrorNone;
5139                 }
5140                 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
5141                         || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
5142                     DEBUG_PRINT_ERROR(
5143                             "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
5144                              (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
5145                              (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
5146                     eRet = OMX_ErrorBadParameter;
5147                 } else {
5148                     eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
5149                 }
5150             } else {
5151                 DEBUG_PRINT_ERROR(
5152                         "Prepare for adaptive playback supported only on output port");
5153                 eRet = OMX_ErrorBadParameter;
5154             }
5155             break;
5156         }
5157 
5158         case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
5159         {
5160             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5161             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
5162             m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5163             if (m_disable_dynamic_buf_mode) {
5164                 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
5165             }
5166             break;
5167         }
5168 #endif
5169         case OMX_QcomIndexParamVideoCustomBufferSize:
5170         {
5171             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
5172             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
5173             QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
5174             if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5175                 struct v4l2_control control;
5176                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
5177                 control.value = pParam->nBufferSize;
5178                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5179                     DEBUG_PRINT_ERROR("Failed to set input buffer size");
5180                     eRet = OMX_ErrorUnsupportedSetting;
5181                 } else {
5182                     eRet = get_buffer_req(&drv_ctx.ip_buf);
5183                     if (eRet == OMX_ErrorNone) {
5184                         m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
5185                         DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
5186                             m_custom_buffersize.input_buffersize);
5187                     } else {
5188                         DEBUG_PRINT_ERROR("Failed to get buffer requirement");
5189                     }
5190                 }
5191             } else {
5192                 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
5193                 eRet = OMX_ErrorBadParameter;
5194             }
5195             break;
5196         }
5197         case OMX_QTIIndexParamVQZIPSEIType:
5198         {
5199             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
5200             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
5201             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
5202                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
5203                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
5204 
5205             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
5206                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5207             if (eRet != OMX_ErrorNone) {
5208                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
5209                 eRet = OMX_ErrorBadParameter;
5210                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5211                 break;
5212             }
5213             eRet = enable_extradata(OMX_QP_EXTRADATA, false,
5214                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
5215             if (eRet != OMX_ErrorNone) {
5216                 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
5217                 eRet = OMX_ErrorBadParameter;
5218                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5219                 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5220                 break;
5221             }
5222             eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
5223                         ((QOMX_ENABLETYPE *)paramData)->bEnable);
5224             if (eRet != OMX_ErrorNone) {
5225                 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
5226                 eRet = OMX_ErrorBadParameter;
5227                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5228                 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5229                 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
5230             }
5231             break;
5232         }
5233         case OMX_QTIIndexParamPassInputBufferFd:
5234         {
5235             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5236             if (arbitrary_bytes) {
5237                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
5238                 eRet = OMX_ErrorUnsupportedSetting;
5239                 break;
5240             }
5241 
5242             m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5243             if (m_input_pass_buffer_fd)
5244                 DEBUG_PRINT_LOW("Enable passing input buffer FD");
5245             break;
5246         }
5247         case OMX_QTIIndexParamForceCompressedForDPB:
5248         {
5249             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
5250             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
5251             OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
5252                 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
5253             if (m_disable_ubwc_mode) {
5254                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
5255                 eRet = OMX_ErrorUnsupportedSetting;
5256                 break;
5257             }
5258             if (!paramData) {
5259                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
5260                eRet = OMX_ErrorBadParameter;
5261                break;
5262             }
5263 
5264             m_force_compressed_for_dpb = pParam->bEnable;
5265             break;
5266         }
5267         case OMX_QTIIndexParamForceUnCompressedForOPB:
5268         {
5269             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
5270             OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
5271                 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
5272             if (!paramData) {
5273                 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
5274                 eRet = OMX_ErrorBadParameter;
5275                 break;
5276             }
5277             m_disable_ubwc_mode = pParam->bEnable;
5278             DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
5279             break;
5280         }
5281         case OMX_QTIIndexParamDitherControl:
5282         {
5283             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
5284             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
5285             QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
5286             DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
5287             if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
5288                 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
5289                 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
5290                 eRet = OMX_ErrorBadParameter;
5291                 break;
5292             }
5293             m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
5294             DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
5295             break;
5296         }
5297         default: {
5298                  DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
5299                  eRet = OMX_ErrorUnsupportedIndex;
5300              }
5301     }
5302     if (eRet != OMX_ErrorNone)
5303         DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
5304     return eRet;
5305 }
5306 
5307 /* ======================================================================
5308    FUNCTION
5309    omx_vdec::GetConfig
5310 
5311    DESCRIPTION
5312    OMX Get Config Method implementation.
5313 
5314    PARAMETERS
5315    <TBD>.
5316 
5317    RETURN VALUE
5318    OMX Error None if successful.
5319 
5320    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)5321 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
5322         OMX_IN OMX_INDEXTYPE configIndex,
5323         OMX_INOUT OMX_PTR     configData)
5324 {
5325     (void) hComp;
5326     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5327 
5328     if (m_state == OMX_StateInvalid) {
5329         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5330         return OMX_ErrorInvalidState;
5331     }
5332 
5333     switch ((unsigned long)configIndex) {
5334         case OMX_QcomIndexConfigInterlaced: {
5335                                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
5336                                 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
5337                                     (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
5338                                 if (configFmt->nPortIndex == 1) {
5339                                     if (configFmt->nIndex == 0) {
5340                                         configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
5341                                     } else if (configFmt->nIndex == 1) {
5342                                         configFmt->eInterlaceType =
5343                                             OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
5344                                     } else if (configFmt->nIndex == 2) {
5345                                         configFmt->eInterlaceType =
5346                                             OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
5347                                     } else {
5348                                         DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
5349                                                 " NoMore Interlaced formats");
5350                                         eRet = OMX_ErrorNoMore;
5351                                     }
5352 
5353                                 } else {
5354                                     DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
5355                                             (int)configFmt->nPortIndex);
5356                                     eRet = OMX_ErrorBadPortIndex;
5357                                 }
5358                                 break;
5359                             }
5360         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5361                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5362                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5363                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5364                                      decoderinstances->nNumOfInstances = 16;
5365                                      /*TODO: How to handle this case */
5366                                      break;
5367                                  }
5368         case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5369                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5370                                               VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5371                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5372                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5373                                               memcpy(configFmt, &m_frame_pack_arrangement,
5374                                                   sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5375                                           } else {
5376                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5377                                           }
5378                                           break;
5379                                       }
5380         case OMX_IndexConfigCommonOutputCrop: {
5381                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5382                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5383                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5384                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5385                                         rectangle.nLeft, rectangle.nTop,
5386                                         rectangle.nWidth, rectangle.nHeight);
5387                                   break;
5388                               }
5389         case OMX_QcomIndexConfigPerfLevel: {
5390                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
5391                 struct v4l2_control control;
5392                 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5393                         (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5394 
5395                 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5396                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
5397                     DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
5398                     eRet = OMX_ErrorHardware;
5399                 }
5400 
5401                 if (eRet == OMX_ErrorNone) {
5402                     switch (control.value) {
5403                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
5404                             perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
5405                             break;
5406                         default:
5407                             DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
5408                             /* Fall through */
5409                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
5410                             perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
5411                             break;
5412                     }
5413                 }
5414 
5415                 break;
5416         }
5417         case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5418             VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5419             QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5420             struct v4l2_control control;
5421 
5422             if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5423                 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5424                 eRet = OMX_ErrorNotImplemented;
5425                 break;
5426             }
5427 
5428             control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5429             if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5430                 coding->bCabac = (OMX_BOOL)
5431                     (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5432                 /* We can't query driver at the moment for the cabac mode, so
5433                  * just use 0xff...f as a place holder for future improvement */
5434                 coding->nCabacInitIdc = ~0;
5435             } else {
5436                 eRet = OMX_ErrorUnsupportedIndex;
5437             }
5438 
5439             break;
5440         }
5441         case OMX_QTIIndexConfigDescribeColorAspects:
5442         {
5443             VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5444             DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5445 
5446             if (params->bRequestingDataSpace) {
5447                 DEBUG_PRINT_HIGH("Does not handle dataspace request");
5448                 return OMX_ErrorUnsupportedSetting;
5449             }
5450 
5451             print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5452             print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5453 
5454             // For VPX, use client-color if specified.
5455             // For the rest, try to use the stream-color if present
5456             bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
5457                     output_capability == V4L2_PIX_FMT_VP9);
5458 
5459             const ColorAspects &preferredColor = preferClientColor ?
5460                     m_client_color_space.sAspects : m_internal_color_space.sAspects;
5461             const ColorAspects &defaultColor = preferClientColor ?
5462                     m_internal_color_space.sAspects : m_client_color_space.sAspects;
5463 
5464             params->sAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
5465                     preferredColor.mPrimaries : defaultColor.mPrimaries;
5466             params->sAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
5467                     preferredColor.mTransfer : defaultColor.mTransfer;
5468             params->sAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
5469                     preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
5470             params->sAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
5471                     preferredColor.mRange : defaultColor.mRange;
5472 
5473             print_debug_color_aspects(&(params->sAspects), "GetConfig");
5474 
5475             break;
5476         }
5477         case OMX_QTIIndexConfigDescribeHDRColorInfo:
5478         {
5479             VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5480             DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5481             auto_lock lock(m_hdr_info_client_lock);
5482 
5483             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5484             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5485 
5486             if (m_change_client_hdr_info) {
5487                 DEBUG_PRINT_LOW("Updating Client's HDR Info with internal");
5488                 memcpy(&m_client_hdr_info.sInfo,
5489                        &m_internal_hdr_info.sInfo, sizeof(HDRStaticInfo));
5490                 m_change_client_hdr_info = false;
5491             }
5492 
5493             memcpy(&(params->sInfo), &(m_client_hdr_info.sInfo), sizeof(HDRStaticInfo));
5494 
5495             break;
5496         }
5497         case OMX_IndexConfigAndroidVendorExtension:
5498         {
5499             VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5500 
5501             OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5502                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5503             VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5504             return get_vendor_extension_config(ext);
5505         }
5506         default:
5507         {
5508             DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5509             eRet = OMX_ErrorBadParameter;
5510         }
5511 
5512     }
5513 
5514     return eRet;
5515 }
5516 
5517 /* ======================================================================
5518    FUNCTION
5519    omx_vdec::SetConfig
5520 
5521    DESCRIPTION
5522    OMX Set Config method implementation
5523 
5524    PARAMETERS
5525    <TBD>.
5526 
5527    RETURN VALUE
5528    OMX Error None if successful.
5529    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5530 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5531         OMX_IN OMX_INDEXTYPE configIndex,
5532         OMX_IN OMX_PTR        configData)
5533 {
5534     (void) hComp;
5535     if (m_state == OMX_StateInvalid) {
5536         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5537         return OMX_ErrorInvalidState;
5538     }
5539 
5540     OMX_ERRORTYPE ret = OMX_ErrorNone;
5541     OMX_VIDEO_CONFIG_NALSIZE *pNal;
5542 
5543     DEBUG_PRINT_LOW("Set Config Called");
5544 
5545     if (configIndex == OMX_IndexConfigVideoNalSize) {
5546         struct v4l2_control temp;
5547         temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5548 
5549         VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5550         pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5551         switch (pNal->nNaluBytes) {
5552             case 0:
5553                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5554                 break;
5555             case 2:
5556                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5557                 break;
5558             case 4:
5559                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5560                 break;
5561             default:
5562                 return OMX_ErrorUnsupportedSetting;
5563         }
5564 
5565         if (!arbitrary_bytes) {
5566             /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5567              * with start code, so only need to notify driver in frame by frame mode */
5568             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5569                 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5570                 return OMX_ErrorHardware;
5571             }
5572         }
5573 
5574         nal_length = pNal->nNaluBytes;
5575         m_frame_parser.init_nal_length(nal_length);
5576 
5577         DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5578         return ret;
5579     } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5580         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5581         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5582 
5583         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5584             if (config->bEnabled) {
5585                 if ((config->nFps >> 16) > 0 &&
5586                         (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5587                     m_fps_received = config->nFps;
5588                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5589                             (unsigned int)config->nFps >> 16);
5590                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5591                             drv_ctx.frame_rate.fps_denominator);
5592 
5593                     if (!drv_ctx.frame_rate.fps_numerator) {
5594                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5595                         drv_ctx.frame_rate.fps_numerator = 30;
5596                     }
5597 
5598                     if (drv_ctx.frame_rate.fps_denominator) {
5599                         drv_ctx.frame_rate.fps_numerator = (int)
5600                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5601                     }
5602 
5603                     drv_ctx.frame_rate.fps_denominator = 1;
5604                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5605                         drv_ctx.frame_rate.fps_numerator;
5606 
5607                     struct v4l2_outputparm oparm;
5608                     /*XXX: we're providing timing info as seconds per frame rather than frames
5609                      * per second.*/
5610                     oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5611                     oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5612 
5613                     struct v4l2_streamparm sparm;
5614                     sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5615                     sparm.parm.output = oparm;
5616                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5617                         DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5618                                 performance might be affected");
5619                         ret = OMX_ErrorHardware;
5620                     }
5621                     client_set_fps = true;
5622                 } else {
5623                     DEBUG_PRINT_ERROR("Frame rate not supported.");
5624                     ret = OMX_ErrorUnsupportedSetting;
5625                 }
5626             } else {
5627                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5628                 client_set_fps = false;
5629             }
5630         } else {
5631             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5632                     (int)config->nPortIndex);
5633             ret = OMX_ErrorBadPortIndex;
5634         }
5635 
5636         return ret;
5637     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5638         OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5639             (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5640         struct v4l2_control control;
5641 
5642         DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5643         control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5644 
5645         switch (perf->ePerfLevel) {
5646             case OMX_QCOM_PerfLevelNominal:
5647                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5648                 m_need_turbo &= ~TURBO_MODE_CLIENT_REQUESTED;
5649                 break;
5650             case OMX_QCOM_PerfLevelTurbo:
5651                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5652                 m_need_turbo |= TURBO_MODE_CLIENT_REQUESTED;
5653                 break;
5654             default:
5655                 ret = OMX_ErrorUnsupportedSetting;
5656                 break;
5657         }
5658 
5659         if (ret == OMX_ErrorNone) {
5660             ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5661                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5662         }
5663 
5664         return ret;
5665     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5666         OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5667             (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5668         struct v4l2_control control;
5669         DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5670         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5671 
5672         switch (config->eDecodeType) {
5673             case OMX_QCOM_PictypeDecode_I:
5674                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5675                 break;
5676             case OMX_QCOM_PictypeDecode_IPB:
5677             default:
5678                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5679                 break;
5680         }
5681 
5682         ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5683                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5684         if (ret)
5685             DEBUG_PRINT_ERROR("Failed to set picture type decode");
5686 
5687         return ret;
5688     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5689         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5690         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5691 
5692         struct v4l2_control control;
5693 
5694         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5695         if (priority->nU32 == 0)
5696             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5697         else
5698             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5699 
5700         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5701             DEBUG_PRINT_ERROR("Failed to set Priority");
5702             ret = OMX_ErrorUnsupportedSetting;
5703         }
5704         return ret;
5705     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5706         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5707         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5708 
5709         struct v4l2_control control;
5710 
5711         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5712         control.value = rate->nU32;
5713 
5714         operating_frame_rate = rate->nU32 >> 16;
5715 
5716         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5717             ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5718                     OMX_ErrorUnsupportedSetting;
5719             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5720                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5721         }
5722         return ret;
5723 
5724     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5725         VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5726         DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5727         if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5728             enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5729         }
5730 
5731         print_debug_color_aspects(&(params->sAspects), "Set Config");
5732         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5733         return ret;
5734     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5735         VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5736         DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5737         if (!DEFAULT_EXTRADATA & OMX_HDR_COLOR_INFO_EXTRADATA) {
5738             ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, true, true);
5739             if (ret != OMX_ErrorNone) {
5740                 DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5741                 return ret;
5742             }
5743         }
5744 
5745         print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5746         memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5747         return ret;
5748 
5749     } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5750         VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5751 
5752         OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5753                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5754         VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5755 
5756         return set_vendor_extension_config(ext);
5757     }
5758 
5759     return OMX_ErrorNotImplemented;
5760 }
5761 
5762 #define extn_equals(param, extn) (!strcmp(param, extn))
5763 
5764 /* ======================================================================
5765    FUNCTION
5766    omx_vdec::GetExtensionIndex
5767 
5768    DESCRIPTION
5769    OMX GetExtensionIndex method implementaion.  <TBD>
5770 
5771    PARAMETERS
5772    <TBD>.
5773 
5774    RETURN VALUE
5775    OMX Error None if everything successful.
5776 
5777    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5778 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5779         OMX_IN OMX_STRING      paramName,
5780         OMX_OUT OMX_INDEXTYPE* indexType)
5781 {
5782     (void) hComp;
5783     if (m_state == OMX_StateInvalid) {
5784         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5785         return OMX_ErrorInvalidState;
5786     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5787         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5788     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5789         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5790     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5791         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5792     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5793         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5794     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5795         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5796     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5797         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5798     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5799         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5800     }
5801 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5802     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5803         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5804     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5805         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5806     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5807         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5808     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5809         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5810     }
5811 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5812     else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5813         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5814     }
5815 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5816 #endif
5817     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5818         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5819     }
5820 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5821     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5822         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5823     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5824         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5825     }
5826 #endif
5827 #ifdef FLEXYUV_SUPPORTED
5828     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5829         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5830     }
5831 #endif
5832     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5833         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5834     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5835         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5836     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5837         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5838     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5839         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5840     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5841         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5842     } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5843         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5844     } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5845         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5846     } else {
5847         DEBUG_PRINT_HIGH("Extension: %s not implemented", paramName);
5848         return OMX_ErrorNotImplemented;
5849     }
5850     return OMX_ErrorNone;
5851 }
5852 
5853 /* ======================================================================
5854    FUNCTION
5855    omx_vdec::GetState
5856 
5857    DESCRIPTION
5858    Returns the state information back to the caller.<TBD>
5859 
5860    PARAMETERS
5861    <TBD>.
5862 
5863    RETURN VALUE
5864    Error None if everything is successful.
5865    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5866 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5867         OMX_OUT OMX_STATETYPE* state)
5868 {
5869     (void) hComp;
5870     *state = m_state;
5871     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5872     return OMX_ErrorNone;
5873 }
5874 
5875 /* ======================================================================
5876    FUNCTION
5877    omx_vdec::ComponentTunnelRequest
5878 
5879    DESCRIPTION
5880    OMX Component Tunnel Request method implementation. <TBD>
5881 
5882    PARAMETERS
5883    None.
5884 
5885    RETURN VALUE
5886    OMX Error None if everything successful.
5887 
5888    ========================================================================== */
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)5889 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5890         OMX_IN OMX_U32                        port,
5891         OMX_IN OMX_HANDLETYPE        peerComponent,
5892         OMX_IN OMX_U32                    peerPort,
5893         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5894 {
5895     (void) hComp;
5896     (void) port;
5897     (void) peerComponent;
5898     (void) peerPort;
5899     (void) tunnelSetup;
5900     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5901     return OMX_ErrorNotImplemented;
5902 }
5903 
5904 /* ======================================================================
5905    FUNCTION
5906    omx_vdec::UseOutputBuffer
5907 
5908    DESCRIPTION
5909    Helper function for Use buffer in the input pin
5910 
5911    PARAMETERS
5912    None.
5913 
5914    RETURN VALUE
5915    true/false
5916 
5917    ========================================================================== */
allocate_extradata()5918 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5919 {
5920 #ifdef USE_ION
5921     if (drv_ctx.extradata_info.buffer_size) {
5922         if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5923             munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5924             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5925             free_ion_memory(&drv_ctx.extradata_info.ion);
5926         }
5927         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5928         drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5929                 drv_ctx.extradata_info.size, 4096,
5930                 &drv_ctx.extradata_info.ion.ion_alloc_data,
5931                 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5932         if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5933             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5934             return OMX_ErrorInsufficientResources;
5935         }
5936         drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5937                 drv_ctx.extradata_info.size,
5938                 PROT_READ|PROT_WRITE, MAP_SHARED,
5939                 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5940         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5941             DEBUG_PRINT_ERROR("Failed to map extradata memory");
5942             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5943             free_ion_memory(&drv_ctx.extradata_info.ion);
5944             return OMX_ErrorInsufficientResources;
5945         }
5946     }
5947 #endif
5948     if (!m_other_extradata) {
5949         m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5950         if (!m_other_extradata) {
5951             DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5952             return OMX_ErrorInsufficientResources;
5953         }
5954     }
5955     return OMX_ErrorNone;
5956 }
5957 
free_extradata()5958 void omx_vdec::free_extradata()
5959 {
5960 #ifdef USE_ION
5961     if (drv_ctx.extradata_info.uaddr) {
5962         munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5963         close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5964         free_ion_memory(&drv_ctx.extradata_info.ion);
5965     }
5966 #endif
5967     if (m_other_extradata) {
5968         free(m_other_extradata);
5969         m_other_extradata = NULL;
5970     }
5971 }
5972 
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)5973 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5974         OMX_IN OMX_HANDLETYPE            hComp,
5975         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5976         OMX_IN OMX_U32                   port,
5977         OMX_IN OMX_PTR                   appData,
5978         OMX_IN OMX_U32                   bytes,
5979         OMX_IN OMX_U8*                   buffer)
5980 {
5981     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5982     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5983     unsigned                         i= 0; // Temporary counter
5984     struct vdec_setbuffer_cmd setbuffers;
5985     OMX_PTR privateAppData = NULL;
5986     private_handle_t *handle = NULL;
5987     OMX_U8 *buff = buffer;
5988     struct v4l2_buffer buf;
5989     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5990     int extra_idx = 0;
5991     (void) hComp;
5992     (void) port;
5993 
5994     if (!m_out_mem_ptr) {
5995         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5996         eRet = allocate_output_headers();
5997         if (eRet == OMX_ErrorNone)
5998             eRet = allocate_extradata();
5999         output_use_buffer = true;
6000     }
6001 
6002     if (eRet == OMX_ErrorNone) {
6003         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6004             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6005                 break;
6006             }
6007         }
6008     }
6009 
6010     if (i >= drv_ctx.op_buf.actualcount) {
6011         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
6012         eRet = OMX_ErrorInsufficientResources;
6013     }
6014 
6015     if (eRet != OMX_ErrorNone)
6016        return eRet;
6017 
6018     if (dynamic_buf_mode) {
6019         *bufferHdr = (m_out_mem_ptr + i );
6020         (*bufferHdr)->pBuffer = NULL;
6021         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
6022             enum v4l2_buf_type buf_type;
6023             int rr = 0;
6024             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6025             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
6026                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
6027                 return OMX_ErrorInsufficientResources;
6028             } else {
6029                 streaming[CAPTURE_PORT] = true;
6030                 DEBUG_PRINT_LOW("STREAMON Successful");
6031             }
6032 
6033             DEBUG_PRINT_HIGH("Enabling Turbo mode");
6034             request_perf_level(VIDC_TURBO);
6035         }
6036         BITMASK_SET(&m_out_bm_count,i);
6037         (*bufferHdr)->pAppPrivate = appData;
6038         (*bufferHdr)->pBuffer = buffer;
6039         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
6040         return eRet;
6041     }
6042 
6043     if (eRet == OMX_ErrorNone) {
6044 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
6045         if (m_enable_android_native_buffers) {
6046             if (m_use_android_native_buffers) {
6047                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
6048                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
6049                 handle = (private_handle_t *)nBuf->handle;
6050                 privateAppData = params->pAppPrivate;
6051             } else {
6052                 handle = (private_handle_t *)buff;
6053                 privateAppData = appData;
6054             }
6055             if (!handle) {
6056                 DEBUG_PRINT_ERROR("handle is invalid");
6057                 return OMX_ErrorBadParameter;
6058             }
6059 
6060             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
6061                 if (secure_mode && secure_scaling_to_non_secure_opb) {
6062                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
6063                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6064                 } else {
6065                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
6066                             " expected %u, got %u",
6067                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6068                     return OMX_ErrorBadParameter;
6069                 }
6070             }
6071 
6072             drv_ctx.op_buf.buffer_size = handle->size;
6073 
6074             if (!m_use_android_native_buffers) {
6075                 if (!secure_mode) {
6076                     buff =  (OMX_U8*)mmap(0, handle->size,
6077                             PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
6078                     if (buff == MAP_FAILED) {
6079                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
6080                         return OMX_ErrorInsufficientResources;
6081                     }
6082                 }
6083             }
6084 #if defined(_ANDROID_ICS_)
6085             native_buffer[i].nativehandle = handle;
6086             native_buffer[i].privatehandle = handle;
6087 #endif
6088             if (!handle) {
6089                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
6090                 return OMX_ErrorBadParameter;
6091             }
6092             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
6093             drv_ctx.ptr_outputbuffer[i].offset = 0;
6094             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6095             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6096             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
6097         } else
6098 #endif
6099 
6100             if (!ouput_egl_buffers && !m_use_output_pmem) {
6101 #ifdef USE_ION
6102                 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6103                         drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
6104                         &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
6105                         &drv_ctx.op_buf_ion_info[i].fd_ion_data,
6106                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
6107                 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
6108                     DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
6109                     return OMX_ErrorInsufficientResources;
6110                 }
6111                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6112                                       drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6113 #else
6114                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6115                                       open (MEM_DEVICE,O_RDWR);
6116 
6117                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6118                     DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6119                     return OMX_ErrorInsufficientResources;
6120                 }
6121 
6122                 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
6123                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
6124                     drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6125                                           open (MEM_DEVICE,O_RDWR);
6126                     if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6127                         DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6128                         return OMX_ErrorInsufficientResources;
6129                     }
6130                 }
6131 
6132                 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
6133                             drv_ctx.op_buf.buffer_size,
6134                             drv_ctx.op_buf.alignment)) {
6135                     DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6136                     close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6137                     return OMX_ErrorInsufficientResources;
6138                 }
6139 #endif
6140                 if (!secure_mode) {
6141                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
6142                         (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
6143                                 PROT_READ|PROT_WRITE, MAP_SHARED,
6144                                 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
6145                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
6146                         close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6147 #ifdef USE_ION
6148                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6149 #endif
6150                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
6151                         return OMX_ErrorInsufficientResources;
6152                     }
6153                 }
6154                 drv_ctx.ptr_outputbuffer[i].offset = 0;
6155                 privateAppData = appData;
6156             } else {
6157 
6158                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
6159                 if (!appData || !bytes ) {
6160                     if (!secure_mode && !buffer) {
6161                         DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
6162                         return OMX_ErrorBadParameter;
6163                     }
6164                 }
6165 
6166                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
6167                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
6168                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
6169                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
6170                         !pmem_list->nEntries ||
6171                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
6172                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
6173                     return OMX_ErrorBadParameter;
6174                 }
6175                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6176                     pmem_list->entryList->entry;
6177                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
6178                         pmem_info->pmem_fd);
6179                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
6180                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
6181                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6182                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
6183                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6184                 privateAppData = appData;
6185             }
6186         m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6187         m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6188         m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6189         m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6190         m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6191 
6192         *bufferHdr = (m_out_mem_ptr + i );
6193         if (secure_mode)
6194             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6195         //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6196         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
6197                 sizeof (vdec_bufferpayload));
6198 
6199         DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
6200                 drv_ctx.ptr_outputbuffer[i].bufferaddr,
6201                 drv_ctx.ptr_outputbuffer[i].pmem_fd );
6202 
6203         buf.index = i;
6204         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6205         buf.memory = V4L2_MEMORY_USERPTR;
6206         plane[0].length = drv_ctx.op_buf.buffer_size;
6207         plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6208             (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6209         plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6210         plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6211         plane[0].data_offset = 0;
6212         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6213         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6214             plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6215             plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6216 #ifdef USE_ION
6217             plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6218 #endif
6219             plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6220             plane[extra_idx].data_offset = 0;
6221         } else if  (extra_idx >= VIDEO_MAX_PLANES) {
6222             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
6223             return OMX_ErrorBadParameter;
6224         }
6225         buf.m.planes = plane;
6226         buf.length = drv_ctx.num_planes;
6227 
6228         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
6229             DEBUG_PRINT_ERROR("Failed to prepare bufs");
6230             /*TODO: How to handle this case */
6231             return OMX_ErrorInsufficientResources;
6232         }
6233 
6234         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
6235             enum v4l2_buf_type buf_type;
6236             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6237             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
6238                 return OMX_ErrorInsufficientResources;
6239             } else {
6240                 streaming[CAPTURE_PORT] = true;
6241                 DEBUG_PRINT_LOW("STREAMON Successful");
6242             }
6243 
6244             DEBUG_PRINT_HIGH("Enabling Turbo mode");
6245             request_perf_level(VIDC_TURBO);
6246         }
6247 
6248         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
6249         if (m_enable_android_native_buffers) {
6250             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
6251             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
6252         } else {
6253             (*bufferHdr)->pBuffer = buff;
6254         }
6255         (*bufferHdr)->pAppPrivate = privateAppData;
6256         BITMASK_SET(&m_out_bm_count,i);
6257     }
6258     return eRet;
6259 }
6260 
allocate_client_output_extradata_headers()6261 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() {
6262     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6263     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
6264     int i = 0;
6265 
6266     if (!m_client_output_extradata_mem_ptr) {
6267         int nBufferCount       = 0;
6268 
6269         nBufferCount = m_client_out_extradata_info.getBufferCount();
6270         DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
6271 
6272         m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
6273 
6274         if (m_client_output_extradata_mem_ptr) {
6275             bufHdr          =  m_client_output_extradata_mem_ptr;
6276             for (i=0; i < nBufferCount; i++) {
6277                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6278                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6279                 // Set the values when we determine the right HxW param
6280                 bufHdr->nAllocLen          = 0;
6281                 bufHdr->nFilledLen         = 0;
6282                 bufHdr->pAppPrivate        = NULL;
6283                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
6284                 bufHdr->pBuffer            = NULL;
6285                 bufHdr->pOutputPortPrivate = NULL;
6286                 bufHdr++;
6287             }
6288         } else {
6289              DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
6290                     m_client_output_extradata_mem_ptr);
6291               eRet =  OMX_ErrorInsufficientResources;
6292         }
6293     }
6294     return eRet;
6295 }
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)6296 OMX_ERRORTYPE  omx_vdec::use_client_output_extradata_buffer(
6297         OMX_IN OMX_HANDLETYPE            hComp,
6298         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6299         OMX_IN OMX_U32                   port,
6300         OMX_IN OMX_PTR                   appData,
6301         OMX_IN OMX_U32                   bytes,
6302         OMX_IN OMX_U8*                   buffer)
6303 {
6304     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6305     unsigned i = 0; // Temporary counter
6306     unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
6307     OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
6308     (void) hComp;
6309 
6310     if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
6311             !client_extradata || bytes != buffer_size|| bufferHdr == NULL) {
6312         DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
6313             "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
6314             OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr);
6315         eRet = OMX_ErrorBadParameter;
6316         return eRet;
6317     }
6318 
6319     if (!m_client_output_extradata_mem_ptr) {
6320         eRet = allocate_client_output_extradata_headers();
6321     }
6322 
6323     if (eRet == OMX_ErrorNone) {
6324         for (i = 0; i < buffer_count; i++) {
6325             if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
6326                 break;
6327             }
6328         }
6329     }
6330 
6331     if (i >= buffer_count) {
6332         DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
6333         eRet = OMX_ErrorInsufficientResources;
6334     }
6335 
6336     if (eRet == OMX_ErrorNone) {
6337         BITMASK_SET(&m_out_extradata_bm_count,i);
6338         *bufferHdr = (m_client_output_extradata_mem_ptr + i );
6339         (*bufferHdr)->pAppPrivate = appData;
6340         (*bufferHdr)->pBuffer = buffer;
6341         (*bufferHdr)->nAllocLen = bytes;
6342     }
6343 
6344     return eRet;
6345 }
6346 /* ======================================================================
6347    FUNCTION
6348    omx_vdec::use_input_heap_buffers
6349 
6350    DESCRIPTION
6351    OMX Use Buffer Heap allocation method implementation.
6352 
6353    PARAMETERS
6354    <TBD>.
6355 
6356    RETURN VALUE
6357    OMX Error None , if everything successful.
6358 
6359    ========================================================================== */
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)6360 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
6361         OMX_IN OMX_HANDLETYPE            hComp,
6362         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6363         OMX_IN OMX_U32                   port,
6364         OMX_IN OMX_PTR                   appData,
6365         OMX_IN OMX_U32                   bytes,
6366         OMX_IN OMX_U8*                   buffer)
6367 {
6368     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
6369     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6370 
6371     if (secure_mode) {
6372         DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
6373         return OMX_ErrorUndefined;
6374     }
6375 
6376     if (!m_inp_heap_ptr)
6377         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
6378             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6379                     drv_ctx.ip_buf.actualcount);
6380     if (!m_phdr_pmem_ptr)
6381         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
6382             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6383                     drv_ctx.ip_buf.actualcount);
6384     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
6385         DEBUG_PRINT_ERROR("Insufficent memory");
6386         eRet = OMX_ErrorInsufficientResources;
6387     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
6388         input_use_buffer = true;
6389         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
6390         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
6391         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
6392         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
6393         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
6394         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
6395         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
6396         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
6397         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
6398         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
6399                     (unsigned)NULL, (unsigned)NULL)) {
6400             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6401             return OMX_ErrorInsufficientResources;
6402         }
6403         m_in_alloc_cnt++;
6404     } else {
6405         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
6406         eRet = OMX_ErrorInsufficientResources;
6407     }
6408     return eRet;
6409 }
6410 
6411 /* ======================================================================
6412    FUNCTION
6413    omx_vdec::UseBuffer
6414 
6415    DESCRIPTION
6416    OMX Use Buffer method implementation.
6417 
6418    PARAMETERS
6419    <TBD>.
6420 
6421    RETURN VALUE
6422    OMX Error None , if everything successful.
6423 
6424    ========================================================================== */
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)6425 OMX_ERRORTYPE  omx_vdec::use_buffer(
6426         OMX_IN OMX_HANDLETYPE            hComp,
6427         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6428         OMX_IN OMX_U32                   port,
6429         OMX_IN OMX_PTR                   appData,
6430         OMX_IN OMX_U32                   bytes,
6431         OMX_IN OMX_U8*                   buffer)
6432 {
6433     OMX_ERRORTYPE error = OMX_ErrorNone;
6434     struct vdec_setbuffer_cmd setbuffers;
6435 
6436     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
6437             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
6438             return OMX_ErrorBadParameter;
6439     }
6440     if (m_state == OMX_StateInvalid) {
6441         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
6442         return OMX_ErrorInvalidState;
6443     }
6444     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6445         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6446         // ensure that use-buffer was called for previous allocation.
6447         // Mix-and-match of useBuffer and allocateBuffer is not allowed
6448         if (m_inp_mem_ptr && !input_use_buffer) {
6449             DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
6450             return OMX_ErrorUndefined;
6451         }
6452         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
6453     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6454         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
6455     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
6456         error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
6457     } else {
6458         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6459         error = OMX_ErrorBadPortIndex;
6460     }
6461     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
6462     if (error == OMX_ErrorNone) {
6463         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6464             // Send the callback now
6465             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6466             post_event(OMX_CommandStateSet,OMX_StateIdle,
6467                     OMX_COMPONENT_GENERATE_EVENT);
6468         }
6469         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
6470                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6471             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6472             post_event(OMX_CommandPortEnable,
6473                     OMX_CORE_INPUT_PORT_INDEX,
6474                     OMX_COMPONENT_GENERATE_EVENT);
6475         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6476                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6477             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6478             post_event(OMX_CommandPortEnable,
6479                     OMX_CORE_OUTPUT_PORT_INDEX,
6480                     OMX_COMPONENT_GENERATE_EVENT);
6481         }
6482     }
6483     return error;
6484 }
6485 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)6486 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6487         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6488 {
6489     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
6490         if (m_inp_heap_ptr[bufferindex].pBuffer)
6491             free(m_inp_heap_ptr[bufferindex].pBuffer);
6492         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
6493     }
6494     if (pmem_bufferHdr)
6495         free_input_buffer(pmem_bufferHdr);
6496     return OMX_ErrorNone;
6497 }
6498 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6499 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6500 {
6501     unsigned int index = 0;
6502     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6503         return OMX_ErrorBadParameter;
6504     }
6505 
6506     index = bufferHdr - m_inp_mem_ptr;
6507     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6508 
6509     bufferHdr->pInputPortPrivate = NULL;
6510 
6511     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6512         DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6513         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6514             struct vdec_setbuffer_cmd setbuffers;
6515             setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
6516             memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
6517                     sizeof (vdec_bufferpayload));
6518             if (!secure_mode) {
6519                 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
6520                         drv_ctx.ptr_inputbuffer[index].pmem_fd);
6521                 DEBUG_PRINT_LOW("unmap the input buffer size=%u  address = %p",
6522                         (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
6523                         drv_ctx.ptr_inputbuffer[index].bufferaddr);
6524                 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6525                         drv_ctx.ptr_inputbuffer[index].mmaped_size);
6526             }
6527 
6528             if (allocate_native_handle){
6529                 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6530                 native_handle_close(nh);
6531                 native_handle_delete(nh);
6532             } else {
6533                 // Close fd for non-secure and secure non-native-handle case
6534                 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6535             }
6536             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6537 
6538             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6539                 free(m_desc_buffer_ptr[index].buf_addr);
6540                 m_desc_buffer_ptr[index].buf_addr = NULL;
6541                 m_desc_buffer_ptr[index].desc_data_size = 0;
6542             }
6543 #ifdef USE_ION
6544             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6545 #endif
6546             m_in_alloc_cnt--;
6547         }
6548     }
6549 
6550     return OMX_ErrorNone;
6551 }
6552 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6553 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6554 {
6555     unsigned int index = 0;
6556 
6557     if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6558         return OMX_ErrorBadParameter;
6559     }
6560 
6561     index = bufferHdr - m_out_mem_ptr;
6562     DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
6563 
6564     if (index < drv_ctx.op_buf.actualcount
6565             && drv_ctx.ptr_outputbuffer) {
6566         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6567                 drv_ctx.ptr_outputbuffer[index].bufferaddr);
6568 
6569         struct vdec_setbuffer_cmd setbuffers;
6570         setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6571         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
6572                 sizeof (vdec_bufferpayload));
6573 
6574         if (!dynamic_buf_mode) {
6575             if (streaming[CAPTURE_PORT] &&
6576                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6577                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6578                     DEBUG_PRINT_ERROR("STREAMOFF Failed");
6579                 } else {
6580                     DEBUG_PRINT_LOW("STREAMOFF Successful");
6581                 }
6582             }
6583 #ifdef _ANDROID_
6584             if (m_enable_android_native_buffers) {
6585                 if (!secure_mode) {
6586                     if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6587                         munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6588                                 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6589                     }
6590                 }
6591                 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6592             } else {
6593 #endif
6594                 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0
6595                     && !ouput_egl_buffers && !m_use_output_pmem) {
6596                     if (drv_ctx.op_buf_map_info[index].free_buffer) {
6597                         if (!secure_mode) {
6598                             DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
6599                                     drv_ctx.ptr_outputbuffer[0].pmem_fd);
6600                             DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
6601                                     (unsigned int)drv_ctx.op_buf_map_info[index].map_size,
6602                                     drv_ctx.op_buf_map_info[index].base_address);
6603                             munmap (drv_ctx.op_buf_map_info[index].base_address,
6604                                     drv_ctx.op_buf_map_info[index].map_size);
6605                         }
6606                         close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
6607                         drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6608 #ifdef USE_ION
6609                         free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
6610 #endif
6611                     } else {
6612                         drv_ctx.op_buf_ion_info[index].ion_device_fd = -1;
6613                         drv_ctx.op_buf_ion_info[index].ion_alloc_data.handle = 0;
6614                         drv_ctx.op_buf_ion_info[index].fd_ion_data.fd = -1;
6615                     }
6616                     drv_ctx.op_buf_map_info[index].free_buffer = false;
6617                     drv_ctx.op_buf_map_info[index].base_address = NULL;
6618                     drv_ctx.op_buf_map_info[index].map_size = 0;
6619                     drv_ctx.op_buf_map_info[index].offset = 0;
6620                 }
6621 #ifdef _ANDROID_
6622             }
6623 #endif
6624         } //!dynamic_buf_mode
6625         if (release_output_done()) {
6626             free_extradata();
6627         }
6628     }
6629 
6630     return OMX_ErrorNone;
6631 
6632 }
6633 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6634 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
6635         OMX_BUFFERHEADERTYPE **bufferHdr,
6636         OMX_U32              port,
6637         OMX_PTR              appData,
6638         OMX_U32              bytes)
6639 {
6640     OMX_BUFFERHEADERTYPE *input = NULL;
6641     unsigned char *buf_addr = NULL;
6642     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6643     unsigned   i = 0;
6644 
6645     /* Sanity Check*/
6646     if (bufferHdr == NULL) {
6647         return OMX_ErrorBadParameter;
6648     }
6649 
6650     if (m_inp_heap_ptr == NULL) {
6651         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6652                  calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6653                          drv_ctx.ip_buf.actualcount);
6654         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6655                   calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6656                           drv_ctx.ip_buf.actualcount);
6657 
6658         if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6659             DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6660             return OMX_ErrorInsufficientResources;
6661         }
6662     }
6663 
6664     /*Find a Free index*/
6665     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6666         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6667             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6668             break;
6669         }
6670     }
6671 
6672     if (i < drv_ctx.ip_buf.actualcount) {
6673         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6674 
6675         if (buf_addr == NULL) {
6676             return OMX_ErrorInsufficientResources;
6677         }
6678 
6679         *bufferHdr = (m_inp_heap_ptr + i);
6680         input = *bufferHdr;
6681         BITMASK_SET(&m_heap_inp_bm_count,i);
6682 
6683         input->pBuffer           = (OMX_U8 *)buf_addr;
6684         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6685         input->nVersion.nVersion = OMX_SPEC_VERSION;
6686         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6687         input->pAppPrivate       = appData;
6688         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6689         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6690         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6691         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6692         /*Add the Buffers to freeq*/
6693         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6694                     (unsigned)NULL, (unsigned)NULL)) {
6695             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6696             return OMX_ErrorInsufficientResources;
6697         }
6698     } else {
6699         return OMX_ErrorBadParameter;
6700     }
6701 
6702     return eRet;
6703 
6704 }
6705 
6706 
6707 /* ======================================================================
6708    FUNCTION
6709    omx_vdec::AllocateInputBuffer
6710 
6711    DESCRIPTION
6712    Helper function for allocate buffer in the input pin
6713 
6714    PARAMETERS
6715    None.
6716 
6717    RETURN VALUE
6718    true/false
6719 
6720    ========================================================================== */
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)6721 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6722         OMX_IN OMX_HANDLETYPE            hComp,
6723         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6724         OMX_IN OMX_U32                   port,
6725         OMX_IN OMX_PTR                   appData,
6726         OMX_IN OMX_U32                   bytes)
6727 {
6728     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6729     struct vdec_setbuffer_cmd setbuffers;
6730     OMX_BUFFERHEADERTYPE *input = NULL;
6731     unsigned   i = 0;
6732     unsigned char *buf_addr = NULL;
6733     int pmem_fd = -1, ret = 0;
6734     unsigned int align_size = 0;
6735 
6736     (void) hComp;
6737     (void) port;
6738 
6739 
6740     if (bytes != drv_ctx.ip_buf.buffer_size) {
6741         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6742                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6743         return OMX_ErrorBadParameter;
6744     }
6745 
6746     if (!m_inp_mem_ptr) {
6747         struct v4l2_requestbuffers bufreq;
6748         bufreq.memory = V4L2_MEMORY_USERPTR;
6749         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6750         bufreq.count = drv_ctx.ip_buf.actualcount;
6751         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6752         if (ret) {
6753             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %s", strerror(errno));
6754             /*TODO: How to handle this case */
6755             eRet = OMX_ErrorInsufficientResources;
6756         } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6757             DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6758                 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6759             eRet = OMX_ErrorInsufficientResources;
6760         }
6761 
6762         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6763                 drv_ctx.ip_buf.actualcount,
6764                 (unsigned int)drv_ctx.ip_buf.buffer_size);
6765 
6766         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6767                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6768 
6769         if (m_inp_mem_ptr == NULL) {
6770             return OMX_ErrorInsufficientResources;
6771         }
6772 
6773         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6774                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6775 
6776         if (drv_ctx.ptr_inputbuffer == NULL) {
6777             return OMX_ErrorInsufficientResources;
6778         }
6779 #ifdef USE_ION
6780         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6781                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6782 
6783         if (drv_ctx.ip_buf_ion_info == NULL) {
6784             return OMX_ErrorInsufficientResources;
6785         }
6786 #endif
6787 
6788         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6789             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6790 #ifdef USE_ION
6791             drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6792 #endif
6793         }
6794     }
6795 
6796     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6797         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6798             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6799             break;
6800         }
6801     }
6802 
6803     if (i < drv_ctx.ip_buf.actualcount) {
6804         struct v4l2_buffer buf;
6805         struct v4l2_plane plane;
6806         int rc;
6807         DEBUG_PRINT_LOW("Allocate input Buffer");
6808 #ifdef USE_ION
6809         align_size = drv_ctx.ip_buf.buffer_size + 512;
6810         align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6811         drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6812                 align_size, drv_ctx.op_buf.alignment,
6813                 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6814                 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6815                 SECURE_FLAGS_INPUT_BUFFER : 0);
6816         if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6817             return OMX_ErrorInsufficientResources;
6818         }
6819         pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6820 #else
6821         pmem_fd = open (MEM_DEVICE,O_RDWR);
6822 
6823         if (pmem_fd < 0) {
6824             DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6825             return OMX_ErrorInsufficientResources;
6826         }
6827 
6828         if (pmem_fd == 0) {
6829             pmem_fd = open (MEM_DEVICE,O_RDWR);
6830 
6831             if (pmem_fd < 0) {
6832                 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6833                 return OMX_ErrorInsufficientResources;
6834             }
6835         }
6836 
6837         if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6838                     drv_ctx.ip_buf.alignment)) {
6839             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6840             close(pmem_fd);
6841             return OMX_ErrorInsufficientResources;
6842         }
6843 #endif
6844         if (!secure_mode) {
6845             buf_addr = (unsigned char *)mmap(NULL,
6846                     drv_ctx.ip_buf.buffer_size,
6847                     PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6848 
6849             if (buf_addr == MAP_FAILED) {
6850                 close(pmem_fd);
6851 #ifdef USE_ION
6852                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6853 #endif
6854                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6855                 return OMX_ErrorInsufficientResources;
6856             }
6857         }
6858         *bufferHdr = (m_inp_mem_ptr + i);
6859         if (secure_mode)
6860             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6861         else
6862             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6863         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6864         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6865         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6866         drv_ctx.ptr_inputbuffer [i].offset = 0;
6867 
6868 
6869         buf.index = i;
6870         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6871         buf.memory = V4L2_MEMORY_USERPTR;
6872         plane.bytesused = 0;
6873         plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6874         plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6875         plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6876         plane.reserved[1] = 0;
6877         plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6878         buf.m.planes = &plane;
6879         buf.length = 1;
6880 
6881         DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6882                 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6883 
6884         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6885 
6886         if (rc) {
6887             DEBUG_PRINT_ERROR("Failed to prepare bufs");
6888             /*TODO: How to handle this case */
6889             return OMX_ErrorInsufficientResources;
6890         }
6891 
6892         input = *bufferHdr;
6893         BITMASK_SET(&m_inp_bm_count,i);
6894         DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6895         if (allocate_native_handle) {
6896             native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6897             if (!nh) {
6898                 DEBUG_PRINT_ERROR("Native handle create failed");
6899                 return OMX_ErrorInsufficientResources;
6900             }
6901             nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6902             input->pBuffer = (OMX_U8 *)nh;
6903         } else if (secure_mode || m_input_pass_buffer_fd) {
6904             /*Legacy method, pass ion fd stashed directly in pBuffer*/
6905             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6906         } else {
6907             input->pBuffer           = (OMX_U8 *)buf_addr;
6908         }
6909         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6910         input->nVersion.nVersion = OMX_SPEC_VERSION;
6911         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6912         input->pAppPrivate       = appData;
6913         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6914         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6915 
6916         if (drv_ctx.disable_dmx) {
6917             eRet = allocate_desc_buffer(i);
6918         }
6919     } else {
6920         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6921         eRet = OMX_ErrorInsufficientResources;
6922     }
6923     return eRet;
6924 }
6925 
6926 
6927 /* ======================================================================
6928    FUNCTION
6929    omx_vdec::AllocateOutputBuffer
6930 
6931    DESCRIPTION
6932    Helper fn for AllocateBuffer in the output pin
6933 
6934    PARAMETERS
6935    <TBD>.
6936 
6937    RETURN VALUE
6938    OMX Error None if everything went well.
6939 
6940    ========================================================================== */
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)6941 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6942         OMX_IN OMX_HANDLETYPE            hComp,
6943         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6944         OMX_IN OMX_U32                   port,
6945         OMX_IN OMX_PTR                   appData,
6946         OMX_IN OMX_U32                   bytes)
6947 {
6948     (void)hComp;
6949     (void)port;
6950     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6951     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6952     unsigned                         i= 0; // Temporary counter
6953     struct vdec_setbuffer_cmd setbuffers;
6954     int extra_idx = 0;
6955 #ifdef USE_ION
6956     int ion_device_fd =-1;
6957     struct ion_allocation_data ion_alloc_data;
6958     struct ion_fd_data fd_ion_data;
6959 #endif
6960     if (!m_out_mem_ptr) {
6961         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6962                 drv_ctx.op_buf.actualcount,
6963                 (unsigned int)drv_ctx.op_buf.buffer_size);
6964         int nBufHdrSize        = 0;
6965         int nPlatformEntrySize = 0;
6966         int nPlatformListSize  = 0;
6967         int nPMEMInfoSize = 0;
6968 
6969         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6970         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6971         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6972 
6973         DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6974                 drv_ctx.op_buf.actualcount);
6975         nBufHdrSize        = drv_ctx.op_buf.actualcount *
6976             sizeof(OMX_BUFFERHEADERTYPE);
6977 
6978         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6979             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6980         nPlatformListSize  = drv_ctx.op_buf.actualcount *
6981             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6982         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6983             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6984 
6985         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6986                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6987                 nPMEMInfoSize,
6988                 nPlatformListSize);
6989         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6990                 drv_ctx.op_buf.actualcount);
6991         unsigned char *pmem_baseaddress_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {NULL};
6992         int pmem_fd[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {-1};
6993         int alloc_size[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {0};
6994         static const int block_max_size = 128 * 1024 * 1024;
6995         unsigned int block_buf_count = block_max_size / drv_ctx.op_buf.buffer_size;
6996         unsigned int last_block_buf_count = 0, block_count = 1;
6997         if (drv_ctx.op_buf.actualcount <= block_buf_count) {
6998             block_buf_count = drv_ctx.op_buf.actualcount;
6999         } else {
7000             last_block_buf_count = drv_ctx.op_buf.actualcount % block_buf_count;
7001             block_count = (drv_ctx.op_buf.actualcount + block_buf_count - 1) / block_buf_count;
7002         }
7003         unsigned int idx = 0;
7004         DEBUG_PRINT_LOW("block_count = %d block_buf_count = %d last_block_buf_count = %d",
7005             block_count, block_buf_count, last_block_buf_count);
7006 #ifdef USE_ION
7007         struct vdec_ion op_buf_ion_info_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS];
7008         int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
7009         for (; idx < block_count; idx++) {
7010             int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
7011                 last_block_buf_count : block_buf_count;
7012             alloc_size[idx] = drv_ctx.op_buf.buffer_size * cnt;
7013             // Allocate output buffers as cached to improve performance of software-reading
7014             // of the YUVs. Output buffers are cache-invalidated in driver.
7015             // If color-conversion is involved, Only the C2D output buffers are cached, no
7016             // need to cache the decoder's output buffers
7017             op_buf_ion_info_temp[idx].ion_device_fd = alloc_map_ion_memory(
7018                     alloc_size[idx],
7019                     secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
7020                     &op_buf_ion_info_temp[idx].ion_alloc_data, &op_buf_ion_info_temp[idx].fd_ion_data,
7021                     (secure_mode && !secure_scaling_to_non_secure_opb) ?
7022                     SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
7023             if (op_buf_ion_info_temp[idx].ion_device_fd < 0) {
7024                 DEBUG_PRINT_LOW("Failed to allocate chunk %ul size = %d", idx, alloc_size[idx]);
7025                 break;
7026             }
7027             pmem_fd[idx] = op_buf_ion_info_temp[idx].fd_ion_data.fd;
7028             DEBUG_PRINT_LOW("Allocated chunk %ul fd = %ul size = %d", idx, pmem_fd[idx], alloc_size[idx]);
7029         }
7030         if (idx != block_count) {
7031             for (OMX_U32 i = 0; i < idx; i++) {
7032                 close(pmem_fd[i]);
7033                 free_ion_memory(&op_buf_ion_info_temp[i]);
7034             }
7035             return OMX_ErrorInsufficientResources;
7036         }
7037 
7038 #else
7039         for (idx = 0; idx < block_count; idx++) {
7040             pmem_fd[idx] = open (MEM_DEVICE,O_RDWR);
7041 
7042             if (pmem_fd[idx] < 0) {
7043                 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
7044                         drv_ctx.op_buf.buffer_size);
7045                 break;
7046             }
7047             int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
7048                 last_block_buf_count : block_buf_count;
7049             if (!align_pmem_buffers(pmem_fd[idx], drv_ctx.op_buf.buffer_size * cnt,
7050                         drv_ctx.op_buf.alignment)) {
7051                 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
7052                 close(pmem_fd[idx]);
7053                 break;
7054             }
7055         }
7056         if (idx != block_count) {
7057             for (i = 0; i < idx; i++) {
7058                 close(pmem_fd[i]);
7059             }
7060             return OMX_ErrorInsufficientResources;
7061         }
7062 #endif
7063         if (!secure_mode) {
7064             idx = 0;
7065             for (; idx < block_count; idx++) {
7066                 pmem_baseaddress_temp[idx] = (unsigned char *)mmap(NULL,
7067                         alloc_size[idx],
7068                         PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd[idx], 0);
7069 
7070                 if (pmem_baseaddress_temp[idx] == MAP_FAILED) {
7071                     DEBUG_PRINT_ERROR("MMAP failed for Size %u for fd = %d",
7072                             (unsigned int)alloc_size[idx], pmem_fd[idx]);
7073                     close(pmem_fd[idx]);
7074 #ifdef USE_ION
7075                     free_ion_memory(&op_buf_ion_info_temp[idx]);
7076 #endif
7077                     break;
7078                 }
7079             }
7080             if (idx != block_count) {
7081                 for (i = 0; i < idx; i++) {
7082                     munmap(pmem_baseaddress_temp[idx], alloc_size[idx]);
7083                     close(pmem_fd[i]);
7084 #ifdef USE_ION
7085                     free_ion_memory(&op_buf_ion_info_temp[i]);
7086 #endif
7087                 }
7088                 return OMX_ErrorInsufficientResources;
7089             }
7090         }
7091         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
7092         // Alloc mem for platform specific info
7093         char *pPtr=NULL;
7094         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7095                 nPMEMInfoSize,1);
7096         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
7097                        calloc (sizeof(struct vdec_bufferpayload),
7098                                drv_ctx.op_buf.actualcount);
7099         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
7100                      calloc (sizeof (struct vdec_output_frameinfo),
7101                              drv_ctx.op_buf.actualcount);
7102         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
7103             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
7104             return OMX_ErrorInsufficientResources;
7105         }
7106 
7107 #ifdef USE_ION
7108         drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
7109                       calloc (sizeof(struct vdec_ion),
7110                               drv_ctx.op_buf.actualcount);
7111         if (!drv_ctx.op_buf_ion_info) {
7112             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
7113             return OMX_ErrorInsufficientResources;
7114         }
7115 #endif
7116         drv_ctx.op_buf_map_info = (struct vdec_ion_map_info *)\
7117                       calloc (sizeof(struct vdec_ion_map_info),
7118                               drv_ctx.op_buf.actualcount);
7119         if (!drv_ctx.op_buf_map_info) {
7120             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_map_info");
7121             return OMX_ErrorInsufficientResources;
7122         }
7123 
7124         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
7125                 && drv_ctx.ptr_respbuffer) {
7126             drv_ctx.ptr_outputbuffer[0].mmaped_size =
7127                 (drv_ctx.op_buf.buffer_size *
7128                  drv_ctx.op_buf.actualcount);
7129             bufHdr          =  m_out_mem_ptr;
7130             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7131             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7132                 (((char *) m_platform_list)  + nPlatformListSize);
7133             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7134                 (((char *) m_platform_entry) + nPlatformEntrySize);
7135             pPlatformList   = m_platform_list;
7136             pPlatformEntry  = m_platform_entry;
7137             pPMEMInfo       = m_pmem_info;
7138 
7139             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
7140 
7141             // Settting the entire storage nicely
7142             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
7143             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
7144             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
7145                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
7146                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
7147                 // Set the values when we determine the right HxW param
7148                 bufHdr->nAllocLen          = bytes;
7149                 bufHdr->nFilledLen         = 0;
7150                 bufHdr->pAppPrivate        = appData;
7151                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
7152                 // Platform specific PMEM Information
7153                 // Initialize the Platform Entry
7154                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
7155                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7156                 pPlatformEntry->entry      = pPMEMInfo;
7157                 // Initialize the Platform List
7158                 pPlatformList->nEntries    = 1;
7159                 pPlatformList->entryList   = pPlatformEntry;
7160                 // Keep pBuffer NULL till vdec is opened
7161                 bufHdr->pBuffer            = NULL;
7162                 bufHdr->nOffset            = 0;
7163 
7164                 pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
7165                 pPMEMInfo->pmem_fd = -1;
7166                 bufHdr->pPlatformPrivate = pPlatformList;
7167 
7168                 int block_idx = i / block_buf_count;
7169                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd[block_idx];
7170                 m_pmem_info[i].pmem_fd = pmem_fd[block_idx];
7171 #ifdef USE_ION
7172                 drv_ctx.op_buf_ion_info[i].ion_device_fd = op_buf_ion_info_temp[block_idx].ion_device_fd;
7173                 drv_ctx.op_buf_ion_info[i].ion_alloc_data = op_buf_ion_info_temp[block_idx].ion_alloc_data;
7174                 drv_ctx.op_buf_ion_info[i].fd_ion_data = op_buf_ion_info_temp[block_idx].fd_ion_data;
7175 #endif
7176                 drv_ctx.op_buf_map_info[i].free_buffer = !(i % block_buf_count);
7177                 drv_ctx.op_buf_map_info[i].base_address = pmem_baseaddress_temp[block_idx];
7178                 drv_ctx.op_buf_map_info[i].map_size = alloc_size[block_idx];
7179                 drv_ctx.op_buf_map_info[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7180 
7181                 /*Create a mapping between buffers*/
7182                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7183                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
7184                                     &drv_ctx.ptr_outputbuffer[i];
7185                 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7186                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
7187                     pmem_baseaddress_temp[block_idx] + (drv_ctx.op_buf.buffer_size * (i % block_buf_count));
7188                 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
7189                 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
7190                 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
7191 
7192                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
7193                         pmem_fd[block_idx], (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
7194                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
7195                 // Move the buffer and buffer header pointers
7196                 bufHdr++;
7197                 pPMEMInfo++;
7198                 pPlatformEntry++;
7199                 pPlatformList++;
7200             }
7201         } else {
7202             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7203                     m_out_mem_ptr, pPtr);
7204             if (m_out_mem_ptr) {
7205                 free(m_out_mem_ptr);
7206                 m_out_mem_ptr = NULL;
7207             }
7208             if (pPtr) {
7209                 free(pPtr);
7210                 pPtr = NULL;
7211             }
7212             if (drv_ctx.ptr_outputbuffer) {
7213                 free(drv_ctx.ptr_outputbuffer);
7214                 drv_ctx.ptr_outputbuffer = NULL;
7215             }
7216             if (drv_ctx.ptr_respbuffer) {
7217                 free(drv_ctx.ptr_respbuffer);
7218                 drv_ctx.ptr_respbuffer = NULL;
7219             }
7220 #ifdef USE_ION
7221             if (drv_ctx.op_buf_ion_info) {
7222                 DEBUG_PRINT_LOW("Free o/p ion context");
7223                 free(drv_ctx.op_buf_ion_info);
7224                 drv_ctx.op_buf_ion_info = NULL;
7225             }
7226 #endif
7227             free(drv_ctx.op_buf_map_info);
7228             drv_ctx.op_buf_map_info = NULL;
7229            eRet =  OMX_ErrorInsufficientResources;
7230         }
7231         if (eRet == OMX_ErrorNone)
7232             eRet = allocate_extradata();
7233     }
7234 
7235     for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
7236         if (BITMASK_ABSENT(&m_out_bm_count,i)) {
7237             DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
7238             break;
7239         }
7240     }
7241 
7242     if (eRet == OMX_ErrorNone) {
7243         if (i < drv_ctx.op_buf.actualcount) {
7244             struct v4l2_buffer buf;
7245             struct v4l2_plane plane[VIDEO_MAX_PLANES];
7246             int rc;
7247             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
7248 
7249             drv_ctx.ptr_outputbuffer[i].buffer_len =
7250                 drv_ctx.op_buf.buffer_size;
7251 
7252             *bufferHdr = (m_out_mem_ptr + i );
7253             if (secure_mode) {
7254 #ifdef USE_ION
7255                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
7256                     (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7257 #else
7258                 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
7259 #endif
7260             }
7261             drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
7262 
7263             buf.index = i;
7264             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7265             buf.memory = V4L2_MEMORY_USERPTR;
7266             plane[0].length = drv_ctx.op_buf.buffer_size;
7267             plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
7268                 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
7269 #ifdef USE_ION
7270             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7271 #endif
7272             plane[0].reserved[1] = drv_ctx.op_buf_map_info[i].offset;
7273             plane[0].data_offset = 0;
7274             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7275             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7276                 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7277                 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
7278 #ifdef USE_ION
7279                 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7280 #endif
7281                 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
7282                 plane[extra_idx].data_offset = 0;
7283             } else if (extra_idx >= VIDEO_MAX_PLANES) {
7284                 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
7285                 return OMX_ErrorBadParameter;
7286             }
7287             buf.m.planes = plane;
7288             buf.length = drv_ctx.num_planes;
7289             DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
7290             rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
7291             if (rc) {
7292                 /*TODO: How to handle this case */
7293                 return OMX_ErrorInsufficientResources;
7294             }
7295 
7296             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
7297                 enum v4l2_buf_type buf_type;
7298                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7299                 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7300                 if (rc) {
7301                     return OMX_ErrorInsufficientResources;
7302                 } else {
7303                     streaming[CAPTURE_PORT] = true;
7304                     DEBUG_PRINT_LOW("STREAMON Successful");
7305                 }
7306 
7307                 DEBUG_PRINT_HIGH("Enabling Turbo mode");
7308                 request_perf_level(VIDC_TURBO);
7309             }
7310 
7311             (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
7312             (*bufferHdr)->pAppPrivate = appData;
7313             BITMASK_SET(&m_out_bm_count,i);
7314         } else {
7315             DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
7316             eRet = OMX_ErrorInsufficientResources;
7317         }
7318     }
7319 
7320     return eRet;
7321 }
7322 
7323 
7324 // AllocateBuffer  -- API Call
7325 /* ======================================================================
7326    FUNCTION
7327    omx_vdec::AllocateBuffer
7328 
7329    DESCRIPTION
7330    Returns zero if all the buffers released..
7331 
7332    PARAMETERS
7333    None.
7334 
7335    RETURN VALUE
7336    true/false
7337 
7338    ========================================================================== */
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)7339 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
7340         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7341         OMX_IN OMX_U32                        port,
7342         OMX_IN OMX_PTR                     appData,
7343         OMX_IN OMX_U32                       bytes)
7344 {
7345     unsigned i = 0;
7346     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
7347 
7348     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
7349     if (m_state == OMX_StateInvalid) {
7350         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
7351         return OMX_ErrorInvalidState;
7352     }
7353 
7354     if (port == OMX_CORE_INPUT_PORT_INDEX) {
7355         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
7356         // ensure that use-buffer was never called.
7357         // Mix-and-match of useBuffer and allocateBuffer is not allowed
7358         if (m_inp_mem_ptr && input_use_buffer) {
7359             DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
7360             return OMX_ErrorUndefined;
7361         }
7362         if (arbitrary_bytes) {
7363             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
7364         } else {
7365             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
7366         }
7367     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7368         if (output_use_buffer) {
7369             DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
7370             return OMX_ErrorBadParameter;
7371         }
7372         eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
7373                 appData,bytes);
7374     } else {
7375         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
7376         eRet = OMX_ErrorBadPortIndex;
7377     }
7378     DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
7379     if (eRet == OMX_ErrorNone) {
7380         if (allocate_done()) {
7381             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
7382                 // Send the callback now
7383                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
7384                 post_event(OMX_CommandStateSet,OMX_StateIdle,
7385                         OMX_COMPONENT_GENERATE_EVENT);
7386             }
7387         }
7388         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
7389             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
7390                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
7391                 post_event(OMX_CommandPortEnable,
7392                         OMX_CORE_INPUT_PORT_INDEX,
7393                         OMX_COMPONENT_GENERATE_EVENT);
7394             }
7395         }
7396         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
7397             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
7398                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
7399                 post_event(OMX_CommandPortEnable,
7400                         OMX_CORE_OUTPUT_PORT_INDEX,
7401                         OMX_COMPONENT_GENERATE_EVENT);
7402             }
7403         }
7404     }
7405     DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
7406     return eRet;
7407 }
7408 
7409 // Free Buffer - API call
7410 /* ======================================================================
7411    FUNCTION
7412    omx_vdec::FreeBuffer
7413 
7414    DESCRIPTION
7415 
7416    PARAMETERS
7417    None.
7418 
7419    RETURN VALUE
7420    true/false
7421 
7422    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7423 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7424         OMX_IN OMX_U32                 port,
7425         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7426 {
7427     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7428     unsigned int nPortIndex;
7429     (void) hComp;
7430     DEBUG_PRINT_LOW("In for decoder free_buffer");
7431 
7432     auto_lock l(buf_lock);
7433     if (m_state == OMX_StateIdle &&
7434             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7435         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
7436     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
7437             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
7438         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
7439     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
7440                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
7441             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
7442              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
7443         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
7444     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
7445         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
7446         post_event(OMX_EventError,
7447                 OMX_ErrorPortUnpopulated,
7448                 OMX_COMPONENT_GENERATE_EVENT);
7449         m_buffer_error = true;
7450         return OMX_ErrorIncorrectStateOperation;
7451     } else if (m_state != OMX_StateInvalid) {
7452         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
7453         post_event(OMX_EventError,
7454                 OMX_ErrorPortUnpopulated,
7455                 OMX_COMPONENT_GENERATE_EVENT);
7456     }
7457 
7458     if (port == OMX_CORE_INPUT_PORT_INDEX) {
7459         /*Check if arbitrary bytes*/
7460         if (!arbitrary_bytes && !input_use_buffer)
7461             nPortIndex = buffer - m_inp_mem_ptr;
7462         else
7463             nPortIndex = buffer - m_inp_heap_ptr;
7464 
7465         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
7466         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
7467                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
7468             // Clear the bit associated with it.
7469             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
7470             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
7471             if (input_use_buffer == true) {
7472 
7473                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
7474                 if (m_phdr_pmem_ptr)
7475                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
7476             } else {
7477                 if (arbitrary_bytes) {
7478                     if (m_phdr_pmem_ptr)
7479                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
7480                     else
7481                         free_input_buffer(nPortIndex,NULL);
7482                 } else
7483                     free_input_buffer(buffer);
7484             }
7485             m_inp_bPopulated = OMX_FALSE;
7486             if(release_input_done())
7487                 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
7488             /*Free the Buffer Header*/
7489             if (release_input_done()) {
7490                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
7491                 free_input_buffer_header();
7492             }
7493         } else {
7494             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
7495             eRet = OMX_ErrorBadPortIndex;
7496         }
7497 
7498         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
7499                 && release_input_done()) {
7500             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7501             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
7502             post_event(OMX_CommandPortDisable,
7503                     OMX_CORE_INPUT_PORT_INDEX,
7504                     OMX_COMPONENT_GENERATE_EVENT);
7505         }
7506     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7507         // check if the buffer is valid
7508         nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7509         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7510                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
7511             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
7512             // Clear the bit associated with it.
7513             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
7514             m_out_bPopulated = OMX_FALSE;
7515             client_buffers.free_output_buffer (buffer);
7516 
7517             if(release_output_done()) {
7518                 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
7519             }
7520             if (release_output_done()) {
7521                 free_output_buffer_header();
7522             }
7523         } else {
7524             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
7525             eRet = OMX_ErrorBadPortIndex;
7526         }
7527         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
7528                 && release_output_done()) {
7529             DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
7530 
7531             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7532             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
7533 #ifdef _ANDROID_ICS_
7534             if (m_enable_android_native_buffers) {
7535                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
7536                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7537             }
7538 #endif
7539 
7540             post_event(OMX_CommandPortDisable,
7541                     OMX_CORE_OUTPUT_PORT_INDEX,
7542                     OMX_COMPONENT_GENERATE_EVENT);
7543         }
7544     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
7545         nPortIndex = buffer - m_client_output_extradata_mem_ptr;
7546         DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
7547 
7548         BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
7549 
7550         if (release_output_extradata_done()) {
7551             free_output_extradata_buffer_header();
7552         }
7553     } else {
7554         eRet = OMX_ErrorBadPortIndex;
7555     }
7556     if ((eRet == OMX_ErrorNone) &&
7557             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7558         if (release_done()) {
7559             /*
7560              * Reset buffer requirements here to ensure setting buffer requirement
7561              * when component move to executing state from loaded state via idle.
7562              */
7563             drv_ctx.op_buf.buffer_size = 0;
7564             drv_ctx.op_buf.actualcount = 0;
7565 
7566             // Send the callback now
7567             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
7568             post_event(OMX_CommandStateSet, OMX_StateLoaded,
7569                     OMX_COMPONENT_GENERATE_EVENT);
7570             m_buffer_error = false;
7571         }
7572     }
7573     return eRet;
7574 }
7575 
7576 
7577 /* ======================================================================
7578    FUNCTION
7579    omx_vdec::EmptyThisBuffer
7580 
7581    DESCRIPTION
7582    This routine is used to push the encoded video frames to
7583    the video decoder.
7584 
7585    PARAMETERS
7586    None.
7587 
7588    RETURN VALUE
7589    OMX Error None if everything went successful.
7590 
7591    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7592 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7593         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7594 {
7595     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
7596     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
7597 
7598     if (m_state != OMX_StateExecuting &&
7599             m_state != OMX_StatePause &&
7600             m_state != OMX_StateIdle) {
7601         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
7602         return OMX_ErrorInvalidState;
7603     }
7604 
7605     if (buffer == NULL) {
7606         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
7607         return OMX_ErrorBadParameter;
7608     }
7609 
7610     if (!m_inp_bEnabled) {
7611         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7612         return OMX_ErrorIncorrectStateOperation;
7613     }
7614 
7615     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7616         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7617         return OMX_ErrorBadPortIndex;
7618     }
7619 
7620     if (perf_flag) {
7621         if (!latency) {
7622             dec_time.stop();
7623             latency = dec_time.processing_time_us();
7624             dec_time.start();
7625         }
7626     }
7627 
7628     if (arbitrary_bytes) {
7629         nBufferIndex = buffer - m_inp_heap_ptr;
7630     } else {
7631         if (input_use_buffer == true) {
7632             nBufferIndex = buffer - m_inp_heap_ptr;
7633             if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7634                 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7635                 return OMX_ErrorBadParameter;
7636             }
7637             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7638             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7639             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7640             buffer = &m_inp_mem_ptr[nBufferIndex];
7641             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7642                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7643         } else {
7644             nBufferIndex = buffer - m_inp_mem_ptr;
7645         }
7646     }
7647 
7648     if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7649         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7650         return OMX_ErrorBadParameter;
7651     }
7652 
7653     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7654         codec_config_flag = true;
7655         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7656     }
7657 
7658     /* The client should not set this when codec is in arbitrary bytes mode */
7659     if (m_input_pass_buffer_fd) {
7660         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7661     }
7662 
7663     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7664             buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7665     if (arbitrary_bytes) {
7666         post_event ((unsigned long)hComp,(unsigned long)buffer,
7667                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7668     } else {
7669         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7670     }
7671     time_stamp_dts.insert_timestamp(buffer);
7672     return OMX_ErrorNone;
7673 }
7674 
7675 /* ======================================================================
7676    FUNCTION
7677    omx_vdec::empty_this_buffer_proxy
7678 
7679    DESCRIPTION
7680    This routine is used to push the encoded video frames to
7681    the video decoder.
7682 
7683    PARAMETERS
7684    None.
7685 
7686    RETURN VALUE
7687    OMX Error None if everything went successful.
7688 
7689    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7690 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
7691         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7692 {
7693     VIDC_TRACE_NAME_HIGH("ETB");
7694     (void) hComp;
7695     int push_cnt = 0,i=0;
7696     unsigned nPortIndex = 0;
7697     OMX_ERRORTYPE ret = OMX_ErrorNone;
7698     struct vdec_input_frameinfo frameinfo;
7699     struct vdec_bufferpayload *temp_buffer;
7700     struct vdec_seqheader seq_header;
7701     bool port_setting_changed = true;
7702 
7703     /*Should we generate a Aync error event*/
7704     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7705         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7706         return OMX_ErrorBadParameter;
7707     }
7708 
7709     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7710 
7711     if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7712         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7713                 nPortIndex);
7714         return OMX_ErrorBadParameter;
7715     }
7716 
7717     pending_input_buffers++;
7718     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
7719 
7720     /* return zero length and not an EOS buffer */
7721     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7722             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7723         DEBUG_PRINT_HIGH("return zero legth buffer");
7724         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7725                 OMX_COMPONENT_GENERATE_EBD);
7726         return OMX_ErrorNone;
7727     }
7728 
7729     if (input_flush_progress == true) {
7730         DEBUG_PRINT_LOW("Flush in progress return buffer ");
7731         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7732                 OMX_COMPONENT_GENERATE_EBD);
7733         return OMX_ErrorNone;
7734     }
7735 
7736     auto_lock l(buf_lock);
7737     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7738 
7739     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7740         return OMX_ErrorBadParameter;
7741     }
7742 
7743     if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7744         DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7745         return OMX_ErrorBadParameter;
7746     }
7747     /* If its first frame, H264 codec and reject is true, then parse the nal
7748        and get the profile. Based on this, reject the clip playback */
7749     if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
7750             m_reject_avc_1080p_mp) {
7751         first_frame = 1;
7752         DEBUG_PRINT_ERROR("Parse nal to get the profile");
7753         h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
7754                 NALU_TYPE_SPS);
7755         m_profile = h264_parser->get_profile();
7756         ret = is_video_session_supported();
7757         if (ret) {
7758             post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7759             post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7760             /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7761             m_state = OMX_StateInvalid;
7762             return OMX_ErrorNone;
7763         }
7764     }
7765 
7766     VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7767     VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7768     DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7769     /*for use buffer we need to memcpy the data*/
7770     temp_buffer->buffer_len = buffer->nFilledLen;
7771 
7772     if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7773         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7774             if (arbitrary_bytes) {
7775                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7776             } else {
7777                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7778                         buffer->nFilledLen);
7779             }
7780         } else {
7781             return OMX_ErrorBadParameter;
7782         }
7783 
7784     }
7785 
7786     frameinfo.bufferaddr = temp_buffer->bufferaddr;
7787     frameinfo.client_data = (void *) buffer;
7788     frameinfo.datalen = temp_buffer->buffer_len;
7789     frameinfo.flags = 0;
7790     frameinfo.offset = buffer->nOffset;
7791     frameinfo.pmem_fd = temp_buffer->pmem_fd;
7792     frameinfo.pmem_offset = temp_buffer->offset;
7793     frameinfo.timestamp = buffer->nTimeStamp;
7794     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7795         DEBUG_PRINT_LOW("ETB: dmx enabled");
7796         if (m_demux_entries == 0) {
7797             extract_demux_addr_offsets(buffer);
7798         }
7799 
7800         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7801         handle_demux_data(buffer);
7802         frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7803         frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7804     } else {
7805         frameinfo.desc_addr = NULL;
7806         frameinfo.desc_size = 0;
7807     }
7808     if (!arbitrary_bytes) {
7809         frameinfo.flags |= buffer->nFlags;
7810     }
7811 
7812 #ifdef _ANDROID_
7813     if (m_debug_timestamp) {
7814         if (arbitrary_bytes) {
7815             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7816             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7817         } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7818             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7819             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7820         }
7821     }
7822 #endif
7823 
7824     log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7825 
7826 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7827         frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7828         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7829     }
7830 
7831     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7832         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7833         frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7834         h264_scratch.nFilledLen = 0;
7835         nal_count = 0;
7836         look_ahead_nal = false;
7837         frame_count = 0;
7838         if (m_frame_parser.mutils)
7839             m_frame_parser.mutils->initialize_frame_checking_environment();
7840         m_frame_parser.flush();
7841         h264_last_au_ts = LLONG_MAX;
7842         h264_last_au_flags = 0;
7843         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7844         m_demux_entries = 0;
7845     }
7846     struct v4l2_buffer buf;
7847     struct v4l2_plane plane;
7848     memset( (void *)&buf, 0, sizeof(buf));
7849     memset( (void *)&plane, 0, sizeof(plane));
7850     int rc;
7851     unsigned long  print_count;
7852     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7853         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7854         DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7855     }
7856     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7857     buf.index = nPortIndex;
7858     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7859     buf.memory = V4L2_MEMORY_USERPTR;
7860     plane.bytesused = temp_buffer->buffer_len;
7861     plane.length = drv_ctx.ip_buf.buffer_size;
7862     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7863         (unsigned long)temp_buffer->offset;
7864     plane.reserved[0] = temp_buffer->pmem_fd;
7865     plane.reserved[1] = temp_buffer->offset;
7866     plane.data_offset = 0;
7867     buf.m.planes = &plane;
7868     buf.length = 1;
7869     if (frameinfo.timestamp >= LLONG_MAX) {
7870         buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7871     }
7872     //assumption is that timestamp is in milliseconds
7873     buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7874     buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7875     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7876     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7877 
7878     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7879         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7880         android_atomic_inc(&m_queued_codec_config_count);
7881     }
7882 
7883     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7884     if (rc) {
7885         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7886         m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7887         return OMX_ErrorHardware;
7888     }
7889 
7890     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7891         codec_config_flag = false;
7892     }
7893     if (!streaming[OUTPUT_PORT]) {
7894         enum v4l2_buf_type buf_type;
7895         int ret,r;
7896 
7897         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7898         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7899         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7900         if (!ret) {
7901             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7902             streaming[OUTPUT_PORT] = true;
7903         } else if (errno == EBUSY) {
7904             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7905             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7906                     OMX_COMPONENT_GENERATE_EBD);
7907             return OMX_ErrorInsufficientResources;
7908         } else {
7909             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7910             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7911             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7912                     OMX_COMPONENT_GENERATE_EBD);
7913             return OMX_ErrorBadParameter;
7914         }
7915     }
7916     DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7917             frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7918             (unsigned int)frameinfo.datalen);
7919 
7920     return ret;
7921 }
7922 
7923 /* ======================================================================
7924    FUNCTION
7925    omx_vdec::FillThisBuffer
7926 
7927    DESCRIPTION
7928    IL client uses this method to release the frame buffer
7929    after displaying them.
7930 
7931    PARAMETERS
7932    None.
7933 
7934    RETURN VALUE
7935    true/false
7936 
7937    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7938 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7939         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7940 {
7941     if (m_state != OMX_StateExecuting &&
7942             m_state != OMX_StatePause &&
7943             m_state != OMX_StateIdle) {
7944         DEBUG_PRINT_ERROR("FTB in Invalid State");
7945         return OMX_ErrorInvalidState;
7946     }
7947 
7948     if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7949         DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7950         return OMX_ErrorBadPortIndex;
7951     }
7952 
7953     if (!m_out_bEnabled) {
7954         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7955         return OMX_ErrorIncorrectStateOperation;
7956     }
7957 
7958     unsigned nPortIndex = 0;
7959     if (dynamic_buf_mode) {
7960         private_handle_t *handle = NULL;
7961         struct VideoDecoderOutputMetaData *meta;
7962         unsigned int nPortIndex = 0;
7963 
7964         if (!buffer || !buffer->pBuffer) {
7965             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7966             return OMX_ErrorBadParameter;
7967         }
7968 
7969         //get the buffer type and fd info
7970         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7971         handle = (private_handle_t *)meta->pHandle;
7972         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7973 
7974         if (!handle) {
7975             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7976             return OMX_ErrorBadParameter;
7977         }
7978         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7979         nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7980         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7981             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7982             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7983             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7984 
7985            //Store private handle from GraphicBuffer
7986             native_buffer[nPortIndex].privatehandle = handle;
7987             native_buffer[nPortIndex].nativehandle = handle;
7988         } else {
7989             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7990             return OMX_ErrorBadParameter;
7991         }
7992 
7993         //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7994         //this with a more sane size so that we don't compensate in rest of code
7995         //We'll restore this size later on, so that it's transparent to client
7996         buffer->nFilledLen = 0;
7997         buffer->nAllocLen = handle->size;
7998 
7999         if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
8000             m_is_display_session = true;
8001         } else {
8002             m_is_display_session = false;
8003         }
8004         DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
8005 
8006         drv_ctx.op_buf.buffer_size = handle->size;
8007     }
8008 
8009     nPortIndex = buffer - client_buffers.get_il_buf_hdr();
8010     if (buffer == NULL ||
8011             (nPortIndex >= drv_ctx.op_buf.actualcount)) {
8012         DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
8013             nPortIndex, drv_ctx.op_buf.actualcount);
8014         return OMX_ErrorBadParameter;
8015     }
8016 
8017     DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8018     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
8019     return OMX_ErrorNone;
8020 }
8021 /* ======================================================================
8022    FUNCTION
8023    omx_vdec::fill_this_buffer_proxy
8024 
8025    DESCRIPTION
8026    IL client uses this method to release the frame buffer
8027    after displaying them.
8028 
8029    PARAMETERS
8030    None.
8031 
8032    RETURN VALUE
8033    true/false
8034 
8035    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)8036 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
8037         OMX_IN OMX_HANDLETYPE        hComp,
8038         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
8039 {
8040     VIDC_TRACE_NAME_HIGH("FTB");
8041     OMX_ERRORTYPE nRet = OMX_ErrorNone;
8042     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
8043     unsigned nPortIndex = 0;
8044     struct vdec_fillbuffer_cmd fillbuffer;
8045     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
8046     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
8047 
8048     auto_lock l(buf_lock);
8049     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8050 
8051     if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
8052         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
8053             nPortIndex, drv_ctx.op_buf.actualcount);
8054         return OMX_ErrorBadParameter;
8055     }
8056 
8057     if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
8058         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
8059         return OMX_ErrorBadParameter;
8060     }
8061     DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
8062             bufferAdd, bufferAdd->pBuffer);
8063     /*Return back the output buffer to client*/
8064     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
8065         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
8066         buffer->nFilledLen = 0;
8067         m_cb.FillBufferDone (hComp,m_app_data,buffer);
8068         return OMX_ErrorNone;
8069     }
8070 
8071     if (dynamic_buf_mode) {
8072         drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
8073         drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
8074         buf_ref_add(nPortIndex);
8075         drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
8076     }
8077 
8078     pending_output_buffers++;
8079     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8080     buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
8081     if (!buffer) {
8082        DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
8083        return OMX_ErrorBadParameter;
8084     }
8085     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
8086     if (ptr_respbuffer) {
8087         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
8088     }
8089 
8090     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
8091         DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
8092         buffer->nFilledLen = 0;
8093         m_cb.FillBufferDone (hComp,m_app_data,buffer);
8094         pending_output_buffers--;
8095         VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8096         return OMX_ErrorBadParameter;
8097     }
8098 
8099     int rc = 0;
8100     struct v4l2_buffer buf;
8101     struct v4l2_plane plane[VIDEO_MAX_PLANES];
8102     memset( (void *)&buf, 0, sizeof(buf));
8103     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
8104     unsigned int extra_idx = 0;
8105 
8106     buf.index = nPortIndex;
8107     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8108     buf.memory = V4L2_MEMORY_USERPTR;
8109     plane[0].bytesused = buffer->nFilledLen;
8110     plane[0].length = buffer->nAllocLen;
8111     plane[0].m.userptr =
8112         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
8113         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
8114     plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
8115     plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
8116     plane[0].data_offset = 0;
8117     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
8118     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8119         plane[extra_idx].bytesused = 0;
8120         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
8121         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
8122 #ifdef USE_ION
8123         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
8124 #endif
8125         plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
8126         plane[extra_idx].data_offset = 0;
8127     } else if (extra_idx >= VIDEO_MAX_PLANES) {
8128         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8129         return OMX_ErrorBadParameter;
8130     }
8131     buf.m.planes = plane;
8132     buf.length = drv_ctx.num_planes;
8133     DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8134              plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
8135 
8136     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
8137     if (rc) {
8138         buffer->nFilledLen = 0;
8139         DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
8140         m_cb.FillBufferDone(hComp, m_app_data, buffer);
8141         return OMX_ErrorHardware;
8142     }
8143 
8144     return OMX_ErrorNone;
8145 }
8146 
8147 /* ======================================================================
8148    FUNCTION
8149    omx_vdec::SetCallbacks
8150 
8151    DESCRIPTION
8152    Set the callbacks.
8153 
8154    PARAMETERS
8155    None.
8156 
8157    RETURN VALUE
8158    OMX Error None if everything successful.
8159 
8160    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)8161 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
8162         OMX_IN OMX_CALLBACKTYPE* callbacks,
8163         OMX_IN OMX_PTR             appData)
8164 {
8165     (void) hComp;
8166     m_cb       = *callbacks;
8167     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
8168             m_cb.EventHandler,m_cb.FillBufferDone);
8169     m_app_data =    appData;
8170     return OMX_ErrorNotImplemented;
8171 }
8172 
8173 /* ======================================================================
8174    FUNCTION
8175    omx_vdec::ComponentDeInit
8176 
8177    DESCRIPTION
8178    Destroys the component and release memory allocated to the heap.
8179 
8180    PARAMETERS
8181    <TBD>.
8182 
8183    RETURN VALUE
8184    OMX Error None if everything successful.
8185 
8186    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)8187 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
8188 {
8189    (void) hComp;
8190 
8191     unsigned i = 0;
8192     if (OMX_StateLoaded != m_state) {
8193         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
8194                 m_state);
8195         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
8196     } else {
8197         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
8198     }
8199 
8200     /*Check if the output buffers have to be cleaned up*/
8201     if (m_out_mem_ptr) {
8202         DEBUG_PRINT_LOW("Freeing the Output Memory");
8203         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
8204             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
8205                 BITMASK_CLEAR(&m_out_bm_count, i);
8206                 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
8207             }
8208 
8209             if (release_output_done()) {
8210                 break;
8211             }
8212         }
8213 #ifdef _ANDROID_ICS_
8214         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
8215 #endif
8216     }
8217 
8218     /*Check if the input buffers have to be cleaned up*/
8219     if (m_inp_mem_ptr || m_inp_heap_ptr) {
8220         DEBUG_PRINT_LOW("Freeing the Input Memory");
8221         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
8222 
8223             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
8224                 BITMASK_CLEAR(&m_inp_bm_count, i);
8225                 if (m_inp_mem_ptr)
8226                     free_input_buffer (i,&m_inp_mem_ptr[i]);
8227                 else
8228                     free_input_buffer (i,NULL);
8229             }
8230 
8231             if (release_input_done()) {
8232                 break;
8233             }
8234        }
8235     }
8236     free_input_buffer_header();
8237     free_output_buffer_header();
8238     if (h264_scratch.pBuffer) {
8239         free(h264_scratch.pBuffer);
8240         h264_scratch.pBuffer = NULL;
8241     }
8242 
8243     if (h264_parser) {
8244         delete h264_parser;
8245         h264_parser = NULL;
8246     }
8247 
8248     if (m_frame_parser.mutils) {
8249         DEBUG_PRINT_LOW("Free utils parser");
8250         delete (m_frame_parser.mutils);
8251         m_frame_parser.mutils = NULL;
8252     }
8253 
8254     if (m_platform_list) {
8255         free(m_platform_list);
8256         m_platform_list = NULL;
8257     }
8258     if (m_vendor_config.pData) {
8259         free(m_vendor_config.pData);
8260         m_vendor_config.pData = NULL;
8261     }
8262 
8263     // Reset counters in mesg queues
8264     m_ftb_q.m_size=0;
8265     m_cmd_q.m_size=0;
8266     m_etb_q.m_size=0;
8267     m_ftb_q.m_read = m_ftb_q.m_write =0;
8268     m_cmd_q.m_read = m_cmd_q.m_write =0;
8269     m_etb_q.m_read = m_etb_q.m_write =0;
8270 #ifdef _ANDROID_
8271     if (m_debug_timestamp) {
8272         m_timestamp_list.reset_ts_list();
8273     }
8274 #endif
8275 
8276     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
8277     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
8278     // NULL);
8279     DEBUG_PRINT_HIGH("Close the driver instance");
8280 
8281     if (m_debug.infile) {
8282         fclose(m_debug.infile);
8283         m_debug.infile = NULL;
8284     }
8285     if (m_debug.outfile) {
8286         fclose(m_debug.outfile);
8287         m_debug.outfile = NULL;
8288     }
8289     if (m_debug.out_ymeta_file) {
8290         fclose(m_debug.out_ymeta_file);
8291         m_debug.out_ymeta_file = NULL;
8292     }
8293     if (m_debug.out_uvmeta_file) {
8294         fclose(m_debug.out_uvmeta_file);
8295         m_debug.out_uvmeta_file = NULL;
8296     }
8297 #ifdef OUTPUT_EXTRADATA_LOG
8298     if (outputExtradataFile)
8299         fclose (outputExtradataFile);
8300 #endif
8301     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
8302     return OMX_ErrorNone;
8303 }
8304 
8305 /* ======================================================================
8306    FUNCTION
8307    omx_vdec::UseEGLImage
8308 
8309    DESCRIPTION
8310    OMX Use EGL Image method implementation <TBD>.
8311 
8312    PARAMETERS
8313    <TBD>.
8314 
8315    RETURN VALUE
8316    Not Implemented error.
8317 
8318    ========================================================================== */
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)8319 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
8320         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
8321         OMX_IN OMX_U32                        port,
8322         OMX_IN OMX_PTR                     appData,
8323         OMX_IN void*                      eglImage)
8324 {
8325     (void) appData;
8326     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
8327     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
8328     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
8329 
8330 #ifdef USE_EGL_IMAGE_GPU
8331     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
8332     EGLint fd = -1, offset = 0,pmemPtr = 0;
8333 #else
8334     int fd = -1, offset = 0;
8335 #endif
8336     DEBUG_PRINT_HIGH("use EGL image support for decoder");
8337     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
8338         DEBUG_PRINT_ERROR("Invalid EGL image");
8339     }
8340 #ifdef USE_EGL_IMAGE_GPU
8341     if (m_display_id == NULL) {
8342         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
8343         return OMX_ErrorInsufficientResources;
8344     }
8345     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
8346         eglGetProcAddress("eglQueryImageKHR");
8347     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
8348     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
8349     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
8350 #else //with OMX test app
8351     struct temp_egl {
8352         int pmem_fd;
8353         int offset;
8354     };
8355     struct temp_egl *temp_egl_id = NULL;
8356     void * pmemPtr = (void *) eglImage;
8357     temp_egl_id = (struct temp_egl *)eglImage;
8358     if (temp_egl_id != NULL) {
8359         fd = temp_egl_id->pmem_fd;
8360         offset = temp_egl_id->offset;
8361     }
8362 #endif
8363     if (fd < 0) {
8364         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
8365         return OMX_ErrorInsufficientResources;
8366     }
8367     pmem_info.pmem_fd = (OMX_U32) fd;
8368     pmem_info.offset = (OMX_U32) offset;
8369     pmem_entry.entry = (void *) &pmem_info;
8370     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8371     pmem_list.entryList = &pmem_entry;
8372     pmem_list.nEntries = 1;
8373     ouput_egl_buffers = true;
8374     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
8375                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
8376                 (OMX_U8 *)pmemPtr)) {
8377         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
8378         return OMX_ErrorInsufficientResources;
8379     }
8380     return OMX_ErrorNone;
8381 }
8382 
8383 /* ======================================================================
8384    FUNCTION
8385    omx_vdec::ComponentRoleEnum
8386 
8387    DESCRIPTION
8388    OMX Component Role Enum method implementation.
8389 
8390    PARAMETERS
8391    <TBD>.
8392 
8393    RETURN VALUE
8394    OMX Error None if everything is successful.
8395    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)8396 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
8397         OMX_OUT OMX_U8*        role,
8398         OMX_IN OMX_U32        index)
8399 {
8400     (void) hComp;
8401     OMX_ERRORTYPE eRet = OMX_ErrorNone;
8402 
8403     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
8404         if ((0 == index) && role) {
8405             strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
8406             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8407         } else {
8408             eRet = OMX_ErrorNoMore;
8409         }
8410     }
8411     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
8412         if ((0 == index) && role) {
8413             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
8414             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8415         } else {
8416             eRet = OMX_ErrorNoMore;
8417         }
8418     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
8419         if ((0 == index) && role) {
8420             strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
8421             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8422         } else {
8423             DEBUG_PRINT_LOW("No more roles");
8424             eRet = OMX_ErrorNoMore;
8425         }
8426     }
8427 
8428     else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
8429             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
8430         if ((0 == index) && role) {
8431             strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
8432             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8433         } else {
8434             DEBUG_PRINT_LOW("No more roles");
8435             eRet = OMX_ErrorNoMore;
8436         }
8437     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
8438         if ((0 == index) && role) {
8439             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
8440             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8441         } else {
8442             DEBUG_PRINT_LOW("No more roles");
8443             eRet = OMX_ErrorNoMore;
8444         }
8445     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
8446         if ((0 == index) && role) {
8447             strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
8448             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8449         } else {
8450             DEBUG_PRINT_LOW("No more roles");
8451             eRet = OMX_ErrorNoMore;
8452         }
8453     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
8454         if ((0 == index) && role) {
8455             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
8456             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
8457         } else {
8458             DEBUG_PRINT_LOW("No more roles");
8459             eRet = OMX_ErrorNoMore;
8460         }
8461     } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
8462             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
8463           ) {
8464         if ((0 == index) && role) {
8465             strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
8466             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8467         } else {
8468             DEBUG_PRINT_LOW("No more roles");
8469             eRet = OMX_ErrorNoMore;
8470         }
8471     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
8472         if ((0 == index) && role) {
8473             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
8474             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8475         } else {
8476             DEBUG_PRINT_LOW("No more roles");
8477             eRet = OMX_ErrorNoMore;
8478         }
8479     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
8480         if ((0 == index) && role) {
8481             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
8482             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8483         } else {
8484             DEBUG_PRINT_LOW("No more roles");
8485             eRet = OMX_ErrorNoMore;
8486         }
8487     } else {
8488         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
8489         eRet = OMX_ErrorInvalidComponentName;
8490     }
8491     return eRet;
8492 }
8493 
8494 
8495 
8496 
8497 /* ======================================================================
8498    FUNCTION
8499    omx_vdec::AllocateDone
8500 
8501    DESCRIPTION
8502    Checks if entire buffer pool is allocated by IL Client or not.
8503    Need this to move to IDLE state.
8504 
8505    PARAMETERS
8506    None.
8507 
8508    RETURN VALUE
8509    true/false.
8510 
8511    ========================================================================== */
allocate_done(void)8512 bool omx_vdec::allocate_done(void)
8513 {
8514     bool bRet = false;
8515     bool bRet_In = false;
8516     bool bRet_Out = false;
8517     bool bRet_Out_Extra = false;
8518 
8519     bRet_In = allocate_input_done();
8520     bRet_Out = allocate_output_done();
8521     bRet_Out_Extra = allocate_output_extradata_done();
8522 
8523     if (bRet_In && bRet_Out && bRet_Out_Extra) {
8524         bRet = true;
8525     }
8526 
8527     return bRet;
8528 }
8529 /* ======================================================================
8530    FUNCTION
8531    omx_vdec::AllocateInputDone
8532 
8533    DESCRIPTION
8534    Checks if I/P buffer pool is allocated by IL Client or not.
8535 
8536    PARAMETERS
8537    None.
8538 
8539    RETURN VALUE
8540    true/false.
8541 
8542    ========================================================================== */
allocate_input_done(void)8543 bool omx_vdec::allocate_input_done(void)
8544 {
8545     bool bRet = false;
8546     unsigned i=0;
8547 
8548     if (m_inp_mem_ptr == NULL) {
8549         return bRet;
8550     }
8551     if (m_inp_mem_ptr ) {
8552         for (; i<drv_ctx.ip_buf.actualcount; i++) {
8553             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
8554                 break;
8555             }
8556         }
8557     }
8558     if (i == drv_ctx.ip_buf.actualcount) {
8559         bRet = true;
8560         DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
8561     }
8562     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
8563         m_inp_bPopulated = OMX_TRUE;
8564     }
8565     return bRet;
8566 }
8567 /* ======================================================================
8568    FUNCTION
8569    omx_vdec::AllocateOutputDone
8570 
8571    DESCRIPTION
8572    Checks if entire O/P buffer pool is allocated by IL Client or not.
8573 
8574    PARAMETERS
8575    None.
8576 
8577    RETURN VALUE
8578    true/false.
8579 
8580    ========================================================================== */
allocate_output_done(void)8581 bool omx_vdec::allocate_output_done(void)
8582 {
8583     bool bRet = false;
8584     unsigned j=0;
8585 
8586     if (m_out_mem_ptr == NULL) {
8587         return bRet;
8588     }
8589 
8590     if (m_out_mem_ptr) {
8591         for (; j < drv_ctx.op_buf.actualcount; j++) {
8592             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
8593                 break;
8594             }
8595         }
8596     }
8597 
8598     if (j == drv_ctx.op_buf.actualcount) {
8599         bRet = true;
8600         DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
8601         if (m_out_bEnabled)
8602             m_out_bPopulated = OMX_TRUE;
8603     }
8604 
8605     return bRet;
8606 }
8607 
allocate_output_extradata_done(void)8608 bool omx_vdec::allocate_output_extradata_done(void) {
8609     bool bRet = false;
8610     unsigned j=0;
8611     unsigned nBufferCount = 0;
8612 
8613     nBufferCount = m_client_out_extradata_info.getBufferCount();
8614 
8615     if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
8616         return true;
8617     }
8618 
8619     if (m_client_output_extradata_mem_ptr) {
8620         for (; j < nBufferCount; j++) {
8621             if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
8622                 break;
8623             }
8624         }
8625 
8626         if (j == nBufferCount) {
8627             bRet = true;
8628             DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
8629         }
8630     }
8631 
8632     return bRet;
8633 }
8634 /* ======================================================================
8635    FUNCTION
8636    omx_vdec::ReleaseDone
8637 
8638    DESCRIPTION
8639    Checks if IL client has released all the buffers.
8640 
8641    PARAMETERS
8642    None.
8643 
8644    RETURN VALUE
8645    true/false
8646 
8647    ========================================================================== */
release_done(void)8648 bool omx_vdec::release_done(void)
8649 {
8650     bool bRet = false;
8651 
8652     if (release_input_done()) {
8653         if (release_output_done()) {
8654             if (release_output_extradata_done()) {
8655                 bRet = true;
8656             }
8657         }
8658     }
8659     return bRet;
8660 }
8661 
8662 
8663 /* ======================================================================
8664    FUNCTION
8665    omx_vdec::ReleaseOutputDone
8666 
8667    DESCRIPTION
8668    Checks if IL client has released all the buffers.
8669 
8670    PARAMETERS
8671    None.
8672 
8673    RETURN VALUE
8674    true/false
8675 
8676    ========================================================================== */
release_output_done(void)8677 bool omx_vdec::release_output_done(void)
8678 {
8679     bool bRet = false;
8680     unsigned i=0,j=0;
8681 
8682     DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
8683     if (m_out_mem_ptr) {
8684         for (; j < drv_ctx.op_buf.actualcount ; j++) {
8685             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8686                 break;
8687             }
8688         }
8689         if (j == drv_ctx.op_buf.actualcount) {
8690             m_out_bm_count = 0;
8691             bRet = true;
8692         }
8693     } else {
8694         m_out_bm_count = 0;
8695         bRet = true;
8696     }
8697     return bRet;
8698 }
8699 /* ======================================================================
8700    FUNCTION
8701    omx_vdec::ReleaseInputDone
8702 
8703    DESCRIPTION
8704    Checks if IL client has released all the buffers.
8705 
8706    PARAMETERS
8707    None.
8708 
8709    RETURN VALUE
8710    true/false
8711 
8712    ========================================================================== */
release_input_done(void)8713 bool omx_vdec::release_input_done(void)
8714 {
8715     bool bRet = false;
8716     unsigned i=0,j=0;
8717 
8718     DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
8719     if (m_inp_mem_ptr) {
8720         for (; j<drv_ctx.ip_buf.actualcount; j++) {
8721             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8722                 break;
8723             }
8724         }
8725         if (j==drv_ctx.ip_buf.actualcount) {
8726             bRet = true;
8727         }
8728     } else {
8729         bRet = true;
8730     }
8731     return bRet;
8732 }
8733 
release_output_extradata_done(void)8734 bool omx_vdec::release_output_extradata_done(void) {
8735     bool bRet = false;
8736     unsigned i=0,j=0, buffer_count=0;
8737 
8738     buffer_count = m_client_out_extradata_info.getBufferCount();
8739     DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
8740             m_client_output_extradata_mem_ptr, buffer_count);
8741 
8742     if (m_client_output_extradata_mem_ptr) {
8743         for (; j<buffer_count; j++) {
8744             if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
8745                 break;
8746             }
8747         }
8748         if (j == buffer_count) {
8749             bRet = true;
8750         }
8751     } else {
8752         bRet = true;
8753     }
8754     return bRet;
8755 }
8756 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8757 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8758         OMX_BUFFERHEADERTYPE * buffer)
8759 {
8760     VIDC_TRACE_NAME_HIGH("FBD");
8761     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8762     if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
8763         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8764         return OMX_ErrorBadParameter;
8765     } else if (output_flush_progress) {
8766         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8767         buffer->nFilledLen = 0;
8768         buffer->nTimeStamp = 0;
8769         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8770         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8771         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8772     }
8773 
8774     if (m_debug_extradata) {
8775         if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8776             DEBUG_PRINT_HIGH("***************************************************");
8777             DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8778             DEBUG_PRINT_HIGH("***************************************************");
8779         }
8780 
8781         if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8782             DEBUG_PRINT_HIGH("***************************************************");
8783             DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8784             DEBUG_PRINT_HIGH("***************************************************");
8785         }
8786     }
8787 
8788 
8789     DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
8790             buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
8791     pending_output_buffers --;
8792     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8793 
8794     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8795         DEBUG_PRINT_HIGH("Output EOS has been reached");
8796         if (!output_flush_progress)
8797             post_event((unsigned)NULL, (unsigned)NULL,
8798                     OMX_COMPONENT_GENERATE_EOS_DONE);
8799 
8800         if (psource_frame) {
8801             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8802             psource_frame = NULL;
8803         }
8804         if (pdest_frame) {
8805             pdest_frame->nFilledLen = 0;
8806             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8807                     (unsigned)NULL);
8808             pdest_frame = NULL;
8809         }
8810     }
8811 
8812 #ifdef OUTPUT_EXTRADATA_LOG
8813     if (outputExtradataFile) {
8814         int buf_index = buffer - m_out_mem_ptr;
8815         OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8816 
8817         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8818         p_extra = (OMX_OTHER_EXTRADATATYPE *)
8819             ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8820 
8821         while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8822             DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8823                                     p_extra->nSize, p_extra->eType);
8824             fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8825 
8826             if (p_extra->eType == OMX_ExtraDataNone) {
8827                 break;
8828             }
8829             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8830         }
8831     }
8832 #endif
8833 
8834     /* For use buffer we need to copy the data */
8835     if (!output_flush_progress) {
8836         /* This is the error check for non-recoverable errros */
8837         bool is_duplicate_ts_valid = true;
8838         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8839 
8840         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8841                 output_capability == V4L2_PIX_FMT_MPEG2 ||
8842                 output_capability == V4L2_PIX_FMT_DIVX ||
8843                 output_capability == V4L2_PIX_FMT_DIVX_311)
8844             is_duplicate_ts_valid = false;
8845 
8846         if ((output_capability == V4L2_PIX_FMT_H264 ||
8847                 output_capability == V4L2_PIX_FMT_H264_MVC) &&
8848                 is_interlaced) {
8849             if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8850                 is_interlaced = false;
8851             }
8852         }
8853 
8854         if (buffer->nFilledLen > 0) {
8855             time_stamp_dts.get_next_timestamp(buffer,
8856                     is_interlaced && is_duplicate_ts_valid);
8857             if (m_debug_timestamp) {
8858                 {
8859                     OMX_TICKS expected_ts = 0;
8860                     m_timestamp_list.pop_min_ts(expected_ts);
8861                     if (is_interlaced && is_duplicate_ts_valid) {
8862                         m_timestamp_list.pop_min_ts(expected_ts);
8863                     }
8864                     DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8865                             buffer->nTimeStamp, expected_ts);
8866 
8867                     if (buffer->nTimeStamp != expected_ts) {
8868                         DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8869                     }
8870                 }
8871             }
8872         }
8873     }
8874     VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8875 
8876     if (m_cb.FillBufferDone) {
8877         if (buffer->nFilledLen > 0) {
8878             if (arbitrary_bytes)
8879                 adjust_timestamp(buffer->nTimeStamp);
8880             else
8881                 set_frame_rate(buffer->nTimeStamp);
8882 
8883             proc_frms++;
8884             if (perf_flag) {
8885                 if (1 == proc_frms) {
8886                     dec_time.stop();
8887                     latency = dec_time.processing_time_us() - latency;
8888                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8889                     dec_time.start();
8890                     fps_metrics.start();
8891                 }
8892                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8893                     OMX_U64 proc_time = 0;
8894                     fps_metrics.stop();
8895                     proc_time = fps_metrics.processing_time_us();
8896                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8897                             (unsigned int)proc_frms, (float)proc_time / 1e6,
8898                             (float)(1e6 * proc_frms) / proc_time);
8899                 }
8900             }
8901         }
8902         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8903             prev_ts = LLONG_MAX;
8904             rst_prev_ts = true;
8905             proc_frms = 0;
8906         }
8907 
8908         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8909             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8910              buffer->pPlatformPrivate)->entryList->entry;
8911         DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8912         OMX_BUFFERHEADERTYPE *il_buffer;
8913         il_buffer = client_buffers.get_il_buf_hdr(buffer);
8914         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8915 
8916         if (il_buffer && m_last_rendered_TS >= 0) {
8917             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8918 
8919             // Current frame can be send for rendering if
8920             // (a) current FPS is <=  60
8921             // (b) is the next frame after the frame with TS 0
8922             // (c) is the first frame after seek
8923             // (d) the delta TS b\w two consecutive frames is > 16 ms
8924             // (e) its TS is equal to previous frame TS
8925             // (f) if marked EOS
8926 
8927             if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8928                il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8929                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8930                m_last_rendered_TS = il_buffer->nTimeStamp;
8931             } else {
8932                //mark for droping
8933                buffer->nFilledLen = 0;
8934             }
8935 
8936             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8937                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8938                               il_buffer->nTimeStamp,ts_delta);
8939 
8940             //above code makes sure that delta b\w two consecutive frames is not
8941             //greater than 16ms, slow-mo feature, so cap fps to max 60
8942             if (current_framerate > 60 ) {
8943                 current_framerate = 60;
8944             }
8945         }
8946 
8947         // add current framerate to gralloc meta data
8948         if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && m_out_mem_ptr) {
8949             // If valid fps was received, directly send it to display for the 1st fbd.
8950             // Otherwise, calculate fps using fbd timestamps
8951             float refresh_rate = m_fps_prev;
8952             if (m_fps_received) {
8953                 if (1 == proc_frms) {
8954                     refresh_rate = m_fps_received / (float)(1<<16);
8955                 }
8956             } else {
8957                 // check if dynamic refresh rate change feature enabled or not
8958                 if (m_drc_enable) {
8959                     // set coarse fps when 2 fbds received and
8960                     // set fps again when 30 fbds received as it should be
8961                     // more accurate than the one set when only 2 fbds received.
8962                     if (2 == proc_frms || 30 == proc_frms) {
8963                         if (drv_ctx.frame_rate.fps_denominator) {
8964                             refresh_rate = drv_ctx.frame_rate.fps_numerator /
8965                                     (float) drv_ctx.frame_rate.fps_denominator;
8966                         }
8967                     }
8968                 } else {
8969                     // calculate and set refresh rate for every frame from second frame onwards
8970                     // display will assume the default refresh rate for first frame (which is 60 fps)
8971                     if (m_fps_prev) {
8972                         if (drv_ctx.frame_rate.fps_denominator) {
8973                             refresh_rate = drv_ctx.frame_rate.fps_numerator /
8974                                     (float) drv_ctx.frame_rate.fps_denominator;
8975                         }
8976                     }
8977                 }
8978             }
8979             if (refresh_rate > 60) {
8980                 refresh_rate = 60;
8981             }
8982             DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8983             OMX_U32 buf_index = buffer - m_out_mem_ptr;
8984             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8985                          UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8986             m_fps_prev = refresh_rate;
8987         }
8988 
8989         if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) {
8990             OMX_U32 buf_index = buffer - m_out_mem_ptr;
8991             DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8992             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8993                                S3D_FORMAT, (void*)&stereo_output_mode);
8994         }
8995 
8996         if (il_buffer) {
8997             log_output_buffers(il_buffer);
8998             if (dynamic_buf_mode) {
8999                 unsigned int nPortIndex = 0;
9000                 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
9001 
9002                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
9003                 // to size of the handle. Do it _after_ log_output_buffers which
9004                 // requires the respective sizes to be accurate.
9005 
9006                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
9007                 buffer->nFilledLen = buffer->nFilledLen ?
9008                         sizeof(struct VideoDecoderOutputMetaData) : 0;
9009 
9010                 //Clear graphic buffer handles in dynamic mode
9011                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
9012                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
9013                     native_buffer[nPortIndex].privatehandle = NULL;
9014                     native_buffer[nPortIndex].nativehandle = NULL;
9015                 } else {
9016                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
9017                     return OMX_ErrorBadParameter;
9018                 }
9019             }
9020             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
9021         } else {
9022             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
9023             return OMX_ErrorBadParameter;
9024         }
9025         DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
9026     } else {
9027         return OMX_ErrorBadParameter;
9028     }
9029 
9030 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
9031     if (m_smoothstreaming_mode && m_out_mem_ptr) {
9032         OMX_U32 buf_index = buffer - m_out_mem_ptr;
9033         BufferDim_t dim;
9034         private_handle_t *private_handle = NULL;
9035         dim.sliceWidth = framesize.nWidth;
9036         dim.sliceHeight = framesize.nHeight;
9037         if (buf_index < drv_ctx.op_buf.actualcount &&
9038             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
9039             native_buffer[buf_index].privatehandle)
9040             private_handle = native_buffer[buf_index].privatehandle;
9041         if (private_handle) {
9042             DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
9043                 dim.sliceWidth, dim.sliceHeight);
9044             setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
9045         }
9046     }
9047 #endif
9048 
9049     return OMX_ErrorNone;
9050 }
9051 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9052 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
9053         OMX_BUFFERHEADERTYPE* buffer)
9054 {
9055     VIDC_TRACE_NAME_HIGH("EBD");
9056     int nBufferIndex = buffer - m_inp_mem_ptr;
9057 
9058     if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
9059         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
9060         return OMX_ErrorBadParameter;
9061     }
9062 
9063     DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
9064             buffer, buffer->pBuffer, buffer->nFlags);
9065     pending_input_buffers--;
9066     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
9067 
9068     if (arbitrary_bytes) {
9069         if (pdest_frame == NULL && input_flush_progress == false) {
9070             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
9071             pdest_frame = buffer;
9072             buffer->nFilledLen = 0;
9073             buffer->nTimeStamp = LLONG_MAX;
9074             push_input_buffer (hComp);
9075         } else {
9076             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
9077             buffer->nFilledLen = 0;
9078             if (!m_input_free_q.insert_entry((unsigned long)buffer,
9079                         (unsigned)NULL, (unsigned)NULL)) {
9080                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
9081             }
9082         }
9083     } else if (m_cb.EmptyBufferDone) {
9084         buffer->nFilledLen = 0;
9085         if (input_use_buffer == true) {
9086             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
9087         }
9088 
9089         /* Restore the FD that we over-wrote in ETB */
9090         if (m_input_pass_buffer_fd) {
9091             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
9092         }
9093 
9094         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
9095     }
9096     return OMX_ErrorNone;
9097 }
9098 
async_message_process(void * context,void * message)9099 int omx_vdec::async_message_process (void *context, void* message)
9100 {
9101     omx_vdec* omx = NULL;
9102     struct vdec_msginfo *vdec_msg = NULL;
9103     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
9104     struct v4l2_buffer *v4l2_buf_ptr = NULL;
9105     struct v4l2_plane *plane = NULL;
9106     struct vdec_output_frameinfo *output_respbuf = NULL;
9107     int rc=1;
9108     if (context == NULL || message == NULL) {
9109         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
9110         return -1;
9111     }
9112     vdec_msg = (struct vdec_msginfo *)message;
9113 
9114     omx = reinterpret_cast<omx_vdec*>(context);
9115 
9116     switch (vdec_msg->msgcode) {
9117 
9118         case VDEC_MSG_EVT_HW_ERROR:
9119             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9120                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9121             break;
9122 
9123         case VDEC_MSG_EVT_HW_OVERLOAD:
9124             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9125                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
9126             break;
9127 
9128         case VDEC_MSG_EVT_HW_UNSUPPORTED:
9129             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9130                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
9131             break;
9132 
9133         case VDEC_MSG_RESP_START_DONE:
9134             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9135                     OMX_COMPONENT_GENERATE_START_DONE);
9136             break;
9137 
9138         case VDEC_MSG_RESP_STOP_DONE:
9139             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9140                     OMX_COMPONENT_GENERATE_STOP_DONE);
9141             break;
9142 
9143         case VDEC_MSG_RESP_RESUME_DONE:
9144             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9145                     OMX_COMPONENT_GENERATE_RESUME_DONE);
9146             break;
9147 
9148         case VDEC_MSG_RESP_PAUSE_DONE:
9149             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9150                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
9151             break;
9152 
9153         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
9154             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9155                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
9156             break;
9157         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
9158             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9159                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
9160             break;
9161         case VDEC_MSG_RESP_INPUT_FLUSHED:
9162         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
9163 
9164             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
9165                vdec_msg->msgdata.input_frame_clientdata; */
9166 
9167             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
9168             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
9169                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
9170                 omxhdr = NULL;
9171                 vdec_msg->status_code = VDEC_S_EFATAL;
9172                 break;
9173 
9174             }
9175             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
9176 
9177             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
9178                 DEBUG_PRINT_HIGH("Unsupported input");
9179                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9180                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9181             }
9182             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
9183                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9184                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
9185             }
9186             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
9187 
9188                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
9189                 android_atomic_dec(&omx->m_queued_codec_config_count);
9190                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
9191                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
9192                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
9193                     sem_post(&omx->m_safe_flush);
9194                 }
9195             }
9196             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
9197                 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
9198                 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9199             }
9200             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
9201                     OMX_COMPONENT_GENERATE_EBD);
9202             break;
9203         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
9204             int64_t *timestamp;
9205             timestamp = (int64_t *) malloc(sizeof(int64_t));
9206             if (timestamp) {
9207                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
9208                 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
9209                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
9210                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
9211                         (long long)vdec_msg->msgdata.output_frame.time_stamp);
9212             }
9213             break;
9214         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
9215         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
9216 
9217            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
9218            if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
9219                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
9220                omxhdr = NULL;
9221                vdec_msg->status_code = VDEC_S_EFATAL;
9222                break;
9223            }
9224            plane = v4l2_buf_ptr->m.planes;
9225            omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
9226 
9227            if (omxhdr && omxhdr->pOutputPortPrivate &&
9228                    ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
9229                    (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
9230                      - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
9231 
9232                if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
9233                    omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
9234                    omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
9235                    omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
9236                    omxhdr->nFlags = 0;
9237 
9238                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
9239                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
9240                         //rc = -1;
9241                    }
9242                    if (omxhdr->nFilledLen) {
9243                        omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
9244                    }
9245                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
9246                        omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9247                    } else {
9248                        omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
9249                    }
9250                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
9251                        omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9252                    }
9253                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
9254                        omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
9255                    }
9256                    if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
9257                        omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
9258                    }
9259                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
9260                         omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
9261                         DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
9262                                    omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
9263                    }
9264 
9265                    if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
9266                            !omx->output_flush_progress &&
9267                            !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
9268                            !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
9269                        omx->time_stamp_dts.remove_time_stamp(
9270                                omxhdr->nTimeStamp,
9271                                (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
9272                                ?true:false);
9273 
9274                        omxhdr->nFilledLen = 0;
9275                        omx->pending_output_buffers--;
9276                        omx->post_event ((unsigned long)NULL,(unsigned long)omx->client_buffers.get_il_buf_hdr(omxhdr),
9277                                OMX_COMPONENT_GENERATE_FTB);
9278                        break;
9279                    }
9280                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
9281                        omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9282                    }
9283 
9284                    output_respbuf = (struct vdec_output_frameinfo *)\
9285                             omxhdr->pOutputPortPrivate;
9286                    if (!output_respbuf) {
9287                      DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
9288                      return -1;
9289                    }
9290                    output_respbuf->len = vdec_msg->msgdata.output_frame.len;
9291                    output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
9292 
9293                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
9294                        output_respbuf->pic_type = PICTURE_TYPE_I;
9295                    }
9296                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
9297                        output_respbuf->pic_type = PICTURE_TYPE_P;
9298                    }
9299                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
9300                        output_respbuf->pic_type = PICTURE_TYPE_B;
9301                    }
9302 
9303                    if (vdec_msg->msgdata.output_frame.len) {
9304                        if (!omx->output_flush_progress && (omxhdr->nFilledLen > 0)) {
9305                            // set the default colorspace advised by client, since the bitstream may be
9306                            // devoid of colorspace-info.
9307                            if (omx->m_enable_android_native_buffers) {
9308                                ColorSpace_t color_space = ITU_R_601;
9309 
9310                            // Disabled ?
9311                            // WA for VP8. Vp8 encoder does not embed color-info (yet!).
9312                            // Encoding RGBA results in 601-LR for all resolutions.
9313                            // This conflicts with the client't defaults which are based on resolution.
9314                            //   Eg: 720p will be encoded as 601-LR. Client will say 709.
9315                            // Re-enable this code once vp8 encoder generates color-info and hence the
9316                            // decoder will be able to override with the correct source color.
9317 #if 0
9318                                switch (omx->m_client_color_space.sAspects.mPrimaries) {
9319                                    case ColorAspects::PrimariesBT601_6_625:
9320                                    case ColorAspects::PrimariesBT601_6_525:
9321                                    {
9322                                        color_space = omx->m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
9323                                                ITU_R_601_FR : ITU_R_601;
9324                                        break;
9325                                    }
9326                                    case ColorAspects::PrimariesBT709_5:
9327                                    {
9328                                        color_space = ITU_R_709;
9329                                        break;
9330                                    }
9331                                    default:
9332                                    {
9333                                        break;
9334                                    }
9335                                }
9336 #endif
9337                                DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
9338                                        color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
9339                                omx->set_colorspace_in_handle(color_space, omxhdr - omx->m_out_mem_ptr);
9340                            }
9341                        }
9342 
9343                        DEBUG_PRINT_LOW("Processing extradata");
9344                        omx->handle_extradata(omxhdr);
9345 
9346                        if (omx->m_extradata_info.output_crop_updated) {
9347                            DEBUG_PRINT_LOW("Read FBD crop from output extra data");
9348                            vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
9349                            vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
9350                            vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
9351                            vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
9352                            vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
9353                            vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
9354                        } else {
9355                            DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
9356                            vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
9357                            vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
9358                            vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
9359                            vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
9360                            vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
9361                            vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
9362 
9363                            /* Copy these values back to OMX internal variables to make both handlign same*/
9364 
9365                            omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
9366                            omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
9367                            omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
9368                            omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
9369                            omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9370                            omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9371                        }
9372                    }
9373 
9374                    vdec_msg->msgdata.output_frame.bufferaddr =
9375                        omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
9376 
9377                    if (vdec_msg->msgdata.output_frame.len)
9378                        memcpy(&omx->drv_ctx.frame_size,
9379                                &vdec_msg->msgdata.output_frame.framesize,
9380                                sizeof(struct vdec_framesize));
9381 
9382                    DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
9383                            " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
9384                            omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
9385                            omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
9386                            vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
9387                            (unsigned int)vdec_msg->msgdata.output_frame.len,
9388                            vdec_msg->msgdata.output_frame.framesize.left,
9389                            vdec_msg->msgdata.output_frame.framesize.top,
9390                            vdec_msg->msgdata.output_frame.framesize.right,
9391                            vdec_msg->msgdata.output_frame.framesize.bottom);
9392 
9393                    /* Post event if resolution OR crop changed */
9394                    /* filled length will be changed if resolution changed */
9395                    /* Crop parameters can be changed even without resolution change */
9396                    if (omxhdr->nFilledLen
9397                        && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
9398                        || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
9399                        || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
9400                        || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
9401                        || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
9402                        || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
9403                        || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
9404 
9405                        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",
9406                                omx->prev_n_filled_len,
9407                                omx->drv_ctx.video_resolution.frame_width,
9408                                omx->drv_ctx.video_resolution.frame_height,
9409                                omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
9410                                omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
9411                                omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
9412                                vdec_msg->msgdata.output_frame.picsize.frame_height,
9413                                vdec_msg->msgdata.output_frame.framesize.left,
9414                                vdec_msg->msgdata.output_frame.framesize.top,
9415                                vdec_msg->msgdata.output_frame.framesize.right,
9416                                vdec_msg->msgdata.output_frame.framesize.bottom);
9417 
9418                        omx->drv_ctx.video_resolution.frame_width =
9419                                vdec_msg->msgdata.output_frame.picsize.frame_width;
9420                        omx->drv_ctx.video_resolution.frame_height =
9421                                vdec_msg->msgdata.output_frame.picsize.frame_height;
9422                        if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
9423                            omx->drv_ctx.video_resolution.stride =
9424                                VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
9425                            omx->drv_ctx.video_resolution.scan_lines =
9426                                VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
9427                        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
9428                            omx->drv_ctx.video_resolution.stride =
9429                                VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
9430                            omx->drv_ctx.video_resolution.scan_lines =
9431                                VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
9432                        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
9433                            omx->drv_ctx.video_resolution.stride =
9434                                VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
9435                            omx->drv_ctx.video_resolution.scan_lines =
9436                                VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
9437                         }
9438 
9439                        omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9440                                 OMX_IndexConfigCommonOutputCrop,
9441                                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9442                    }
9443 
9444                    if (omxhdr->nFilledLen)
9445                        omx->prev_n_filled_len = omxhdr->nFilledLen;
9446 
9447                    if (omxhdr && omxhdr->nFilledLen && !omx->m_need_turbo) {
9448                         omx->request_perf_level(VIDC_NOMINAL);
9449                    }
9450                    if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
9451                        vdec_msg->msgdata.output_frame.bufferaddr)
9452                        memcpy ( omxhdr->pBuffer, (void *)
9453                                ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
9454                                 (unsigned long)vdec_msg->msgdata.output_frame.offset),
9455                                vdec_msg->msgdata.output_frame.len);
9456                } else {
9457                    DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
9458                            (unsigned int)vdec_msg->msgdata.output_frame.len,
9459                            omxhdr->nAllocLen, omx->prev_n_filled_len);
9460                    omxhdr->nFilledLen = 0;
9461                }
9462 
9463                omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
9464                         OMX_COMPONENT_GENERATE_FBD);
9465 
9466             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
9467                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
9468                         OMX_COMPONENT_GENERATE_EOS_DONE);
9469             } else {
9470                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
9471                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9472             }
9473             break;
9474         case VDEC_MSG_EVT_CONFIG_CHANGED:
9475             DEBUG_PRINT_HIGH("Port settings changed");
9476             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9477             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9478             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
9479                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9480             if (!omx->m_need_turbo) {
9481                 omx->request_perf_level(VIDC_NOMINAL);
9482             }
9483             break;
9484         default:
9485             break;
9486     }
9487     return rc;
9488 }
9489 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9490 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
9491         OMX_HANDLETYPE hComp,
9492         OMX_BUFFERHEADERTYPE *buffer
9493         )
9494 {
9495     unsigned address,p2,id;
9496     DEBUG_PRINT_LOW("Empty this arbitrary");
9497 
9498     if (buffer == NULL) {
9499         return OMX_ErrorBadParameter;
9500     }
9501     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
9502     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
9503             (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
9504 
9505     /* return zero length and not an EOS buffer */
9506     /* return buffer if input flush in progress */
9507     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
9508                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
9509         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
9510         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
9511         return OMX_ErrorNone;
9512     }
9513 
9514     if (psource_frame == NULL) {
9515         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
9516         psource_frame = buffer;
9517         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
9518         push_input_buffer (hComp);
9519     } else {
9520         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
9521         if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
9522                     (unsigned)NULL)) {
9523             return OMX_ErrorBadParameter;
9524         }
9525     }
9526 
9527     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
9528         codec_config_flag = false;
9529     }
9530     return OMX_ErrorNone;
9531 }
9532 
push_input_buffer(OMX_HANDLETYPE hComp)9533 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
9534 {
9535     unsigned long address,p2,id;
9536     OMX_ERRORTYPE ret = OMX_ErrorNone;
9537 
9538     if (pdest_frame == NULL || psource_frame == NULL) {
9539         /*Check if we have a destination buffer*/
9540         if (pdest_frame == NULL) {
9541             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
9542             if (m_input_free_q.m_size) {
9543                 m_input_free_q.pop_entry(&address,&p2,&id);
9544                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
9545                 pdest_frame->nFilledLen = 0;
9546                 pdest_frame->nTimeStamp = LLONG_MAX;
9547                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
9548             }
9549         }
9550 
9551         /*Check if we have a destination buffer*/
9552         if (psource_frame == NULL) {
9553             DEBUG_PRINT_LOW("Get a source buffer from the queue");
9554             if (m_input_pending_q.m_size) {
9555                 m_input_pending_q.pop_entry(&address,&p2,&id);
9556                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9557                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9558                         psource_frame->nTimeStamp);
9559                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9560                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9561 
9562             }
9563         }
9564 
9565     }
9566 
9567     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
9568         switch (codec_type_parse) {
9569             case CODEC_TYPE_MPEG4:
9570             case CODEC_TYPE_H263:
9571             case CODEC_TYPE_MPEG2:
9572                 ret =  push_input_sc_codec(hComp);
9573                 break;
9574             case CODEC_TYPE_H264:
9575                 ret = push_input_h264(hComp);
9576                 break;
9577             case CODEC_TYPE_HEVC:
9578                 ret = push_input_hevc(hComp);
9579                 break;
9580             case CODEC_TYPE_VC1:
9581                 ret = push_input_vc1(hComp);
9582                 break;
9583             default:
9584                 break;
9585         }
9586         if (ret != OMX_ErrorNone) {
9587             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
9588             omx_report_error ();
9589             break;
9590         }
9591     }
9592 
9593     return ret;
9594 }
9595 
push_input_sc_codec(OMX_HANDLETYPE hComp)9596 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
9597 {
9598     OMX_U32 partial_frame = 1;
9599     OMX_BOOL generate_ebd = OMX_TRUE;
9600     unsigned long address = 0, p2 = 0, id = 0;
9601 
9602     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
9603             psource_frame,psource_frame->nTimeStamp);
9604     if (m_frame_parser.parse_sc_frame(psource_frame,
9605                 pdest_frame,&partial_frame) == -1) {
9606         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9607         return OMX_ErrorBadParameter;
9608     }
9609 
9610     if (partial_frame == 0) {
9611         DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
9612                 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
9613 
9614 
9615         DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
9616         /*First Parsed buffer will have only header Hence skip*/
9617         if (frame_count == 0) {
9618             DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
9619 
9620             if (codec_type_parse == CODEC_TYPE_MPEG4 ||
9621                     codec_type_parse == CODEC_TYPE_DIVX) {
9622                 mp4StreamType psBits;
9623                 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
9624                 psBits.numBytes = pdest_frame->nFilledLen;
9625                 mp4_headerparser.parseHeader(&psBits);
9626             }
9627 
9628             frame_count++;
9629         } else {
9630             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9631             if (pdest_frame->nFilledLen) {
9632                 /*Push the frame to the Decoder*/
9633                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9634                     return OMX_ErrorBadParameter;
9635                 }
9636                 frame_count++;
9637                 pdest_frame = NULL;
9638 
9639                 if (m_input_free_q.m_size) {
9640                     m_input_free_q.pop_entry(&address,&p2,&id);
9641                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9642                     pdest_frame->nFilledLen = 0;
9643                 }
9644             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
9645                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
9646                 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
9647                         (unsigned)NULL);
9648                 pdest_frame = NULL;
9649             }
9650         }
9651     } else {
9652         DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
9653         /*Check if Destination Buffer is full*/
9654         if (pdest_frame->nAllocLen ==
9655                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
9656             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
9657             return OMX_ErrorStreamCorrupt;
9658         }
9659     }
9660 
9661     if (psource_frame->nFilledLen == 0) {
9662         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9663             if (pdest_frame) {
9664                 pdest_frame->nFlags |= psource_frame->nFlags;
9665                 pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
9666                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
9667                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9668                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9669                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
9670                 /*Push the frame to the Decoder*/
9671                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9672                     return OMX_ErrorBadParameter;
9673                 }
9674                 frame_count++;
9675                 pdest_frame = NULL;
9676             } else {
9677                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
9678                 generate_ebd = OMX_FALSE;
9679             }
9680         }
9681         if (generate_ebd) {
9682             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
9683             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9684             psource_frame = NULL;
9685 
9686             if (m_input_pending_q.m_size) {
9687                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9688                 m_input_pending_q.pop_entry(&address,&p2,&id);
9689                 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9690                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9691                         psource_frame->nTimeStamp);
9692                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9693                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9694             }
9695         }
9696     }
9697     return OMX_ErrorNone;
9698 }
9699 
push_input_h264(OMX_HANDLETYPE hComp)9700 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
9701 {
9702     OMX_U32 partial_frame = 1;
9703     unsigned long address = 0, p2 = 0, id = 0;
9704     OMX_BOOL isNewFrame = OMX_FALSE;
9705     OMX_BOOL generate_ebd = OMX_TRUE;
9706 
9707     if (h264_scratch.pBuffer == NULL) {
9708         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
9709         return OMX_ErrorBadParameter;
9710     }
9711     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
9712             "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
9713     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
9714     if (h264_scratch.nFilledLen && look_ahead_nal) {
9715         look_ahead_nal = false;
9716         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9717                 h264_scratch.nFilledLen) {
9718             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9719                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
9720             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9721             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
9722             h264_scratch.nFilledLen = 0;
9723         } else {
9724             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
9725             return OMX_ErrorBadParameter;
9726         }
9727     }
9728 
9729     /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
9730        in EOS flag getting associated with the destination
9731     */
9732     if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
9733             pdest_frame->nFilledLen) {
9734         DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
9735         generate_ebd = OMX_FALSE;
9736     }
9737 
9738     if (nal_length == 0) {
9739         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
9740         if (m_frame_parser.parse_sc_frame(psource_frame,
9741                     &h264_scratch,&partial_frame) == -1) {
9742             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9743             return OMX_ErrorBadParameter;
9744         }
9745     } else {
9746         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9747         if (m_frame_parser.parse_h264_nallength(psource_frame,
9748                     &h264_scratch,&partial_frame) == -1) {
9749             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9750             return OMX_ErrorBadParameter;
9751         }
9752     }
9753 
9754     if (partial_frame == 0) {
9755         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9756             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9757             nal_count++;
9758             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9759             h264_scratch.nFlags = psource_frame->nFlags;
9760         } else {
9761             DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9762             if (h264_scratch.nFilledLen) {
9763                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9764                         NALU_TYPE_SPS);
9765 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9766                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9767                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9768                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9769                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9770                     // If timeinfo is present frame info from SEI is already processed
9771                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9772                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9773 #endif
9774                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9775                 nal_count++;
9776                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9777                     pdest_frame->nTimeStamp = h264_last_au_ts;
9778                     pdest_frame->nFlags = h264_last_au_flags;
9779 #ifdef PANSCAN_HDLR
9780                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9781                         h264_parser->update_panscan_data(h264_last_au_ts);
9782 #endif
9783                 }
9784                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9785                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9786                     h264_last_au_ts = h264_scratch.nTimeStamp;
9787                     h264_last_au_flags = h264_scratch.nFlags;
9788 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9789                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9790                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9791                         if (!VALID_TS(h264_last_au_ts))
9792                             h264_last_au_ts = ts_in_sei;
9793                     }
9794 #endif
9795                 } else
9796                     h264_last_au_ts = LLONG_MAX;
9797             }
9798 
9799             if (!isNewFrame) {
9800                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9801                         h264_scratch.nFilledLen) {
9802                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9803                             (unsigned int)h264_scratch.nFilledLen);
9804                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9805                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
9806                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9807                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9808                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9809                     h264_scratch.nFilledLen = 0;
9810                 } else {
9811                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9812                     return OMX_ErrorBadParameter;
9813                 }
9814             } else if(h264_scratch.nFilledLen) {
9815                 look_ahead_nal = true;
9816                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9817                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9818                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9819                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
9820 
9821                 if (pdest_frame->nFilledLen == 0) {
9822                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9823                     look_ahead_nal = false;
9824                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9825                             h264_scratch.nFilledLen) {
9826                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9827                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9828                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9829                         h264_scratch.nFilledLen = 0;
9830                     } else {
9831                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9832                         return OMX_ErrorBadParameter;
9833                     }
9834                 } else {
9835                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9836                         DEBUG_PRINT_LOW("Reset the EOS Flag");
9837                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9838                     }
9839                     /*Push the frame to the Decoder*/
9840                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9841                         return OMX_ErrorBadParameter;
9842                     }
9843                     //frame_count++;
9844                     pdest_frame = NULL;
9845                     if (m_input_free_q.m_size) {
9846                         m_input_free_q.pop_entry(&address,&p2,&id);
9847                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9848                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9849                         pdest_frame->nFilledLen = 0;
9850                         pdest_frame->nFlags = 0;
9851                         pdest_frame->nTimeStamp = LLONG_MAX;
9852                     }
9853                 }
9854             }
9855         }
9856     } else {
9857         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9858         /*Check if Destination Buffer is full*/
9859         if (h264_scratch.nAllocLen ==
9860                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9861             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9862             return OMX_ErrorStreamCorrupt;
9863         }
9864     }
9865 
9866     if (!psource_frame->nFilledLen) {
9867         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9868 
9869         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9870             if (pdest_frame) {
9871                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9872                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9873                         h264_scratch.nFilledLen) {
9874                     if(pdest_frame->nFilledLen == 0) {
9875                         /* No residual frame from before, send whatever
9876                          * we have left */
9877                         memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9878                                 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9879                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9880                         h264_scratch.nFilledLen = 0;
9881                         pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9882                     } else {
9883                         m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9884                         if(!isNewFrame) {
9885                             /* Have a residual frame, but we know that the
9886                              * AU in this frame is belonging to whatever
9887                              * frame we had left over.  So append it */
9888                              memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9889                                      h264_scratch.pBuffer,h264_scratch.nFilledLen);
9890                              pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9891                              h264_scratch.nFilledLen = 0;
9892                              if (h264_last_au_ts != LLONG_MAX)
9893                                  pdest_frame->nTimeStamp = h264_last_au_ts;
9894                         } else {
9895                             /* Completely new frame, let's just push what
9896                              * we have now.  The resulting EBD would trigger
9897                              * another push */
9898                             generate_ebd = OMX_FALSE;
9899                             pdest_frame->nTimeStamp = h264_last_au_ts;
9900                             h264_last_au_ts = h264_scratch.nTimeStamp;
9901                         }
9902                     }
9903                 } else {
9904                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9905                     return OMX_ErrorBadParameter;
9906                 }
9907 
9908                 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9909                 if(generate_ebd == OMX_TRUE) {
9910                      pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9911                 }
9912 
9913                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9914                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9915                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9916 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9917                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9918                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9919                     if (!VALID_TS(pdest_frame->nTimeStamp))
9920                         pdest_frame->nTimeStamp = ts_in_sei;
9921                 }
9922 #endif
9923                 /*Push the frame to the Decoder*/
9924                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9925                     return OMX_ErrorBadParameter;
9926                 }
9927                 frame_count++;
9928                 pdest_frame = NULL;
9929             } else {
9930                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9931                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9932                 generate_ebd = OMX_FALSE;
9933             }
9934         }
9935     }
9936     if (generate_ebd && !psource_frame->nFilledLen) {
9937         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9938         psource_frame = NULL;
9939         if (m_input_pending_q.m_size) {
9940             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9941             m_input_pending_q.pop_entry(&address,&p2,&id);
9942             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9943             DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9944                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9945         }
9946     }
9947     return OMX_ErrorNone;
9948 }
9949 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9950 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9951 {
9952     OMX_ERRORTYPE rc = OMX_ErrorNone;
9953     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9954         memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9955         if (pDst->nTimeStamp == LLONG_MAX) {
9956             pDst->nTimeStamp = pSrc->nTimeStamp;
9957             DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9958         }
9959         pDst->nFilledLen += pSrc->nFilledLen;
9960         pSrc->nFilledLen = 0;
9961     } else {
9962         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9963         rc = OMX_ErrorBadParameter;
9964     }
9965     return rc;
9966 }
9967 
push_input_hevc(OMX_HANDLETYPE hComp)9968 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9969 {
9970     OMX_U32 partial_frame = 1;
9971     unsigned long address,p2,id;
9972     OMX_BOOL isNewFrame = OMX_FALSE;
9973     OMX_BOOL generate_ebd = OMX_TRUE;
9974     OMX_ERRORTYPE rc = OMX_ErrorNone;
9975     if (h264_scratch.pBuffer == NULL) {
9976         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9977         return OMX_ErrorBadParameter;
9978     }
9979 
9980     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9981             pdest_frame nFilledLen %u nTimeStamp %lld",
9982             (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9983 
9984     if (h264_scratch.nFilledLen && look_ahead_nal) {
9985         look_ahead_nal = false;
9986         rc = copy_buffer(pdest_frame, &h264_scratch);
9987         if (rc != OMX_ErrorNone) {
9988             return rc;
9989         }
9990     }
9991 
9992     if (nal_length == 0) {
9993         if (m_frame_parser.parse_sc_frame(psource_frame,
9994                     &h264_scratch,&partial_frame) == -1) {
9995             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9996             return OMX_ErrorBadParameter;
9997         }
9998     } else {
9999         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
10000         if (m_frame_parser.parse_h264_nallength(psource_frame,
10001                     &h264_scratch,&partial_frame) == -1) {
10002             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
10003             return OMX_ErrorBadParameter;
10004         }
10005     }
10006 
10007     if (partial_frame == 0) {
10008         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
10009             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
10010             nal_count++;
10011             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
10012             h264_scratch.nFlags = psource_frame->nFlags;
10013         } else {
10014             DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
10015             if (h264_scratch.nFilledLen) {
10016                 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
10017                 nal_count++;
10018             }
10019 
10020             if (!isNewFrame) {
10021                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
10022                         nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
10023                         (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
10024                         (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
10025                 rc = copy_buffer(pdest_frame, &h264_scratch);
10026                 if (rc != OMX_ErrorNone) {
10027                     return rc;
10028                 }
10029             } else {
10030                 look_ahead_nal = true;
10031                 if (pdest_frame->nFilledLen == 0) {
10032                     look_ahead_nal = false;
10033                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
10034                     rc = copy_buffer(pdest_frame, &h264_scratch);
10035                     if (rc != OMX_ErrorNone) {
10036                         return OMX_ErrorBadParameter;
10037                     }
10038                 } else {
10039                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
10040                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
10041                     }
10042                     DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
10043                             nTimeStamp %lld, look_ahead_nal in h264_scratch \
10044                             nFilledLen %u nTimeStamp %lld",
10045                             frame_count++, (unsigned int)pdest_frame->nFilledLen,
10046                             pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
10047                             h264_scratch.nTimeStamp);
10048                     if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
10049                         return OMX_ErrorBadParameter;
10050                     }
10051                     pdest_frame = NULL;
10052                     if (m_input_free_q.m_size) {
10053                         m_input_free_q.pop_entry(&address, &p2, &id);
10054                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
10055                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
10056                         pdest_frame->nFilledLen = 0;
10057                         pdest_frame->nFlags = 0;
10058                         pdest_frame->nTimeStamp = LLONG_MAX;
10059                     }
10060                 }
10061             }
10062         }
10063     } else {
10064         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
10065                 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
10066                 nFilledLen %u nTimeStamp %lld",
10067                 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
10068                 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
10069                 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
10070 
10071         if (h264_scratch.nAllocLen ==
10072                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
10073             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
10074             return OMX_ErrorStreamCorrupt;
10075         }
10076     }
10077 
10078     if (!psource_frame->nFilledLen) {
10079         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
10080         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
10081             if (pdest_frame) {
10082                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
10083                 rc = copy_buffer(pdest_frame, &h264_scratch);
10084                 if ( rc != OMX_ErrorNone ) {
10085                     return rc;
10086                 }
10087                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
10088                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
10089                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
10090                         frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
10091                 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
10092                     return OMX_ErrorBadParameter;
10093                 }
10094                 frame_count++;
10095                 pdest_frame = NULL;
10096             } else {
10097                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
10098                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
10099                 generate_ebd = OMX_FALSE;
10100             }
10101         }
10102     }
10103 
10104     if (generate_ebd && !psource_frame->nFilledLen) {
10105         m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
10106         psource_frame = NULL;
10107         if (m_input_pending_q.m_size) {
10108             m_input_pending_q.pop_entry(&address, &p2, &id);
10109             psource_frame = (OMX_BUFFERHEADERTYPE *)address;
10110             DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
10111                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
10112         }
10113     }
10114     return OMX_ErrorNone;
10115 }
10116 
push_input_vc1(OMX_HANDLETYPE hComp)10117 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
10118 {
10119     OMX_U8 *buf, *pdest;
10120     OMX_U32 partial_frame = 1;
10121     OMX_U32 buf_len, dest_len;
10122 
10123     if (first_frame == 0) {
10124         first_frame = 1;
10125         DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
10126         if (!m_vendor_config.pData) {
10127             DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
10128             buf = psource_frame->pBuffer;
10129             buf_len = psource_frame->nFilledLen;
10130 
10131             if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
10132                     VC1_SP_MP_START_CODE) {
10133                 m_vc1_profile = VC1_SP_MP_RCV;
10134             } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
10135                 m_vc1_profile = VC1_AP;
10136             } else {
10137                 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
10138                 return OMX_ErrorStreamCorrupt;
10139             }
10140         } else {
10141             pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
10142                 pdest_frame->nOffset;
10143             dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
10144                     pdest_frame->nOffset);
10145 
10146             if (dest_len < m_vendor_config.nDataSize) {
10147                 DEBUG_PRINT_ERROR("Destination buffer full");
10148                 return OMX_ErrorBadParameter;
10149             } else {
10150                 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
10151                 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
10152             }
10153         }
10154     }
10155 
10156     switch (m_vc1_profile) {
10157         case VC1_AP:
10158             DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
10159             if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
10160                 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
10161                 return OMX_ErrorBadParameter;
10162             }
10163             break;
10164 
10165         case VC1_SP_MP_RCV:
10166         default:
10167             DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
10168             return OMX_ErrorBadParameter;
10169     }
10170     return OMX_ErrorNone;
10171 }
10172 
10173 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)10174 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
10175         OMX_U32 alignment)
10176 {
10177     struct pmem_allocation allocation;
10178     allocation.size = buffer_size;
10179     allocation.align = clip2(alignment);
10180     if (allocation.align < 4096) {
10181         allocation.align = 4096;
10182     }
10183     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
10184         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
10185                 allocation.align, allocation.size);
10186         return false;
10187     }
10188     return true;
10189 }
10190 #endif
10191 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,OMX_U32 alignment,struct ion_allocation_data * alloc_data,struct ion_fd_data * fd_data,int flag)10192 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
10193         OMX_U32 alignment, struct ion_allocation_data *alloc_data,
10194         struct ion_fd_data *fd_data, int flag)
10195 {
10196     int fd = -EINVAL;
10197     int rc = -EINVAL;
10198     int ion_dev_flag;
10199     struct vdec_ion ion_buf_info;
10200     if (!alloc_data || buffer_size <= 0 || !fd_data) {
10201         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
10202         return -EINVAL;
10203     }
10204     ion_dev_flag = O_RDONLY;
10205     fd = open (MEM_DEVICE, ion_dev_flag);
10206     if (fd < 0) {
10207         DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
10208         return fd;
10209     }
10210 
10211     alloc_data->flags = flag;
10212     alloc_data->len = buffer_size;
10213     alloc_data->align = clip2(alignment);
10214     if (alloc_data->align < 4096) {
10215         alloc_data->align = 4096;
10216     }
10217 
10218     alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
10219     if (secure_mode && (alloc_data->flags & ION_SECURE)) {
10220         alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
10221     }
10222 
10223     /* Use secure display cma heap for obvious reasons. */
10224     if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
10225         alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
10226     }
10227 
10228     rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
10229     if (rc || !alloc_data->handle) {
10230         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
10231         alloc_data->handle = 0;
10232         close(fd);
10233         fd = -ENOMEM;
10234         return fd;
10235     }
10236     fd_data->handle = alloc_data->handle;
10237     rc = ioctl(fd,ION_IOC_MAP,fd_data);
10238     if (rc) {
10239         DEBUG_PRINT_ERROR("ION MAP failed ");
10240         ion_buf_info.ion_alloc_data = *alloc_data;
10241         ion_buf_info.ion_device_fd = fd;
10242         ion_buf_info.fd_ion_data = *fd_data;
10243         free_ion_memory(&ion_buf_info);
10244         fd_data->fd =-1;
10245         fd = -ENOMEM;
10246     }
10247 
10248     return fd;
10249 }
10250 
free_ion_memory(struct vdec_ion * buf_ion_info)10251 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
10252 {
10253 
10254     if (!buf_ion_info) {
10255         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
10256         return;
10257     }
10258     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
10259                 &buf_ion_info->ion_alloc_data.handle)) {
10260         DEBUG_PRINT_ERROR("ION: free failed" );
10261     }
10262     close(buf_ion_info->ion_device_fd);
10263     buf_ion_info->ion_device_fd = -1;
10264     buf_ion_info->ion_alloc_data.handle = 0;
10265     buf_ion_info->fd_ion_data.fd = -1;
10266 }
10267 #endif
free_output_buffer_header()10268 void omx_vdec::free_output_buffer_header()
10269 {
10270     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
10271     output_use_buffer = false;
10272     ouput_egl_buffers = false;
10273 
10274     if (m_out_mem_ptr) {
10275         free (m_out_mem_ptr);
10276         m_out_mem_ptr = NULL;
10277     }
10278 
10279     if (m_platform_list) {
10280         free(m_platform_list);
10281         m_platform_list = NULL;
10282     }
10283 
10284     if (drv_ctx.ptr_respbuffer) {
10285         free (drv_ctx.ptr_respbuffer);
10286         drv_ctx.ptr_respbuffer = NULL;
10287     }
10288     if (drv_ctx.ptr_outputbuffer) {
10289         free (drv_ctx.ptr_outputbuffer);
10290         drv_ctx.ptr_outputbuffer = NULL;
10291     }
10292 #ifdef USE_ION
10293     if (drv_ctx.op_buf_ion_info) {
10294         DEBUG_PRINT_LOW("Free o/p ion context");
10295         free(drv_ctx.op_buf_ion_info);
10296         drv_ctx.op_buf_ion_info = NULL;
10297     }
10298 #endif
10299     free(drv_ctx.op_buf_map_info);
10300     drv_ctx.op_buf_map_info = NULL;
10301     buf_ref_remove();
10302 }
10303 
free_input_buffer_header()10304 void omx_vdec::free_input_buffer_header()
10305 {
10306     input_use_buffer = false;
10307     if (arbitrary_bytes) {
10308         if (m_inp_heap_ptr) {
10309             DEBUG_PRINT_LOW("Free input Heap Pointer");
10310             free (m_inp_heap_ptr);
10311             m_inp_heap_ptr = NULL;
10312         }
10313 
10314         if (m_phdr_pmem_ptr) {
10315             DEBUG_PRINT_LOW("Free input pmem header Pointer");
10316             free (m_phdr_pmem_ptr);
10317             m_phdr_pmem_ptr = NULL;
10318         }
10319     }
10320     if (m_inp_mem_ptr) {
10321         DEBUG_PRINT_LOW("Free input pmem Pointer area");
10322         free (m_inp_mem_ptr);
10323         m_inp_mem_ptr = NULL;
10324     }
10325     /* We just freed all the buffer headers, every thing in m_input_free_q,
10326      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
10327     while (m_input_free_q.m_size) {
10328         unsigned long address, p2, id;
10329         m_input_free_q.pop_entry(&address, &p2, &id);
10330     }
10331     while (m_input_pending_q.m_size) {
10332         unsigned long address, p2, id;
10333         m_input_pending_q.pop_entry(&address, &p2, &id);
10334     }
10335     pdest_frame = NULL;
10336     psource_frame = NULL;
10337     if (drv_ctx.ptr_inputbuffer) {
10338         DEBUG_PRINT_LOW("Free Driver Context pointer");
10339         free (drv_ctx.ptr_inputbuffer);
10340         drv_ctx.ptr_inputbuffer = NULL;
10341     }
10342 #ifdef USE_ION
10343     if (drv_ctx.ip_buf_ion_info) {
10344         DEBUG_PRINT_LOW("Free ion context");
10345         free(drv_ctx.ip_buf_ion_info);
10346         drv_ctx.ip_buf_ion_info = NULL;
10347     }
10348 #endif
10349 }
10350 
free_output_extradata_buffer_header()10351 void omx_vdec::free_output_extradata_buffer_header() {
10352     client_extradata = false;
10353     if (m_client_output_extradata_mem_ptr) {
10354         DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
10355         free(m_client_output_extradata_mem_ptr);
10356         m_client_output_extradata_mem_ptr = NULL;
10357     }
10358 }
10359 
stream_off(OMX_U32 port)10360 int omx_vdec::stream_off(OMX_U32 port)
10361 {
10362     enum v4l2_buf_type btype;
10363     int rc = 0;
10364     enum v4l2_ports v4l2_port = OUTPUT_PORT;
10365 
10366     if (port == OMX_CORE_INPUT_PORT_INDEX) {
10367         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10368         v4l2_port = OUTPUT_PORT;
10369     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10370         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10371         v4l2_port = CAPTURE_PORT;
10372     } else if (port == OMX_ALL) {
10373         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
10374         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
10375 
10376         if (!rc_input)
10377             return rc_input;
10378         else
10379             return rc_output;
10380     }
10381 
10382     if (!streaming[v4l2_port]) {
10383         // already streamed off, warn and move on
10384         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
10385                 " which is already streamed off", v4l2_port);
10386         return 0;
10387     }
10388 
10389     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
10390 
10391     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
10392     if (rc) {
10393         /*TODO: How to handle this case */
10394         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
10395     } else {
10396         streaming[v4l2_port] = false;
10397     }
10398 
10399     return rc;
10400 }
10401 
get_buffer_req(vdec_allocatorproperty * buffer_prop)10402 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
10403 {
10404     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10405     struct v4l2_requestbuffers bufreq;
10406     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
10407     unsigned int final_extra_data_size = 0;
10408     struct v4l2_format fmt;
10409     int ret = 0;
10410     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10411             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10412     bufreq.memory = V4L2_MEMORY_USERPTR;
10413     bufreq.count = 1;
10414     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10415         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10416         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10417         fmt.fmt.pix_mp.pixelformat = output_capability;
10418     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10419         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10420         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10421         fmt.fmt.pix_mp.pixelformat = capture_capability;
10422     } else {
10423         eRet = OMX_ErrorBadParameter;
10424     }
10425     if (eRet==OMX_ErrorNone) {
10426         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10427     }
10428     if (ret) {
10429         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10430         /*TODO: How to handle this case */
10431         eRet = OMX_ErrorInsufficientResources;
10432         return eRet;
10433     } else {
10434         bool is_res_1080p_or_below = (drv_ctx.video_resolution.frame_width <= 1920 &&
10435                                      drv_ctx.video_resolution.frame_height <= 1088) ||
10436                                      (drv_ctx.video_resolution.frame_height <= 1088 &&
10437                                       drv_ctx.video_resolution.frame_width <= 1920);
10438 
10439         int fps = drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator;
10440         bool fps_above_180 =  (fps >= 180 || operating_frame_rate >= 180) ? true : false;
10441         bool increase_output = (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) && (bufreq.count >= 16);
10442 
10443         if (increase_output && fps_above_180 &&
10444             output_capability == V4L2_PIX_FMT_H264 &&
10445             is_res_1080p_or_below) {
10446             m_need_turbo |= TURBO_MODE_HIGH_FPS;
10447             DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate);
10448             DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps",
10449                             bufreq.count, bufreq.count + 10);
10450             bufreq.count += 10;
10451             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10452             if (ret) {
10453                 DEBUG_PRINT_ERROR("(Failed to set updated buffer count to driver");
10454                 eRet = OMX_ErrorInsufficientResources;
10455                 return eRet;
10456             }
10457             DEBUG_PRINT_LOW("new buf count = %d set to driver", bufreq.count);
10458             request_perf_level(VIDC_TURBO);
10459         }
10460 
10461         buffer_prop->actualcount = bufreq.count;
10462         buffer_prop->mincount = bufreq.count;
10463         DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
10464     }
10465     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10466             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10467 
10468     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10469 
10470     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
10471         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
10472     DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
10473 
10474     if (ret) {
10475         /*TODO: How to handle this case */
10476         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10477         eRet = OMX_ErrorInsufficientResources;
10478     } else {
10479         int extra_idx = 0;
10480 
10481         eRet = is_video_session_supported();
10482         if (eRet)
10483             return eRet;
10484 
10485         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10486         buf_size = buffer_prop->buffer_size;
10487         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
10488         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
10489             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
10490         } else if (extra_idx >= VIDEO_MAX_PLANES) {
10491             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
10492             return OMX_ErrorBadParameter;
10493         }
10494 
10495         default_extra_data_size = VENUS_EXTRADATA_SIZE(
10496                 drv_ctx.video_resolution.frame_height,
10497                 drv_ctx.video_resolution.frame_width);
10498         final_extra_data_size = extra_data_size > default_extra_data_size ?
10499             extra_data_size : default_extra_data_size;
10500 
10501         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
10502             (~(buffer_prop->alignment - 1));
10503 
10504         drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
10505         drv_ctx.extradata_info.count = buffer_prop->actualcount;
10506         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
10507         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10508         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
10509                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
10510         if (extra_data_size)
10511             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
10512                 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
10513 
10514         if (in_reconfig) // BufReq will be set to driver when port is disabled
10515             buffer_prop->buffer_size = buf_size;
10516         else if (buf_size != buffer_prop->buffer_size) {
10517             buffer_prop->buffer_size = buf_size;
10518             eRet = set_buffer_req(buffer_prop);
10519         }
10520     }
10521     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
10522             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10523     return eRet;
10524 }
10525 
set_buffer_req(vdec_allocatorproperty * buffer_prop)10526 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
10527 {
10528     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10529     unsigned buf_size = 0;
10530     struct v4l2_format fmt, c_fmt;
10531     struct v4l2_requestbuffers bufreq;
10532     int ret = 0;
10533     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
10534             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10535     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10536     if (buf_size != buffer_prop->buffer_size) {
10537         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
10538                 (unsigned int)buffer_prop->buffer_size, buf_size);
10539         eRet = OMX_ErrorBadParameter;
10540     } else {
10541         memset(&fmt, 0x0, sizeof(struct v4l2_format));
10542         memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
10543         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10544         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10545         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10546 
10547         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10548             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10549             fmt.fmt.pix_mp.pixelformat = output_capability;
10550             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10551         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10552             c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10553             c_fmt.fmt.pix_mp.pixelformat = capture_capability;
10554             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
10555             c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10556             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
10557         } else {
10558             eRet = OMX_ErrorBadParameter;
10559         }
10560 
10561         if (ret) {
10562             /*TODO: How to handle this case */
10563             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
10564             eRet = OMX_ErrorInsufficientResources;
10565         }
10566 
10567         bufreq.memory = V4L2_MEMORY_USERPTR;
10568         bufreq.count = buffer_prop->actualcount;
10569         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10570             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10571         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10572             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10573         } else {
10574             eRet = OMX_ErrorBadParameter;
10575         }
10576 
10577         if (eRet==OMX_ErrorNone) {
10578             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10579         }
10580 
10581         if (ret) {
10582             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
10583             /*TODO: How to handle this case */
10584             eRet = OMX_ErrorInsufficientResources;
10585         } else if (bufreq.count < buffer_prop->actualcount) {
10586             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
10587                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
10588                     buffer_prop->actualcount, bufreq.count);
10589             eRet = OMX_ErrorInsufficientResources;
10590         } else {
10591             if (!client_buffers.update_buffer_req()) {
10592                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
10593                 eRet = OMX_ErrorInsufficientResources;
10594             }
10595         }
10596     }
10597     return eRet;
10598 }
10599 
update_picture_resolution()10600 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
10601 {
10602     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10603     return eRet;
10604 }
10605 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)10606 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
10607 {
10608     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10609     struct v4l2_format fmt;
10610     if (!portDefn) {
10611         return OMX_ErrorBadParameter;
10612     }
10613     DEBUG_PRINT_LOW("omx_vdec::update_portdef");
10614     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
10615     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10616     portDefn->eDomain    = OMX_PortDomainVideo;
10617     memset(&fmt, 0x0, sizeof(struct v4l2_format));
10618     if (0 == portDefn->nPortIndex) {
10619         portDefn->eDir =  OMX_DirInput;
10620         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
10621         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
10622         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
10623         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10624         portDefn->format.video.eCompressionFormat = eCompressionFormat;
10625         //for input port, always report the fps value set by client,
10626         //to distinguish whether client got valid fps from parser.
10627         portDefn->format.video.xFramerate = m_fps_received;
10628         portDefn->bEnabled   = m_inp_bEnabled;
10629         portDefn->bPopulated = m_inp_bPopulated;
10630 
10631         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10632         fmt.fmt.pix_mp.pixelformat = output_capability;
10633         ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10634     } else if (1 == portDefn->nPortIndex) {
10635         unsigned int buf_size = 0;
10636         int ret = 0;
10637        if (in_reconfig && !is_down_scalar_enabled) {
10638            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10639            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10640            fmt.fmt.pix_mp.pixelformat = capture_capability;
10641            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10642            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10643        }
10644 
10645        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10646        fmt.fmt.pix_mp.pixelformat = capture_capability;
10647        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10648        if (ret) {
10649            DEBUG_PRINT_ERROR("Get Resolution failed");
10650            return OMX_ErrorHardware;
10651        }
10652        drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10653        if (!client_buffers.update_buffer_req()) {
10654            DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
10655            return OMX_ErrorHardware;
10656        }
10657 
10658         if (!client_buffers.get_buffer_req(buf_size)) {
10659             DEBUG_PRINT_ERROR("update buffer requirements");
10660             return OMX_ErrorHardware;
10661         }
10662         portDefn->nBufferSize = buf_size;
10663         portDefn->eDir =  OMX_DirOutput;
10664         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
10665         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
10666         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10667         if (drv_ctx.frame_rate.fps_denominator > 0)
10668             portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
10669                 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
10670         else {
10671             DEBUG_PRINT_ERROR("Error: Divide by zero");
10672             return OMX_ErrorBadParameter;
10673         }
10674         portDefn->bEnabled   = m_out_bEnabled;
10675         portDefn->bPopulated = m_out_bPopulated;
10676         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
10677             DEBUG_PRINT_ERROR("Error in getting color format");
10678             return OMX_ErrorHardware;
10679         }
10680         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10681         fmt.fmt.pix_mp.pixelformat = capture_capability;
10682     } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
10683         portDefn->nBufferSize = m_client_out_extradata_info.getSize();
10684         portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10685         portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10686         portDefn->eDir =  OMX_DirOutput;
10687     } else {
10688         portDefn->eDir = OMX_DirMax;
10689         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
10690                 (int)portDefn->nPortIndex);
10691         eRet = OMX_ErrorBadPortIndex;
10692     }
10693     update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10694         fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
10695 
10696         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
10697         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
10698         portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10699         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10700 
10701     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
10702        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
10703            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
10704            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
10705     }
10706     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
10707             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
10708             (unsigned int)portDefn->nPortIndex,
10709             (unsigned int)portDefn->format.video.nFrameWidth,
10710             (unsigned int)portDefn->format.video.nFrameHeight,
10711             (int)portDefn->format.video.nStride,
10712             (unsigned int)portDefn->format.video.nSliceHeight,
10713             (unsigned int)portDefn->format.video.eColorFormat,
10714             (unsigned int)portDefn->nBufferSize,
10715             (unsigned int)portDefn->nBufferCountActual);
10716 
10717     return eRet;
10718 }
10719 
allocate_output_headers()10720 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
10721 {
10722     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10723     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
10724     unsigned i = 0;
10725 
10726     if (!m_out_mem_ptr) {
10727         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
10728         int nBufHdrSize        = 0;
10729         int nPlatformEntrySize = 0;
10730         int nPlatformListSize  = 0;
10731         int nPMEMInfoSize = 0;
10732         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
10733         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
10734         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
10735 
10736         DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
10737                 drv_ctx.op_buf.actualcount);
10738         nBufHdrSize        = drv_ctx.op_buf.actualcount *
10739             sizeof(OMX_BUFFERHEADERTYPE);
10740 
10741         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
10742             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
10743         nPlatformListSize  = drv_ctx.op_buf.actualcount *
10744             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
10745         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
10746             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
10747 
10748         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
10749                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
10750                 nPMEMInfoSize,
10751                 nPlatformListSize);
10752         DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
10753                 m_out_bm_count);
10754         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
10755         // Alloc mem for platform specific info
10756         char *pPtr=NULL;
10757         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
10758                 nPMEMInfoSize,1);
10759         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
10760                        calloc (sizeof(struct vdec_bufferpayload),
10761                                drv_ctx.op_buf.actualcount);
10762         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
10763                      calloc (sizeof (struct vdec_output_frameinfo),
10764                              drv_ctx.op_buf.actualcount);
10765         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
10766             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
10767             return OMX_ErrorInsufficientResources;
10768         }
10769 
10770 #ifdef USE_ION
10771         drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
10772                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
10773         if (!drv_ctx.op_buf_ion_info) {
10774             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
10775             return OMX_ErrorInsufficientResources;
10776         }
10777 #endif
10778         if (dynamic_buf_mode) {
10779             out_dynamic_list = (struct dynamic_buf_list *) \
10780                 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
10781             if (out_dynamic_list) {
10782                for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
10783                   out_dynamic_list[i].dup_fd = -1;
10784             }
10785         }
10786 
10787         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
10788                 && drv_ctx.ptr_respbuffer) {
10789             bufHdr          =  m_out_mem_ptr;
10790             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
10791             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
10792                 (((char *) m_platform_list)  + nPlatformListSize);
10793             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10794                 (((char *) m_platform_entry) + nPlatformEntrySize);
10795             pPlatformList   = m_platform_list;
10796             pPlatformEntry  = m_platform_entry;
10797             pPMEMInfo       = m_pmem_info;
10798 
10799             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
10800 
10801             // Settting the entire storage nicely
10802             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10803                     m_out_mem_ptr,pPlatformEntry);
10804             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10805             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10806                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
10807                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
10808                 // Set the values when we determine the right HxW param
10809                 bufHdr->nAllocLen          = 0;
10810                 bufHdr->nFilledLen         = 0;
10811                 bufHdr->pAppPrivate        = NULL;
10812                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
10813                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10814                 pPlatformEntry->entry      = pPMEMInfo;
10815                 // Initialize the Platform List
10816                 pPlatformList->nEntries    = 1;
10817                 pPlatformList->entryList   = pPlatformEntry;
10818                 // Keep pBuffer NULL till vdec is opened
10819                 bufHdr->pBuffer            = NULL;
10820                 pPMEMInfo->offset          =  0;
10821                 pPMEMInfo->pmem_fd = -1;
10822                 bufHdr->pPlatformPrivate = pPlatformList;
10823                 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
10824 #ifdef USE_ION
10825                 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
10826 #endif
10827                 /*Create a mapping between buffers*/
10828                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
10829                 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
10830                                     &drv_ctx.ptr_outputbuffer[i];
10831                 // Move the buffer and buffer header pointers
10832                 bufHdr++;
10833                 pPMEMInfo++;
10834                 pPlatformEntry++;
10835                 pPlatformList++;
10836             }
10837         } else {
10838             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10839                     m_out_mem_ptr, pPtr);
10840             if (m_out_mem_ptr) {
10841                 free(m_out_mem_ptr);
10842                 m_out_mem_ptr = NULL;
10843             }
10844             if (pPtr) {
10845                 free(pPtr);
10846                 pPtr = NULL;
10847             }
10848             if (drv_ctx.ptr_outputbuffer) {
10849                 free(drv_ctx.ptr_outputbuffer);
10850                 drv_ctx.ptr_outputbuffer = NULL;
10851             }
10852             if (drv_ctx.ptr_respbuffer) {
10853                 free(drv_ctx.ptr_respbuffer);
10854                 drv_ctx.ptr_respbuffer = NULL;
10855             }
10856 #ifdef USE_ION
10857             if (drv_ctx.op_buf_ion_info) {
10858                 DEBUG_PRINT_LOW("Free o/p ion context");
10859                 free(drv_ctx.op_buf_ion_info);
10860                 drv_ctx.op_buf_ion_info = NULL;
10861             }
10862 #endif
10863             free(drv_ctx.op_buf_map_info);
10864             drv_ctx.op_buf_map_info = NULL;
10865             eRet =  OMX_ErrorInsufficientResources;
10866         }
10867     } else {
10868         eRet =  OMX_ErrorInsufficientResources;
10869     }
10870     return eRet;
10871 }
10872 
complete_pending_buffer_done_cbs()10873 void omx_vdec::complete_pending_buffer_done_cbs()
10874 {
10875     unsigned long p1, p2, ident;
10876     omx_cmd_queue tmp_q, pending_bd_q;
10877     pthread_mutex_lock(&m_lock);
10878     // pop all pending GENERATE FDB from ftb queue
10879     while (m_ftb_q.m_size) {
10880         m_ftb_q.pop_entry(&p1,&p2,&ident);
10881         if (ident == OMX_COMPONENT_GENERATE_FBD) {
10882             pending_bd_q.insert_entry(p1,p2,ident);
10883         } else {
10884             tmp_q.insert_entry(p1,p2,ident);
10885         }
10886     }
10887     //return all non GENERATE FDB to ftb queue
10888     while (tmp_q.m_size) {
10889         tmp_q.pop_entry(&p1,&p2,&ident);
10890         m_ftb_q.insert_entry(p1,p2,ident);
10891     }
10892     // pop all pending GENERATE EDB from etb queue
10893     while (m_etb_q.m_size) {
10894         m_etb_q.pop_entry(&p1,&p2,&ident);
10895         if (ident == OMX_COMPONENT_GENERATE_EBD) {
10896             pending_bd_q.insert_entry(p1,p2,ident);
10897         } else {
10898             tmp_q.insert_entry(p1,p2,ident);
10899         }
10900     }
10901     //return all non GENERATE FDB to etb queue
10902     while (tmp_q.m_size) {
10903         tmp_q.pop_entry(&p1,&p2,&ident);
10904         m_etb_q.insert_entry(p1,p2,ident);
10905     }
10906     pthread_mutex_unlock(&m_lock);
10907     // process all pending buffer dones
10908     while (pending_bd_q.m_size) {
10909         pending_bd_q.pop_entry(&p1,&p2,&ident);
10910         switch (ident) {
10911             case OMX_COMPONENT_GENERATE_EBD:
10912                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10913                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10914                     omx_report_error ();
10915                 }
10916                 break;
10917 
10918             case OMX_COMPONENT_GENERATE_FBD:
10919                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10920                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10921                     omx_report_error ();
10922                 }
10923                 break;
10924         }
10925     }
10926 }
10927 
set_frame_rate(OMX_S64 act_timestamp)10928 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10929 {
10930     OMX_U32 new_frame_interval = 0;
10931     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10932             && llabs(act_timestamp - prev_ts) > 2000) {
10933         new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10934             llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10935         if (new_frame_interval != frm_int || frm_int == 0) {
10936             frm_int = new_frame_interval;
10937             if (frm_int) {
10938                 drv_ctx.frame_rate.fps_numerator = 1e6;
10939                 drv_ctx.frame_rate.fps_denominator = frm_int;
10940                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10941                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10942                         (float)drv_ctx.frame_rate.fps_denominator);
10943                 m_perf_control.request_cores(frm_int);
10944                 /* We need to report the difference between this FBD and the previous FBD
10945                  * back to the driver for clock scaling purposes. */
10946                 struct v4l2_outputparm oparm;
10947                 /*XXX: we're providing timing info as seconds per frame rather than frames
10948                  * per second.*/
10949                 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10950                 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10951 
10952                 struct v4l2_streamparm sparm;
10953                 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10954                 sparm.parm.output = oparm;
10955                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10956                     DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10957                             performance might be affected");
10958                 }
10959 
10960             }
10961         }
10962     }
10963     prev_ts = act_timestamp;
10964 }
10965 
adjust_timestamp(OMX_S64 & act_timestamp)10966 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10967 {
10968     if (rst_prev_ts && VALID_TS(act_timestamp)) {
10969         prev_ts = act_timestamp;
10970         prev_ts_actual = act_timestamp;
10971         rst_prev_ts = false;
10972     } else if (VALID_TS(prev_ts)) {
10973         bool codec_cond = (drv_ctx.timestamp_adjust)?
10974             (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10975             (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10976              prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10977         if (frm_int > 0 && codec_cond) {
10978             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10979             act_timestamp = prev_ts + frm_int;
10980             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10981             prev_ts = act_timestamp;
10982         } else {
10983             if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10984                 // ensure that timestamps can never step backwards when in display order
10985                 act_timestamp = prev_ts;
10986             }
10987             set_frame_rate(act_timestamp);
10988         }
10989     } else if (frm_int > 0)          // In this case the frame rate was set along
10990     {                               // with the port definition, start ts with 0
10991         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
10992         rst_prev_ts = true;
10993     }
10994 }
10995 
get_omx_output_buffer_header(int index)10996 OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index)
10997 {
10998     return m_out_mem_ptr + index;
10999 }
11000 
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorSpace_t * color_space,ColorAspects * aspects)11001 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
11002     OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
11003 {
11004     switch (primaries) {
11005         case MSM_VIDC_BT709_5:
11006             *color_space = ITU_R_709;
11007             aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
11008             break;
11009         case MSM_VIDC_BT470_6_M:
11010             aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
11011             break;
11012         case MSM_VIDC_BT601_6_625:
11013             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
11014             break;
11015         case MSM_VIDC_BT601_6_525:
11016             *color_space = range ? ITU_R_601_FR : ITU_R_601;
11017             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
11018             break;
11019         case MSM_VIDC_GENERIC_FILM:
11020             aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
11021             break;
11022         case MSM_VIDC_BT2020:
11023             aspects->mPrimaries = ColorAspects::PrimariesBT2020;
11024             break;
11025         case MSM_VIDC_UNSPECIFIED:
11026             //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
11027         default:
11028             //aspects->mPrimaries = ColorAspects::PrimariesOther;
11029             aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11030             break;
11031     }
11032 
11033     aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
11034 
11035     switch (transfer) {
11036         case MSM_VIDC_TRANSFER_BT709_5:
11037         case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
11038             aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11039             break;
11040         case MSM_VIDC_TRANSFER_BT_470_6_M:
11041             aspects->mTransfer = ColorAspects::TransferGamma22;
11042             break;
11043         case MSM_VIDC_TRANSFER_BT_470_6_BG:
11044             aspects->mTransfer = ColorAspects::TransferGamma28;
11045             break;
11046         case MSM_VIDC_TRANSFER_SMPTE_240M:
11047             aspects->mTransfer = ColorAspects::TransferSMPTE240M;
11048             break;
11049         case MSM_VIDC_TRANSFER_LINEAR:
11050             aspects->mTransfer = ColorAspects::TransferLinear;
11051             break;
11052         case MSM_VIDC_TRANSFER_IEC_61966:
11053             aspects->mTransfer = ColorAspects::TransferXvYCC;
11054             break;
11055         case MSM_VIDC_TRANSFER_BT_1361:
11056             aspects->mTransfer = ColorAspects::TransferBT1361;
11057             break;
11058         case MSM_VIDC_TRANSFER_SRGB:
11059             aspects->mTransfer = ColorAspects::TransferSRGB;
11060             break;
11061         case MSM_VIDC_TRANSFER_SMPTE_ST2084:
11062             aspects->mTransfer = ColorAspects::TransferST2084;
11063             break;
11064         case MSM_VIDC_TRANSFER_HLG:
11065             aspects->mTransfer = ColorAspects::TransferHLG;
11066             break;
11067         default:
11068             //aspects->mTransfer = ColorAspects::TransferOther;
11069             aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
11070             break;
11071     }
11072 
11073     switch (matrix) {
11074         case MSM_VIDC_MATRIX_BT_709_5:
11075             aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11076             break;
11077         case MSM_VIDC_MATRIX_FCC_47:
11078             aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
11079             break;
11080         case MSM_VIDC_MATRIX_601_6_625:
11081         case MSM_VIDC_MATRIX_601_6_525:
11082             aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11083             break;
11084         case MSM_VIDC_MATRIX_SMPTE_240M:
11085             aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
11086             break;
11087         case MSM_VIDC_MATRIX_BT_2020:
11088             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
11089             break;
11090         case MSM_VIDC_MATRIX_BT_2020_CONST:
11091             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
11092             break;
11093         default:
11094             //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
11095             aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
11096             break;
11097     }
11098 }
11099 
print_debug_color_aspects(ColorAspects * a,const char * prefix)11100 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) {
11101         DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)",
11102                 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange),
11103                 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs));
11104 }
11105 
prepare_color_aspects_metadata(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorMetaData * color_mdata)11106 void omx_vdec::prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range,
11107                                               OMX_U32 transfer, OMX_U32 matrix,
11108                                               ColorMetaData *color_mdata)
11109 {
11110 
11111     /* ColorAspects in qdMetaData */
11112     color_mdata->colorPrimaries = (enum ColorPrimaries) primaries;
11113     color_mdata->range = (enum ColorRange)range;
11114     color_mdata->transfer = (enum GammaTransfer)transfer;
11115     color_mdata->matrixCoefficients = (enum MatrixCoEfficients)matrix;
11116 }
11117 
handle_color_space_info(void * data,ColorSpace_t * color_space,ColorMetaData * color_mdata,bool & set_color_aspects_only)11118 bool omx_vdec::handle_color_space_info(void *data,
11119                                        ColorSpace_t *color_space,
11120                                        ColorMetaData *color_mdata,
11121                                        bool& set_color_aspects_only)
11122 {
11123     ColorAspects tempAspects;
11124     memset(&tempAspects, 0x0, sizeof(ColorAspects));
11125     ColorAspects *aspects = &tempAspects;
11126 
11127     /* Set default ColorAspects */
11128     prepare_color_aspects_metadata(ColorPrimaries_BT601_6_625, Range_Full,
11129                                            Transfer_SMPTE_170M, MatrixCoEff_BT601_6_625,
11130                                            color_mdata);
11131 
11132     switch(output_capability) {
11133         case V4L2_PIX_FMT_MPEG2:
11134             {
11135                 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
11136                 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
11137 
11138                 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
11139                  * understand this code */
11140 
11141                 if (seqdisp_payload && seqdisp_payload->color_descp) {
11142 
11143                     convert_color_space_info(seqdisp_payload->color_primaries, 1,
11144                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
11145                             color_space,aspects);
11146                     m_disp_hor_size = seqdisp_payload->disp_width;
11147                     m_disp_vert_size = seqdisp_payload->disp_height;
11148                     set_color_aspects_only = true;
11149                     prepare_color_aspects_metadata(seqdisp_payload->color_primaries, 1,
11150                                                     seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
11151                                                     color_mdata);
11152                 }
11153             }
11154             break;
11155         case V4L2_PIX_FMT_H264:
11156         case V4L2_PIX_FMT_HEVC:
11157             {
11158                 struct msm_vidc_vui_display_info_payload *display_info_payload;
11159                 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
11160 
11161                 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
11162 
11163                 if (display_info_payload->video_signal_present_flag &&
11164                         display_info_payload->color_description_present_flag) {
11165                     convert_color_space_info(display_info_payload->color_primaries,
11166                             display_info_payload->video_full_range_flag,
11167                             display_info_payload->transfer_characteristics,
11168                             display_info_payload->matrix_coefficients,
11169                             color_space,aspects);
11170                     set_color_aspects_only = true;
11171                     prepare_color_aspects_metadata(display_info_payload->color_primaries,
11172                                                    display_info_payload->video_full_range_flag,
11173                                                    display_info_payload->transfer_characteristics,
11174                                                    display_info_payload->matrix_coefficients,
11175                                                    color_mdata);
11176                 }
11177             }
11178             break;
11179         case V4L2_PIX_FMT_VC1_ANNEX_G:
11180         case V4L2_PIX_FMT_VC1_ANNEX_L:
11181             {
11182                 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
11183                 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
11184 
11185                 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
11186                  * SMPTE 421M to understand this code */
11187 
11188                 if (m_enable_android_native_buffers &&
11189                         vc1_seq_disp_payload->color_primaries) {
11190 
11191                     convert_color_space_info(vc1_seq_disp_payload->color_primaries,
11192                             1,
11193                             vc1_seq_disp_payload->transfer_char,
11194                             vc1_seq_disp_payload->matrix_coeffs,
11195                             color_space,aspects);
11196                     set_color_aspects_only = true;
11197                     prepare_color_aspects_metadata(vc1_seq_disp_payload->color_primaries,
11198                                                    1,
11199                                                    vc1_seq_disp_payload->transfer_char,
11200                                                    vc1_seq_disp_payload->matrix_coeffs,
11201                                                    color_mdata);
11202                 }
11203             }
11204             break;
11205         case V4L2_PIX_FMT_VP8:
11206             {
11207                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
11208                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
11209                 set_color_aspects_only = false;
11210                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
11211                  * to understand this code */
11212 
11213                 if (vpx_color_space_payload->color_space == 0) {
11214                     *color_space = ITU_R_601;
11215                     aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
11216                     aspects->mRange = ColorAspects::RangeLimited;
11217                 } else {
11218                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
11219                     break;
11220                 }
11221             }
11222             break;
11223         case V4L2_PIX_FMT_VP9:
11224             {
11225                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
11226                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
11227                 set_color_aspects_only = false;
11228                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
11229                  * to understand this code */
11230 
11231                 switch(vpx_color_space_payload->color_space) {
11232                     case MSM_VIDC_CS_BT_601:
11233                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11234                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11235                         aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
11236                         aspects->mRange = m_client_color_space.sAspects.mRange;
11237                         break;
11238                     case MSM_VIDC_CS_BT_709:
11239                         *color_space = ITU_R_709;
11240                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11241                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11242                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
11243                         aspects->mRange = m_client_color_space.sAspects.mRange;
11244                         break;
11245                     case MSM_VIDC_CS_SMPTE_170:
11246                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11247                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11248                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11249                         aspects->mRange = m_client_color_space.sAspects.mRange;
11250                         break;
11251                     case MSM_VIDC_CS_SMPTE_240:
11252                         aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
11253                         aspects->mTransfer = ColorAspects::TransferSMPTE240M;
11254                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11255                         aspects->mRange = m_client_color_space.sAspects.mRange;
11256                         break;
11257                     case MSM_VIDC_CS_BT_2020:
11258                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
11259                         aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
11260                         aspects->mPrimaries = ColorAspects::PrimariesBT2020;
11261                         aspects->mRange = m_client_color_space.sAspects.mRange;
11262                         break;
11263                     case MSM_VIDC_CS_RESERVED:
11264                         aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
11265                         aspects->mTransfer = ColorAspects::TransferOther;
11266                         aspects->mPrimaries = ColorAspects::PrimariesOther;
11267                         aspects->mRange = m_client_color_space.sAspects.mRange;
11268                         break;
11269                     case MSM_VIDC_CS_RGB:
11270                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11271                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11272                         aspects->mPrimaries = ColorAspects::PrimariesOther;
11273                         aspects->mRange = m_client_color_space.sAspects.mRange;
11274                         break;
11275                     default:
11276                         break;
11277                 }
11278             }
11279             break;
11280         default:
11281             break;
11282     }
11283 
11284     print_debug_color_aspects(aspects, "Bitstream");
11285 
11286     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
11287             m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
11288             m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
11289             m_internal_color_space.sAspects.mRange != aspects->mRange) {
11290         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
11291 
11292         m_color_mdata.colorPrimaries = color_mdata->colorPrimaries;
11293         m_color_mdata.range = color_mdata->range;
11294         m_color_mdata.transfer = color_mdata->transfer;
11295         m_color_mdata.matrixCoefficients = color_mdata->matrixCoefficients;
11296 
11297         DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
11298         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
11299         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
11300 
11301         post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11302                 OMX_QTIIndexConfigDescribeColorAspects,
11303                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11304         return true;
11305     }
11306     return false;
11307 }
11308 
set_colorspace_in_handle(ColorSpace_t color_space,unsigned int buf_index)11309 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
11310     private_handle_t *private_handle = NULL;
11311     if (buf_index < drv_ctx.op_buf.actualcount &&
11312             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11313             native_buffer[buf_index].privatehandle) {
11314         private_handle = native_buffer[buf_index].privatehandle;
11315     }
11316     if (private_handle) {
11317         setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
11318     }
11319 }
11320 
print_debug_hdr_color_info(HDRStaticInfo * hdr_info,const char * prefix)11321 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
11322 {
11323     if (!hdr_info->mID) {
11324         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
11325                          hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
11326         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
11327                          hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
11328         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
11329                          hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
11330         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
11331                          hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
11332         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
11333                          hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
11334         DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
11335                         hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
11336     }
11337 
11338 }
11339 
print_debug_hdr_color_info_mdata(ColorMetaData * color_mdata)11340 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
11341 {
11342     DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
11343                     color_mdata->colorPrimaries, color_mdata->range,
11344                     color_mdata->transfer, color_mdata->matrixCoefficients);
11345 
11346     for(uint8_t i = 0; i < 3; i++) {
11347         for(uint8_t j = 0; j < 2; j++) {
11348             DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
11349         }
11350     }
11351 
11352     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
11353                     color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
11354                     color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
11355 
11356     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
11357                     color_mdata->masteringDisplayInfo.maxDisplayLuminance,
11358                     color_mdata->masteringDisplayInfo.minDisplayLuminance);
11359 
11360     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
11361                     color_mdata->contentLightLevel.maxContentLightLevel,
11362                     color_mdata->contentLightLevel.minPicAverageLightLevel);
11363 
11364 
11365 }
11366 
handle_content_light_level_info(void * data,ContentLightLevel * light_level_mdata)11367 bool omx_vdec::handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata)
11368 {
11369     struct msm_vidc_content_light_level_sei_payload *light_level_payload =
11370         (msm_vidc_content_light_level_sei_payload*)(data);
11371 
11372     light_level_mdata->lightLevelSEIEnabled = true;
11373     light_level_mdata->maxContentLightLevel = light_level_payload->nMaxContentLight;
11374     light_level_mdata->minPicAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11375 
11376     if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
11377         (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
11378         m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
11379         m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11380         return true;
11381     }
11382     return false;
11383 }
11384 
handle_mastering_display_color_info(void * data,MasteringDisplay * mastering_display_mdata)11385 bool omx_vdec::handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata)
11386 {
11387     struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
11388         (msm_vidc_mastering_display_colour_sei_payload*)(data);
11389     HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
11390     bool internal_disp_changed_flag = false;
11391 
11392     mastering_display_mdata->colorVolumeSEIEnabled = true;
11393     for (uint8_t i = 0; i < 3; i++) {
11394         mastering_display_mdata->primaries.rgbPrimaries[i][0] = mastering_display_payload->nDisplayPrimariesX[i];
11395         mastering_display_mdata->primaries.rgbPrimaries[i][1] = mastering_display_payload->nDisplayPrimariesY[i];
11396     }
11397     mastering_display_mdata->primaries.whitePoint[0] = mastering_display_payload->nWhitePointX;
11398     mastering_display_mdata->primaries.whitePoint[1] = mastering_display_payload->nWhitePointY;
11399     mastering_display_mdata->maxDisplayLuminance = mastering_display_payload->nMaxDisplayMasteringLuminance;
11400     mastering_display_mdata->minDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11401 
11402     internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
11403         (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[0]);
11404     internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
11405         (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[1]);
11406     internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
11407         (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[2]);
11408 
11409     internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
11410         (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
11411 
11412     /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
11413        requires it in cd/m2, so dividing by 10000 and rounding the value after division
11414     */
11415     uint16_t max_display_luminance_cd_m2 =
11416         static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
11417     internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
11418         (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
11419 
11420     if (internal_disp_changed_flag) {
11421         hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[0];
11422         hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[0];
11423         hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[1];
11424         hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[1];
11425         hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[2];
11426         hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[2];
11427         hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
11428         hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
11429 
11430         hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
11431         hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11432     }
11433 
11434     return internal_disp_changed_flag;
11435 }
11436 
set_colormetadata_in_handle(ColorMetaData * color_mdata,unsigned int buf_index)11437 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
11438 {
11439     private_handle_t *private_handle = NULL;
11440     if (buf_index < drv_ctx.op_buf.actualcount &&
11441         buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11442         native_buffer[buf_index].privatehandle) {
11443         private_handle = native_buffer[buf_index].privatehandle;
11444     }
11445     if (private_handle) {
11446         setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
11447     }
11448 }
11449 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)11450 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11451 {
11452     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
11453     OMX_U8 *pBuffer = NULL;
11454     OMX_U32 num_conceal_MB = 0;
11455     OMX_TICKS time_stamp = 0;
11456     OMX_U32 frame_rate = 0;
11457     unsigned long consumed_len = 0;
11458     OMX_U32 num_MB_in_frame;
11459     OMX_U32 recovery_sei_flags = 1;
11460     int enable = OMX_InterlaceFrameProgressive;
11461     bool internal_hdr_info_changed_flag = false;
11462     bool color_event = false;
11463     ColorMetaData color_mdata;
11464     memset(&color_mdata, 0x0, sizeof(ColorMetaData));
11465     bool set_disp_color_aspects_only = false;
11466     ColorSpace_t color_space = ITU_R_601;
11467 
11468     int buf_index = p_buf_hdr - m_out_mem_ptr;
11469     if (buf_index >= drv_ctx.extradata_info.count) {
11470         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
11471                 buf_index, drv_ctx.extradata_info.count);
11472         return;
11473     }
11474     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
11475 
11476     if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
11477         DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
11478         return;
11479     }
11480 
11481     if (!drv_ctx.extradata_info.uaddr) {
11482         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
11483         return;
11484     }
11485     if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
11486         DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
11487         p_extra = NULL;
11488         return;
11489     }
11490     if (!secure_mode) {
11491         pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
11492                     PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
11493         if (pBuffer == MAP_FAILED) {
11494             DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno);
11495             return;
11496         }
11497         p_extra = (OMX_OTHER_EXTRADATATYPE *)
11498             ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
11499     } else
11500         p_extra = m_other_extradata;
11501 
11502     AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
11503     if (m_client_output_extradata_mem_ptr &&
11504         m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
11505         p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
11506     }
11507 
11508     char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
11509 
11510     if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11511         p_extra = NULL;
11512         DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11513         return;
11514     }
11515     m_extradata_info.output_crop_updated = OMX_FALSE;
11516     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
11517     if (data && p_extra) {
11518         while ((consumed_len < drv_ctx.extradata_info.buffer_size)
11519                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
11520             if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
11521                 DEBUG_PRINT_LOW("Invalid extra data size");
11522                 break;
11523             }
11524 
11525             if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11526                 p_extra = NULL;
11527                 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11528                 return;
11529             }
11530 
11531             DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
11532             switch ((unsigned long)data->eType) {
11533                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
11534                     struct msm_vidc_interlace_payload *payload;
11535                     OMX_U32 interlace_color_format;
11536                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
11537                     if (payload) {
11538                         enable = OMX_InterlaceFrameProgressive;
11539                         switch (payload->format) {
11540                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
11541                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11542                                 break;
11543                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
11544                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11545                                 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
11546                                 break;
11547                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
11548                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11549                                 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11550                                 break;
11551                             default:
11552                                 DEBUG_PRINT_LOW("default case - set to progressive");
11553                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11554                         }
11555                         switch (payload->color_format) {
11556                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
11557                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11558                                break;
11559                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
11560                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11561                                break;
11562                            default:
11563                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11564                                DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
11565                         }
11566                     }
11567 
11568                     if (m_enable_android_native_buffers) {
11569                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
11570                                          payload->format, interlace_color_format ,enable,
11571                                         (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
11572 
11573                         setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11574                                PP_PARAM_INTERLACED, (void*)&enable);
11575 
11576                         if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
11577                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11578                                LINEAR_FORMAT, (void*)&interlace_color_format);
11579                         } else if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11580                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11581                                LINEAR_FORMAT, NULL);
11582                         }
11583                     }
11584                     if (client_extradata & OMX_INTERLACE_EXTRADATA) {
11585                         append_interlace_extradata(p_extra, payload->format);
11586                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11587                         if (p_client_extra) {
11588                             append_interlace_extradata(p_client_extra, payload->format);
11589                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
11590                                 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11591                         }
11592                     }
11593                     break;
11594                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
11595                     struct msm_vidc_framerate_payload *frame_rate_payload;
11596                     frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
11597                     frame_rate = frame_rate_payload->frame_rate;
11598                     break;
11599                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
11600                     struct msm_vidc_ts_payload *time_stamp_payload;
11601                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
11602                     time_stamp = time_stamp_payload->timestamp_lo;
11603                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
11604                     p_buf_hdr->nTimeStamp = time_stamp;
11605                     break;
11606                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
11607                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
11608                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
11609                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11610                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11611                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
11612                     break;
11613                 case MSM_VIDC_EXTRADATA_INDEX:
11614                     int *etype;
11615                     etype  = (int *)(void *)data->data;
11616                     if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
11617                         struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
11618                         aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
11619                         if (aspect_ratio_payload) {
11620                             ((struct vdec_output_frameinfo *)
11621                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
11622                             ((struct vdec_output_frameinfo *)
11623                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
11624                         }
11625                     } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
11626                         struct msm_vidc_output_crop_payload *output_crop_payload;
11627                         output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
11628                         if (output_crop_payload) {
11629                             m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
11630                             m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
11631                             m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
11632                             m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
11633                             m_extradata_info.output_width = output_crop_payload->width;
11634                             m_extradata_info.output_height = output_crop_payload->height;
11635                             m_extradata_info.output_crop_updated = OMX_TRUE;
11636                         }
11637                     }
11638                     break;
11639                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
11640                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
11641                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
11642                     recovery_sei_flags = recovery_sei_payload->flags;
11643                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
11644                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
11645                         DEBUG_PRINT_HIGH("***************************************************");
11646                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
11647                         DEBUG_PRINT_HIGH("***************************************************");
11648                     }
11649                     break;
11650                case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
11651                     panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
11652                     if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
11653                         DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
11654                         DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
11655                             MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
11656                         return;
11657                     }
11658                     break;
11659                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
11660                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
11661                 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
11662                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
11663                     color_event = handle_color_space_info((void *)data->data, &color_space, &color_mdata, set_disp_color_aspects_only);
11664                     break;
11665                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
11666                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
11667                     s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
11668                     switch (s3d_frame_packing_payload->fpa_type) {
11669                         case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
11670                             if (s3d_frame_packing_payload->content_interprtation_type == 1)
11671                                 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
11672                             else if (s3d_frame_packing_payload->content_interprtation_type == 2)
11673                                 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
11674                             else {
11675                                 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
11676                                 stereo_output_mode = HAL_NO_3D;
11677                             }
11678                             break;
11679                         case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
11680                             stereo_output_mode = HAL_3D_TOP_BOTTOM;
11681                             break;
11682                         default:
11683                             DEBUG_PRINT_ERROR("Unsupported framepacking type");
11684                             stereo_output_mode = HAL_NO_3D;
11685                     }
11686                     DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
11687                         s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
11688                     if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
11689                         append_framepack_extradata(p_extra, s3d_frame_packing_payload);
11690                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11691                         if (p_client_extra) {
11692                             append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
11693                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11694                         }
11695                     }
11696                     break;
11697                 case MSM_VIDC_EXTRADATA_FRAME_QP:
11698                     struct msm_vidc_frame_qp_payload *qp_payload;
11699                     qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
11700                     if (client_extradata & OMX_QP_EXTRADATA) {
11701                         append_qp_extradata(p_extra, qp_payload);
11702                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11703                         if (p_client_extra) {
11704                             append_qp_extradata(p_client_extra, qp_payload);
11705                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11706                         }
11707                     }
11708                     break;
11709                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
11710                     struct msm_vidc_frame_bits_info_payload *bits_info_payload;
11711                     bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
11712                     if (client_extradata & OMX_BITSINFO_EXTRADATA) {
11713                         append_bitsinfo_extradata(p_extra, bits_info_payload);
11714                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11715                         if (p_client_extra) {
11716                             append_bitsinfo_extradata(p_client_extra, bits_info_payload);
11717                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11718                         }
11719                     }
11720                     break;
11721                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
11722                     if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
11723                         append_user_extradata(p_extra, data);
11724                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11725                         if (p_client_extra) {
11726                             append_user_extradata(p_client_extra, data);
11727                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11728                         }
11729                     }
11730                     break;
11731                 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
11732                     struct msm_vidc_vqzip_sei_payload *vqzip_payload;
11733                     vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
11734                     if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
11735                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11736                         append_vqzip_extradata(p_extra, vqzip_payload);
11737                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11738                         if (p_client_extra) {
11739                             append_vqzip_extradata(p_client_extra, vqzip_payload);
11740                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11741                         }
11742                     }
11743                     break;
11744                 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
11745 
11746                     internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data,
11747                                                                                       &(color_mdata.contentLightLevel));
11748                     break;
11749                 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
11750                     internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data,
11751                                                                                           &(color_mdata.masteringDisplayInfo));
11752                     break;
11753                 default:
11754                     DEBUG_PRINT_LOW("Unrecognized extradata");
11755                     goto unrecognized_extradata;
11756             }
11757             consumed_len += data->nSize;
11758             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
11759         }
11760         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
11761             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11762             append_frame_info_extradata(p_extra,
11763                     num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11764                     time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11765                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11766             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11767             if (p_client_extra) {
11768                 append_frame_info_extradata(p_client_extra,
11769                         num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11770                         time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11771                             p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11772                 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11773             }
11774         }
11775         if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
11776             append_frame_dimension_extradata(p_extra);
11777             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11778             if (p_client_extra) {
11779                 append_frame_dimension_extradata(p_client_extra);
11780                 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11781             }
11782         }
11783 
11784         if(internal_hdr_info_changed_flag) {
11785             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
11786             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
11787             memcpy(&m_color_mdata, &color_mdata, sizeof(ColorMetaData));
11788             auto_lock lock(m_hdr_info_client_lock);
11789             m_change_client_hdr_info = true;
11790             if(!color_event) {
11791                 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
11792                 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11793                            OMX_QTIIndexConfigDescribeHDRColorInfo,
11794                            OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11795             }
11796         }
11797 
11798         if (m_enable_android_native_buffers) {
11799             if (set_disp_color_aspects_only) {
11800                 print_debug_hdr_color_info_mdata(&m_color_mdata);
11801                 set_colormetadata_in_handle(&m_color_mdata, buf_index);
11802             } else {
11803                 DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
11804                 set_colorspace_in_handle(color_space, buf_index);
11805             }
11806         }
11807 
11808     }
11809 unrecognized_extradata:
11810     if (client_extradata && p_extra) {
11811         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11812         append_terminator_extradata(p_extra);
11813         if (p_client_extra) {
11814             append_terminator_extradata(p_client_extra);
11815         }
11816     }
11817     if (secure_mode && p_extradata && m_other_extradata) {
11818         struct vdec_output_frameinfo  *ptr_extradatabuff = NULL;
11819         memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
11820         ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
11821         ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
11822         ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
11823         ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd;
11824         ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size;
11825         ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size;
11826     }
11827     return;
11828 }
11829 
enable_extradata(OMX_U64 requested_extradata,bool is_internal,bool enable)11830 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
11831         bool is_internal, bool enable)
11832 {
11833     OMX_ERRORTYPE ret = OMX_ErrorNone;
11834     struct v4l2_control control;
11835     if (m_state != OMX_StateLoaded) {
11836         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
11837         return OMX_ErrorIncorrectStateOperation;
11838     }
11839     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
11840             (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
11841 
11842     if (!is_internal) {
11843         if (enable)
11844             client_extradata |= requested_extradata;
11845         else
11846             client_extradata = client_extradata & ~requested_extradata;
11847     }
11848 
11849     if (enable) {
11850         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
11851             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11852             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
11853             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11854                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
11855                         " Quality of interlaced clips might be impacted.");
11856             }
11857         }
11858         if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
11859             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11860             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
11861             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11862                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
11863             }
11864             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11865             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
11866             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11867                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
11868             }
11869             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11870             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
11871             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11872                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
11873             }
11874             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11875             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
11876             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11877                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11878             }
11879             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11880             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
11881             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11882                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11883             }
11884             if (output_capability == V4L2_PIX_FMT_MPEG2) {
11885                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11886                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11887                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11888                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11889                 }
11890             }
11891         }
11892         if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
11893             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11894             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
11895             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11896                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
11897             }
11898         }
11899         if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
11900             if (output_capability == V4L2_PIX_FMT_H264) {
11901                 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
11902                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11903                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
11904                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11905                     DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
11906                 }
11907             } else {
11908                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
11909             }
11910         }
11911         if (requested_extradata & OMX_QP_EXTRADATA) {
11912             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11913             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11914             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11915                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11916             }
11917         }
11918         if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
11919             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11920             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
11921             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11922                 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
11923             }
11924         }
11925         if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
11926             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11927             control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
11928             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11929                 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
11930             }
11931         }
11932         if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
11933             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11934             control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
11935             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11936                 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
11937             }
11938             client_extradata |= OMX_VQZIPSEI_EXTRADATA;
11939 
11940             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11941             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11942             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11943                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11944             }
11945             client_extradata |= OMX_QP_EXTRADATA;
11946         }
11947         if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11948             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11949             control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
11950             DEBUG_PRINT_LOW("Enable output crop extra data");
11951             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11952                 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11953             }
11954         }
11955         if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
11956             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11957             switch(output_capability) {
11958                 case V4L2_PIX_FMT_H264:
11959                 case V4L2_PIX_FMT_HEVC:
11960                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
11961                     break;
11962                 case CODEC_TYPE_MPEG2:
11963                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11964                     break;
11965                 case V4L2_PIX_FMT_VP8:
11966                 case V4L2_PIX_FMT_VP9:
11967                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
11968                     break;
11969                 case V4L2_PIX_FMT_VC1_ANNEX_G:
11970                 case V4L2_PIX_FMT_VC1_ANNEX_L:
11971                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
11972                     break;
11973                 default:
11974                     DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
11975                     return ret;
11976             }
11977 
11978             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11979                 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
11980             }
11981         }
11982         if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
11983             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11984             if (output_capability == V4L2_PIX_FMT_H264 ||
11985                 output_capability == V4L2_PIX_FMT_HEVC) {
11986                 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
11987                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11988                     DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
11989                 }
11990                 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
11991                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11992                     DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
11993                 }
11994             }
11995         }
11996     }
11997     ret = get_buffer_req(&drv_ctx.op_buf);
11998     return ret;
11999 }
12000 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)12001 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12002 {
12003     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
12004     OMX_U8 *data_ptr = extra->data, data = 0;
12005     while (byte_count < extra->nDataSize) {
12006         data = *data_ptr;
12007         while (data) {
12008             num_MB += (data&0x01);
12009             data >>= 1;
12010         }
12011         data_ptr++;
12012         byte_count++;
12013     }
12014     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
12015             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
12016     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
12017 }
12018 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)12019 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12020 {
12021     if (!m_debug_extradata || !extra)
12022         return;
12023 
12024 
12025     DEBUG_PRINT_HIGH(
12026             "============== Extra Data ==============\n"
12027             "           Size: %u\n"
12028             "        Version: %u\n"
12029             "      PortIndex: %u\n"
12030             "           Type: %x\n"
12031             "       DataSize: %u",
12032             (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
12033             (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
12034 
12035     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
12036         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
12037         DEBUG_PRINT_HIGH(
12038                 "------ Interlace Format ------\n"
12039                 "                Size: %u\n"
12040                 "             Version: %u\n"
12041                 "           PortIndex: %u\n"
12042                 " Is Interlace Format: %d\n"
12043                 "   Interlace Formats: %u\n"
12044                 "=========== End of Interlace ===========",
12045                 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
12046                 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
12047     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
12048         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
12049 
12050         DEBUG_PRINT_HIGH(
12051                 "-------- Frame Format --------\n"
12052                 "             Picture Type: %d\n"
12053                 "           Interlace Type: %d\n"
12054                 " Pan Scan Total Frame Num: %u\n"
12055                 "   Concealed Macro Blocks: %u\n"
12056                 "        Recovery SEI Flag: %u\n"
12057                 "               frame rate: %u\n"
12058                 "               Time Stamp: %llu\n"
12059                 "           Aspect Ratio X: %u\n"
12060                 "           Aspect Ratio Y: %u",
12061                 fminfo->ePicType,
12062                 fminfo->interlaceType,
12063                 (unsigned int)fminfo->panScan.numWindows,
12064                 (unsigned int)fminfo->nConcealedMacroblocks,
12065                 (unsigned int)fminfo->nRecoverySeiFlag,
12066                 (unsigned int)fminfo->nFrameRate,
12067                 fminfo->nTimeStamp,
12068                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
12069                 (unsigned int)fminfo->aspectRatio.aspectRatioY);
12070 
12071         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
12072             DEBUG_PRINT_HIGH(
12073                     "------------------------------"
12074                     "     Pan Scan Frame Num: %u\n"
12075                     "            Rectangle x: %d\n"
12076                     "            Rectangle y: %d\n"
12077                     "           Rectangle dx: %d\n"
12078                     "           Rectangle dy: %d",
12079                     (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
12080                     (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
12081         }
12082 
12083         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
12084     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
12085         OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12086         DEBUG_PRINT_HIGH(
12087                 "------------------ Framepack Format ----------\n"
12088                 "                           id: %u \n"
12089                 "                  cancel_flag: %u \n"
12090                 "                         type: %u \n"
12091                 " quincunx_sampling_flagFormat: %u \n"
12092                 "  content_interpretation_type: %u \n"
12093                 "        spatial_flipping_flag: %u \n"
12094                 "          frame0_flipped_flag: %u \n"
12095                 "             field_views_flag: %u \n"
12096                 " current_frame_is_frame0_flag: %u \n"
12097                 "   frame0_self_contained_flag: %u \n"
12098                 "   frame1_self_contained_flag: %u \n"
12099                 "       frame0_grid_position_x: %u \n"
12100                 "       frame0_grid_position_y: %u \n"
12101                 "       frame1_grid_position_x: %u \n"
12102                 "       frame1_grid_position_y: %u \n"
12103                 "                reserved_byte: %u \n"
12104                 "            repetition_period: %u \n"
12105                 "               extension_flag: %u \n"
12106                 "================== End of Framepack ===========",
12107                 (unsigned int)framepack->id,
12108                 (unsigned int)framepack->cancel_flag,
12109                 (unsigned int)framepack->type,
12110                 (unsigned int)framepack->quincunx_sampling_flag,
12111                 (unsigned int)framepack->content_interpretation_type,
12112                 (unsigned int)framepack->spatial_flipping_flag,
12113                 (unsigned int)framepack->frame0_flipped_flag,
12114                 (unsigned int)framepack->field_views_flag,
12115                 (unsigned int)framepack->current_frame_is_frame0_flag,
12116                 (unsigned int)framepack->frame0_self_contained_flag,
12117                 (unsigned int)framepack->frame1_self_contained_flag,
12118                 (unsigned int)framepack->frame0_grid_position_x,
12119                 (unsigned int)framepack->frame0_grid_position_y,
12120                 (unsigned int)framepack->frame1_grid_position_x,
12121                 (unsigned int)framepack->frame1_grid_position_y,
12122                 (unsigned int)framepack->reserved_byte,
12123                 (unsigned int)framepack->repetition_period,
12124                 (unsigned int)framepack->extension_flag);
12125     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
12126         OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12127         DEBUG_PRINT_HIGH(
12128                 "---- QP (Frame quantization parameter) ----\n"
12129                 "    Frame QP: %u \n"
12130                 "================ End of QP ================\n",
12131                 (unsigned int)qp->nQP);
12132     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
12133         OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
12134         DEBUG_PRINT_HIGH(
12135                 "--------- Input bits information --------\n"
12136                 "    Header bits: %u \n"
12137                 "     Frame bits: %u \n"
12138                 "===== End of Input bits information =====\n",
12139                 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
12140     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
12141         OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
12142         OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
12143         OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
12144         OMX_U32 i = 0;
12145         DEBUG_PRINT_HIGH(
12146                 "--------------  Userdata  -------------\n"
12147                 "    Stream userdata type: %u\n"
12148                 "          userdata size: %u\n"
12149                 "    STREAM_USERDATA:",
12150                 (unsigned int)userdata->type, (unsigned int)userdata_size);
12151                 for (i = 0; i < userdata_size; i+=4) {
12152                     DEBUG_PRINT_HIGH("        %x %x %x %x",
12153                         data_ptr[i], data_ptr[i+1],
12154                         data_ptr[i+2], data_ptr[i+3]);
12155                 }
12156         DEBUG_PRINT_HIGH(
12157                 "=========== End of Userdata ===========");
12158     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
12159         OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
12160         DEBUG_PRINT_HIGH(
12161                 "--------------  VQZip  -------------\n"
12162                 "    Size: %u\n",
12163                 (unsigned int)vq->nSize);
12164         DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
12165     } else if (extra->eType == OMX_ExtraDataNone) {
12166         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
12167     } else {
12168         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
12169     }
12170 }
12171 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)12172 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12173         OMX_U32 interlaced_format_type)
12174 {
12175     OMX_STREAMINTERLACEFORMAT *interlace_format;
12176 
12177     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
12178         return;
12179     }
12180     if (!extra) {
12181        DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
12182        return;
12183     }
12184     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
12185     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12186     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12187     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
12188     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12189     interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
12190     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12191     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
12192     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12193 
12194     if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
12195         interlace_format->bInterlaceFormat = OMX_FALSE;
12196         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12197         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12198     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
12199         interlace_format->bInterlaceFormat = OMX_TRUE;
12200         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
12201         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
12202     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
12203         interlace_format->bInterlaceFormat = OMX_TRUE;
12204         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
12205         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
12206     } else {
12207         //default case - set to progressive
12208         interlace_format->bInterlaceFormat = OMX_FALSE;
12209         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12210         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12211     }
12212     print_debug_extradata(extra);
12213 }
12214 
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)12215 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12216 {
12217     OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
12218     if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
12219         return;
12220     }
12221     extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
12222     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12223     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12224     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
12225     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
12226     frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
12227     frame_dimension->nDecWidth = rectangle.nLeft;
12228     frame_dimension->nDecHeight = rectangle.nTop;
12229     frame_dimension->nActualWidth = rectangle.nWidth;
12230     frame_dimension->nActualHeight = rectangle.nHeight;
12231 }
12232 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)12233 void omx_vdec::fill_aspect_ratio_info(
12234         struct vdec_aspectratioinfo *aspect_ratio_info,
12235         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
12236 {
12237     m_extradata = frame_info;
12238     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
12239     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
12240     DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
12241             (unsigned int)m_extradata->aspectRatio.aspectRatioY);
12242 }
12243 
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)12244 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12245         OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
12246         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
12247         struct vdec_aspectratioinfo *aspect_ratio_info)
12248 {
12249     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
12250     struct msm_vidc_panscan_window *panscan_window;
12251     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
12252         return;
12253     }
12254     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
12255     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12256     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12257     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
12258     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
12259     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
12260     switch (picture_type) {
12261         case PICTURE_TYPE_I:
12262             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
12263             break;
12264         case PICTURE_TYPE_P:
12265             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
12266             break;
12267         case PICTURE_TYPE_B:
12268             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
12269             break;
12270         default:
12271             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
12272     }
12273     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
12274         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
12275     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
12276         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
12277     else
12278         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
12279     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
12280     frame_info->nConcealedMacroblocks = num_conceal_mb;
12281     frame_info->nRecoverySeiFlag = recovery_sei_flag;
12282     frame_info->nFrameRate = frame_rate;
12283     frame_info->nTimeStamp = time_stamp;
12284     frame_info->panScan.numWindows = 0;
12285     if (output_capability == V4L2_PIX_FMT_MPEG2) {
12286         if (m_disp_hor_size && m_disp_vert_size) {
12287             frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
12288             frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
12289         } else {
12290             frame_info->displayAspectRatio.displayHorizontalSize = 0;
12291             frame_info->displayAspectRatio.displayVerticalSize = 0;
12292         }
12293     }
12294 
12295     if (panscan_payload) {
12296         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
12297         panscan_window = &panscan_payload->wnd[0];
12298         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
12299             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
12300             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
12301             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
12302             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
12303             panscan_window++;
12304         }
12305     }
12306     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
12307     print_debug_extradata(extra);
12308 }
12309 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)12310 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12311 {
12312     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
12313     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
12314     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12315     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12316     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
12317     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
12318     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
12319     *portDefn = m_port_def;
12320     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
12321             "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
12322             (unsigned int)portDefn->format.video.nFrameWidth,
12323             (unsigned int)portDefn->format.video.nStride,
12324             (unsigned int)portDefn->format.video.nSliceHeight);
12325 }
12326 
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)12327 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12328         struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
12329 {
12330     OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
12331     if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
12332         DEBUG_PRINT_ERROR("frame packing size mismatch");
12333         return;
12334     }
12335     extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
12336     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12337     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12338     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
12339     extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12340     framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12341     framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12342     framepack->nVersion.nVersion = OMX_SPEC_VERSION;
12343     framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12344     memcpy(&framepack->id, s3d_frame_packing_payload,
12345         sizeof(struct msm_vidc_s3d_frame_packing_payload));
12346     memcpy(&m_frame_pack_arrangement, framepack,
12347         sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
12348     print_debug_extradata(extra);
12349 }
12350 
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)12351 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12352             struct msm_vidc_frame_qp_payload *qp_payload)
12353 {
12354     OMX_QCOM_EXTRADATA_QP * qp = NULL;
12355     if (!qp_payload) {
12356         DEBUG_PRINT_ERROR("QP payload is NULL");
12357         return;
12358     }
12359     extra->nSize = OMX_QP_EXTRADATA_SIZE;
12360     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12361     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12362     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
12363     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
12364     qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12365     qp->nQP = qp_payload->frame_qp;
12366     print_debug_extradata(extra);
12367 }
12368 
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)12369 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12370             struct msm_vidc_frame_bits_info_payload *bits_payload)
12371 {
12372     OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
12373     if (!bits_payload) {
12374         DEBUG_PRINT_ERROR("bits info payload is NULL");
12375         return;
12376     }
12377     extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
12378     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12379     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12380     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
12381     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
12382     bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
12383     bits->frame_bits = bits_payload->frame_bits;
12384     bits->header_bits = bits_payload->header_bits;
12385     print_debug_extradata(extra);
12386 }
12387 
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)12388 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12389             OMX_OTHER_EXTRADATATYPE *p_user)
12390 {
12391     int userdata_size = 0;
12392     struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
12393     userdata_payload =
12394         (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
12395     userdata_size = p_user->nDataSize;
12396     extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
12397     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12398     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12399     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
12400     extra->nDataSize = userdata_size;
12401     if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
12402         memcpy(extra->data, p_user->data, extra->nDataSize);
12403     print_debug_extradata(extra);
12404 }
12405 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)12406 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12407 {
12408     if (!client_extradata) {
12409         return;
12410     }
12411     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
12412     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12413     extra->eType = OMX_ExtraDataNone;
12414     extra->nDataSize = 0;
12415     extra->data[0] = 0;
12416 
12417     print_debug_extradata(extra);
12418 }
12419 
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)12420 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12421         struct msm_vidc_vqzip_sei_payload *vqzip_payload)
12422 {
12423     OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
12424 
12425     extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
12426     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12427     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12428     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
12429     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
12430 
12431     vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
12432     vq->nSize = vqzip_payload->size;
12433     memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
12434 
12435     print_debug_extradata(extra);
12436 }
12437 
allocate_desc_buffer(OMX_U32 index)12438 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
12439 {
12440     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12441     if (index >= drv_ctx.ip_buf.actualcount) {
12442         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
12443         return OMX_ErrorInsufficientResources;
12444     }
12445     if (m_desc_buffer_ptr == NULL) {
12446         m_desc_buffer_ptr = (desc_buffer_hdr*) \
12447                     calloc( (sizeof(desc_buffer_hdr)),
12448                             drv_ctx.ip_buf.actualcount);
12449         if (m_desc_buffer_ptr == NULL) {
12450             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
12451             return OMX_ErrorInsufficientResources;
12452         }
12453     }
12454 
12455     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
12456     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
12457         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
12458         return OMX_ErrorInsufficientResources;
12459     }
12460 
12461     return eRet;
12462 }
12463 
insert_demux_addr_offset(OMX_U32 address_offset)12464 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
12465 {
12466     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
12467     if (m_demux_entries < 8192) {
12468         m_demux_offsets[m_demux_entries++] = address_offset;
12469     }
12470     return;
12471 }
12472 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)12473 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
12474 {
12475     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
12476     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
12477     OMX_U32 index = 0;
12478 
12479     m_demux_entries = 0;
12480 
12481     while (index < bytes_to_parse) {
12482         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12483                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
12484                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12485                  (buf[index+2] == 0x01)) ) {
12486             //Found start code, insert address offset
12487             insert_demux_addr_offset(index);
12488             if (buf[index+2] == 0x01) // 3 byte start code
12489                 index += 3;
12490             else                      //4 byte start code
12491                 index += 4;
12492         } else
12493             index++;
12494     }
12495     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
12496     return;
12497 }
12498 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)12499 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
12500 {
12501     //fix this, handle 3 byte start code, vc1 terminator entry
12502     OMX_U8 *p_demux_data = NULL;
12503     OMX_U32 desc_data = 0;
12504     OMX_U32 start_addr = 0;
12505     OMX_U32 nal_size = 0;
12506     OMX_U32 suffix_byte = 0;
12507     OMX_U32 demux_index = 0;
12508     OMX_U32 buffer_index = 0;
12509 
12510     if (m_desc_buffer_ptr == NULL) {
12511         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
12512         return OMX_ErrorBadParameter;
12513     }
12514 
12515     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
12516     if (buffer_index > drv_ctx.ip_buf.actualcount) {
12517         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
12518         return OMX_ErrorBadParameter;
12519     }
12520 
12521     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
12522 
12523     if ( ((OMX_U8*)p_demux_data == NULL) ||
12524             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
12525         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
12526         return OMX_ErrorBadParameter;
12527     } else {
12528         for (; demux_index < m_demux_entries; demux_index++) {
12529             desc_data = 0;
12530             start_addr = m_demux_offsets[demux_index];
12531             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
12532                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
12533             } else {
12534                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
12535             }
12536             if (demux_index < (m_demux_entries - 1)) {
12537                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
12538             } else {
12539                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
12540             }
12541             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
12542                     (unsigned int)start_addr,
12543                     (unsigned int)suffix_byte,
12544                     (unsigned int)nal_size,
12545                     (unsigned int)demux_index);
12546             desc_data = (start_addr >> 3) << 1;
12547             desc_data |= (start_addr & 7) << 21;
12548             desc_data |= suffix_byte << 24;
12549 
12550             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12551             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
12552             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12553             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12554 
12555             p_demux_data += 16;
12556         }
12557         if (codec_type_parse == CODEC_TYPE_VC1) {
12558             DEBUG_PRINT_LOW("VC1 terminator entry");
12559             desc_data = 0;
12560             desc_data = 0x82 << 24;
12561             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12562             memset(p_demux_data + 4, 0, sizeof(OMX_U32));
12563             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12564             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12565             p_demux_data += 16;
12566             m_demux_entries++;
12567         }
12568         //Add zero word to indicate end of descriptors
12569         memset(p_demux_data, 0, sizeof(OMX_U32));
12570 
12571         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
12572         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
12573     }
12574     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
12575     m_demux_entries = 0;
12576     DEBUG_PRINT_LOW("Demux table complete!");
12577     return OMX_ErrorNone;
12578 }
12579 
request_perf_level(enum vidc_perf_level perf_level)12580 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
12581 {
12582     struct v4l2_control control;
12583     char property_value[PROPERTY_VALUE_MAX] = {0};
12584 
12585     property_get("vendor.vidc.debug.turbo", property_value, "0");
12586     memset(&control, 0, sizeof(v4l2_control));
12587     control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
12588     switch (perf_level) {
12589     case VIDC_NOMINAL:
12590         if (atoi(property_value))
12591             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12592         else
12593             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
12594         break;
12595     case VIDC_TURBO:
12596         control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12597         break;
12598      default:
12599         DEBUG_PRINT_ERROR("Requested PERF level not supported");
12600         break;
12601     }
12602     if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
12603         return;
12604 
12605     DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
12606     if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
12607         current_perf_level = control.value;
12608     } else {
12609         DEBUG_PRINT_ERROR("Failed to set PERF level");
12610     }
12611 }
12612 
allocate_color_convert_buf()12613 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
12614 {
12615     enabled = false;
12616     omx = NULL;
12617     init_members();
12618     ColorFormat = OMX_COLOR_FormatMax;
12619     dest_format = YCbCr420P;
12620     m_c2d_width = 0;
12621     m_c2d_height = 0;
12622 }
12623 
set_vdec_client(void * client)12624 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
12625 {
12626     omx = reinterpret_cast<omx_vdec*>(client);
12627 }
12628 
init_members()12629 void omx_vdec::allocate_color_convert_buf::init_members()
12630 {
12631     allocated_count = 0;
12632     buffer_size_req = 0;
12633     buffer_alignment_req = 0;
12634     m_c2d_width = m_c2d_height = 0;
12635     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
12636     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
12637     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
12638     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
12639 #ifdef USE_ION
12640     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
12641 #endif
12642     for (int i = 0; i < MAX_COUNT; i++)
12643         pmem_fd[i] = -1;
12644 }
12645 
~allocate_color_convert_buf()12646 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
12647 {
12648     c2d.destroy();
12649 }
12650 
update_buffer_req()12651 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
12652 {
12653     bool status = true;
12654     unsigned int src_size = 0, destination_size = 0;
12655     unsigned int height, width;
12656     struct v4l2_format fmt;
12657     OMX_COLOR_FORMATTYPE drv_color_format;
12658 
12659     if (!omx) {
12660         DEBUG_PRINT_ERROR("Invalid client in color convert");
12661         return false;
12662     }
12663     if (!enabled) {
12664         DEBUG_PRINT_HIGH("No color conversion required");
12665         return status;
12666     }
12667     pthread_mutex_lock(&omx->c_lock);
12668 
12669     memset(&fmt, 0x0, sizeof(struct v4l2_format));
12670     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
12671     fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
12672     ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
12673     width = fmt.fmt.pix_mp.width;
12674     height =  fmt.fmt.pix_mp.height;
12675 
12676     bool resolution_upgrade = (height > m_c2d_height ||
12677             width > m_c2d_width);
12678     if (resolution_upgrade) {
12679         // resolution upgraded ? ensure we are yet to allocate;
12680         // failing which, c2d buffers will never be reallocated and bad things will happen
12681         if (allocated_count > 0) {
12682             DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
12683                     allocated_count);
12684             status = false;
12685             goto fail_update_buf_req;
12686         }
12687     }
12688 
12689     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
12690             ColorFormat != OMX_COLOR_FormatYUV420Planar) {
12691         DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
12692         status = false;
12693         goto fail_update_buf_req;
12694     }
12695     c2d.close();
12696     status = c2d.open(height,
12697             width,
12698             NV12_128m,dest_format);
12699     if (status) {
12700         status = c2d.get_buffer_size(C2D_INPUT,src_size);
12701         if (status)
12702             status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
12703     }
12704     if (status) {
12705         if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
12706                 !destination_size) {
12707             DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
12708                     "driver size %u destination size %d",
12709                     src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
12710                     destination_size);
12711             status = false;
12712             c2d.close();
12713             buffer_size_req = 0;
12714             // TODO: make this fatal. Driver is not supposed to quote size
12715             //  smaller than what C2D needs !!
12716         } else {
12717             buffer_size_req = destination_size;
12718             m_c2d_height = height;
12719             m_c2d_width = width;
12720         }
12721     }
12722 fail_update_buf_req:
12723     pthread_mutex_unlock(&omx->c_lock);
12724     return status;
12725 }
12726 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)12727 bool omx_vdec::allocate_color_convert_buf::set_color_format(
12728         OMX_COLOR_FORMATTYPE dest_color_format)
12729 {
12730     bool status = true, drv_colorformat_c2d_enable = false;
12731     bool dest_color_format_c2d_enable = false;
12732     OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
12733     if (!omx) {
12734         DEBUG_PRINT_ERROR("Invalid client in color convert");
12735         return false;
12736     }
12737     pthread_mutex_lock(&omx->c_lock);
12738     if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
12739         if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
12740             drv_color_format = (OMX_COLOR_FORMATTYPE)
12741                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12742         else
12743             drv_color_format = (OMX_COLOR_FORMATTYPE)
12744                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12745      else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
12746          drv_color_format = (OMX_COLOR_FORMATTYPE)
12747                   QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12748      } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
12749             drv_color_format = (OMX_COLOR_FORMATTYPE)
12750                     QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12751      } else {
12752         DEBUG_PRINT_ERROR("Incorrect color format");
12753         status = false;
12754     }
12755     drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
12756         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12757                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
12758         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12759                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12760         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12761                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12762 
12763     dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
12764             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12765             (dest_color_format != (OMX_COLOR_FORMATTYPE)
12766                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12767 
12768     if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
12769         DEBUG_PRINT_LOW("Enabling C2D");
12770         if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
12771            (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
12772             DEBUG_PRINT_ERROR("Unsupported color format for c2d");
12773             status = false;
12774         } else {
12775             ColorFormat = dest_color_format;
12776             dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
12777                     YCbCr420P : YCbCr420SP;
12778             if (enabled)
12779                 c2d.destroy();
12780             enabled = false;
12781             if (!c2d.init()) {
12782                 DEBUG_PRINT_ERROR("open failed for c2d");
12783                 status = false;
12784             } else
12785                 enabled = true;
12786         }
12787     } else {
12788         if (enabled)
12789             c2d.destroy();
12790         enabled = false;
12791     }
12792     pthread_mutex_unlock(&omx->c_lock);
12793     return status;
12794 }
12795 
get_il_buf_hdr()12796 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
12797 {
12798     if (!omx) {
12799         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12800         return NULL;
12801     }
12802     if (!enabled)
12803         return omx->m_out_mem_ptr;
12804     return m_out_mem_ptr_client;
12805 }
12806 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12807     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
12808 (OMX_BUFFERHEADERTYPE *bufadd)
12809 {
12810     if (!omx) {
12811         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12812         return NULL;
12813     }
12814     if (!enabled)
12815         return bufadd;
12816 
12817     unsigned index = 0;
12818     index = bufadd - omx->m_out_mem_ptr;
12819     if (index < omx->drv_ctx.op_buf.actualcount) {
12820         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12821         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
12822         bool status;
12823         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
12824             pthread_mutex_lock(&omx->c_lock);
12825             cache_clean_buffer(index);
12826             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
12827                     omx->drv_ctx.op_buf_map_info[index].base_address, bufadd->pBuffer, pmem_fd[index],
12828                     pmem_baseaddress[index], pmem_baseaddress[index]);
12829             if (!status) {
12830                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
12831                 m_out_mem_ptr_client[index].nFilledLen = 0;
12832                 pthread_mutex_unlock(&omx->c_lock);
12833                 return &m_out_mem_ptr_client[index];
12834             } else {
12835                 unsigned int filledLen = 0;
12836                 c2d.get_output_filled_length(filledLen);
12837                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
12838                 cache_clean_invalidate_buffer(index);
12839             }
12840             pthread_mutex_unlock(&omx->c_lock);
12841         } else
12842             m_out_mem_ptr_client[index].nFilledLen = 0;
12843         return &m_out_mem_ptr_client[index];
12844     }
12845     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
12846     return NULL;
12847 }
12848 
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12849     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
12850 (OMX_BUFFERHEADERTYPE *bufadd)
12851 {
12852     if (!omx) {
12853         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12854         return NULL;
12855     }
12856     if (!enabled)
12857         return bufadd;
12858     unsigned index = 0;
12859     index = bufadd - m_out_mem_ptr_client;
12860     if (index < omx->drv_ctx.op_buf.actualcount) {
12861         return &omx->m_out_mem_ptr[index];
12862     }
12863     DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
12864     return NULL;
12865 }
get_buffer_req(unsigned int & buffer_size)12866     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
12867 (unsigned int &buffer_size)
12868 {
12869     bool status = true;
12870     pthread_mutex_lock(&omx->c_lock);
12871      /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
12872         always uses VideoNativeMetadata and OMX receives buffer type as
12873         grallocsource via storeMetaDataInBuffers_l API. The buffer_size
12874         will be communicated to frameworks via IndexParamPortdefinition. */
12875     if (!enabled)
12876         buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
12877                       omx->drv_ctx.op_buf.buffer_size;
12878     else {
12879         if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
12880             DEBUG_PRINT_ERROR("Get buffer size failed");
12881             status = false;
12882             goto fail_get_buffer_size;
12883         }
12884     }
12885 fail_get_buffer_size:
12886     pthread_mutex_unlock(&omx->c_lock);
12887     return status;
12888 }
12889 
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)12890 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
12891         OMX_U32 buffer_size, OMX_U32 actual_count)
12892 {
12893     OMX_U32 expectedSize = is_color_conversion_enabled() ? buffer_size_req : omx->dynamic_buf_mode ?
12894             sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
12895     if (buffer_size < expectedSize) {
12896         DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
12897                 buffer_size, expectedSize);
12898         return OMX_ErrorBadParameter;
12899     }
12900     if (actual_count < omx->drv_ctx.op_buf.actualcount) {
12901         DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
12902                 actual_count, omx->drv_ctx.op_buf.actualcount);
12903         return OMX_ErrorBadParameter;
12904     }
12905 
12906     bool reqs_updated = false;
12907     if (enabled) {
12908         // disallow changing buffer size/count while we have active allocated buffers
12909         if (allocated_count > 0) {
12910             DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
12911                     buffer_size_req, buffer_size, allocated_count);
12912             return OMX_ErrorInvalidState;
12913         }
12914 
12915         buffer_size_req = buffer_size;
12916     } else {
12917         if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
12918             omx->drv_ctx.op_buf.buffer_size = buffer_size;
12919             reqs_updated = true;
12920         }
12921     }
12922 
12923     if (actual_count > omx->drv_ctx.op_buf.actualcount) {
12924         omx->drv_ctx.op_buf.actualcount = actual_count;
12925         reqs_updated = true;
12926     }
12927 
12928     if (reqs_updated) {
12929         omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
12930         omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
12931                 omx->drv_ctx.extradata_info.buffer_size;
12932         return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
12933     }
12934     return OMX_ErrorNone;
12935 }
12936 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)12937 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
12938         OMX_BUFFERHEADERTYPE *bufhdr)
12939 {
12940     unsigned int index = 0;
12941 
12942     if (!enabled)
12943         return omx->free_output_buffer(bufhdr);
12944     if (enabled && omx->is_component_secure())
12945         return OMX_ErrorNone;
12946     if (!allocated_count || !bufhdr) {
12947         DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
12948         return OMX_ErrorBadParameter;
12949     }
12950     index = bufhdr - m_out_mem_ptr_client;
12951     if (index >= omx->drv_ctx.op_buf.actualcount) {
12952         DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
12953         return OMX_ErrorBadParameter;
12954     }
12955     if (pmem_fd[index] >= 0) {
12956         munmap(pmem_baseaddress[index], buffer_size_req);
12957         close(pmem_fd[index]);
12958     }
12959     pmem_fd[index] = -1;
12960 #ifdef USE_ION
12961     omx->free_ion_memory(&op_buf_ion_info[index]);
12962 #endif
12963     if (allocated_count > 0)
12964         allocated_count--;
12965     else
12966         allocated_count = 0;
12967     if (!allocated_count) {
12968         pthread_mutex_lock(&omx->c_lock);
12969         c2d.close();
12970         init_members();
12971         pthread_mutex_unlock(&omx->c_lock);
12972     }
12973     return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
12974 }
12975 
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)12976 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
12977         OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
12978 {
12979     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12980     if (!enabled) {
12981         eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
12982         return eRet;
12983     }
12984     if (enabled && omx->is_component_secure()) {
12985         DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
12986                 omx->is_component_secure());
12987         return OMX_ErrorUnsupportedSetting;
12988     }
12989     if (!bufferHdr || bytes > buffer_size_req) {
12990         DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
12991         DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
12992                 (unsigned int)buffer_size_req, (unsigned int)bytes);
12993         return OMX_ErrorBadParameter;
12994     }
12995     if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
12996         DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
12997         return OMX_ErrorInsufficientResources;
12998     }
12999     OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
13000     eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
13001             port,appData,omx->drv_ctx.op_buf.buffer_size);
13002     if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
13003         DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
13004         return eRet;
13005     }
13006     if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
13007             (int)omx->drv_ctx.op_buf.actualcount) {
13008         DEBUG_PRINT_ERROR("Invalid header index %ld",
13009                (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
13010         return OMX_ErrorUndefined;
13011     }
13012     unsigned int i = allocated_count;
13013 #ifdef USE_ION
13014     // Allocate color-conversion buffers as cached to improve software-reading
13015     // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
13016     // cache invalidation.
13017     op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
13018             buffer_size_req,buffer_alignment_req,
13019             &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
13020             ION_FLAG_CACHED);
13021     pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
13022     if (op_buf_ion_info[i].ion_device_fd < 0) {
13023         DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
13024         return OMX_ErrorInsufficientResources;
13025     }
13026     pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
13027             PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
13028 
13029     if (pmem_baseaddress[i] == MAP_FAILED) {
13030         DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
13031         close(pmem_fd[i]);
13032         omx->free_ion_memory(&op_buf_ion_info[i]);
13033         return OMX_ErrorInsufficientResources;
13034     }
13035 #endif
13036     m_pmem_info_client[i].offset = 0;
13037     m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
13038     m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
13039     m_platform_list_client[i].nEntries = 1;
13040     m_platform_list_client[i].entryList = &m_platform_entry_client[i];
13041     m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
13042     m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
13043     m_out_mem_ptr_client[i].nFilledLen = 0;
13044     m_out_mem_ptr_client[i].nFlags = 0;
13045     m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
13046     m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
13047     m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
13048     m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
13049     m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
13050     m_out_mem_ptr_client[i].pAppPrivate = appData;
13051     *bufferHdr = &m_out_mem_ptr_client[i];
13052     DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
13053     allocated_count++;
13054     return eRet;
13055 }
13056 
is_component_secure()13057 bool omx_vdec::is_component_secure()
13058 {
13059     return secure_mode;
13060 }
13061 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)13062 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
13063 {
13064     bool status = true;
13065     if (!enabled) {
13066         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
13067             if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
13068                     dest_color_format = (OMX_COLOR_FORMATTYPE)
13069                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
13070                 else
13071                     dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
13072         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
13073              dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
13074         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC){
13075              dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
13076         } else
13077             status = false;
13078     } else {
13079         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
13080             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
13081             dest_color_format = ColorFormat;
13082         } else
13083             status = false;
13084     }
13085     return status;
13086 }
13087 
cache_ops(unsigned int index,unsigned int cmd)13088 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
13089         unsigned int index, unsigned int cmd)
13090 {
13091     if (!enabled) {
13092         return OMX_ErrorNone;
13093     }
13094 
13095     if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
13096         DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
13097         return OMX_ErrorBadParameter;
13098     }
13099 
13100     struct ion_flush_data flush_data;
13101     struct ion_custom_data custom_data;
13102 
13103     memset(&flush_data, 0x0, sizeof(flush_data));
13104     memset(&custom_data, 0x0, sizeof(custom_data));
13105 
13106     flush_data.vaddr = pmem_baseaddress[index];
13107     flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
13108     flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
13109     flush_data.length = buffer_size_req;
13110     custom_data.cmd = cmd;
13111     custom_data.arg = (unsigned long)&flush_data;
13112 
13113     DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
13114             (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
13115             flush_data.fd, flush_data.handle, flush_data.vaddr,
13116             flush_data.length);
13117     int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
13118     if (ret < 0) {
13119         DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
13120                 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
13121                 strerror(errno));
13122         return OMX_ErrorUndefined;
13123     }
13124     return OMX_ErrorNone;
13125 }
13126 
buf_ref_add(int nPortIndex)13127 void omx_vdec::buf_ref_add(int nPortIndex)
13128 {
13129     unsigned long i = 0;
13130     bool buf_present = false;
13131     long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
13132     OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
13133 
13134     if (!dynamic_buf_mode || !out_dynamic_list) {
13135         return;
13136     }
13137 
13138     pthread_mutex_lock(&m_lock);
13139     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13140         //check the buffer fd, offset, uv addr with list contents
13141         //If present increment reference.
13142         if ((out_dynamic_list[i].fd == fd) &&
13143             (out_dynamic_list[i].offset == offset)) {
13144                DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
13145                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13146                if (!secure_mode) {
13147                    drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
13148                }
13149                buf_present = true;
13150                break;
13151         }
13152     }
13153     if (!buf_present) {
13154         for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13155             //search for a entry to insert details of the new buffer
13156             if (out_dynamic_list[i].dup_fd < 0) {
13157                 out_dynamic_list[i].fd = fd;
13158                 out_dynamic_list[i].offset = offset;
13159                 out_dynamic_list[i].dup_fd = dup(fd);
13160                 out_dynamic_list[i].ref_count++;
13161                 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
13162                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13163 
13164                 if (!secure_mode) {
13165                     drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
13166                             (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
13167                                           PROT_READ|PROT_WRITE, MAP_SHARED,
13168                                           drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
13169                     //mmap returns (void *)-1 on failure and sets error code in errno.
13170                     if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
13171                         DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
13172                         drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
13173                         break;
13174                     }
13175                     out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
13176                     out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
13177                     DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
13178                 }
13179                 break;
13180             }
13181         }
13182     }
13183    pthread_mutex_unlock(&m_lock);
13184 }
13185 
buf_ref_remove()13186 void omx_vdec::buf_ref_remove()
13187 {
13188     unsigned long i = 0;
13189 
13190     if (!dynamic_buf_mode || !out_dynamic_list) {
13191         return;
13192     }
13193 
13194     pthread_mutex_lock(&m_lock);
13195     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13196         if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
13197             DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
13198             munmap(out_dynamic_list[i].buffaddr,
13199                         out_dynamic_list[i].mapped_size);
13200         }
13201 
13202          DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
13203                  (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13204          close(out_dynamic_list[i].dup_fd);
13205          out_dynamic_list[i].dup_fd = -1;
13206     }
13207     pthread_mutex_unlock(&m_lock);
13208 
13209     if (out_dynamic_list) {
13210         free(out_dynamic_list);
13211         out_dynamic_list = NULL;
13212     }
13213 }
13214 
13215 #ifdef _MSM8974_
send_codec_config()13216 void omx_vdec::send_codec_config() {
13217     if (codec_config_flag) {
13218         unsigned long p1 = 0; // Parameter - 1
13219         unsigned long p2 = 0; // Parameter - 2
13220         unsigned long ident = 0;
13221         pthread_mutex_lock(&m_lock);
13222         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
13223         while (m_etb_q.m_size) {
13224             m_etb_q.pop_entry(&p1,&p2,&ident);
13225             if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
13226                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
13227                     if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
13228                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
13229                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
13230                         omx_report_error();
13231                     }
13232                 } else {
13233                     DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
13234                     m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
13235                 }
13236             } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
13237                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
13238                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
13239                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
13240                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
13241                         omx_report_error ();
13242                     }
13243                 } else {
13244                     pending_input_buffers++;
13245                     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
13246                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
13247                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
13248                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
13249                 }
13250             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
13251                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
13252                         (OMX_BUFFERHEADERTYPE *)p1);
13253                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
13254             }
13255         }
13256         pthread_mutex_unlock(&m_lock);
13257     }
13258 }
13259 #endif
13260 
perf_control()13261 omx_vdec::perf_control::perf_control()
13262 {
13263     m_perf_lib = NULL;
13264     m_perf_handle = 0;
13265     m_perf_lock_acquire = NULL;
13266     m_perf_lock_release = NULL;
13267 }
13268 
~perf_control()13269 omx_vdec::perf_control::~perf_control()
13270 {
13271     if (m_perf_handle != 0 && m_perf_lock_release) {
13272         DEBUG_PRINT_LOW("NOTE2: release perf lock");
13273         m_perf_lock_release(m_perf_handle);
13274     }
13275     if (m_perf_lib) {
13276         dlclose(m_perf_lib);
13277     }
13278 }
13279 
13280 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
13281 
13282 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
13283 
send_hint_to_mpctl(bool state)13284 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
13285 {
13286     if (load_lib() == false) {
13287        return;
13288     }
13289     m_perf_lock.lock();
13290     /* 0x4401 maps to video decode playback hint
13291      * in perflock, enum number is 44 and state
13292      * being sent on perflock acquire is 01 (true)
13293      */
13294     int arg = 0x4401;
13295 
13296     if (state == true) {
13297         mpctl_obj.vid_inst_count++;
13298     } else if (state == false) {
13299         mpctl_obj.vid_inst_count--;
13300     }
13301 
13302     if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
13303         mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
13304         mpctl_obj.vid_acquired = true;
13305         DEBUG_PRINT_INFO("Video slvp perflock acquired");
13306     } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
13307         m_perf_lock_release(mpctl_obj.vid_disp_handle);
13308         mpctl_obj.vid_acquired = false;
13309         DEBUG_PRINT_INFO("Video slvp perflock released");
13310     }
13311     m_perf_lock.unlock();
13312 }
13313 
request_cores(int frame_duration_us)13314 void omx_vdec::perf_control::request_cores(int frame_duration_us)
13315 {
13316     if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
13317         return;
13318     }
13319     bool retVal = load_lib();
13320     if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
13321         int arg = 0x700 /*base value*/ + 2 /*cores*/;
13322         m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
13323         if (m_perf_handle) {
13324             DEBUG_PRINT_HIGH("perf lock acquired");
13325         }
13326     }
13327 }
13328 
load_lib()13329 bool omx_vdec::perf_control::load_lib()
13330 {
13331     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
13332     if (m_perf_lib)
13333         return true;
13334 
13335     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
13336         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
13337         goto handle_err;
13338     }
13339 
13340     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
13341         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
13342         goto handle_err;
13343     } else {
13344         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
13345         if (m_perf_lock_acquire == NULL) {
13346             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
13347             goto handle_err;
13348         }
13349         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
13350         if (m_perf_lock_release == NULL) {
13351             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
13352             goto handle_err;
13353         }
13354     }
13355     return true;
13356 
13357 handle_err:
13358     if (m_perf_lib) {
13359         dlclose(m_perf_lib);
13360     }
13361     m_perf_lib = NULL;
13362     return false;
13363 }
13364 
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)13365 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
13366                             unsigned long nMaxFrameHeight)
13367 {
13368 
13369     OMX_ERRORTYPE eRet = OMX_ErrorNone;
13370     int ret = 0;
13371     unsigned long min_res_buf_count = 0;
13372 
13373     eRet = enable_smoothstreaming();
13374     if (eRet != OMX_ErrorNone) {
13375          DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
13376          return eRet;
13377      }
13378 
13379      DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
13380              nMaxFrameWidth,
13381              nMaxFrameHeight);
13382      m_smoothstreaming_mode = true;
13383      m_smoothstreaming_width = nMaxFrameWidth;
13384      m_smoothstreaming_height = nMaxFrameHeight;
13385 
13386      //Get upper limit buffer count for min supported resolution
13387      struct v4l2_format fmt;
13388      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13389      fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
13390      fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
13391      fmt.fmt.pix_mp.pixelformat = output_capability;
13392 
13393      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13394      if (ret) {
13395          DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
13396                            m_decoder_capability.min_height,
13397                            m_decoder_capability.min_width);
13398          return OMX_ErrorUnsupportedSetting;
13399      }
13400 
13401      eRet = get_buffer_req(&drv_ctx.op_buf);
13402      if (eRet != OMX_ErrorNone) {
13403          DEBUG_PRINT_ERROR("failed to get_buffer_req");
13404          return eRet;
13405      }
13406 
13407      min_res_buf_count = drv_ctx.op_buf.mincount;
13408      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
13409                      min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
13410 
13411      m_extradata_info.output_crop_rect.nLeft = 0;
13412      m_extradata_info.output_crop_rect.nTop = 0;
13413      m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
13414      m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
13415 
13416      update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
13417                        m_smoothstreaming_width, m_smoothstreaming_height);
13418      eRet = is_video_session_supported();
13419      if (eRet != OMX_ErrorNone) {
13420          DEBUG_PRINT_ERROR("video session is not supported");
13421          return eRet;
13422      }
13423 
13424      //Get upper limit buffer size for max smooth streaming resolution set
13425      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13426      fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
13427      fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
13428      fmt.fmt.pix_mp.pixelformat = output_capability;
13429      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13430      if (ret) {
13431          DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
13432          return OMX_ErrorUnsupportedSetting;
13433      }
13434 
13435      eRet = get_buffer_req(&drv_ctx.op_buf);
13436      if (eRet != OMX_ErrorNone) {
13437          DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
13438          return eRet;
13439      }
13440      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
13441                      (unsigned int)drv_ctx.op_buf.buffer_size);
13442 
13443      drv_ctx.op_buf.mincount = min_res_buf_count;
13444      drv_ctx.op_buf.actualcount = min_res_buf_count;
13445      drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
13446      eRet = set_buffer_req(&drv_ctx.op_buf);
13447      if (eRet != OMX_ErrorNone) {
13448          DEBUG_PRINT_ERROR("failed to set_buffer_req");
13449          return eRet;
13450      }
13451 
13452      eRet = get_buffer_req(&drv_ctx.op_buf);
13453      if (eRet != OMX_ErrorNone) {
13454          DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
13455          return eRet;
13456      }
13457      DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
13458                       drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
13459      return eRet;
13460 }
13461 
13462 //static
describeColorFormat(OMX_PTR pParam)13463 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
13464 
13465 #ifndef FLEXYUV_SUPPORTED
13466     return OMX_ErrorUndefined;
13467 #else
13468 
13469     if (pParam == NULL) {
13470         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
13471         return OMX_ErrorBadParameter;
13472     }
13473 
13474     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
13475 
13476     MediaImage *img = &(params->sMediaImage);
13477     switch(params->eColorFormat) {
13478         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
13479         {
13480             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
13481             img->mNumPlanes = 3;
13482             // mWidth and mHeight represent the W x H of the largest plane
13483             // In our case, this happens to be the Stride x Scanlines of Y plane
13484             img->mWidth = params->nFrameWidth;
13485             img->mHeight = params->nFrameHeight;
13486             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13487             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
13488             img->mBitDepth = 8;
13489             //Plane 0 (Y)
13490             img->mPlane[MediaImage::Y].mOffset = 0;
13491             img->mPlane[MediaImage::Y].mColInc = 1;
13492             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
13493             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
13494             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
13495             //Plane 1 (U)
13496             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
13497             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
13498             img->mPlane[MediaImage::U].mRowInc =
13499                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13500             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
13501             img->mPlane[MediaImage::U].mVertSubsampling = 2;
13502             //Plane 2 (V)
13503             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
13504             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
13505             img->mPlane[MediaImage::V].mRowInc =
13506                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13507             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
13508             img->mPlane[MediaImage::V].mVertSubsampling = 2;
13509             break;
13510         }
13511 
13512         case OMX_COLOR_FormatYUV420Planar:
13513         case OMX_COLOR_FormatYUV420SemiPlanar:
13514             // We need not describe the standard OMX linear formats as these are
13515             // understood by client. Fail this deliberately to let client fill-in
13516             return OMX_ErrorUnsupportedSetting;
13517 
13518         default:
13519             // Rest all formats which are non-linear cannot be described
13520             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
13521             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
13522             return OMX_ErrorNone;
13523     };
13524 
13525     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
13526     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
13527     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
13528     for (size_t i = 0; i < img->mNumPlanes; ++i) {
13529         DEBUG_PRINT_LOW("  Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
13530                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
13531     }
13532     return OMX_ErrorNone;
13533 #endif //FLEXYUV_SUPPORTED
13534 }
13535 
prefetchNewBuffers()13536 void omx_vdec::prefetchNewBuffers() {
13537 
13538     struct v4l2_decoder_cmd dec;
13539     uint32_t prefetch_count;
13540     uint32_t prefetch_size;
13541     uint32_t want_size;
13542     uint32_t have_size;
13543     int color_fmt, rc;
13544     uint32_t new_calculated_size;
13545     uint32_t new_buffer_size;
13546     uint32_t new_buffer_count;
13547     uint32_t old_buffer_size;
13548     uint32_t old_buffer_count;
13549 
13550     memset((void *)&dec, 0 , sizeof(dec));
13551     DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n",
13552             drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
13553             drv_ctx.video_resolution.frame_width,
13554             drv_ctx.video_resolution.frame_height);
13555     dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
13556     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
13557         DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
13558     } else {
13559         DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
13560                 dec.raw.data[0], dec.raw.data[1]);
13561     }
13562 
13563     switch ((int)drv_ctx.output_format) {
13564     case VDEC_YUV_FORMAT_NV12:
13565         color_fmt = COLOR_FMT_NV12;
13566         break;
13567     case VDEC_YUV_FORMAT_NV12_UBWC:
13568         color_fmt = COLOR_FMT_NV12_UBWC;
13569         break;
13570     case VDEC_YUV_FORMAT_NV12_TP10_UBWC:
13571         color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
13572         break;
13573     default:
13574         color_fmt = -1;
13575         DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format);
13576         return;
13577     }
13578 
13579     new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
13580     DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
13581             m_reconfig_width, m_reconfig_height, new_calculated_size);
13582     new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
13583     new_buffer_count = dec.raw.data[1];
13584     old_buffer_size = drv_ctx.op_buf.buffer_size;
13585     old_buffer_count = drv_ctx.op_buf.actualcount;
13586 
13587     new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
13588 
13589     prefetch_count = new_buffer_count;
13590     prefetch_size = new_buffer_size - old_buffer_size;
13591     want_size = new_buffer_size * new_buffer_count;
13592     have_size = old_buffer_size * old_buffer_count;
13593 
13594     if (want_size > have_size) {
13595         DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
13596         DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
13597 
13598         int ion_fd = open(MEM_DEVICE, O_RDONLY);
13599         if (ion_fd < 0) {
13600             DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
13601             return;
13602         }
13603 
13604         struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
13605         struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
13606         struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
13607         size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
13608 
13609         if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
13610             DEBUG_PRINT_ERROR("prefetch data allocation failed");
13611             goto prefetch_exit;
13612         }
13613 
13614         for (uint32_t i = 0; i < prefetch_count; i++) {
13615             sizes[i] = prefetch_size;
13616         }
13617 
13618         regions[0].nr_sizes = prefetch_count;
13619         regions[0].sizes = sizes;
13620         regions[0].vmid = ION_FLAG_CP_PIXEL;
13621 
13622         prefetch_data->nr_regions = 1;
13623         prefetch_data->regions = regions;
13624         prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
13625 
13626         custom_data->cmd = ION_IOC_PREFETCH;
13627         custom_data->arg = (unsigned long )prefetch_data;
13628 
13629         rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
13630         if (rc) {
13631             DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
13632         }
13633 
13634 prefetch_exit:
13635         close(ion_fd);
13636         free(sizes);
13637         free(regions);
13638         free(prefetch_data);
13639         free(custom_data);
13640     }
13641 }
13642 
13643 
13644 // No code beyond this !
13645 
13646 // inline import of vendor-extensions implementation
13647 #include "omx_vdec_extensions.hpp"
13648