• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2020, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 /*============================================================================
30                             O p e n M A X   w r a p p e r s
31                              O p e n  M A X   C o r e
32 
33   This module contains the implementation of the OpenMAX core & component.
34 
35 *//*========================================================================*/
36 
37 //////////////////////////////////////////////////////////////////////////////
38 //                             Include Files
39 //////////////////////////////////////////////////////////////////////////////
40 
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43 
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include "vidc_common.h"
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <stdlib.h>
55 #include <media/hardware/HardwareAPI.h>
56 #include <sys/eventfd.h>
57 #include "PlatformConfig.h"
58 #include <linux/dma-buf.h>
59 #include <linux/videodev2.h>
60 
61 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
62 #include <sys/ioctl.h>
63 #include <sys/mman.h>
64 #endif
65 
66 #ifdef _ANDROID_
67 #include <cutils/properties.h>
68 
69 #ifdef _QUERY_DISP_RES_
70 #include "display_config.h"
71 #endif
72 #endif
73 
74 #ifdef _USE_GLIB_
75 #include <glib.h>
76 #define strlcpy g_strlcpy
77 #endif
78 
79 #include <qdMetaData.h>
80 #include <gralloc_priv.h>
81 
82 #ifdef ANDROID_JELLYBEAN_MR2
83 #include "QComOMXMetadata.h"
84 #endif
85 
86 #define BUFFER_LOG_LOC "/data/vendor/media"
87 
88 #ifdef OUTPUT_EXTRADATA_LOG
89 FILE *outputExtradataFile;
90 char output_extradata_filename [] = "/data/vendor/media/extradata";
91 #endif
92 
93 #define POLL_TIMEOUT 0x7fffffff
94 
95 #ifdef _ANDROID_
96 extern "C" {
97 #include<utils/Log.h>
98 }
99 #endif//_ANDROID_
100 
101 #define PREFETCH_PIXEL_BUFFER_COUNT 16
102 #define PREFETCH_NON_PIXEL_BUFFER_COUNT 1
103 
104 #ifndef ION_FLAG_CP_BITSTREAM
105 #define ION_FLAG_CP_BITSTREAM 0
106 #endif
107 
108 #ifndef ION_FLAG_CP_PIXEL
109 #define ION_FLAG_CP_PIXEL 0
110 #endif
111 
112 #ifdef SLAVE_SIDE_CP
113 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
114 #define SECURE_ALIGN SZ_1M
115 #define SECURE_FLAGS_INPUT_BUFFER ION_FLAG_SECURE
116 #define SECURE_FLAGS_OUTPUT_BUFFER ION_FLAG_SECURE
117 #else //MASTER_SIDE_CP
118 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
119 #define SECURE_ALIGN SZ_4K
120 #define SECURE_FLAGS_INPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_BITSTREAM)
121 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_PIXEL)
122 #endif
123 
124 #define LUMINANCE_DIV_FACTOR 10000.0
125 
126 /* defined in mp-ctl.h */
127 #define MPCTLV3_VIDEO_DECODE_PB_HINT 0x41C04000
128 
129 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
130 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
131 
132 /*
133 To enable sending vp9/hevc hdr10plus metadata via private gralloc
134 handle to display, define HDR10PLUS_SETMETADATA_ENABLE as 1.This
135 disables sending metadata via framework. To enable sending vp9/hevc
136 hdr10plus metadata via framework, define HDR10PLUS_SETMETADATA_ENABLE
137 as 0. This disables sending metadata via gralloc handle.
138 */
139 #define HDR10_SETMETADATA_ENABLE 0
140 #define DEC_HDR_DISABLE_FLAG 0x1
141 
142 #define THUMBNAIL_YUV420P_8BIT 0x01
143 #define THUMBNAIL_YUV420P_10BIT 0x02
144 
145 using namespace android;
146 
async_message_thread(void * input)147 void* async_message_thread (void *input)
148 {
149     OMX_BUFFERHEADERTYPE *buffer;
150     struct v4l2_plane plane[VIDEO_MAX_PLANES];
151     struct pollfd pfds[2];
152     struct v4l2_buffer v4l2_buf;
153     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
154     struct v4l2_event dqevent;
155     omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
156     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
157     pfds[1].events = POLLIN | POLLERR;
158     pfds[0].fd = omx->drv_ctx.video_driver_fd;
159     pfds[1].fd = omx->m_poll_efd;
160     int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
161     DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
162     prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
163     while (!omx->async_thread_force_stop) {
164         rc = poll(pfds, 2, POLL_TIMEOUT);
165         if (!rc) {
166             DEBUG_PRINT_ERROR("Poll timedout");
167             break;
168         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
169             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
170             break;
171         }
172         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
173             DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
174             break;
175         }
176         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
177             struct vdec_msginfo vdec_msg;
178             memset(&vdec_msg, 0, sizeof(vdec_msg));
179             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
180             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
181             v4l2_buf.length = omx->drv_ctx.num_planes;
182             v4l2_buf.m.planes = plane;
183             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
184                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
185                 vdec_msg.status_code=VDEC_S_SUCCESS;
186                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
187                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
188                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
189                 vdec_msg.msgdata.output_frame.time_stamp= ((int64_t)v4l2_buf.timestamp.tv_sec * (int64_t)1000000) +
190                     (int64_t)v4l2_buf.timestamp.tv_usec;
191 
192                 if (omx->async_message_process(input,&vdec_msg) < 0) {
193                     DEBUG_PRINT_HIGH("async_message_thread Exited");
194                     break;
195                 }
196             }
197         }
198         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
199             struct vdec_msginfo vdec_msg;
200             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
201             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
202             v4l2_buf.length = 1;
203             v4l2_buf.m.planes = plane;
204             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
205                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
206                 vdec_msg.status_code=VDEC_S_SUCCESS;
207                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
208                 if (omx->async_message_process(input,&vdec_msg) < 0) {
209                     DEBUG_PRINT_HIGH("async_message_thread Exited");
210                     break;
211                 }
212             }
213         }
214         if (pfds[0].revents & POLLPRI) {
215             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
216             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
217                 struct vdec_msginfo vdec_msg;
218                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
219 
220                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
221                 vdec_msg.status_code=VDEC_S_SUCCESS;
222                 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[MSM_VIDC_HEIGHT];
223                 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[MSM_VIDC_WIDTH];
224                 vdec_msg.msgdata.output_frame.flags = true; // INSUFFICIENT event
225                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
226                 omx->dpb_bit_depth = ptr[MSM_VIDC_BIT_DEPTH];
227                 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth - %d", ptr[MSM_VIDC_BIT_DEPTH]);
228                 omx->m_progressive = ptr[MSM_VIDC_PIC_STRUCT];
229                 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct - %d", ptr[MSM_VIDC_PIC_STRUCT]);
230                 omx->m_color_space = (ptr[MSM_VIDC_COLOR_SPACE] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
231                                       (omx_vdec:: EXCEPT_BT2020));
232                 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace - %d", omx->m_color_space);
233                 if (omx->async_message_process(input,&vdec_msg) < 0) {
234                     DEBUG_PRINT_HIGH("async_message_thread Exited");
235                     break;
236                 }
237             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
238                 struct vdec_msginfo vdec_msg;
239                 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
240                 // Old driver doesn't send flushType information.
241                 // To make this backward compatible fallback to old approach
242                 // if the flush_type is not present.
243                 vdec_msg.status_code=VDEC_S_SUCCESS;
244                 if (!flush_type || (flush_type & V4L2_CMD_FLUSH_OUTPUT)) {
245                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
246                     DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
247                     if (omx->async_message_process(input,&vdec_msg) < 0) {
248                         DEBUG_PRINT_HIGH("async_message_thread Exited");
249                         break;
250                     }
251                 }
252 
253                 if (!flush_type || (flush_type & V4L2_CMD_FLUSH_CAPTURE)) {
254                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
255                     DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
256                     if (omx->async_message_process(input,&vdec_msg) < 0) {
257                         DEBUG_PRINT_HIGH("async_message_thread Exited");
258                         break;
259                     }
260                 }
261             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
262                 struct vdec_msginfo vdec_msg;
263                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
264                 vdec_msg.status_code=VDEC_S_SUCCESS;
265                 DEBUG_PRINT_ERROR("HW Overload received");
266                 if (omx->async_message_process(input,&vdec_msg) < 0) {
267                     DEBUG_PRINT_HIGH("async_message_thread Exited");
268                     break;
269                 }
270             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
271                 struct vdec_msginfo vdec_msg;
272                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
273                 vdec_msg.status_code=VDEC_S_SUCCESS;
274                 DEBUG_PRINT_ERROR("HW Unsupported received");
275                 if (omx->async_message_process(input,&vdec_msg) < 0) {
276                     DEBUG_PRINT_HIGH("async_message_thread Exited");
277                     break;
278                 }
279             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
280                 struct vdec_msginfo vdec_msg;
281                 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
282                 vdec_msg.status_code = VDEC_S_SUCCESS;
283                 DEBUG_PRINT_HIGH("SYS Error Recieved");
284                 if (omx->async_message_process(input,&vdec_msg) < 0) {
285                     DEBUG_PRINT_HIGH("async_message_thread Exited");
286                     break;
287                 }
288             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
289                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
290 
291                 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
292             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
293                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
294                 struct vdec_msginfo vdec_msg;
295 
296                 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
297 
298                 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
299                 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
300                 v4l2_buf.length = omx->drv_ctx.num_planes;
301                 v4l2_buf.m.planes = plane;
302                 v4l2_buf.index = ptr[5];
303                 v4l2_buf.flags = 0;
304 
305                 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
306                 vdec_msg.status_code = VDEC_S_SUCCESS;
307                 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
308                 vdec_msg.msgdata.output_frame.len = 0;
309                 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
310                 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
311                     (uint64_t)ptr[4];
312                 if (omx->async_message_process(input,&vdec_msg) < 0) {
313                     DEBUG_PRINT_HIGH("async_message_thread Exitedn");
314                     break;
315                 }
316             } else {
317                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
318                 continue;
319             }
320         }
321     }
322     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
323     return NULL;
324 }
325 
message_thread_dec(void * input)326 void* message_thread_dec(void *input)
327 {
328     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
329     int res = 0;
330 
331     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
332     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
333     while (!omx->message_thread_stop) {
334         res = omx->signal.wait(2 * 1000000000);
335         if (res == ETIMEDOUT || omx->message_thread_stop) {
336             continue;
337         } else if (res) {
338             DEBUG_PRINT_ERROR("omx_vdec: message_thread_dec wait on condition failed, exiting");
339             break;
340         }
341         omx->process_event_cb(omx);
342     }
343     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
344     return 0;
345 }
346 
post_message(omx_vdec * omx,unsigned char id)347 void post_message(omx_vdec *omx, unsigned char id)
348 {
349     (void)id;
350     omx->signal.signal();
351 }
352 
353 // omx_cmd_queue destructor
~omx_cmd_queue()354 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
355 {
356     // Nothing to do
357 }
358 
359 // omx cmd queue constructor
omx_cmd_queue()360 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
361 {
362     memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
363 }
364 
365 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)366 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
367 {
368     bool ret = true;
369     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
370         m_q[m_write].id       = id;
371         m_q[m_write].param1   = p1;
372         m_q[m_write].param2   = p2;
373         m_write++;
374         m_size ++;
375         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
376             m_write = 0;
377         }
378     } else {
379         ret = false;
380         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
381     }
382     return ret;
383 }
384 
385 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)386 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
387 {
388     bool ret = true;
389     if (m_size > 0) {
390         *id = m_q[m_read].id;
391         *p1 = m_q[m_read].param1;
392         *p2 = m_q[m_read].param2;
393         // Move the read pointer ahead
394         ++m_read;
395         --m_size;
396         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
397             m_read = 0;
398         }
399     } else {
400         ret = false;
401     }
402     return ret;
403 }
404 
405 // Retrieve the first mesg type in the queue
get_q_msg_type()406 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
407 {
408     return m_q[m_read].id;
409 }
410 
411 #ifdef _ANDROID_
ts_arr_list()412 omx_vdec::ts_arr_list::ts_arr_list()
413 {
414     //initialize timestamps array
415     memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
416 }
~ts_arr_list()417 omx_vdec::ts_arr_list::~ts_arr_list()
418 {
419     //free m_ts_arr_list?
420 }
421 
insert_ts(OMX_TICKS ts)422 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
423 {
424     bool ret = true;
425     bool duplicate_ts = false;
426     int idx = 0;
427 
428     //insert at the first available empty location
429     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
430         if (!m_ts_arr_list[idx].valid) {
431             //found invalid or empty entry, save timestamp
432             m_ts_arr_list[idx].valid = true;
433             m_ts_arr_list[idx].timestamp = ts;
434             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
435                     ts, idx);
436             break;
437         }
438     }
439 
440     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
441         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
442         ret = false;
443     }
444     return ret;
445 }
446 
pop_min_ts(OMX_TICKS & ts)447 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
448 {
449     bool ret = true;
450     int min_idx = -1;
451     OMX_TICKS min_ts = 0;
452     int idx = 0;
453 
454     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
455 
456         if (m_ts_arr_list[idx].valid) {
457             //found valid entry, save index
458             if (min_idx < 0) {
459                 //first valid entry
460                 min_ts = m_ts_arr_list[idx].timestamp;
461                 min_idx = idx;
462             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
463                 min_ts = m_ts_arr_list[idx].timestamp;
464                 min_idx = idx;
465             }
466         }
467 
468     }
469 
470     if (min_idx < 0) {
471         //no valid entries found
472         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
473         ts = 0;
474         ret = false;
475     } else {
476         ts = m_ts_arr_list[min_idx].timestamp;
477         m_ts_arr_list[min_idx].valid = false;
478         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
479                 ts, min_idx);
480     }
481 
482     return ret;
483 
484 }
485 
486 
reset_ts_list()487 bool omx_vdec::ts_arr_list::reset_ts_list()
488 {
489     bool ret = true;
490     int idx = 0;
491 
492     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
493     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
494         m_ts_arr_list[idx].valid = false;
495     }
496     return ret;
497 }
498 #endif
499 
500 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)501 void *get_omx_component_factory_fn(void)
502 {
503     return (new omx_vdec);
504 }
505 
is_platform_tp10capture_supported()506 bool is_platform_tp10capture_supported()
507 {
508     DEBUG_PRINT_HIGH("TP10 on capture port is supported");
509     return true;
510 }
511 
get_session_codec_type()512 inline int omx_vdec::get_session_codec_type()
513 {
514     return output_capability;
515 }
516 /* ======================================================================
517    FUNCTION
518    omx_vdec::omx_vdec
519 
520    DESCRIPTION
521    Constructor
522 
523    PARAMETERS
524    None
525 
526    RETURN VALUE
527    None.
528    ========================================================================== */
omx_vdec()529 omx_vdec::omx_vdec(): m_error_propogated(false),
530     m_state(OMX_StateInvalid),
531     m_app_data(NULL),
532     m_inp_mem_ptr(NULL),
533     m_out_mem_ptr(NULL),
534     m_intermediate_out_mem_ptr(NULL),
535     m_client_output_extradata_mem_ptr(NULL),
536     input_flush_progress (false),
537     output_flush_progress (false),
538     input_use_buffer (false),
539     output_use_buffer (false),
540     ouput_egl_buffers(false),
541     m_use_output_pmem(OMX_FALSE),
542     pending_input_buffers(0),
543     pending_output_buffers(0),
544     m_out_bm_count(0),
545     m_inp_bm_count(0),
546     m_out_extradata_bm_count(0),
547     m_inp_bPopulated(OMX_FALSE),
548     m_out_bPopulated(OMX_FALSE),
549     m_flags(0),
550     m_inp_bEnabled(OMX_TRUE),
551     m_out_bEnabled(OMX_TRUE),
552     m_in_alloc_cnt(0),
553     m_platform_list(NULL),
554     m_platform_entry(NULL),
555     m_pmem_info(NULL),
556     psource_frame (NULL),
557     pdest_frame (NULL),
558     m_inp_heap_ptr (NULL),
559     m_phdr_pmem_ptr(NULL),
560     m_heap_inp_bm_count (0),
561     first_frame_meta (true),
562     frame_count (0),
563     nal_count (0),
564     nal_length(0),
565     first_frame(0),
566     first_buffer(NULL),
567     first_frame_size (0),
568     m_device_file_ptr(NULL),
569     m_disp_hor_size(0),
570     m_disp_vert_size(0),
571     prev_ts(LLONG_MAX),
572     frm_int(0),
573     m_fps_received(0),
574     in_reconfig(false),
575     c2d_enable_pending(false),
576     m_display_id(NULL),
577 #ifdef _ANDROID_
578     m_enable_android_native_buffers(OMX_FALSE),
579     m_use_android_native_buffers(OMX_FALSE),
580 #endif
581     m_disable_dynamic_buf_mode(0),
582     m_desc_buffer_ptr(NULL),
583     secure_mode(false),
584     allocate_native_handle(false),
585     client_set_fps(false),
586     stereo_output_mode(HAL_NO_3D),
587     m_last_rendered_TS(-1),
588     m_dec_hfr_fps(0),
589     m_dec_secure_prefetch_size_internal(0),
590     m_dec_secure_prefetch_size_output(0),
591     m_queued_codec_config_count(0),
592     m_thumbnail_yuv_output(0),
593     m_prefetch_done(0),
594     m_buffer_error(false)
595 {
596     m_poll_efd = -1;
597     memset(&drv_ctx, 0, sizeof(drv_ctx));
598     drv_ctx.video_driver_fd = -1;
599     for (int i = 0; i < VIDEO_MAX_FRAME; i++) {
600         drv_ctx.extradata_info.ion[i].data_fd = -1;
601         drv_ctx.extradata_info.ion[i].dev_fd = -1;
602     }
603     /* Assumption is that , to begin with , we have all the frames with decoder */
604     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
605     memset(&m_debug,0,sizeof(m_debug));
606 #ifdef _ANDROID_
607 
608     char property_value[PROPERTY_VALUE_MAX] = {0};
609     property_get("vendor.vidc.debug.level", property_value, "1");
610     debug_level = strtoul(property_value, NULL, 16);
611     property_value[0] = '\0';
612 
613     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
614 
615     // TODO: Support in XML
616     perf_flag = 0;
617     if (perf_flag) {
618         DEBUG_PRINT_HIGH("perf flag is %d", perf_flag);
619         dec_time.start();
620     }
621     proc_frms = latency = 0;
622     prev_n_filled_len = 0;
623 
624     Platform::Config::getInt32(Platform::vidc_dec_log_in,
625             (int32_t *)&m_debug.in_buffer_log, 0);
626     Platform::Config::getInt32(Platform::vidc_dec_log_out,
627             (int32_t *)&m_debug.out_buffer_log, 0);
628 
629     Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_internal,
630             (int32_t *)&m_dec_secure_prefetch_size_internal, 0);
631     Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_output,
632             (int32_t *)&m_dec_secure_prefetch_size_output, 0);
633 
634     DEBUG_PRINT_HIGH("Prefetch size internal = %d, output = %d",
635             m_dec_secure_prefetch_size_internal, m_dec_secure_prefetch_size_output);
636 
637     Platform::Config::getInt32(Platform::vidc_perf_control_enable,
638             (int32_t *)&m_perf_control.m_perf_control_enable, 0);
639     if (m_perf_control.m_perf_control_enable) {
640         DEBUG_PRINT_HIGH("perf cotrol enabled");
641         m_perf_control.load_perf_library();
642     }
643 
644     Platform::Config::getInt32(Platform::vidc_dec_thumbnail_yuv_output,
645             (int32_t *)&m_thumbnail_yuv_output, 0);
646 
647     Platform::Config::getInt32(Platform::vidc_disable_hdr,
648             (int32_t *)&m_disable_hdr, 0);
649 
650     Platform::Config::getInt32(Platform::vidc_dec_output_rate,
651             (int32_t *)&m_dec_output_rate, 60);
652 
653     property_value[0] = '\0';
654     property_get("vendor.vidc.dec.log.in", property_value, "0");
655     m_debug.in_buffer_log |= atoi(property_value);
656 
657     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.in value is %d", m_debug.in_buffer_log);
658 
659     property_value[0] = '\0';
660     property_get("vendor.vidc.dec.log.out", property_value, "0");
661     m_debug.out_buffer_log |= atoi(property_value);
662 
663     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.out value is %d", m_debug.out_buffer_log);
664 
665     property_value[0] = '\0';
666     property_get("vendor.vidc.dec.log.cc.out", property_value, "0");
667     m_debug.out_cc_buffer_log |= atoi(property_value);
668 
669     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.cc.out value is %d", m_debug.out_buffer_log);
670 
671     property_value[0] = '\0';
672     property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
673     m_debug.out_meta_buffer_log = atoi(property_value);
674 
675     property_value[0] = '\0';
676     property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
677     if (*property_value)
678         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
679 
680     struct timeval te;
681     gettimeofday(&te, NULL);
682     m_debug.session_id = te.tv_sec*1000LL + te.tv_usec/1000;
683     m_debug.seq_count = 0;
684 
685 #ifdef _UBWC_
686     property_value[0] = '\0';
687     property_get("vendor.gralloc.disable_ubwc", property_value, "0");
688     m_disable_ubwc_mode = atoi(property_value);
689     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
690 #else
691     m_disable_ubwc_mode = true;
692 #endif
693 #endif
694     memset(&m_cmp,0,sizeof(m_cmp));
695     memset(&m_cb,0,sizeof(m_cb));
696     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
697     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
698     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
699     memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
700     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
701     memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
702     memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
703     m_demux_entries = 0;
704     msg_thread_id = 0;
705     async_thread_id = 0;
706     msg_thread_created = false;
707     async_thread_created = false;
708     async_thread_force_stop = false;
709     message_thread_stop = false;
710 #ifdef _ANDROID_ICS_
711     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
712 #endif
713 
714     drv_ctx.timestamp_adjust = false;
715     m_vendor_config.pData = NULL;
716     pthread_mutex_init(&m_lock, NULL);
717     pthread_mutex_init(&c_lock, NULL);
718     pthread_mutex_init(&buf_lock, NULL);
719     pthread_mutex_init(&m_hdr10pluslock, NULL);
720     sem_init(&m_cmd_lock,0,0);
721     sem_init(&m_safe_flush, 0, 0);
722     streaming[CAPTURE_PORT] =
723         streaming[OUTPUT_PORT] = false;
724 #ifdef _ANDROID_
725     // TODO: Support in XML
726 #endif
727     m_client_extradata = EXTRADATA_NONE;
728     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
729     client_buffers.set_vdec_client(this);
730     dynamic_buf_mode = false;
731     m_reconfig_height = 0;
732     m_reconfig_width = 0;
733     m_decode_order_mode = false;
734     m_perf_control.perf_lock_acquire();
735     m_input_pass_buffer_fd = false;
736     memset(&m_extradata_misr, 0, sizeof(m_extradata_misr));
737     m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
738     m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
739     m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
740     m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
741     m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
742 
743     m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
744     m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
745     m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
746     m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
747     m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
748     m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
749 
750     m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
751     m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
752 
753     m_etb_count = 0;
754     m_etb_timestamp = 0;
755 
756     m_color_space = EXCEPT_BT2020;
757 
758     init_color_aspects_map();
759     m_hist_metadata.stat_len = 0;
760 
761     profile_level_converter::init();
762     clientSet_profile_level.eProfile = 0;
763     clientSet_profile_level.eLevel = 0;
764 #ifdef USE_GBM
765      drv_ctx.gbm_device_fd = -1;
766 #endif
767 }
768 
769 static const int event_type[] = {
770     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
771     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
772     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
773     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
774     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
775     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
776     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
777 };
778 
subscribe_to_events(int fd)779 static OMX_ERRORTYPE subscribe_to_events(int fd)
780 {
781     OMX_ERRORTYPE eRet = OMX_ErrorNone;
782     struct v4l2_event_subscription sub;
783     int array_sz = sizeof(event_type)/sizeof(int);
784     int i,rc;
785     if (fd < 0) {
786         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
787         return OMX_ErrorBadParameter;
788     }
789 
790     for (i = 0; i < array_sz; ++i) {
791         memset(&sub, 0, sizeof(sub));
792         sub.type = event_type[i];
793         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
794         if (rc) {
795             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
796             break;
797         }
798     }
799     if (i < array_sz) {
800         for (--i; i >=0 ; i--) {
801             memset(&sub, 0, sizeof(sub));
802             sub.type = event_type[i];
803             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
804             if (rc)
805                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
806         }
807         eRet = OMX_ErrorNotImplemented;
808     }
809     return eRet;
810 }
811 
812 
unsubscribe_to_events(int fd)813 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
814 {
815     OMX_ERRORTYPE eRet = OMX_ErrorNone;
816     struct v4l2_event_subscription sub;
817     int array_sz = sizeof(event_type)/sizeof(int);
818     int i,rc;
819     if (fd < 0) {
820         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
821         return OMX_ErrorBadParameter;
822     }
823 
824     for (i = 0; i < array_sz; ++i) {
825         memset(&sub, 0, sizeof(sub));
826         sub.type = event_type[i];
827         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
828         if (rc) {
829             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
830             break;
831         }
832     }
833     return eRet;
834 }
835 
836 /* ======================================================================
837    FUNCTION
838    omx_vdec::~omx_vdec
839 
840    DESCRIPTION
841    Destructor
842 
843    PARAMETERS
844    None
845 
846    RETURN VALUE
847    None.
848    ========================================================================== */
~omx_vdec()849 omx_vdec::~omx_vdec()
850 {
851     m_pmem_info = NULL;
852     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
853     if (msg_thread_created) {
854         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
855         message_thread_stop = true;
856         post_message(this, OMX_COMPONENT_CLOSE_MSG);
857         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
858         pthread_join(msg_thread_id,NULL);
859     }
860     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
861     if(eventfd_write(m_poll_efd, 1)) {
862          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
863          async_thread_force_stop = true;
864     }
865     if (async_thread_created)
866         pthread_join(async_thread_id,NULL);
867 
868     if (m_prefetch_done & 0x1)
869         prefetch_buffers(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, ION_IOC_DRAIN, ION_FLAG_CP_PIXEL);
870     if (m_prefetch_done & 0x2)
871         prefetch_buffers(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, ION_IOC_DRAIN, ION_FLAG_CP_NON_PIXEL);
872 
873     unsubscribe_to_events(drv_ctx.video_driver_fd);
874     close(m_poll_efd);
875     close(drv_ctx.video_driver_fd);
876     clear_hdr10plusinfo();
877     pthread_mutex_destroy(&m_lock);
878     pthread_mutex_destroy(&c_lock);
879     pthread_mutex_destroy(&buf_lock);
880     pthread_mutex_destroy(&m_hdr10pluslock);
881     sem_destroy(&m_cmd_lock);
882     if (perf_flag) {
883         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
884         dec_time.end();
885     }
886     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
887     m_perf_control.perf_lock_release();
888 }
889 
check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)890 bool omx_vdec::check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)
891 {
892     if(required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
893          required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus) {
894          //for now, the flexible formats should be NV12 by default for 8bit cases
895          //it will change to P010 after 10bit port-reconfig accordingly
896        return OMX_TRUE;
897     }
898     else {
899        return OMX_FALSE;
900     }
901 }
902 
903 /* ======================================================================
904    FUNCTION
905    omx_vdec::OMXCntrlProcessMsgCb
906 
907    DESCRIPTION
908    IL Client callbacks are generated through this routine. The decoder
909    provides the thread context for this routine.
910 
911    PARAMETERS
912    ctxt -- Context information related to the self.
913    id   -- Event identifier. This could be any of the following:
914    1. Command completion event
915    2. Buffer done callback event
916    3. Frame done callback event
917 
918    RETURN VALUE
919    None.
920 
921    ========================================================================== */
process_event_cb(void * ctxt)922 void omx_vdec::process_event_cb(void *ctxt)
923 {
924     unsigned long p1; // Parameter - 1
925     unsigned long p2; // Parameter - 2
926     unsigned long ident;
927     unsigned qsize=0; // qsize
928     omx_vdec *pThis = (omx_vdec *) ctxt;
929 
930     if (!pThis) {
931         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
932                 __func__);
933         return;
934     }
935 
936     // Protect the shared queue data structure
937     do {
938         /*Read the message id's from the queue*/
939         pthread_mutex_lock(&pThis->m_lock);
940         qsize = pThis->m_cmd_q.m_size;
941         if (qsize) {
942             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
943         }
944 
945         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
946             qsize = pThis->m_ftb_q.m_size;
947             if (qsize) {
948                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
949             }
950         }
951 
952         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
953             qsize = pThis->m_etb_q.m_size;
954             if (qsize) {
955                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
956             }
957         }
958         pthread_mutex_unlock(&pThis->m_lock);
959 
960         /*process message if we have one*/
961         if (qsize > 0) {
962             switch (ident) {
963                 case OMX_COMPONENT_GENERATE_EVENT:
964                     if (pThis->m_cb.EventHandler) {
965                         switch (p1) {
966                             case OMX_CommandStateSet:
967                                 pThis->m_state = (OMX_STATETYPE) p2;
968                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
969                                         pThis->m_state);
970                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
971                                         OMX_EventCmdComplete, p1, p2, NULL);
972                                 break;
973 
974                             case OMX_EventError:
975                                 if (p2 == OMX_StateInvalid) {
976                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
977                                     pThis->m_state = (OMX_STATETYPE) p2;
978                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
979                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
980                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
981                                     pThis->omx_report_error();
982                                 } else {
983                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
984                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
985                                 }
986                                 break;
987 
988                             case OMX_CommandPortDisable:
989                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
990                                 if (BITMASK_PRESENT(&pThis->m_flags,
991                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
992                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
993                                     break;
994                                 }
995                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
996                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
997                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
998                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
999                                     pThis->in_reconfig = false;
1000                                     pThis->client_buffers.enable_color_conversion(pThis->c2d_enable_pending);
1001                                     if (eRet !=  OMX_ErrorNone) {
1002                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1003                                         pThis->omx_report_error();
1004                                         break;
1005                                     }
1006                                 }
1007                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1008                                         OMX_EventCmdComplete, p1, p2, NULL );
1009                                 break;
1010                             case OMX_CommandPortEnable:
1011                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1012                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1013                                         OMX_EventCmdComplete, p1, p2, NULL );
1014                                 break;
1015 
1016                             default:
1017                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1018                                         OMX_EventCmdComplete, p1, p2, NULL );
1019                                 break;
1020 
1021                         }
1022                     } else {
1023                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1024                     }
1025                     break;
1026                 case OMX_COMPONENT_GENERATE_ETB: {
1027                         OMX_ERRORTYPE iret;
1028                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1029                         if (iret == OMX_ErrorInsufficientResources) {
1030                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1031                             pThis->omx_report_hw_overload ();
1032                         } else if (iret != OMX_ErrorNone) {
1033                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1034                             pThis->omx_report_error ();
1035                         }
1036                     }
1037                     break;
1038 
1039                 case OMX_COMPONENT_GENERATE_FTB:
1040                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1041                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1042                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1043                         pThis->omx_report_error ();
1044                     }
1045                     break;
1046 
1047                 case OMX_COMPONENT_GENERATE_COMMAND:
1048                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1049                             (OMX_U32)p2,(OMX_PTR)NULL);
1050                     break;
1051 
1052                 case OMX_COMPONENT_GENERATE_EBD:
1053                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1054                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1055                         pThis->omx_report_error ();
1056                     } else {
1057                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1058                             OMX_BUFFERHEADERTYPE* buffer =
1059                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
1060                             if (!buffer->pMarkData && !buffer->hMarkTargetComponent) {
1061                                 pThis->time_stamp_dts.remove_time_stamp(
1062                                         buffer->nTimeStamp,
1063                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1064                                         ?true:false);
1065                             }
1066                         }
1067 
1068                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1069                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1070                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1071                             pThis->omx_report_error ();
1072                         }
1073                     }
1074                     break;
1075                 case OMX_COMPONENT_GENERATE_FBD:
1076                     if (p2 != VDEC_S_SUCCESS) {
1077                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1078                         pThis->omx_report_error ();
1079                         break;
1080                     }
1081 #if !HDR10_SETMETADATA_ENABLE
1082                     if (pThis->m_cb.EventHandler) {
1083                         OMX_BUFFERHEADERTYPE * buffer = (OMX_BUFFERHEADERTYPE *)(intptr_t)p1;
1084                         if (buffer->nFilledLen && (pThis->output_capability == V4L2_PIX_FMT_HEVC ||
1085                             (pThis->output_capability == V4L2_PIX_FMT_VP9 && buffer->pMarkData))) {
1086                            bool is_list_empty;
1087                            is_list_empty = false;
1088                            pthread_mutex_lock(&pThis->m_hdr10pluslock);
1089                            is_list_empty = pThis->m_hdr10pluslist.empty();
1090                            pthread_mutex_unlock(&pThis->m_hdr10pluslock);
1091                            if (!is_list_empty) {
1092                                DEBUG_PRINT_LOW("fill_buffer_done: event config update");
1093                                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1094                                        OMX_EventConfigUpdate, OMX_CORE_OUTPUT_PORT_INDEX,
1095                                        OMX_QTIIndexConfigDescribeHDR10PlusInfo, NULL);
1096                            }
1097                         }
1098                     }
1099 #endif
1100                     if (pThis->fill_buffer_done(&pThis->m_cmp,
1101                                (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1102                         DEBUG_PRINT_ERROR("fill_buffer_done failure");
1103                         pThis->omx_report_error ();
1104                     }
1105                     break;
1106 
1107                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1108                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete, flags %#llx",
1109                                                 (unsigned long long)pThis->m_flags);
1110                                         if (!pThis->input_flush_progress) {
1111                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1112                                         } else {
1113                                             pThis->execute_input_flush();
1114                                             if (pThis->m_cb.EventHandler) {
1115                                                 if (p2 != VDEC_S_SUCCESS) {
1116                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1117                                                     pThis->omx_report_error ();
1118                                                 } else {
1119                                                     /*Check if we need generate event for Flush done*/
1120                                                     pThis->notify_flush_done(ctxt);
1121 
1122                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1123                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1124                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1125                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1126                                                             pThis->omx_report_error ();
1127                                                         } else {
1128                                                             pThis->streaming[OUTPUT_PORT] = false;
1129                                                         }
1130                                                         if (!pThis->output_flush_progress) {
1131                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1132                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1133                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1134                                                         }
1135                                                     }
1136                                                 }
1137                                             } else {
1138                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1139                                             }
1140                                         }
1141                                         break;
1142 
1143                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1144                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete, flags %#llx",
1145                                                 (unsigned long long)pThis->m_flags);
1146                                         if (!pThis->output_flush_progress) {
1147                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1148                                         } else {
1149                                             pThis->execute_output_flush();
1150                                             if (pThis->m_cb.EventHandler) {
1151                                                 if (p2 != VDEC_S_SUCCESS) {
1152                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1153                                                     pThis->omx_report_error ();
1154                                                 } else {
1155                                                     /*Check if we need generate event for Flush done*/
1156                                                     pThis->notify_flush_done(ctxt);
1157 
1158                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1159                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1160                                                         DEBUG_PRINT_LOW("Internal flush complete");
1161                                                         BITMASK_CLEAR (&pThis->m_flags,
1162                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1163                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1164                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1165                                                             pThis->post_event(OMX_CommandPortDisable,
1166                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1167                                                                     OMX_COMPONENT_GENERATE_EVENT);
1168                                                             BITMASK_CLEAR (&pThis->m_flags,
1169                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1170                                                             BITMASK_CLEAR (&pThis->m_flags,
1171                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1172 
1173                                                         }
1174                                                     }
1175 
1176                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1177                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1178                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1179                                                             pThis->omx_report_error ();
1180                                                             break;
1181                                                         }
1182                                                         pThis->streaming[CAPTURE_PORT] = false;
1183                                                         if (!pThis->input_flush_progress) {
1184                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1185                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1186                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1187                                                         }
1188                                                     }
1189                                                 }
1190                                             } else {
1191                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1192                                             }
1193                                         }
1194                                         break;
1195 
1196                 case OMX_COMPONENT_GENERATE_START_DONE:
1197                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE, flags %#llx",
1198                                                 (unsigned long long)pThis->m_flags);
1199                                         if (pThis->m_cb.EventHandler) {
1200                                             if (p2 != VDEC_S_SUCCESS) {
1201                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1202                                                 pThis->omx_report_error ();
1203                                             } else {
1204                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1205                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1206                                                     DEBUG_PRINT_LOW("Move to executing");
1207                                                     // Send the callback now
1208                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1209                                                     pThis->m_state = OMX_StateExecuting;
1210                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1211                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1212                                                             OMX_StateExecuting, NULL);
1213                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1214                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1215                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1216                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1217                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1218                                                         pThis->omx_report_error ();
1219                                                     }
1220                                                 }
1221                                             }
1222                                         } else {
1223                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1224                                         }
1225                                         break;
1226 
1227                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1228                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1229                                         if (pThis->m_cb.EventHandler) {
1230                                             if (p2 != VDEC_S_SUCCESS) {
1231                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1232                                                 pThis->omx_report_error ();
1233                                             } else {
1234                                                 pThis->complete_pending_buffer_done_cbs();
1235                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1236                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1237                                                     //Send the callback now
1238                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1239                                                     pThis->m_state = OMX_StatePause;
1240                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1241                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1242                                                             OMX_StatePause, NULL);
1243                                                 }
1244                                             }
1245                                         } else {
1246                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1247                                         }
1248 
1249                                         break;
1250 
1251                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1252                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1253                                         if (pThis->m_cb.EventHandler) {
1254                                             if (p2 != VDEC_S_SUCCESS) {
1255                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1256                                                 pThis->omx_report_error ();
1257                                             } else {
1258                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1259                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1260                                                     // Send the callback now
1261                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1262                                                     pThis->m_state = OMX_StateExecuting;
1263                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1264                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1265                                                             OMX_StateExecuting,NULL);
1266                                                 }
1267                                             }
1268                                         } else {
1269                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1270                                         }
1271 
1272                                         break;
1273 
1274                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1275                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1276                                         if (pThis->m_cb.EventHandler) {
1277                                             if (p2 != VDEC_S_SUCCESS) {
1278                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1279                                                 pThis->omx_report_error ();
1280                                             } else {
1281                                                 pThis->complete_pending_buffer_done_cbs();
1282                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1283                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1284                                                     // Send the callback now
1285                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1286                                                     pThis->m_state = OMX_StateIdle;
1287                                                     DEBUG_PRINT_LOW("Move to Idle State");
1288                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1289                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1290                                                             OMX_StateIdle,NULL);
1291                                                 }
1292                                             }
1293                                         } else {
1294                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1295                                         }
1296 
1297                                         break;
1298 
1299                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1300                                         if (p2 == OMX_IndexParamPortDefinition) {
1301                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1302                                             pThis->in_reconfig = true;
1303                                             pThis->prev_n_filled_len = 0;
1304                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1305                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1306                                             /* Update new crop information */
1307                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1308                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1309                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1310                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1311 
1312                                             /* Validate the new crop information */
1313                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1314                                                 pThis->drv_ctx.video_resolution.frame_width) {
1315 
1316                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1317                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1318                                                         pThis->drv_ctx.video_resolution.frame_width);
1319                                                 pThis->rectangle.nLeft = 0;
1320 
1321                                                 if (pThis->rectangle.nWidth >
1322                                                     pThis->drv_ctx.video_resolution.frame_width) {
1323 
1324                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1325                                                             pThis->rectangle.nWidth,
1326                                                             pThis->drv_ctx.video_resolution.frame_width);
1327                                                     pThis->rectangle.nWidth =
1328                                                         pThis->drv_ctx.video_resolution.frame_width;
1329                                                 }
1330                                             }
1331                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1332                                                 pThis->drv_ctx.video_resolution.frame_height) {
1333 
1334                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1335                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1336                                                     pThis->drv_ctx.video_resolution.frame_height);
1337                                                 pThis->rectangle.nTop = 0;
1338 
1339                                                 if (pThis->rectangle.nHeight >
1340                                                     pThis->drv_ctx.video_resolution.frame_height) {
1341 
1342                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1343                                                         pThis->rectangle.nHeight,
1344                                                         pThis->drv_ctx.video_resolution.frame_height);
1345                                                     pThis->rectangle.nHeight =
1346                                                         pThis->drv_ctx.video_resolution.frame_height;
1347                                                 }
1348                                             }
1349                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1350                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1351                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1352                                         } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1353                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1354                                         } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1355                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1356                                         } else {
1357                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1358                                             break;
1359                                         }
1360                                         if (pThis->m_debug.outfile) {
1361                                             fclose(pThis->m_debug.outfile);
1362                                             pThis->m_debug.outfile = NULL;
1363                                         }
1364                                         if (pThis->m_debug.ccoutfile) {
1365                                             fclose(pThis->m_debug.ccoutfile);
1366                                             pThis->m_debug.ccoutfile = NULL;
1367                                         }
1368                                         if (pThis->m_debug.out_ymeta_file) {
1369                                             fclose(pThis->m_debug.out_ymeta_file);
1370                                             pThis->m_debug.out_ymeta_file = NULL;
1371                                         }
1372                                         if (pThis->m_debug.out_uvmeta_file) {
1373                                             fclose(pThis->m_debug.out_uvmeta_file);
1374                                             pThis->m_debug.out_uvmeta_file = NULL;
1375                                         }
1376                                         pThis->m_debug.seq_count++;
1377 
1378                                         if (pThis->m_cb.EventHandler) {
1379                                             void *frame_data = NULL;
1380                                             reconfig_client_data port_data;
1381                                             reconfig_client_crop_data crop_data;
1382                                             if (p2 == OMX_IndexConfigCommonOutputCrop) {
1383                                                 crop_data.width = pThis->rectangle.nWidth;
1384                                                 crop_data.height = pThis->rectangle.nHeight;
1385                                                 crop_data.left = pThis->rectangle.nLeft;
1386                                                 crop_data.top = pThis->rectangle.nTop;
1387                                                 crop_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1388                                                 frame_data = (void*)&crop_data;
1389                                             } else if (p2 == OMX_IndexParamPortDefinition){
1390                                                 port_data.width = pThis->m_reconfig_width;
1391                                                 port_data.height = pThis->m_reconfig_height;
1392                                                 port_data.dpb_bit_depth = pThis->dpb_bit_depth;
1393                                                 port_data.m_progressive = pThis->m_progressive;
1394                                                 port_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1395                                                 frame_data = (void*)&port_data;
1396                                             }
1397                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1398                                                      OMX_EventPortSettingsChanged, p1, p2, (void*)frame_data);
1399                                         } else {
1400                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1401                                         }
1402                                         break;
1403 
1404                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1405                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1406                                         if (pThis->m_cb.EventHandler) {
1407                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1408                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1409                                         } else {
1410                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1411                                         }
1412                                         pThis->prev_ts = LLONG_MAX;
1413                                         break;
1414 
1415                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1416                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1417                                         pThis->omx_report_error();
1418                                         break;
1419 
1420                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1421                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1422                                         pThis->omx_report_unsupported_setting();
1423                                         break;
1424 
1425                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1426                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1427                                         pThis->omx_report_hw_overload();
1428                                         break;
1429 
1430                 case OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL:
1431                                         DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL");
1432                                         pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_PIXEL);
1433                                         break;
1434 
1435                 case OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL:
1436                                         DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL");
1437                                         pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_NON_PIXEL) << 1;
1438                                         break;
1439 
1440                 default:
1441                                         break;
1442             }
1443         }
1444         pthread_mutex_lock(&pThis->m_lock);
1445         qsize = pThis->m_cmd_q.m_size;
1446         if (pThis->m_state != OMX_StatePause)
1447             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1448         pthread_mutex_unlock(&pThis->m_lock);
1449     } while (qsize>0);
1450 
1451 }
1452 
update_resolution(int width,int height,int stride,int scan_lines)1453 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1454 {
1455     int format_changed = 0;
1456     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1457             (width != (int)drv_ctx.video_resolution.frame_width)) {
1458         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1459                 width, drv_ctx.video_resolution.frame_width,
1460                 height,drv_ctx.video_resolution.frame_height);
1461         format_changed = 1;
1462     }
1463     drv_ctx.video_resolution.frame_height = height;
1464     drv_ctx.video_resolution.frame_width = width;
1465     drv_ctx.video_resolution.scan_lines = scan_lines;
1466     drv_ctx.video_resolution.stride = stride;
1467 
1468     rectangle.nLeft = m_extradata_misr.output_crop_rect.nLeft;
1469     rectangle.nTop = m_extradata_misr.output_crop_rect.nTop;
1470     rectangle.nWidth = m_extradata_misr.output_crop_rect.nWidth;
1471     rectangle.nHeight = m_extradata_misr.output_crop_rect.nHeight;
1472 
1473     return format_changed;
1474 }
1475 
log_input_buffers(const char * buffer_addr,int buffer_len,uint64_t timeStamp,int fd)1476 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len, uint64_t timeStamp, int fd)
1477 {
1478     if (!m_debug.in_buffer_log)
1479         return 0;
1480 
1481     sync_start_read(fd);
1482     if (m_debug.in_buffer_log && !m_debug.infile) {
1483         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1484                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p_%" PRId64 ".mpg", m_debug.log_loc,
1485                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this, m_debug.session_id);
1486         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
1487                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
1488                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1489         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1490                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1491                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1492         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1493                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1494                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1495         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1496                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1497                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1498         } else {
1499                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.bin",
1500                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1501         }
1502         m_debug.infile = fopen (m_debug.infile_name, "ab");
1503         if (!m_debug.infile) {
1504             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging (%d:%s)",
1505                              m_debug.infile_name, errno, strerror(errno));
1506             m_debug.infile_name[0] = '\0';
1507             sync_end_read(fd);
1508             return -1;
1509         }
1510         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1511                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1512             bool isVp9 = drv_ctx.decoder_format == VDEC_CODECTYPE_VP9;
1513             int width = drv_ctx.video_resolution.frame_width;
1514             int height = drv_ctx.video_resolution.frame_height;
1515             int fps = drv_ctx.frame_rate.fps_numerator;
1516             IvfFileHeader ivfHeader(isVp9, width, height, 1, fps, 0);
1517             fwrite((const char *)&ivfHeader,
1518                     sizeof(ivfHeader),1,m_debug.infile);
1519          }
1520     }
1521     if (m_debug.infile && buffer_addr && buffer_len) {
1522         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1523                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1524             IvfFrameHeader ivfFrameHeader(buffer_len, timeStamp);
1525             fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.infile);
1526         }
1527         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1528     }
1529     sync_end_read(fd);
1530     return 0;
1531 }
1532 
log_cc_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1533 int omx_vdec::log_cc_output_buffers(OMX_BUFFERHEADERTYPE *buffer)
1534 {
1535     vdec_bufferpayload *vdec_buf = NULL;
1536     int index = 0;
1537     if (client_buffers.client_buffers_invalid() ||
1538         !m_debug.out_cc_buffer_log || !buffer || !buffer->nFilledLen)
1539         return 0;
1540 
1541     index = buffer - m_out_mem_ptr;
1542     vdec_buf = &drv_ctx.ptr_outputbuffer[index];
1543     sync_start_read(vdec_buf->pmem_fd);
1544     if (m_debug.out_cc_buffer_log && !m_debug.ccoutfile) {
1545         snprintf(m_debug.ccoutfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_cc_%d_%d_%p_%" PRId64 "_%d.yuv",
1546                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
1547                 m_debug.session_id, m_debug.seq_count);
1548         m_debug.ccoutfile = fopen (m_debug.ccoutfile_name, "ab");
1549         if (!m_debug.ccoutfile) {
1550             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1551             m_debug.ccoutfile_name[0] = '\0';
1552             return -1;
1553         }
1554         DEBUG_PRINT_HIGH("Opened CC output file: %s for logging", m_debug.ccoutfile_name);
1555     }
1556 
1557     fwrite(buffer->pBuffer, buffer->nFilledLen, 1, m_debug.ccoutfile);
1558     sync_end_read(vdec_buf->pmem_fd);
1559     return 0;
1560 }
1561 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1562 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer)
1563 {
1564     int buf_index = 0;
1565     char *temp = NULL;
1566     char *bufaddr = NULL;
1567 
1568     if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
1569         return 0;
1570 
1571     if (m_debug.out_buffer_log && !m_debug.outfile) {
1572         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p_%" PRId64 "_%d.yuv",
1573                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
1574                 m_debug.session_id, m_debug.seq_count);
1575         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1576         if (!m_debug.outfile) {
1577             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1578             m_debug.outfile_name[0] = '\0';
1579             return -1;
1580         }
1581         DEBUG_PRINT_HIGH("Opened output file: %s for logging", m_debug.outfile_name);
1582     }
1583 
1584     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
1585         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
1586                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1587         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
1588                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1589         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
1590         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
1591         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
1592             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
1593             m_debug.out_ymetafile_name[0] = '\0';
1594             m_debug.out_uvmetafile_name[0] = '\0';
1595             return -1;
1596         }
1597     }
1598 
1599     vdec_bufferpayload *vdec_buf = NULL;
1600     if (client_buffers.is_color_conversion_enabled()) {
1601         buf_index = buffer - m_intermediate_out_mem_ptr;
1602         vdec_buf = &drv_ctx.ptr_intermediate_outputbuffer[buf_index];
1603     } else {
1604         buf_index = buffer - m_out_mem_ptr;
1605         vdec_buf = &drv_ctx.ptr_outputbuffer[buf_index];
1606     }
1607     bufaddr = (char *)vdec_buf->bufferaddr;
1608     if (dynamic_buf_mode && !secure_mode) {
1609         bufaddr = ion_map(vdec_buf->pmem_fd,
1610                           vdec_buf->buffer_len);
1611         //mmap returns (void *)-1 on failure and sets error code in errno.
1612         if (bufaddr == MAP_FAILED) {
1613             DEBUG_PRINT_ERROR("mmap failed - errno: %d", errno);
1614             return -1;
1615         }
1616     }
1617     temp = bufaddr;
1618 
1619     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
1620             drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
1621         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
1622             drv_ctx.video_resolution.frame_width,
1623             drv_ctx.video_resolution.frame_height);
1624 
1625         if (m_debug.outfile)
1626             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
1627 
1628         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
1629             unsigned int width = 0, height = 0;
1630             unsigned int y_plane, y_meta_plane;
1631             int y_stride = 0, y_sclines = 0;
1632             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
1633             int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
1634             int i;
1635             int bytes_written = 0;
1636 
1637             width = drv_ctx.video_resolution.frame_width;
1638             height = drv_ctx.video_resolution.frame_height;
1639             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
1640             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
1641             y_stride = VENUS_Y_STRIDE(color_fmt, width);
1642             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
1643             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
1644             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
1645 
1646             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
1647             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
1648 
1649             for (i = 0; i < y_meta_scanlines; i++) {
1650                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
1651                  temp += y_meta_stride;
1652             }
1653 
1654             temp = bufaddr + y_meta_plane + y_plane;
1655             for(i = 0; i < uv_meta_scanlines; i++) {
1656                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
1657                 temp += uv_meta_stride;
1658             }
1659         }
1660     } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
1661         int stride = drv_ctx.video_resolution.stride;
1662         int scanlines = drv_ctx.video_resolution.scan_lines;
1663         unsigned i;
1664         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1665             drv_ctx.video_resolution.frame_width,
1666             drv_ctx.video_resolution.frame_height, stride, scanlines);
1667         int bytes_written = 0;
1668         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1669              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1670              temp += stride;
1671         }
1672         temp = bufaddr + stride * scanlines;
1673         int stride_c = stride;
1674         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1675             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1676             temp += stride_c;
1677         }
1678     } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
1679         int stride = drv_ctx.video_resolution.stride;
1680         int scanlines = drv_ctx.video_resolution.scan_lines;
1681         unsigned i;
1682         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1683             drv_ctx.video_resolution.frame_width,
1684             drv_ctx.video_resolution.frame_height, stride, scanlines);
1685         int bytes_written = 0;
1686         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1687              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
1688              temp += stride;
1689         }
1690         temp = bufaddr + stride * scanlines;
1691         int stride_c = stride;
1692         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1693             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
1694             temp += stride_c;
1695         }
1696     }
1697 
1698     if (dynamic_buf_mode && !secure_mode) {
1699         ion_unmap(vdec_buf->pmem_fd, bufaddr,
1700                   vdec_buf->buffer_len);
1701     }
1702     return 0;
1703 }
1704 
init_color_aspects_map()1705 void omx_vdec::init_color_aspects_map()
1706 {
1707     mPrimariesMap.insert({
1708             {ColorAspects::PrimariesUnspecified, (ColorPrimaries)(2)},
1709             {ColorAspects::PrimariesBT709_5, ColorPrimaries_BT709_5},
1710             {ColorAspects::PrimariesBT470_6M, ColorPrimaries_BT470_6M},
1711             {ColorAspects::PrimariesBT601_6_625, ColorPrimaries_BT601_6_625},
1712             {ColorAspects::PrimariesBT601_6_525, ColorPrimaries_BT601_6_525},
1713             {ColorAspects::PrimariesGenericFilm, ColorPrimaries_GenericFilm},
1714             {ColorAspects::PrimariesBT2020, ColorPrimaries_BT2020},
1715         });
1716     mTransferMap.insert({
1717             {ColorAspects::TransferUnspecified, (GammaTransfer)(2)},
1718             {ColorAspects::TransferLinear, Transfer_Linear},
1719             {ColorAspects::TransferSRGB, Transfer_sRGB},
1720             {ColorAspects::TransferSMPTE170M, Transfer_SMPTE_170M},
1721             {ColorAspects::TransferGamma22, Transfer_Gamma2_2},
1722             {ColorAspects::TransferGamma28, Transfer_Gamma2_8},
1723             {ColorAspects::TransferST2084, Transfer_SMPTE_ST2084},
1724             {ColorAspects::TransferHLG, Transfer_HLG},
1725             {ColorAspects::TransferSMPTE240M, Transfer_SMPTE_240M},
1726             {ColorAspects::TransferXvYCC, Transfer_XvYCC},
1727             {ColorAspects::TransferBT1361, Transfer_BT1361},
1728             {ColorAspects::TransferST428, Transfer_ST_428},
1729         });
1730     mMatrixCoeffMap.insert({
1731             {ColorAspects::MatrixUnspecified, (MatrixCoEfficients)(2)},
1732             {ColorAspects::MatrixBT709_5, MatrixCoEff_BT709_5},
1733             {ColorAspects::MatrixBT470_6M, MatrixCoeff_FCC_73_682},
1734             {ColorAspects::MatrixBT601_6, MatrixCoEff_BT601_6_625},
1735             {ColorAspects::MatrixSMPTE240M, MatrixCoEff_SMPTE240M},
1736             {ColorAspects::MatrixBT2020, MatrixCoEff_BT2020},
1737             {ColorAspects::MatrixBT2020Constant, MatrixCoEff_BT2020Constant},
1738         });
1739     mColorRangeMap.insert({
1740             {ColorAspects::RangeUnspecified, (ColorRange)(2)},
1741             {ColorAspects::RangeFull, Range_Full},
1742             {ColorAspects::RangeLimited, Range_Limited},
1743         });
1744 }
1745 /* ======================================================================
1746    FUNCTION
1747    omx_vdec::ComponentInit
1748 
1749    DESCRIPTION
1750    Initialize the component.
1751 
1752    PARAMETERS
1753    ctxt -- Context information related to the self.
1754    id   -- Event identifier. This could be any of the following:
1755    1. Command completion event
1756    2. Buffer done callback event
1757    3. Frame done callback event
1758 
1759    RETURN VALUE
1760    None.
1761 
1762    ========================================================================== */
component_init(OMX_STRING role)1763 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1764 {
1765 
1766     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1767     struct v4l2_fmtdesc fdesc;
1768     struct v4l2_format fmt;
1769     struct v4l2_requestbuffers bufreq;
1770     struct v4l2_control control;
1771     struct v4l2_frmsizeenum frmsize;
1772     struct v4l2_queryctrl query;
1773     unsigned int   alignment = 0,buffer_size = 0;
1774     int fds[2];
1775     int r,ret=0;
1776     bool codec_ambiguous = false;
1777     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
1778     char property_value[PROPERTY_VALUE_MAX] = {0};
1779     FILE *soc_file = NULL;
1780     char buffer[10];
1781     struct v4l2_control ctrl[2];
1782     int conceal_color_8bit = 0, conceal_color_10bit = 0;
1783 
1784     property_get("ro.board.platform", m_platform_name, "0");
1785 #ifdef _ANDROID_
1786     if (!strncmp(m_platform_name, "msm8610", 7)) {
1787         device_name = (OMX_STRING)"/dev/video/q6_dec";
1788     }
1789 #endif
1790 
1791     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
1792                 OMX_MAX_STRINGNAME_SIZE)) {
1793         secure_mode = true;
1794         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
1795     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
1796                 OMX_MAX_STRINGNAME_SIZE)) {
1797         secure_mode = true;
1798         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
1799     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
1800                 OMX_MAX_STRINGNAME_SIZE)) {
1801         secure_mode = true;
1802         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
1803     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
1804                 OMX_MAX_STRINGNAME_SIZE)) {
1805         secure_mode = true;
1806         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
1807     }
1808 
1809     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1810 
1811     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
1812 
1813     if (drv_ctx.video_driver_fd < 0) {
1814         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
1815         return OMX_ErrorInsufficientResources;
1816     }
1817     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1818     drv_ctx.frame_rate.fps_denominator = 1;
1819     m_poll_efd = eventfd(0, 0);
1820     if (m_poll_efd < 0) {
1821         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
1822         return OMX_ErrorInsufficientResources;
1823     }
1824     ret = subscribe_to_events(drv_ctx.video_driver_fd);
1825     if (!ret) {
1826         async_thread_created = true;
1827         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
1828     }
1829     if (ret) {
1830         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
1831         async_thread_created = false;
1832         return OMX_ErrorInsufficientResources;
1833     }
1834 
1835 #ifdef OUTPUT_EXTRADATA_LOG
1836     outputExtradataFile = fopen (output_extradata_filename, "ab");
1837 #endif
1838 
1839     // Copy the role information which provides the decoder kind
1840     strlcpy(drv_ctx.kind,role,128);
1841 
1842 
1843     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
1844                 OMX_MAX_STRINGNAME_SIZE)) {
1845         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
1846                 OMX_MAX_STRINGNAME_SIZE);
1847         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
1848         output_capability = V4L2_PIX_FMT_MPEG2;
1849         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
1850     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
1851                 OMX_MAX_STRINGNAME_SIZE)) {
1852         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
1853         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
1854         output_capability=V4L2_PIX_FMT_H264;
1855         eCompressionFormat = OMX_VIDEO_CodingAVC;
1856     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
1857                 OMX_MAX_STRINGNAME_SIZE)) {
1858         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
1859         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
1860         output_capability = V4L2_PIX_FMT_HEVC;
1861         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
1862     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
1863                 OMX_MAX_STRINGNAME_SIZE)) {
1864         char version[PROP_VALUE_MAX] = {0};
1865         if (!strncmp(m_platform_name, "lito", 4))
1866             if (property_get("vendor.media.target.version", version, "0") &&
1867                     ((atoi(version) == 2) || (atoi(version) == 3))) {
1868                 //sku version, VP8 is disabled on lagoon
1869                 DEBUG_PRINT_ERROR("VP8 unsupported on lagoon");
1870                 eRet = OMX_ErrorInvalidComponentName;
1871                 return eRet;
1872             }
1873         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
1874         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
1875         output_capability = V4L2_PIX_FMT_VP8;
1876         eCompressionFormat = OMX_VIDEO_CodingVP8;
1877     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
1878                 OMX_MAX_STRINGNAME_SIZE)) {
1879         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
1880         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
1881         output_capability = V4L2_PIX_FMT_VP9;
1882         eCompressionFormat = OMX_VIDEO_CodingVP9;
1883     } else {
1884         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
1885         eRet = OMX_ErrorInvalidComponentName;
1886     }
1887 
1888     m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
1889 
1890     if (eRet == OMX_ErrorNone) {
1891         OMX_COLOR_FORMATTYPE dest_color_format;
1892         if (m_disable_ubwc_mode) {
1893             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
1894         } else {
1895             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
1896         }
1897         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
1898             dest_color_format = (OMX_COLOR_FORMATTYPE)
1899                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
1900         else
1901             dest_color_format = (OMX_COLOR_FORMATTYPE)
1902                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
1903         if (!client_buffers.set_color_format(dest_color_format)) {
1904             DEBUG_PRINT_ERROR("Setting color format failed");
1905             eRet = OMX_ErrorInsufficientResources;
1906         }
1907 
1908         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
1909         is_flexible_format = OMX_FALSE;
1910         is_mbaff = OMX_FALSE;
1911 
1912         if (m_disable_ubwc_mode) {
1913             capture_capability = V4L2_PIX_FMT_NV12;
1914         } else {
1915             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
1916         }
1917 
1918         struct v4l2_capability cap;
1919         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
1920         if (ret) {
1921             DEBUG_PRINT_ERROR("Failed to query capabilities");
1922             /*TODO: How to handle this case */
1923         } else {
1924             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1925                 " version = %d, capabilities = %x", cap.driver, cap.card,
1926                 cap.bus_info, cap.version, cap.capabilities);
1927         }
1928         ret=0;
1929         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1930         fdesc.index=0;
1931         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1932             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1933                     fdesc.pixelformat, fdesc.flags);
1934             fdesc.index++;
1935         }
1936         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1937         fdesc.index=0;
1938         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1939 
1940             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1941                     fdesc.pixelformat, fdesc.flags);
1942             fdesc.index++;
1943         }
1944         m_extradata_misr.output_crop_rect.nLeft = 0;
1945         m_extradata_misr.output_crop_rect.nTop = 0;
1946         m_extradata_misr.output_crop_rect.nWidth = 320;
1947         m_extradata_misr.output_crop_rect.nHeight = 240;
1948         update_resolution(320, 240, 320, 240);
1949 
1950         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1951         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1952         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1953         fmt.fmt.pix_mp.pixelformat = output_capability;
1954         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1955         if (ret) {
1956             /*TODO: How to handle this case */
1957             DEBUG_PRINT_ERROR("Failed to set format on output port");
1958             return OMX_ErrorInsufficientResources;
1959         }
1960         DEBUG_PRINT_HIGH("Set Format was successful");
1961 
1962         /*
1963          * refer macro DEFAULT_CONCEAL_COLOR to set conceal color values
1964          */
1965         Platform::Config::getInt32(Platform::vidc_dec_conceal_color_8bit, &conceal_color_8bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
1966         Platform::Config::getInt32(Platform::vidc_dec_conceal_color_10bit, &conceal_color_10bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
1967         memset(ctrl, 0, sizeof(ctrl));
1968         ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT;
1969         ctrl[0].value = conceal_color_8bit;
1970         ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT;
1971         ctrl[1].value = conceal_color_10bit;
1972 
1973         for(int i=0; i<2; i++) {
1974             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &ctrl[i]);
1975             if (ret) {
1976                 DEBUG_PRINT_ERROR("Failed to set conceal color %s, error %d\n",
1977                                   i==0?"8Bit":"10Bit", ret);
1978             }
1979         }
1980         //Get the hardware capabilities
1981         memset((void *)&frmsize,0,sizeof(frmsize));
1982         frmsize.index = 0;
1983         frmsize.pixel_format = output_capability;
1984         ret = ioctl(drv_ctx.video_driver_fd,
1985                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
1986         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
1987             DEBUG_PRINT_ERROR("Failed to get framesizes");
1988             return OMX_ErrorHardware;
1989         }
1990 
1991         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1992             m_decoder_capability.min_width = frmsize.stepwise.min_width;
1993             m_decoder_capability.max_width = frmsize.stepwise.max_width;
1994             m_decoder_capability.min_height = frmsize.stepwise.min_height;
1995             m_decoder_capability.max_height = frmsize.stepwise.max_height;
1996         }
1997 
1998         memset(&fmt, 0x0, sizeof(struct v4l2_format));
1999         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2000         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2001         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2002         fmt.fmt.pix_mp.pixelformat = capture_capability;
2003         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2004         if (ret) {
2005             /*TODO: How to handle this case */
2006             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2007         }
2008         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2009         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2010         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2011 
2012         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2013         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2014         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2015 
2016         DEBUG_PRINT_HIGH("Set Format was successful");
2017         if (secure_mode) {
2018             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2019             control.value = 1;
2020             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2021             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2022             if (ret) {
2023                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2024                 return OMX_ErrorInsufficientResources;
2025             }
2026         }
2027 
2028         /*Get the Buffer requirements for input and output ports*/
2029         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2030         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2031 
2032         if (secure_mode) {
2033             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2034             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2035         } else {
2036             drv_ctx.op_buf.alignment = SZ_4K;
2037             drv_ctx.ip_buf.alignment = SZ_4K;
2038         }
2039 
2040         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2041         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2042 
2043         control.id = V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER;
2044         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
2045 
2046         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2047         drv_ctx.idr_only_decoding = 0;
2048 
2049         m_state = OMX_StateLoaded;
2050 
2051         eRet = get_buffer_req(&drv_ctx.ip_buf);
2052         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2053         get_buffer_req(&drv_ctx.op_buf);
2054         msg_thread_created = true;
2055         r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2056 
2057         if (r < 0) {
2058             DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2059             msg_thread_created = false;
2060             eRet = OMX_ErrorInsufficientResources;
2061         } else if (secure_mode) {
2062             this->post_event(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL);
2063             this->post_event(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL);
2064         }
2065     }
2066 
2067     {
2068         VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2069         init_vendor_extensions(*extStore);
2070         mVendorExtensionStore.dumpExtensions((const char *)role);
2071     }
2072 
2073     if (eRet != OMX_ErrorNone) {
2074         DEBUG_PRINT_ERROR("Component Init Failed");
2075     } else {
2076         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2077                 drv_ctx.video_driver_fd);
2078     }
2079 
2080     OMX_INIT_STRUCT(&m_sParamLowLatency, QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE);
2081     m_sParamLowLatency.nNumFrames = 0;
2082     m_sParamLowLatency.bEnableLowLatencyMode = OMX_FALSE;
2083 
2084     return eRet;
2085 }
2086 
2087 /* ======================================================================
2088    FUNCTION
2089    omx_vdec::GetComponentVersion
2090 
2091    DESCRIPTION
2092    Returns the component version.
2093 
2094    PARAMETERS
2095    TBD.
2096 
2097    RETURN VALUE
2098    OMX_ErrorNone.
2099 
2100    ========================================================================== */
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)2101 OMX_ERRORTYPE  omx_vdec::get_component_version
2102 (
2103  OMX_IN OMX_HANDLETYPE hComp,
2104  OMX_OUT OMX_STRING componentName,
2105  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2106  OMX_OUT OMX_VERSIONTYPE* specVersion,
2107  OMX_OUT OMX_UUIDTYPE* componentUUID
2108  )
2109 {
2110     (void) hComp;
2111     (void) componentName;
2112     (void) componentVersion;
2113     (void) componentUUID;
2114     if (m_state == OMX_StateInvalid) {
2115         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2116         return OMX_ErrorInvalidState;
2117     }
2118     /* TBD -- Return the proper version */
2119     if (specVersion) {
2120         specVersion->nVersion = OMX_SPEC_VERSION;
2121     }
2122     return OMX_ErrorNone;
2123 }
2124 /* ======================================================================
2125    FUNCTION
2126    omx_vdec::SendCommand
2127 
2128    DESCRIPTION
2129    Returns zero if all the buffers released..
2130 
2131    PARAMETERS
2132    None.
2133 
2134    RETURN VALUE
2135    true/false
2136 
2137    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2138 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2139         OMX_IN OMX_COMMANDTYPE cmd,
2140         OMX_IN OMX_U32 param1,
2141         OMX_IN OMX_PTR cmdData
2142         )
2143 {
2144     (void) hComp;
2145     (void) cmdData;
2146     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2147     if (m_state == OMX_StateInvalid) {
2148         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2149         return OMX_ErrorInvalidState;
2150     }
2151     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2152             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2153         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2154                 "to invalid port: %u", (unsigned int)param1);
2155         return OMX_ErrorBadPortIndex;
2156     }
2157 
2158     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2159     sem_wait(&m_cmd_lock);
2160     DEBUG_PRINT_LOW("send_command: Command Processed");
2161     return OMX_ErrorNone;
2162 }
2163 
2164 /* ======================================================================
2165    FUNCTION
2166    omx_vdec::SendCommand
2167 
2168    DESCRIPTION
2169    Returns zero if all the buffers released..
2170 
2171    PARAMETERS
2172    None.
2173 
2174    RETURN VALUE
2175    true/false
2176 
2177    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2178 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2179         OMX_IN OMX_COMMANDTYPE cmd,
2180         OMX_IN OMX_U32 param1,
2181         OMX_IN OMX_PTR cmdData
2182         )
2183 {
2184     (void) hComp;
2185     (void) cmdData;
2186     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2187     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2188     int bFlag = 1,sem_posted = 0,ret=0;
2189 
2190     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2191     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2192             m_state, eState);
2193 
2194     if (cmd == OMX_CommandStateSet) {
2195         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2196         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2197         /***************************/
2198         /* Current State is Loaded */
2199         /***************************/
2200         if (m_state == OMX_StateLoaded) {
2201             if (eState == OMX_StateIdle) {
2202                 //if all buffers are allocated or all ports disabled
2203                 if (allocate_done() ||
2204                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2205                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2206                 } else {
2207                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2208                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2209                     // Skip the event notification
2210                     bFlag = 0;
2211                 }
2212             }
2213             /* Requesting transition from Loaded to Loaded */
2214             else if (eState == OMX_StateLoaded) {
2215                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2216                 post_event(OMX_EventError,OMX_ErrorSameState,\
2217                         OMX_COMPONENT_GENERATE_EVENT);
2218                 eRet = OMX_ErrorSameState;
2219             }
2220             /* Requesting transition from Loaded to WaitForResources */
2221             else if (eState == OMX_StateWaitForResources) {
2222                 /* Since error is None , we will post an event
2223                    at the end of this function definition */
2224                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2225             }
2226             /* Requesting transition from Loaded to Executing */
2227             else if (eState == OMX_StateExecuting) {
2228                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2229                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2230                         OMX_COMPONENT_GENERATE_EVENT);
2231                 eRet = OMX_ErrorIncorrectStateTransition;
2232             }
2233             /* Requesting transition from Loaded to Pause */
2234             else if (eState == OMX_StatePause) {
2235                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2236                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2237                         OMX_COMPONENT_GENERATE_EVENT);
2238                 eRet = OMX_ErrorIncorrectStateTransition;
2239             }
2240             /* Requesting transition from Loaded to Invalid */
2241             else if (eState == OMX_StateInvalid) {
2242                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2243                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2244                 eRet = OMX_ErrorInvalidState;
2245             } else {
2246                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2247                         eState);
2248                 eRet = OMX_ErrorBadParameter;
2249             }
2250         }
2251 
2252         /***************************/
2253         /* Current State is IDLE */
2254         /***************************/
2255         else if (m_state == OMX_StateIdle) {
2256             if (eState == OMX_StateLoaded) {
2257                 if (release_done()) {
2258                     /*
2259                      * Since error is None , we will post an event at the end
2260                      * of this function definition
2261                      * Reset buffer requirements here to ensure setting buffer requirement
2262                      * when component move to executing state from loaded state via Idle.
2263                      */
2264                     drv_ctx.op_buf.buffer_size = 0;
2265                     drv_ctx.op_buf.actualcount = 0;
2266                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2267                 } else {
2268                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2269                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2270                     // Skip the event notification
2271                     bFlag = 0;
2272                 }
2273             }
2274             /* Requesting transition from Idle to Executing */
2275             else if (eState == OMX_StateExecuting) {
2276                 bFlag = 1;
2277                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2278                 m_state=OMX_StateExecuting;
2279             }
2280             /* Requesting transition from Idle to Idle */
2281             else if (eState == OMX_StateIdle) {
2282                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2283                 post_event(OMX_EventError,OMX_ErrorSameState,\
2284                         OMX_COMPONENT_GENERATE_EVENT);
2285                 eRet = OMX_ErrorSameState;
2286             }
2287             /* Requesting transition from Idle to WaitForResources */
2288             else if (eState == OMX_StateWaitForResources) {
2289                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2290                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2291                         OMX_COMPONENT_GENERATE_EVENT);
2292                 eRet = OMX_ErrorIncorrectStateTransition;
2293             }
2294             /* Requesting transition from Idle to Pause */
2295             else if (eState == OMX_StatePause) {
2296                 /*To pause the Video core we need to start the driver*/
2297                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2298                       NULL) < */0) {
2299                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2300                     omx_report_error ();
2301                     eRet = OMX_ErrorHardware;
2302                 } else {
2303                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2304                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2305                     bFlag = 0;
2306                 }
2307             }
2308             /* Requesting transition from Idle to Invalid */
2309             else if (eState == OMX_StateInvalid) {
2310                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2311                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2312                 eRet = OMX_ErrorInvalidState;
2313             } else {
2314                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2315                 eRet = OMX_ErrorBadParameter;
2316             }
2317         }
2318 
2319         /******************************/
2320         /* Current State is Executing */
2321         /******************************/
2322         else if (m_state == OMX_StateExecuting) {
2323             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2324             /* Requesting transition from Executing to Idle */
2325             if (eState == OMX_StateIdle) {
2326                 /* Since error is None , we will post an event
2327                    at the end of this function definition
2328                  */
2329                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2330                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2331                 if (!sem_posted) {
2332                     sem_posted = 1;
2333                     sem_post (&m_cmd_lock);
2334                     execute_omx_flush(OMX_ALL);
2335                 }
2336                 bFlag = 0;
2337             }
2338             /* Requesting transition from Executing to Paused */
2339             else if (eState == OMX_StatePause) {
2340                 DEBUG_PRINT_LOW("PAUSE Command Issued");
2341                 m_state = OMX_StatePause;
2342                 bFlag = 1;
2343             }
2344             /* Requesting transition from Executing to Loaded */
2345             else if (eState == OMX_StateLoaded) {
2346                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2347                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2348                         OMX_COMPONENT_GENERATE_EVENT);
2349                 eRet = OMX_ErrorIncorrectStateTransition;
2350             }
2351             /* Requesting transition from Executing to WaitForResources */
2352             else if (eState == OMX_StateWaitForResources) {
2353                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2354                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2355                         OMX_COMPONENT_GENERATE_EVENT);
2356                 eRet = OMX_ErrorIncorrectStateTransition;
2357             }
2358             /* Requesting transition from Executing to Executing */
2359             else if (eState == OMX_StateExecuting) {
2360                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2361                 post_event(OMX_EventError,OMX_ErrorSameState,\
2362                         OMX_COMPONENT_GENERATE_EVENT);
2363                 eRet = OMX_ErrorSameState;
2364             }
2365             /* Requesting transition from Executing to Invalid */
2366             else if (eState == OMX_StateInvalid) {
2367                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2368                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2369                 eRet = OMX_ErrorInvalidState;
2370             } else {
2371                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2372                 eRet = OMX_ErrorBadParameter;
2373             }
2374         }
2375         /***************************/
2376         /* Current State is Pause  */
2377         /***************************/
2378         else if (m_state == OMX_StatePause) {
2379             /* Requesting transition from Pause to Executing */
2380             if (eState == OMX_StateExecuting) {
2381                 DEBUG_PRINT_LOW("Pause --> Executing");
2382                 m_state = OMX_StateExecuting;
2383                 bFlag = 1;
2384             }
2385             /* Requesting transition from Pause to Idle */
2386             else if (eState == OMX_StateIdle) {
2387                 /* Since error is None , we will post an event
2388                    at the end of this function definition */
2389                 DEBUG_PRINT_LOW("Pause --> Idle");
2390                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2391                 if (!sem_posted) {
2392                     sem_posted = 1;
2393                     sem_post (&m_cmd_lock);
2394                     execute_omx_flush(OMX_ALL);
2395                 }
2396                 bFlag = 0;
2397             }
2398             /* Requesting transition from Pause to loaded */
2399             else if (eState == OMX_StateLoaded) {
2400                 DEBUG_PRINT_ERROR("Pause --> loaded");
2401                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2402                         OMX_COMPONENT_GENERATE_EVENT);
2403                 eRet = OMX_ErrorIncorrectStateTransition;
2404             }
2405             /* Requesting transition from Pause to WaitForResources */
2406             else if (eState == OMX_StateWaitForResources) {
2407                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2408                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2409                         OMX_COMPONENT_GENERATE_EVENT);
2410                 eRet = OMX_ErrorIncorrectStateTransition;
2411             }
2412             /* Requesting transition from Pause to Pause */
2413             else if (eState == OMX_StatePause) {
2414                 DEBUG_PRINT_ERROR("Pause --> Pause");
2415                 post_event(OMX_EventError,OMX_ErrorSameState,\
2416                         OMX_COMPONENT_GENERATE_EVENT);
2417                 eRet = OMX_ErrorSameState;
2418             }
2419             /* Requesting transition from Pause to Invalid */
2420             else if (eState == OMX_StateInvalid) {
2421                 DEBUG_PRINT_ERROR("Pause --> Invalid");
2422                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2423                 eRet = OMX_ErrorInvalidState;
2424             } else {
2425                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2426                 eRet = OMX_ErrorBadParameter;
2427             }
2428         }
2429         /***************************/
2430         /* Current State is WaitForResources  */
2431         /***************************/
2432         else if (m_state == OMX_StateWaitForResources) {
2433             /* Requesting transition from WaitForResources to Loaded */
2434             if (eState == OMX_StateLoaded) {
2435                 /* Since error is None , we will post an event
2436                    at the end of this function definition */
2437                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2438             }
2439             /* Requesting transition from WaitForResources to WaitForResources */
2440             else if (eState == OMX_StateWaitForResources) {
2441                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2442                 post_event(OMX_EventError,OMX_ErrorSameState,
2443                         OMX_COMPONENT_GENERATE_EVENT);
2444                 eRet = OMX_ErrorSameState;
2445             }
2446             /* Requesting transition from WaitForResources to Executing */
2447             else if (eState == OMX_StateExecuting) {
2448                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2449                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2450                         OMX_COMPONENT_GENERATE_EVENT);
2451                 eRet = OMX_ErrorIncorrectStateTransition;
2452             }
2453             /* Requesting transition from WaitForResources to Pause */
2454             else if (eState == OMX_StatePause) {
2455                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2456                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2457                         OMX_COMPONENT_GENERATE_EVENT);
2458                 eRet = OMX_ErrorIncorrectStateTransition;
2459             }
2460             /* Requesting transition from WaitForResources to Invalid */
2461             else if (eState == OMX_StateInvalid) {
2462                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2463                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2464                 eRet = OMX_ErrorInvalidState;
2465             }
2466             /* Requesting transition from WaitForResources to Loaded -
2467                is NOT tested by Khronos TS */
2468 
2469         } else {
2470             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2471             eRet = OMX_ErrorBadParameter;
2472         }
2473     }
2474     /********************************/
2475     /* Current State is Invalid */
2476     /*******************************/
2477     else if (m_state == OMX_StateInvalid) {
2478         /* State Transition from Inavlid to any state */
2479         if ((eState == OMX_StateLoaded) || (eState == OMX_StateWaitForResources) ||
2480                 (eState == OMX_StateIdle) || (eState == OMX_StateExecuting) ||
2481                 (eState == OMX_StatePause) || (eState == OMX_StateInvalid)) {
2482             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2483             post_event(OMX_EventError,OMX_ErrorInvalidState,\
2484                     OMX_COMPONENT_GENERATE_EVENT);
2485             eRet = OMX_ErrorInvalidState;
2486         }
2487     } else if (cmd == OMX_CommandFlush) {
2488         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2489                 "with param1: %u", (unsigned int)param1);
2490         send_codec_config();
2491         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2492                     param1 == OMX_ALL)) {
2493             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2494                struct timespec ts;
2495 
2496                clock_gettime(CLOCK_REALTIME, &ts);
2497                ts.tv_sec += 1;
2498                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2499                        m_queued_codec_config_count);
2500                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2501                if (sem_timedwait(&m_safe_flush, &ts)) {
2502                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2503                }
2504                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2505             }
2506         }
2507 
2508         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2509             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2510         }
2511         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2512             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2513         }
2514         if (!sem_posted) {
2515             sem_posted = 1;
2516             DEBUG_PRINT_LOW("Set the Semaphore");
2517             sem_post (&m_cmd_lock);
2518             execute_omx_flush(param1);
2519         }
2520         bFlag = 0;
2521     } else if ( cmd == OMX_CommandPortEnable) {
2522         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2523                 "with param1: %u", (unsigned int)param1);
2524         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2525             m_inp_bEnabled = OMX_TRUE;
2526 
2527             if ( (m_state == OMX_StateLoaded &&
2528                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2529                     || allocate_input_done()) {
2530                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2531                         OMX_COMPONENT_GENERATE_EVENT);
2532             } else {
2533                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2534                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2535                 // Skip the event notification
2536                 bFlag = 0;
2537             }
2538         }
2539         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2540             DEBUG_PRINT_LOW("Enable output Port command recieved");
2541             m_out_bEnabled = OMX_TRUE;
2542 
2543             if ( (m_state == OMX_StateLoaded &&
2544                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2545                     || (allocate_output_done())) {
2546                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2547                         OMX_COMPONENT_GENERATE_EVENT);
2548 
2549             } else {
2550                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2551                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2552                 // Skip the event notification
2553                 bFlag = 0;
2554             }
2555         }
2556     } else if (cmd == OMX_CommandPortDisable) {
2557         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
2558                 "with param1: %u", (unsigned int)param1);
2559         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2560             codec_config_flag = false;
2561             m_inp_bEnabled = OMX_FALSE;
2562             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2563                     && release_input_done()) {
2564                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2565                         OMX_COMPONENT_GENERATE_EVENT);
2566             } else {
2567                 DEBUG_PRINT_HIGH("Set input port disable pending");
2568                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2569                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2570                     if (!sem_posted) {
2571                         sem_posted = 1;
2572                         sem_post (&m_cmd_lock);
2573                     }
2574                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2575                 }
2576 
2577                 // Skip the event notification
2578                 bFlag = 0;
2579             }
2580         }
2581         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2582             m_out_bEnabled = OMX_FALSE;
2583             DEBUG_PRINT_LOW("Disable output Port command recieved");
2584             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2585                     && release_output_done()) {
2586                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2587                         OMX_COMPONENT_GENERATE_EVENT);
2588             } else {
2589                 DEBUG_PRINT_HIGH("Set output port disable pending");
2590                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2591                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2592                     if (!sem_posted) {
2593                         sem_posted = 1;
2594                         sem_post (&m_cmd_lock);
2595                     }
2596                     DEBUG_PRINT_HIGH("Set output port flush in disable pending");
2597                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2598                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2599                 }
2600                 // Skip the event notification
2601                 bFlag = 0;
2602 
2603             }
2604         }
2605     } else {
2606         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
2607         eRet = OMX_ErrorNotImplemented;
2608     }
2609     if (eRet == OMX_ErrorNone && bFlag) {
2610         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2611     }
2612     if (!sem_posted) {
2613         sem_post(&m_cmd_lock);
2614     }
2615 
2616     return eRet;
2617 }
2618 
2619 /* ======================================================================
2620    FUNCTION
2621    omx_vdec::ExecuteOmxFlush
2622 
2623    DESCRIPTION
2624    Executes the OMX flush.
2625 
2626    PARAMETERS
2627    flushtype - input flush(1)/output flush(0)/ both.
2628 
2629    RETURN VALUE
2630    true/false
2631 
2632    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)2633 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
2634 {
2635     bool bRet = false;
2636     struct v4l2_plane plane;
2637     struct v4l2_buffer v4l2_buf;
2638     struct v4l2_decoder_cmd dec;
2639     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
2640     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
2641     dec.cmd = V4L2_CMD_FLUSH;
2642 
2643     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
2644 
2645     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
2646         output_flush_progress = true;
2647         dec.flags = V4L2_CMD_FLUSH_CAPTURE;
2648     } else {
2649         /* XXX: The driver/hardware does not support flushing of individual ports
2650          * in all states. So we pretty much need to flush both ports internally,
2651          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
2652          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
2653          * we automatically omit sending the FLUSH done for the "opposite" port. */
2654         input_flush_progress = true;
2655         output_flush_progress = true;
2656         dec.flags = V4L2_CMD_FLUSH_OUTPUT | V4L2_CMD_FLUSH_CAPTURE;
2657     }
2658 
2659     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
2660         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
2661         bRet = false;
2662     }
2663 
2664     return bRet;
2665 }
2666 /*=========================================================================
2667 FUNCTION : execute_output_flush
2668 
2669 DESCRIPTION
2670 Executes the OMX flush at OUTPUT PORT.
2671 
2672 PARAMETERS
2673 None.
2674 
2675 RETURN VALUE
2676 true/false
2677 ==========================================================================*/
execute_output_flush()2678 bool omx_vdec::execute_output_flush()
2679 {
2680     unsigned long p1 = 0; // Parameter - 1
2681     unsigned long p2 = 0; // Parameter - 2
2682     unsigned long ident = 0;
2683     bool bRet = true;
2684 
2685     /*Generate FBD for all Buffers in the FTBq*/
2686     pthread_mutex_lock(&m_lock);
2687     DEBUG_PRINT_LOW("Initiate Output Flush");
2688 
2689     //reset last render TS
2690     if(m_last_rendered_TS > 0) {
2691         m_last_rendered_TS = 0;
2692     }
2693 
2694     while (m_ftb_q.m_size) {
2695         m_ftb_q.pop_entry(&p1,&p2,&ident);
2696         if (ident == m_fill_output_msg ) {
2697             print_omx_buffer("Flush FBD", (OMX_BUFFERHEADERTYPE *)p2);
2698             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
2699         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
2700             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
2701         }
2702     }
2703     pthread_mutex_unlock(&m_lock);
2704     output_flush_progress = false;
2705 
2706     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
2707     return bRet;
2708 }
2709 /*=========================================================================
2710 FUNCTION : execute_input_flush
2711 
2712 DESCRIPTION
2713 Executes the OMX flush at INPUT PORT.
2714 
2715 PARAMETERS
2716 None.
2717 
2718 RETURN VALUE
2719 true/false
2720 ==========================================================================*/
execute_input_flush()2721 bool omx_vdec::execute_input_flush()
2722 {
2723     unsigned       i =0;
2724     unsigned long p1 = 0; // Parameter - 1
2725     unsigned long p2 = 0; // Parameter - 2
2726     unsigned long ident = 0;
2727     bool bRet = true;
2728 
2729     /*Generate EBD for all Buffers in the ETBq*/
2730     DEBUG_PRINT_LOW("Initiate Input Flush");
2731 
2732     pthread_mutex_lock(&m_lock);
2733     DEBUG_PRINT_LOW("Check if the Queue is empty");
2734     while (m_etb_q.m_size) {
2735         m_etb_q.pop_entry(&p1,&p2,&ident);
2736 
2737         if (ident == OMX_COMPONENT_GENERATE_ETB) {
2738             pending_input_buffers++;
2739             VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
2740             print_omx_buffer("Flush ETB", (OMX_BUFFERHEADERTYPE *)p2);
2741             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2742         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
2743             print_omx_buffer("Flush EBD", (OMX_BUFFERHEADERTYPE *)p1);
2744             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2745         }
2746     }
2747     time_stamp_dts.flush_timestamp();
2748     /*Check if Heap Buffers are to be flushed*/
2749     pthread_mutex_unlock(&m_lock);
2750     input_flush_progress = false;
2751     prev_ts = LLONG_MAX;
2752 
2753     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
2754     return bRet;
2755 }
2756 
2757 /*=========================================================================
2758 FUNCTION : notify_flush_done
2759 
2760 DESCRIPTION
2761 Notifies flush done to the OMX Client.
2762 
2763 PARAMETERS
2764 ctxt -- Context information related to the self..
2765 
2766 RETURN VALUE
2767 NONE
2768 ==========================================================================*/
notify_flush_done(void * ctxt)2769 void omx_vdec::notify_flush_done(void *ctxt)
2770 {
2771 
2772     omx_vdec *pThis = (omx_vdec *) ctxt;
2773 
2774     if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
2775         if (BITMASK_PRESENT(&pThis->m_flags,
2776                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
2777             DEBUG_PRINT_LOW("Notify Output Flush done");
2778             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2779             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
2780                 OMX_EventCmdComplete,OMX_CommandFlush,
2781                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
2782         }
2783 
2784         if (BITMASK_PRESENT(&pThis->m_flags,
2785                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
2786             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
2787             DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
2788             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
2789                     OMX_EventCmdComplete,OMX_CommandFlush,
2790                     OMX_CORE_INPUT_PORT_INDEX,NULL );
2791             //clear hdr10plusinfo list upon input flush done
2792             clear_hdr10plusinfo();
2793         }
2794     }
2795 }
2796 
2797 /* ======================================================================
2798    FUNCTION
2799    omx_vdec::SendCommandEvent
2800 
2801    DESCRIPTION
2802    Send the event to decoder pipe.  This is needed to generate the callbacks
2803    in decoder thread context.
2804 
2805    PARAMETERS
2806    None.
2807 
2808    RETURN VALUE
2809    true/false
2810 
2811    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)2812 bool omx_vdec::post_event(unsigned long p1,
2813         unsigned long p2,
2814         unsigned long id)
2815 {
2816     bool bRet = false;
2817 
2818     /* Just drop messages typically generated by hardware (w/o client request),
2819      * if we've reported an error to client. */
2820     if (m_error_propogated) {
2821         switch (id) {
2822             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
2823             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
2824                 DEBUG_PRINT_ERROR("Dropping message %lx "
2825                         "since client expected to be in error state", id);
2826                 return false;
2827             default:
2828                 /* whatever */
2829                 break;
2830         }
2831     }
2832 
2833     pthread_mutex_lock(&m_lock);
2834 
2835     if (id == m_fill_output_msg ||
2836             id == OMX_COMPONENT_GENERATE_FBD ||
2837             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
2838             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
2839         m_ftb_q.insert_entry(p1,p2,id);
2840     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
2841             id == OMX_COMPONENT_GENERATE_EBD ||
2842             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
2843         m_etb_q.insert_entry(p1,p2,id);
2844     } else {
2845         DEBUG_PRINT_HIGH("post_event(%ld, %ld, %ld)", p1, p2, id);
2846         m_cmd_q.insert_entry(p1,p2,id);
2847     }
2848 
2849     bRet = true;
2850     post_message(this, id);
2851 
2852     pthread_mutex_unlock(&m_lock);
2853 
2854     return bRet;
2855 }
2856 
vdec_query_cap(struct v4l2_queryctrl & cap)2857 bool inline omx_vdec::vdec_query_cap(struct v4l2_queryctrl &cap)
2858 {
2859 
2860     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &cap)) {
2861         DEBUG_PRINT_ERROR("Query caps for id = %u failed\n", cap.id);
2862         return false;
2863     }
2864     return true;
2865 }
2866 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)2867 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
2868 {
2869     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2870     bool hdr_supported = true;
2871     struct v4l2_queryctrl profile_cap, level_cap, tier_cap;
2872     int v4l2_profile;
2873     int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
2874                             QOMX_VIDEO_AVCProfileBaseline,
2875                             QOMX_VIDEO_AVCProfileMain,
2876                             QOMX_VIDEO_AVCProfileConstrainedHigh,
2877                             QOMX_VIDEO_AVCProfileHigh };
2878     int hevc_profiles[5] = { OMX_VIDEO_HEVCProfileMain,
2879                              OMX_VIDEO_HEVCProfileMain10,
2880                              OMX_VIDEO_HEVCProfileMainStill,
2881                              OMX_VIDEO_HEVCProfileMain10HDR10,
2882                              OMX_VIDEO_HEVCProfileMain10HDR10Plus };
2883     int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple,
2884                               OMX_VIDEO_MPEG2ProfileMain};
2885     int vp9_profiles[4] = { OMX_VIDEO_VP9Profile0,
2886                             OMX_VIDEO_VP9Profile2,
2887                             OMX_VIDEO_VP9Profile2HDR,
2888                             OMX_VIDEO_VP9Profile2HDR10Plus};
2889 
2890     if (!profileLevelType)
2891         return OMX_ErrorBadParameter;
2892 
2893     memset(&tier_cap, 0, sizeof(struct v4l2_queryctrl));
2894     memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
2895     memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
2896 
2897     if (output_capability == V4L2_PIX_FMT_H264) {
2898         level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
2899         profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
2900     } else if (output_capability == V4L2_PIX_FMT_VP8) {
2901         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
2902     } else if (output_capability == V4L2_PIX_FMT_VP9) {
2903         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL;
2904         profile_cap.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE;
2905     } else if (output_capability == V4L2_PIX_FMT_HEVC) {
2906         tier_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_TIER;
2907         level_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL;
2908         profile_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE;
2909     } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
2910         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL;
2911         profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE;
2912     } else {
2913         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
2914         return OMX_ErrorInvalidComponent;
2915     }
2916 
2917     if (profile_cap.id) {
2918         if(!vdec_query_cap(profile_cap)) {
2919             DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
2920             return OMX_ErrorHardware;
2921         }
2922     }
2923 
2924     if (level_cap.id) {
2925         if(!vdec_query_cap(level_cap)) {
2926             DEBUG_PRINT_ERROR("Getting capabilities for level failed");
2927             return OMX_ErrorHardware;
2928         }
2929     }
2930 
2931     if (tier_cap.id) {
2932         if(!vdec_query_cap(tier_cap)) {
2933             DEBUG_PRINT_ERROR("Getting capabilities for tier failed");
2934             return OMX_ErrorHardware;
2935         }
2936     }
2937 
2938     /* Get the corresponding omx level from v4l2 level */
2939     if (!profile_level_converter::convert_v4l2_level_to_omx(output_capability, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
2940         DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
2941         return OMX_ErrorHardware;
2942     }
2943     if (output_capability == V4L2_PIX_FMT_HEVC && tier_cap.maximum == V4L2_MPEG_VIDEO_HEVC_TIER_HIGH) {
2944         /* handle HEVC high tier */
2945         profileLevelType->eLevel <<= 1;
2946     }
2947 
2948     /* For given profile index get corresponding profile that needs to be supported */
2949     if (profileLevelType->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
2950         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex);
2951         return OMX_ErrorBadPortIndex;
2952     }
2953 
2954     if (output_capability == V4L2_PIX_FMT_H264) {
2955         if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
2956             profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
2957         } else {
2958             DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2959                                           (unsigned int)profileLevelType->nProfileIndex);
2960             return OMX_ErrorNoMore;
2961         }
2962     } else if (output_capability == V4L2_PIX_FMT_VP8) {
2963         if (profileLevelType->nProfileIndex == 0) {
2964             profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
2965         } else {
2966             DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2967                                           (unsigned int)profileLevelType->nProfileIndex);
2968             return OMX_ErrorNoMore;
2969         }
2970         /* Driver has no notion of VP8 profile. Only one profile is supported.  Return this */
2971         return OMX_ErrorNone;
2972     } else if (output_capability == V4L2_PIX_FMT_VP9) {
2973         if (profileLevelType->nProfileIndex < (sizeof(vp9_profiles)/sizeof(int))) {
2974             profileLevelType->eProfile = vp9_profiles[profileLevelType->nProfileIndex];
2975         } else {
2976             DEBUG_PRINT_LOW("VP9: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2977                                           (unsigned int)profileLevelType->nProfileIndex);
2978             return OMX_ErrorNoMore;
2979         }
2980     } else if (output_capability == V4L2_PIX_FMT_HEVC) {
2981         if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
2982             profileLevelType->eProfile =  hevc_profiles[profileLevelType->nProfileIndex];
2983         } else {
2984             DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2985                                          (unsigned int)profileLevelType->nProfileIndex);
2986             return OMX_ErrorNoMore;
2987         }
2988     } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
2989         if (profileLevelType->nProfileIndex < (sizeof(mpeg2_profiles)/sizeof(int))) {
2990             profileLevelType->eProfile = mpeg2_profiles[profileLevelType->nProfileIndex];
2991         } else {
2992             DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2993                                          (unsigned int)profileLevelType->nProfileIndex);
2994             return OMX_ErrorNoMore;
2995         }
2996     }
2997 
2998     /* Check if the profile is supported by driver or not  */
2999     /* During query caps of profile driver sends a mask of */
3000     /* of all v4l2 profiles supported(in the flags field)  */
3001     if (!profile_level_converter::convert_omx_profile_to_v4l2(output_capability, profileLevelType->eProfile, &v4l2_profile)) {
3002         DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3003         return OMX_ErrorHardware;
3004     }
3005     if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
3006         DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
3007         eRet = OMX_ErrorNoMore;
3008     }
3009     if (m_disable_hdr & DEC_HDR_DISABLE_FLAG) {
3010         if (output_capability == V4L2_PIX_FMT_VP9) {
3011             if (profileLevelType->eProfile == OMX_VIDEO_VP9Profile2HDR || profileLevelType->eProfile == OMX_VIDEO_VP9Profile2HDR10Plus)
3012                 hdr_supported = false;
3013         }
3014         if (output_capability == V4L2_PIX_FMT_HEVC) {
3015             if (profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10 || profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10HDR10
3016             || profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10HDR10Plus) {
3017                 hdr_supported = false;
3018             }
3019         }
3020         if (!hdr_supported) {
3021             DEBUG_PRINT_LOW("%s: HDR profile unsupported", __FUNCTION__);
3022             return OMX_ErrorHardware;
3023         }
3024     }
3025 
3026     DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
3027             (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
3028     return eRet;
3029 }
3030 
3031 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3032 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3033 {
3034     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3035     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3036     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3037 
3038     if ((params == NULL) ||
3039             (params->nativeBuffer == NULL) ||
3040             (params->nativeBuffer->handle == NULL) ||
3041             !m_enable_android_native_buffers)
3042         return OMX_ErrorBadParameter;
3043     m_use_android_native_buffers = OMX_TRUE;
3044     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3045     private_handle_t *handle = (private_handle_t *)nBuf->handle;
3046     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3047         OMX_U8 *buffer = NULL;
3048         if (!secure_mode) {
3049             buffer = (OMX_U8*)mmap(0, handle->size,
3050                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3051             if (buffer == MAP_FAILED) {
3052                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3053                 return OMX_ErrorInsufficientResources;
3054             }
3055         }
3056         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3057     } else {
3058         eRet = OMX_ErrorBadParameter;
3059     }
3060     return eRet;
3061 }
3062 #endif
3063 
3064 /* ======================================================================
3065    FUNCTION
3066    omx_vdec::GetConfig
3067 
3068    DESCRIPTION
3069    OMX Get Config Method implementation.
3070 
3071    PARAMETERS
3072    <TBD>.
3073 
3074    RETURN VALUE
3075    OMX Error None if successful.
3076 
3077    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)3078 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
3079         OMX_IN OMX_INDEXTYPE configIndex,
3080         OMX_INOUT OMX_PTR     configData)
3081 {
3082     (void) hComp;
3083     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3084 
3085     if (m_state == OMX_StateInvalid) {
3086         DEBUG_PRINT_ERROR("Get Config in Invalid State");
3087         return OMX_ErrorInvalidState;
3088     }
3089 
3090     switch ((unsigned long)configIndex) {
3091         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
3092                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
3093                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
3094                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
3095                                      decoderinstances->nNumOfInstances = 16;
3096                                      /*TODO: How to handle this case */
3097                                      break;
3098                                  }
3099         case OMX_IndexConfigCommonOutputCrop: {
3100                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
3101                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
3102                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
3103                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
3104                                         rectangle.nLeft, rectangle.nTop,
3105                                         rectangle.nWidth, rectangle.nHeight);
3106                                   break;
3107                               }
3108         case OMX_QTIIndexConfigDescribeColorAspects:
3109         {
3110             VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
3111             DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
3112 
3113             if (params->bRequestingDataSpace) {
3114                 DEBUG_PRINT_LOW("Does not handle dataspace request. Please ignore this Unsupported Setting (0x80001019).");
3115                 return OMX_ErrorUnsupportedSetting;
3116             }
3117 
3118             print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
3119             print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
3120             get_preferred_color_aspects(params->sAspects);
3121             print_debug_color_aspects(&(params->sAspects), "Frameworks path GetConfig Color Aspects");
3122 
3123             break;
3124         }
3125         case OMX_QTIIndexConfigDescribeHDRColorInfo:
3126         {
3127             VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
3128             DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
3129             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
3130             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
3131             get_preferred_hdr_info(params->sInfo);
3132             print_debug_hdr_color_info(&(params->sInfo), "Frameworks path GetConfig HDR");
3133 
3134             break;
3135         }
3136         case OMX_QTIIndexConfigDescribeHDR10PlusInfo:
3137         {
3138             VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
3139             DescribeHDR10PlusInfoParams *params = (DescribeHDR10PlusInfoParams *)configData;
3140             get_hdr10plusinfo(params);
3141             print_hdr10plusinfo(params);
3142             break;
3143         }
3144         case OMX_IndexConfigAndroidVendorExtension:
3145         {
3146             VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
3147 
3148             OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
3149                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
3150             VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
3151             return get_vendor_extension_config(ext);
3152         }
3153         default:
3154         {
3155             DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
3156             eRet = OMX_ErrorBadParameter;
3157         }
3158 
3159     }
3160 
3161     return eRet;
3162 }
3163 
3164 /* ======================================================================
3165    FUNCTION
3166    omx_vdec::SetConfig
3167 
3168    DESCRIPTION
3169    OMX Set Config method implementation
3170 
3171    PARAMETERS
3172    <TBD>.
3173 
3174    RETURN VALUE
3175    OMX Error None if successful.
3176    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)3177 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
3178         OMX_IN OMX_INDEXTYPE configIndex,
3179         OMX_IN OMX_PTR        configData)
3180 {
3181     (void) hComp;
3182     if (m_state == OMX_StateInvalid) {
3183         DEBUG_PRINT_ERROR("Get Config in Invalid State");
3184         return OMX_ErrorInvalidState;
3185     }
3186 
3187     OMX_ERRORTYPE ret = OMX_ErrorNone;
3188     OMX_VIDEO_CONFIG_NALSIZE *pNal;
3189 
3190     DEBUG_PRINT_LOW("Set Config Called");
3191 
3192 
3193     if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
3194         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
3195         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
3196 
3197         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
3198             if (config->bEnabled) {
3199                 if ((config->nFps >> 16) > 0 &&
3200                         (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
3201                     m_fps_received = config->nFps;
3202                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
3203                             (unsigned int)config->nFps >> 16);
3204                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
3205                             drv_ctx.frame_rate.fps_denominator);
3206 
3207                     if (!drv_ctx.frame_rate.fps_numerator) {
3208                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
3209                         drv_ctx.frame_rate.fps_numerator = 30;
3210                     }
3211 
3212                     if (drv_ctx.frame_rate.fps_denominator) {
3213                         drv_ctx.frame_rate.fps_numerator = (int)
3214                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
3215                     }
3216 
3217                     drv_ctx.frame_rate.fps_denominator = 1;
3218                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
3219                         drv_ctx.frame_rate.fps_numerator;
3220 
3221                     struct v4l2_control control;
3222 
3223                     control.id =  V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
3224                     control.value = drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
3225                     control.value <<= 16;
3226                     control.value |= (0x0000FFFF | drv_ctx.frame_rate.fps_numerator % drv_ctx.frame_rate.fps_denominator);
3227                     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3228                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
3229                        DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
3230                             performance might be affected");
3231                        return OMX_ErrorHardware;
3232                     }
3233                     client_set_fps = true;
3234                 } else {
3235                     DEBUG_PRINT_ERROR("Frame rate not supported.");
3236                     ret = OMX_ErrorUnsupportedSetting;
3237                 }
3238             } else {
3239                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
3240                 client_set_fps = false;
3241             }
3242         } else {
3243             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
3244                     (int)config->nPortIndex);
3245             ret = OMX_ErrorBadPortIndex;
3246         }
3247 
3248         return ret;
3249     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
3250         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
3251         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
3252 
3253         struct v4l2_control control;
3254 
3255         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
3256         if (priority->nU32 == 0)
3257             control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
3258         else
3259             control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
3260 
3261         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
3262             DEBUG_PRINT_ERROR("Failed to set Priority");
3263             ret = OMX_ErrorUnsupportedSetting;
3264         }
3265         return ret;
3266     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
3267         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
3268         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
3269 
3270         struct v4l2_control control;
3271 
3272         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
3273         control.value = rate->nU32;
3274 
3275         if (rate->nU32 > INT_MAX)
3276             control.value = INT_MAX;
3277 
3278         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
3279             ret = errno == EBUSY ? OMX_ErrorInsufficientResources :
3280                     OMX_ErrorUnsupportedSetting;
3281             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
3282                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
3283         }
3284         return ret;
3285 
3286     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
3287         VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
3288         DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
3289         print_debug_color_aspects(&(params->sAspects), "Set Config");
3290         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
3291         return ret;
3292     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
3293         VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
3294         DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
3295         print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
3296         memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
3297         return ret;
3298 
3299     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDR10PlusInfo) {
3300         VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
3301         if (!store_vp9_hdr10plusinfo((DescribeHDR10PlusInfoParams *)configData)) {
3302             DEBUG_PRINT_ERROR("Failed to set hdr10plus info");
3303         }
3304         return ret;
3305 
3306     } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
3307         VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
3308 
3309         OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
3310                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
3311         VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
3312 
3313         return set_vendor_extension_config(ext);
3314     }
3315 
3316     return OMX_ErrorNotImplemented;
3317 }
3318 
3319 #define extn_equals(param, extn) (!strcmp(param, extn))
3320 
3321 /* ======================================================================
3322    FUNCTION
3323    omx_vdec::GetExtensionIndex
3324 
3325    DESCRIPTION
3326    OMX GetExtensionIndex method implementaion.  <TBD>
3327 
3328    PARAMETERS
3329    <TBD>.
3330 
3331    RETURN VALUE
3332    OMX Error None if everything successful.
3333 
3334    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)3335 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
3336         OMX_IN OMX_STRING      paramName,
3337         OMX_OUT OMX_INDEXTYPE* indexType)
3338 {
3339     (void) hComp;
3340     if (m_state == OMX_StateInvalid) {
3341         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
3342         return OMX_ErrorInvalidState;
3343     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
3344         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
3345     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
3346         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
3347     }
3348 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3349     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
3350         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
3351     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
3352         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
3353     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
3354         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
3355         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
3356     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
3357         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
3358     }
3359 #if ALLOCATE_OUTPUT_NATIVEHANDLE
3360     else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
3361         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
3362     }
3363 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
3364 #endif
3365     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
3366         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
3367     }
3368 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
3369     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
3370         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
3371     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
3372         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
3373     }
3374 #endif
3375 #ifdef FLEXYUV_SUPPORTED
3376     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
3377         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
3378     }
3379 #endif
3380     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
3381         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
3382     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
3383         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
3384     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
3385         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
3386     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
3387         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
3388     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
3389         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
3390     } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
3391         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
3392     } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
3393         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
3394     } else if (extn_equals(paramName, "OMX.google.android.index.describeHDR10PlusInfo")) {
3395         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDR10PlusInfo;
3396     }else {
3397         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
3398         return OMX_ErrorNotImplemented;
3399     }
3400     return OMX_ErrorNone;
3401 }
3402 
3403 /* ======================================================================
3404    FUNCTION
3405    omx_vdec::GetState
3406 
3407    DESCRIPTION
3408    Returns the state information back to the caller.<TBD>
3409 
3410    PARAMETERS
3411    <TBD>.
3412 
3413    RETURN VALUE
3414    Error None if everything is successful.
3415    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)3416 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
3417         OMX_OUT OMX_STATETYPE* state)
3418 {
3419     (void) hComp;
3420     *state = m_state;
3421     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
3422     return OMX_ErrorNone;
3423 }
3424 
3425 /* ======================================================================
3426    FUNCTION
3427    omx_vdec::ComponentTunnelRequest
3428 
3429    DESCRIPTION
3430    OMX Component Tunnel Request method implementation. <TBD>
3431 
3432    PARAMETERS
3433    None.
3434 
3435    RETURN VALUE
3436    OMX Error None if everything successful.
3437 
3438    ========================================================================== */
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)3439 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
3440         OMX_IN OMX_U32                        port,
3441         OMX_IN OMX_HANDLETYPE        peerComponent,
3442         OMX_IN OMX_U32                    peerPort,
3443         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
3444 {
3445     (void) hComp;
3446     (void) port;
3447     (void) peerComponent;
3448     (void) peerPort;
3449     (void) tunnelSetup;
3450     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
3451     return OMX_ErrorNotImplemented;
3452 }
3453 
3454 
3455 
3456 /* ======================================================================
3457    FUNCTION
3458    omx_vdec::ion_map
3459 
3460    DESCRIPTION
3461    Map the memory and run the ioctl SYNC operations
3462    on ION fd
3463 
3464    PARAMETERS
3465    fd    : ION fd
3466    len   : Lenth of the memory
3467 
3468    RETURN VALUE
3469    ERROR: mapped memory pointer
3470 
3471    ========================================================================== */
ion_map(int fd,int len)3472 char *omx_vdec::ion_map(int fd, int len)
3473 {
3474     char *bufaddr = (char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
3475                                 MAP_SHARED, fd, 0);
3476     if (bufaddr != MAP_FAILED)
3477         cache_clean_invalidate(fd);
3478     return bufaddr;
3479 }
3480 
3481 /* ======================================================================
3482    FUNCTION
3483    omx_vdec::ion_unmap
3484 
3485    DESCRIPTION
3486    Unmap the memory
3487 
3488    PARAMETERS
3489    fd      : ION fd
3490    bufaddr : buffer address
3491    len     : Lenth of the memory
3492 
3493    RETURN VALUE
3494    OMX_Error*
3495 
3496    ========================================================================== */
ion_unmap(int fd,void * bufaddr,int len)3497 OMX_ERRORTYPE omx_vdec::ion_unmap(int fd, void *bufaddr, int len)
3498 {
3499     cache_clean_invalidate(fd);
3500     if (-1 == munmap(bufaddr, len)) {
3501         DEBUG_PRINT_ERROR("munmap failed.");
3502         return OMX_ErrorInsufficientResources;
3503     }
3504     return OMX_ErrorNone;
3505 }
3506 
3507 /* ======================================================================
3508    FUNCTION
3509    omx_vdec::UseOutputBuffer
3510 
3511    DESCRIPTION
3512    Helper function for Use buffer in the input pin
3513 
3514    PARAMETERS
3515    None.
3516 
3517    RETURN VALUE
3518    true/false
3519 
3520    ========================================================================== */
allocate_extradata()3521 OMX_ERRORTYPE omx_vdec::allocate_extradata()
3522 {
3523 #ifdef USE_ION
3524     if (drv_ctx.extradata_info.buffer_size) {
3525         // free previous extradata if any
3526         free_extradata();
3527 
3528         for (int i = 0; i < drv_ctx.extradata_info.count; i++) {
3529             drv_ctx.extradata_info.buffer_size = (drv_ctx.extradata_info.buffer_size + 4095) & (~4095);
3530             // Decoder extradata is always uncached as buffer sizes are very small
3531             bool status = alloc_map_ion_memory(
3532                     drv_ctx.extradata_info.buffer_size, &drv_ctx.extradata_info.ion[i], 0);
3533             if (status == false) {
3534                 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
3535                 return OMX_ErrorInsufficientResources;
3536             }
3537             DEBUG_PRINT_HIGH("Allocated extradata size : %lu fd: %d",
3538                 drv_ctx.extradata_info.buffer_size, drv_ctx.extradata_info.ion[i].data_fd);
3539             drv_ctx.extradata_info.ion[i].uaddr = ion_map(drv_ctx.extradata_info.ion[i].data_fd,
3540                                                    drv_ctx.extradata_info.buffer_size);
3541             if (drv_ctx.extradata_info.ion[i].uaddr == MAP_FAILED) {
3542                 DEBUG_PRINT_ERROR("Failed to map extradata memory");
3543                 free_ion_memory(&drv_ctx.extradata_info.ion[i]);
3544                 return OMX_ErrorInsufficientResources;
3545             }
3546         }
3547     }
3548 #endif
3549     return OMX_ErrorNone;
3550 }
3551 
free_extradata()3552 void omx_vdec::free_extradata()
3553 {
3554 #ifdef USE_ION
3555     for (int i = 0; i < drv_ctx.extradata_info.count; i++) {
3556         if (drv_ctx.extradata_info.ion[i].uaddr) {
3557             ion_unmap(drv_ctx.extradata_info.ion[i].data_fd,
3558                       (void *)drv_ctx.extradata_info.ion[i].uaddr,
3559                       drv_ctx.extradata_info.ion[i].alloc_data.len);
3560             free_ion_memory(&drv_ctx.extradata_info.ion[i]);
3561             drv_ctx.extradata_info.ion[i].uaddr = NULL;
3562             drv_ctx.extradata_info.ion[i].data_fd = -1;
3563         }
3564     }
3565 #endif
3566 }
3567 
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)3568 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
3569         OMX_IN OMX_HANDLETYPE            hComp,
3570         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3571         OMX_IN OMX_U32                   port,
3572         OMX_IN OMX_PTR                   appData,
3573         OMX_IN OMX_U32                   bytes,
3574         OMX_IN OMX_U8*                   buffer)
3575 {
3576     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3577     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
3578     unsigned                         i= 0; // Temporary counter
3579     OMX_PTR privateAppData = NULL;
3580     private_handle_t *handle = NULL;
3581     OMX_U8 *buff = buffer;
3582     bool intermediate = client_buffers.is_color_conversion_enabled();
3583     (void) hComp;
3584     (void) port;
3585 
3586     if (!m_out_mem_ptr) {
3587         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers C2D(%d)",
3588                          client_buffers.is_color_conversion_enabled());
3589         eRet = allocate_output_headers();
3590         if (eRet == OMX_ErrorNone)
3591             eRet = allocate_extradata();
3592         output_use_buffer = true;
3593     }
3594 
3595     OMX_BUFFERHEADERTYPE  **omx_base_address =
3596         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
3597 
3598     if (eRet == OMX_ErrorNone) {
3599         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
3600             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
3601                 break;
3602             }
3603         }
3604     }
3605 
3606     if (i >= drv_ctx.op_buf.actualcount) {
3607         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
3608         return OMX_ErrorInsufficientResources;
3609     }
3610 
3611     if (intermediate) {
3612         DEBUG_PRINT_HIGH("Use_op_buf:Allocating intermediate output. %d", i);
3613         OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
3614         eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
3615                                       port, appData,
3616                                       drv_ctx.op_buf.buffer_size,
3617                                       true, i);
3618     }
3619 
3620     if (eRet == OMX_ErrorNone && dynamic_buf_mode) {
3621         *bufferHdr = (m_out_mem_ptr + i );
3622         (*bufferHdr)->pBuffer = NULL;
3623         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
3624             enum v4l2_buf_type buf_type;
3625             int rr = 0;
3626             DEBUG_PRINT_LOW("USE intermediate bufferSTREAMON(CAPTURE_MPLANE)");
3627             set_buffer_req(&drv_ctx.op_buf);
3628             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3629             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
3630                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
3631                 return OMX_ErrorInsufficientResources;
3632             } else {
3633                 streaming[CAPTURE_PORT] = true;
3634                 DEBUG_PRINT_LOW("STREAMON Successful");
3635             }
3636         }
3637         BITMASK_SET(&m_out_bm_count,i);
3638         (*bufferHdr)->pAppPrivate = appData;
3639         (*bufferHdr)->pBuffer = buffer;
3640         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
3641         return eRet;
3642     }
3643 
3644     if (eRet == OMX_ErrorNone) {
3645 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
3646         if (m_enable_android_native_buffers) {
3647             if (m_use_android_native_buffers) {
3648                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
3649                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3650                 handle = (private_handle_t *)nBuf->handle;
3651                 privateAppData = params->pAppPrivate;
3652             } else {
3653                 handle = (private_handle_t *)buff;
3654                 privateAppData = appData;
3655             }
3656             if (!handle) {
3657                 DEBUG_PRINT_ERROR("handle is invalid");
3658                 return OMX_ErrorBadParameter;
3659             }
3660 
3661             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
3662                 if (secure_mode) {
3663                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
3664                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
3665                 } else {
3666                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
3667                             " expected %u, got %u",
3668                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
3669                     return OMX_ErrorBadParameter;
3670                 }
3671             }
3672 
3673             drv_ctx.op_buf.buffer_size = handle->size;
3674 
3675             if (!m_use_android_native_buffers) {
3676                 if (!secure_mode) {
3677                     buff = (OMX_U8*)ion_map(handle->fd, handle->size);
3678                     if (buff == MAP_FAILED) {
3679                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3680                         return OMX_ErrorInsufficientResources;
3681                     }
3682                 }
3683             }
3684 #if defined(_ANDROID_ICS_)
3685             native_buffer[i].nativehandle = handle;
3686             native_buffer[i].privatehandle = handle;
3687 #endif
3688             if (!handle) {
3689                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
3690                 return OMX_ErrorBadParameter;
3691             }
3692             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
3693             drv_ctx.ptr_outputbuffer[i].offset = 0;
3694             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3695             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3696             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
3697         } else
3698 #endif
3699             if (!ouput_egl_buffers && !m_use_output_pmem) {
3700 #ifdef USE_GBM
3701                bool status = alloc_map_gbm_memory(
3702                        drv_ctx.video_resolution.frame_width,
3703                        drv_ctx.video_resolution.frame_height,
3704                        drv_ctx.gbm_device_fd,
3705                        &drv_ctx.op_buf_gbm_info[i],
3706                        secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
3707                 if (status == false) {
3708                     DEBUG_PRINT_ERROR("ION device fd is bad %d",
3709                                       (int) drv_ctx.op_buf_ion_info[i].data_fd);
3710                     return OMX_ErrorInsufficientResources;
3711                 }
3712                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3713                                      drv_ctx.op_buf_gbm_info[i].bo_fd;
3714                 if (intermediate)
3715                    m_pmem_info[i].pmeta_fd = drv_ctx.op_buf_gbm_info[i].meta_fd;
3716 #elif defined USE_ION
3717                 bool status = alloc_map_ion_memory(
3718                         drv_ctx.op_buf.buffer_size, &drv_ctx.op_buf_ion_info[i],
3719                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
3720                 if (status == false) {
3721                     DEBUG_PRINT_ERROR("ION device fd is bad %d",
3722                                       (int) drv_ctx.op_buf_ion_info[i].data_fd);
3723                     return OMX_ErrorInsufficientResources;
3724                 }
3725                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3726                                      drv_ctx.op_buf_ion_info[i].data_fd;
3727 #endif
3728                 if (!secure_mode) {
3729                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
3730                         (unsigned char *)ion_map(drv_ctx.ptr_outputbuffer[i].pmem_fd,
3731                                                  drv_ctx.op_buf.buffer_size);
3732                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
3733 #ifdef USE_GBM
3734                         free_gbm_memory(&drv_ctx.op_buf_gbm_info[i]);
3735 #elif defined USE_ION
3736                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
3737 #endif
3738                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
3739                         return OMX_ErrorInsufficientResources;
3740                     }
3741                 }
3742                 drv_ctx.ptr_outputbuffer[i].offset = 0;
3743                 privateAppData = appData;
3744             } else {
3745                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
3746                 if (!appData || !bytes ) {
3747                     if (!secure_mode && !buffer) {
3748                         DEBUG_PRINT_ERROR("Bad parameters for use buffer");
3749                         return OMX_ErrorBadParameter;
3750                     }
3751                 }
3752 
3753                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
3754                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
3755                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
3756                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
3757                         !pmem_list->nEntries ||
3758                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3759                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
3760                     return OMX_ErrorBadParameter;
3761                 }
3762                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
3763                     pmem_list->entryList->entry;
3764                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
3765                         pmem_info->pmem_fd);
3766                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
3767 #ifdef USE_GBM
3768                 if (intermediate)
3769                    m_pmem_info[i].pmeta_fd = pmem_info->pmeta_fd;
3770 #endif
3771                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
3772                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3773                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
3774                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3775                 privateAppData = appData;
3776             }
3777         if (intermediate) {
3778             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
3779             m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
3780             m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
3781             m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
3782             m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
3783         }
3784         *bufferHdr = (m_out_mem_ptr + i );
3785 
3786         if (secure_mode)
3787             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
3788 
3789         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
3790             enum v4l2_buf_type buf_type;
3791             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3792             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
3793                 return OMX_ErrorInsufficientResources;
3794             } else {
3795                 streaming[CAPTURE_PORT] = true;
3796                 DEBUG_PRINT_LOW("STREAMON Successful");
3797             }
3798         }
3799 
3800         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
3801         if (m_enable_android_native_buffers) {
3802             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
3803             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
3804         } else {
3805             (*bufferHdr)->pBuffer = buff;
3806         }
3807         (*bufferHdr)->pAppPrivate = privateAppData;
3808         BITMASK_SET(&m_out_bm_count,i);
3809     }
3810     return eRet;
3811 }
3812 
allocate_client_output_extradata_headers()3813 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers()
3814 {
3815     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3816     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
3817     int i = 0;
3818 
3819     if (!m_client_output_extradata_mem_ptr) {
3820         int nBufferCount       = 0;
3821 
3822         nBufferCount = m_client_out_extradata_info.getBufferCount();
3823         DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
3824 
3825         m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
3826 
3827         if (m_client_output_extradata_mem_ptr) {
3828             bufHdr          =  m_client_output_extradata_mem_ptr;
3829             for (i=0; i < nBufferCount; i++) {
3830                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3831                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
3832                 // Set the values when we determine the right HxW param
3833                 bufHdr->nAllocLen          = 0;
3834                 bufHdr->nFilledLen         = 0;
3835                 bufHdr->pAppPrivate        = NULL;
3836                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
3837                 bufHdr->pBuffer            = NULL;
3838                 bufHdr->pOutputPortPrivate = NULL;
3839                 bufHdr++;
3840             }
3841         } else {
3842              DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
3843                     m_client_output_extradata_mem_ptr);
3844               eRet =  OMX_ErrorInsufficientResources;
3845         }
3846     }
3847     return eRet;
3848 }
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)3849 OMX_ERRORTYPE  omx_vdec::use_client_output_extradata_buffer(
3850         OMX_IN OMX_HANDLETYPE            hComp,
3851         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3852         OMX_IN OMX_U32                   port,
3853         OMX_IN OMX_PTR                   appData,
3854         OMX_IN OMX_U32                   bytes,
3855         OMX_IN OMX_U8*                   buffer)
3856 {
3857     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3858     unsigned i = 0; // Temporary counter
3859     unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
3860     OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
3861     (void) hComp;
3862 
3863     if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
3864             bytes != buffer_size|| bufferHdr == NULL) {
3865         DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
3866             "bytes = %d expected is %d bufferHdr - %p", port,
3867             OMX_CORE_OUTPUT_EXTRADATA_INDEX, bytes, buffer_size, bufferHdr);
3868         eRet = OMX_ErrorBadParameter;
3869         return eRet;
3870     }
3871 
3872     if (!m_client_output_extradata_mem_ptr) {
3873         eRet = allocate_client_output_extradata_headers();
3874     }
3875 
3876     if (eRet == OMX_ErrorNone) {
3877         for (i = 0; i < buffer_count; i++) {
3878             if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
3879                 break;
3880             }
3881         }
3882     }
3883 
3884     if (i >= buffer_count) {
3885         DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
3886         eRet = OMX_ErrorInsufficientResources;
3887     }
3888 
3889     if (eRet == OMX_ErrorNone) {
3890         BITMASK_SET(&m_out_extradata_bm_count,i);
3891         *bufferHdr = (m_client_output_extradata_mem_ptr + i );
3892         (*bufferHdr)->pAppPrivate = appData;
3893         (*bufferHdr)->pBuffer = buffer;
3894         (*bufferHdr)->nAllocLen = bytes;
3895     }
3896 
3897     return eRet;
3898 }
3899 /* ======================================================================
3900    FUNCTION
3901    omx_vdec::use_input_heap_buffers
3902 
3903    DESCRIPTION
3904    OMX Use Buffer Heap allocation method implementation.
3905 
3906    PARAMETERS
3907    <TBD>.
3908 
3909    RETURN VALUE
3910    OMX Error None , if everything successful.
3911 
3912    ========================================================================== */
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)3913 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
3914         OMX_IN OMX_HANDLETYPE            hComp,
3915         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3916         OMX_IN OMX_U32                   port,
3917         OMX_IN OMX_PTR                   appData,
3918         OMX_IN OMX_U32                   bytes,
3919         OMX_IN OMX_U8*                   buffer)
3920 {
3921     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
3922     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3923 
3924     if (secure_mode) {
3925         DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
3926         return OMX_ErrorUndefined;
3927     }
3928 
3929     if (!m_inp_heap_ptr)
3930         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
3931             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
3932                     drv_ctx.ip_buf.actualcount);
3933     if (!m_phdr_pmem_ptr)
3934         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
3935             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
3936                     drv_ctx.ip_buf.actualcount);
3937     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
3938         DEBUG_PRINT_ERROR("Insufficent memory");
3939         eRet = OMX_ErrorInsufficientResources;
3940     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
3941         input_use_buffer = true;
3942         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
3943         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
3944         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
3945         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
3946         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
3947         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
3948         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
3949         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
3950         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
3951         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
3952                     (unsigned)NULL, (unsigned)NULL)) {
3953             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
3954             return OMX_ErrorInsufficientResources;
3955         }
3956         m_in_alloc_cnt++;
3957     } else {
3958         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
3959         eRet = OMX_ErrorInsufficientResources;
3960     }
3961     return eRet;
3962 }
3963 
3964 /* ======================================================================
3965    FUNCTION
3966    omx_vdec::UseBuffer
3967 
3968    DESCRIPTION
3969    OMX Use Buffer method implementation.
3970 
3971    PARAMETERS
3972    <TBD>.
3973 
3974    RETURN VALUE
3975    OMX Error None , if everything successful.
3976 
3977    ========================================================================== */
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)3978 OMX_ERRORTYPE  omx_vdec::use_buffer(
3979         OMX_IN OMX_HANDLETYPE            hComp,
3980         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3981         OMX_IN OMX_U32                   port,
3982         OMX_IN OMX_PTR                   appData,
3983         OMX_IN OMX_U32                   bytes,
3984         OMX_IN OMX_U8*                   buffer)
3985 {
3986     OMX_ERRORTYPE error = OMX_ErrorNone;
3987 
3988     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
3989             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
3990             return OMX_ErrorBadParameter;
3991     }
3992     if (m_state == OMX_StateInvalid) {
3993         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
3994         return OMX_ErrorInvalidState;
3995     }
3996     if (port == OMX_CORE_INPUT_PORT_INDEX) {
3997         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
3998         // ensure that use-buffer was called for previous allocation.
3999         // Mix-and-match of useBuffer and allocateBuffer is not allowed
4000         if (m_inp_mem_ptr && !input_use_buffer) {
4001             DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
4002             return OMX_ErrorUndefined;
4003         }
4004         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
4005     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4006         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
4007     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4008         error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
4009     } else {
4010         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
4011         error = OMX_ErrorBadPortIndex;
4012     }
4013     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
4014     if (error == OMX_ErrorNone) {
4015         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
4016             // Send the callback now
4017             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4018             post_event(OMX_CommandStateSet,OMX_StateIdle,
4019                     OMX_COMPONENT_GENERATE_EVENT);
4020         }
4021         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
4022                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
4023             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4024             post_event(OMX_CommandPortEnable,
4025                     OMX_CORE_INPUT_PORT_INDEX,
4026                     OMX_COMPONENT_GENERATE_EVENT);
4027         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
4028                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
4029             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4030             post_event(OMX_CommandPortEnable,
4031                     OMX_CORE_OUTPUT_PORT_INDEX,
4032                     OMX_COMPONENT_GENERATE_EVENT);
4033         }
4034     }
4035     return error;
4036 }
4037 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)4038 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
4039         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
4040 {
4041     (void)bufferindex;
4042     if (pmem_bufferHdr)
4043         free_input_buffer(pmem_bufferHdr);
4044     return OMX_ErrorNone;
4045 }
4046 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4047 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4048 {
4049     unsigned int index = 0;
4050     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
4051         return OMX_ErrorBadParameter;
4052     }
4053     print_omx_buffer("free_input_buffer", bufferHdr);
4054 
4055     index = bufferHdr - m_inp_mem_ptr;
4056     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
4057 
4058     bufferHdr->pInputPortPrivate = NULL;
4059 
4060     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
4061         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
4062             if (!secure_mode) {
4063                 ion_unmap(drv_ctx.ptr_inputbuffer[index].pmem_fd,
4064                           drv_ctx.ptr_inputbuffer[index].bufferaddr,
4065                           drv_ctx.ptr_inputbuffer[index].mmaped_size);
4066             }
4067 
4068             if (allocate_native_handle){
4069                 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
4070                 native_handle_close(nh);
4071                 native_handle_delete(nh);
4072             } else {
4073 #ifndef USE_ION
4074                 // Close fd for non-secure and secure non-native-handle case
4075                 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
4076 #endif
4077             }
4078             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
4079 
4080             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
4081                 free(m_desc_buffer_ptr[index].buf_addr);
4082                 m_desc_buffer_ptr[index].buf_addr = NULL;
4083                 m_desc_buffer_ptr[index].desc_data_size = 0;
4084             }
4085 #ifdef USE_ION
4086             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
4087 #endif
4088             if (m_in_alloc_cnt)
4089                 m_in_alloc_cnt--;
4090         } else {
4091             DEBUG_PRINT_ERROR("Invalid input buffer fd %d", drv_ctx.ptr_inputbuffer[index].pmem_fd);
4092         }
4093     } else {
4094         DEBUG_PRINT_ERROR("Invalid input buffer index %d, drv_ctx.ptr_inputbuffer %p",
4095             index, drv_ctx.ptr_inputbuffer);
4096     }
4097 
4098     return OMX_ErrorNone;
4099 }
4100 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr,bool intermediate)4101 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr,
4102                                            bool                 intermediate)
4103 {
4104     unsigned int index = 0;
4105 
4106     OMX_BUFFERHEADERTYPE  *omx_base_address =
4107              intermediate?m_intermediate_out_mem_ptr:m_out_mem_ptr;
4108     vdec_bufferpayload *omx_ptr_outputbuffer =
4109          intermediate?drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
4110     vdec_ion *omx_op_buf_ion_info =
4111         intermediate?drv_ctx.op_intermediate_buf_ion_info:drv_ctx.op_buf_ion_info;
4112 #ifdef USE_GBM
4113     vdec_gbm *omx_op_buf_gbm_info =
4114         intermediate?drv_ctx.op_intermediate_buf_gbm_info:drv_ctx.op_buf_gbm_info;
4115 #endif
4116     if (bufferHdr == NULL || omx_base_address == NULL) {
4117         return OMX_ErrorBadParameter;
4118     }
4119     print_omx_buffer("free_output_buffer", bufferHdr);
4120 
4121     index = bufferHdr - omx_base_address;
4122 
4123     if (index < drv_ctx.op_buf.actualcount
4124         && omx_ptr_outputbuffer) {
4125         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
4126                         omx_ptr_outputbuffer[index].bufferaddr);
4127 
4128         if (!dynamic_buf_mode) {
4129             if (streaming[CAPTURE_PORT] &&
4130                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
4131                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
4132                     DEBUG_PRINT_ERROR("STREAMOFF(CAPTURE_MPLANE) Failed");
4133                 } else {
4134                     DEBUG_PRINT_LOW("STREAMOFF(CAPTURE_MPLANE) Successful");
4135                 }
4136             }
4137 #ifdef _ANDROID_
4138             if (m_enable_android_native_buffers) {
4139                 if (!secure_mode) {
4140                     if (omx_ptr_outputbuffer[index].pmem_fd > 0) {
4141                         ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
4142                                   omx_ptr_outputbuffer[index].bufferaddr,
4143                                   omx_ptr_outputbuffer[index].mmaped_size);
4144                     }
4145                 }
4146             } else {
4147 #endif
4148                 if (omx_ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
4149                     if (!secure_mode) {
4150                         ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
4151                                   omx_ptr_outputbuffer[index].bufferaddr,
4152                                   omx_ptr_outputbuffer[index].mmaped_size);
4153                         omx_ptr_outputbuffer[index].bufferaddr = NULL;
4154                         omx_ptr_outputbuffer[index].mmaped_size = 0;
4155                     }
4156 #ifdef USE_GBM
4157                     free_gbm_memory(&omx_op_buf_gbm_info[index]);
4158 #elif defined USE_ION
4159                     free_ion_memory(&omx_op_buf_ion_info[index]);
4160 #endif
4161 
4162                     omx_ptr_outputbuffer[index].pmem_fd = -1;
4163                 }
4164 #ifdef _ANDROID_
4165             }
4166 #endif
4167         } //!dynamic_buf_mode
4168         if (intermediate == false) {
4169             OMX_BUFFERHEADERTYPE *tempBufHdr = m_intermediate_out_mem_ptr + index;
4170             if (client_buffers.is_color_conversion_enabled() &&
4171                 free_output_buffer(tempBufHdr, true) != OMX_ErrorNone) {
4172                 return OMX_ErrorBadParameter;
4173             }
4174 
4175             if (release_output_done()) {
4176             DEBUG_PRINT_HIGH("All output buffers released, free extradata");
4177             free_extradata();
4178             }
4179         }
4180     }
4181 
4182     return OMX_ErrorNone;
4183 }
4184 
4185 /* ======================================================================
4186    FUNCTION
4187    omx_vdec::AllocateInputBuffer
4188 
4189    DESCRIPTION
4190    Helper function for allocate buffer in the input pin
4191 
4192    PARAMETERS
4193    None.
4194 
4195    RETURN VALUE
4196    true/false
4197 
4198    ========================================================================== */
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)4199 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
4200         OMX_IN OMX_HANDLETYPE            hComp,
4201         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4202         OMX_IN OMX_U32                   port,
4203         OMX_IN OMX_PTR                   appData,
4204         OMX_IN OMX_U32                   bytes)
4205 {
4206     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4207     OMX_BUFFERHEADERTYPE *input = NULL;
4208     unsigned   i = 0;
4209     unsigned char *buf_addr = NULL;
4210     int pmem_fd = -1, ret = 0;
4211     unsigned int align_size = 0;
4212 
4213     (void) hComp;
4214     (void) port;
4215 
4216 
4217     if (bytes != drv_ctx.ip_buf.buffer_size) {
4218         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
4219                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
4220         return OMX_ErrorBadParameter;
4221     }
4222 
4223     if (!m_inp_mem_ptr) {
4224         /* Currently buffer reqs is being set only in set port defn                          */
4225         /* Client need not do set port definition if he sees enough buffers in get port defn */
4226         /* In such cases we need to do a set buffer reqs to driver. Doing it here            */
4227         struct v4l2_requestbuffers bufreq;
4228 
4229         DEBUG_PRINT_HIGH("Calling REQBUFS in %s ",__FUNCTION__);
4230         bufreq.memory = V4L2_MEMORY_USERPTR;
4231         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4232         bufreq.count = drv_ctx.ip_buf.actualcount;
4233         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
4234         if (ret) {
4235             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
4236             /*TODO: How to handle this case */
4237             eRet = OMX_ErrorInsufficientResources;
4238         } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
4239             DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
4240                 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
4241             eRet = OMX_ErrorInsufficientResources;
4242         }
4243 
4244         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
4245                 drv_ctx.ip_buf.actualcount,
4246                 (unsigned int)drv_ctx.ip_buf.buffer_size);
4247 
4248         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4249                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4250 
4251         if (m_inp_mem_ptr == NULL) {
4252             return OMX_ErrorInsufficientResources;
4253         }
4254 
4255         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
4256                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
4257 
4258         if (drv_ctx.ptr_inputbuffer == NULL) {
4259             return OMX_ErrorInsufficientResources;
4260         }
4261 #ifdef USE_ION
4262         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
4263                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
4264 
4265         if (drv_ctx.ip_buf_ion_info == NULL) {
4266             return OMX_ErrorInsufficientResources;
4267         }
4268 #endif
4269 
4270         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
4271             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
4272 #ifdef USE_ION
4273             drv_ctx.ip_buf_ion_info[i].data_fd = -1;
4274             drv_ctx.ip_buf_ion_info[i].dev_fd = -1;
4275 #endif
4276         }
4277     }
4278 
4279     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
4280         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
4281             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
4282             break;
4283         }
4284     }
4285 
4286     if (i < drv_ctx.ip_buf.actualcount) {
4287         int rc;
4288         DEBUG_PRINT_LOW("Allocate input Buffer");
4289 #ifdef USE_ION
4290         align_size = drv_ctx.ip_buf.buffer_size + 512;
4291         align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
4292         // Input buffers are cached to make parsing faster
4293         bool status = alloc_map_ion_memory(
4294                 align_size, &drv_ctx.ip_buf_ion_info[i],
4295                 secure_mode ? SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
4296         if (status == false) {
4297             return OMX_ErrorInsufficientResources;
4298         }
4299         pmem_fd = drv_ctx.ip_buf_ion_info[i].data_fd;
4300 #endif
4301         if (!secure_mode) {
4302             buf_addr = (unsigned char *)ion_map(pmem_fd, drv_ctx.ip_buf.buffer_size);
4303             if (buf_addr == MAP_FAILED) {
4304 #ifdef USE_ION
4305                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
4306 #endif
4307                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
4308                 return OMX_ErrorInsufficientResources;
4309             }
4310         }
4311         *bufferHdr = (m_inp_mem_ptr + i);
4312         if (secure_mode)
4313             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
4314         else
4315             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
4316         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
4317         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4318         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
4319         drv_ctx.ptr_inputbuffer [i].offset = 0;
4320 
4321         input = *bufferHdr;
4322         BITMASK_SET(&m_inp_bm_count,i);
4323         if (allocate_native_handle) {
4324             native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
4325             if (!nh) {
4326                 DEBUG_PRINT_ERROR("Native handle create failed");
4327                 return OMX_ErrorInsufficientResources;
4328             }
4329             nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
4330             input->pBuffer = (OMX_U8 *)nh;
4331         } else if (secure_mode || m_input_pass_buffer_fd) {
4332             /*Legacy method, pass ion fd stashed directly in pBuffer*/
4333             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
4334         } else {
4335             input->pBuffer           = (OMX_U8 *)buf_addr;
4336         }
4337         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
4338         input->nVersion.nVersion = OMX_SPEC_VERSION;
4339         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
4340         input->pAppPrivate       = appData;
4341         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
4342         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
4343 
4344         if (drv_ctx.disable_dmx) {
4345             eRet = allocate_desc_buffer(i);
4346         }
4347     } else {
4348         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
4349         eRet = OMX_ErrorInsufficientResources;
4350     }
4351 
4352     if (eRet == OMX_ErrorNone)
4353         DEBUG_PRINT_HIGH("Allocate_input_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d",
4354             i, input, input->pBuffer, input->nAllocLen,
4355             input->nOffset, drv_ctx.ptr_inputbuffer[i].pmem_fd);
4356 
4357     return eRet;
4358 }
4359 
4360 
4361 /* ======================================================================
4362    FUNCTION
4363    omx_vdec::AllocateOutputBuffer
4364 
4365    DESCRIPTION
4366    Helper fn for AllocateBuffer in the output pin
4367 
4368    PARAMETERS
4369    <TBD>.
4370 
4371    RETURN VALUE
4372    OMX Error None if everything went well.
4373 
4374    ========================================================================== */
allocate_output_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN bool intermediate,OMX_IN int index)4375 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
4376         OMX_IN OMX_HANDLETYPE            hComp,
4377         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4378         OMX_IN OMX_U32                   port,
4379         OMX_IN OMX_PTR                   appData,
4380         OMX_IN OMX_U32                   bytes,
4381         OMX_IN bool                      intermediate,
4382         OMX_IN int                       index)
4383 {
4384     (void)hComp;
4385     (void)port;
4386 
4387     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4388     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
4389     unsigned                         i= 0; // Temporary counter
4390 #ifdef USE_ION
4391     struct ion_allocation_data ion_alloc_data;
4392 #endif
4393     OMX_BUFFERHEADERTYPE  **omx_base_address =
4394         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
4395 
4396     vdec_bufferpayload **omx_ptr_outputbuffer =
4397         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
4398     vdec_output_frameinfo **omx_ptr_respbuffer =
4399         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
4400     vdec_ion **omx_op_buf_ion_info =
4401         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
4402 #ifdef USE_GBM
4403     vdec_gbm **omx_op_buf_gbm_info =
4404         intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
4405 #endif
4406 
4407     if (!*omx_base_address) {
4408         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
4409                 drv_ctx.op_buf.actualcount,
4410                 (unsigned int)drv_ctx.op_buf.buffer_size);
4411         int nBufHdrSize        = 0;
4412         int nPlatformEntrySize = 0;
4413         int nPlatformListSize  = 0;
4414         int nPMEMInfoSize = 0;
4415 
4416         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
4417         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
4418         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
4419 
4420         nBufHdrSize        = drv_ctx.op_buf.actualcount *
4421             sizeof(OMX_BUFFERHEADERTYPE);
4422         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
4423             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
4424         nPlatformListSize  = drv_ctx.op_buf.actualcount *
4425             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
4426         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
4427             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
4428 
4429         *omx_base_address = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
4430         // Alloc mem for platform specific info
4431         char *pPtr=NULL;
4432         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
4433                 nPMEMInfoSize,1);
4434         *omx_ptr_outputbuffer = (struct vdec_bufferpayload *)    \
4435                        calloc (sizeof(struct vdec_bufferpayload),
4436                                drv_ctx.op_buf.actualcount);
4437         *omx_ptr_respbuffer = (struct vdec_output_frameinfo  *)\
4438                      calloc (sizeof (struct vdec_output_frameinfo),
4439                              drv_ctx.op_buf.actualcount);
4440         if (!*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
4441             DEBUG_PRINT_ERROR("Failed to alloc outputbuffer or respbuffer ");
4442             free(pPtr);
4443             return OMX_ErrorInsufficientResources;
4444         }
4445 
4446 #ifdef USE_GBM
4447         *omx_op_buf_gbm_info = (struct vdec_gbm *)\
4448                       calloc (sizeof(struct vdec_gbm),
4449                       drv_ctx.op_buf.actualcount);
4450         if (!*omx_op_buf_gbm_info) {
4451                  DEBUG_PRINT_ERROR("Failed to alloc op_buf_gbm_info");
4452             return OMX_ErrorInsufficientResources;
4453         }
4454         drv_ctx.gbm_device_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
4455         if (drv_ctx.gbm_device_fd < 0) {
4456            DEBUG_PRINT_ERROR("opening dri device for gbm failed with fd = %d", drv_ctx.gbm_device_fd);
4457            return OMX_ErrorInsufficientResources;
4458         }
4459 #elif defined USE_ION
4460         *omx_op_buf_ion_info = (struct vdec_ion *)\
4461                       calloc (sizeof(struct vdec_ion),
4462                               drv_ctx.op_buf.actualcount);
4463         if (!*omx_op_buf_ion_info) {
4464             DEBUG_PRINT_ERROR("Failed to alloc op_buf_ion_info");
4465             return OMX_ErrorInsufficientResources;
4466         }
4467 #endif
4468 
4469         if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
4470             && *omx_ptr_respbuffer) {
4471             bufHdr          =  *omx_base_address;
4472             if (m_platform_list) {
4473                 free(m_platform_list);
4474             }
4475             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
4476             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
4477                 (((char *) m_platform_list)  + nPlatformListSize);
4478             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4479                 (((char *) m_platform_entry) + nPlatformEntrySize);
4480             pPlatformList   = m_platform_list;
4481             pPlatformEntry  = m_platform_entry;
4482             pPMEMInfo       = m_pmem_info;
4483 
4484             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
4485 
4486             // Settting the entire storage nicely
4487             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
4488                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
4489                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
4490                 // Set the values when we determine the right HxW param
4491                 bufHdr->nAllocLen          = bytes;
4492                 bufHdr->nFilledLen         = 0;
4493                 bufHdr->pAppPrivate        = appData;
4494                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
4495                 // Platform specific PMEM Information
4496                 // Initialize the Platform Entry
4497                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
4498                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
4499                 pPlatformEntry->entry      = pPMEMInfo;
4500                 // Initialize the Platform List
4501                 pPlatformList->nEntries    = 1;
4502                 pPlatformList->entryList   = pPlatformEntry;
4503                 // Keep pBuffer NULL till vdec is opened
4504                 bufHdr->pBuffer            = NULL;
4505                 bufHdr->nOffset            = 0;
4506                 pPMEMInfo->offset = 0;
4507                 pPMEMInfo->pmem_fd = -1;
4508                 bufHdr->pPlatformPrivate = pPlatformList;
4509                 /*Create a mapping between buffers*/
4510                 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
4511                 (*omx_ptr_respbuffer)[i].client_data = (void *) \
4512                     &(*omx_ptr_outputbuffer)[i];
4513                 // Move the buffer and buffer header pointers
4514                 bufHdr++;
4515                 pPMEMInfo++;
4516                 pPlatformEntry++;
4517                 pPlatformList++;
4518             }
4519         } else {
4520             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
4521                               *omx_base_address, pPtr);
4522             if (*omx_base_address) {
4523                 free(*omx_base_address);
4524                 *omx_base_address = NULL;
4525             }
4526             if (pPtr) {
4527                 free(pPtr);
4528                 pPtr = NULL;
4529             }
4530             if (*omx_ptr_outputbuffer) {
4531                 free(*omx_ptr_outputbuffer);
4532                 *omx_ptr_outputbuffer = NULL;
4533             }
4534             if (*omx_ptr_respbuffer) {
4535                 free(*omx_ptr_respbuffer);
4536                 *omx_ptr_respbuffer = NULL;
4537             }
4538 #ifdef USE_GBM
4539       if(drv_ctx.gbm_device_fd >= 0) {
4540        DEBUG_PRINT_LOW("Close gbm device");
4541        close(drv_ctx.gbm_device_fd);
4542        drv_ctx.gbm_device_fd = -1;
4543     }
4544             if (*omx_op_buf_gbm_info) {
4545                 DEBUG_PRINT_LOW("Free o/p gbm context");
4546                 free(*omx_op_buf_gbm_info);
4547                 *omx_op_buf_gbm_info = NULL;
4548             }
4549 #elif defined USE_ION
4550             if (*omx_op_buf_ion_info) {
4551                 DEBUG_PRINT_LOW("Free o/p ion context");
4552                 free(*omx_op_buf_ion_info);
4553                 *omx_op_buf_ion_info = NULL;
4554             }
4555 #endif
4556             eRet =  OMX_ErrorInsufficientResources;
4557         }
4558         if (eRet == OMX_ErrorNone)
4559             eRet = allocate_extradata();
4560     }
4561 
4562     if (intermediate == true && index != -1) {
4563         i = index;
4564     } else {
4565         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
4566             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
4567                 break;
4568             }
4569         }
4570     }
4571 
4572     if (eRet == OMX_ErrorNone) {
4573         if (i < drv_ctx.op_buf.actualcount) {
4574             int rc;
4575             int pmem_fd = -1;
4576             int fd = -1;
4577             unsigned char *pmem_baseaddress = NULL;
4578 #ifdef USE_GBM
4579             int pmeta_fd = -1;
4580             // Allocate output buffers as cached to improve performance of software-reading
4581             // of the YUVs. Output buffers are cache-invalidated in driver.
4582             // If color-conversion is involved, Only the C2D output buffers are cached, no
4583             // need to cache the decoder's output buffers
4584             int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
4585             bool status = alloc_map_gbm_memory(
4586                                drv_ctx.video_resolution.frame_width,
4587                                drv_ctx.video_resolution.frame_height,
4588                                drv_ctx.gbm_device_fd,
4589                                &(*omx_op_buf_gbm_info)[i],
4590                                (secure_mode) ? SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
4591             if (status == false) {
4592                 return OMX_ErrorInsufficientResources;
4593             }
4594             pmem_fd = (*omx_op_buf_gbm_info)[i].bo_fd;
4595             pmeta_fd = (*omx_op_buf_gbm_info)[i].meta_fd;
4596 #elif defined USE_ION
4597             // Allocate output buffers as cached to improve performance of software-reading
4598             // of the YUVs. Output buffers are cache-invalidated in driver.
4599             // If color-conversion is involved, Only the C2D output buffers are cached, no
4600             // need to cache the decoder's output buffers
4601             int cache_flag = ION_FLAG_CACHED;
4602             if (intermediate == true && client_buffers.is_color_conversion_enabled()) {
4603                 cache_flag = 0;
4604             }
4605             bool status = alloc_map_ion_memory(bytes,
4606                                                &(*omx_op_buf_ion_info)[i],
4607                     (secure_mode) ? SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
4608             if (status == false) {
4609                 return OMX_ErrorInsufficientResources;
4610             }
4611             pmem_fd = (*omx_op_buf_ion_info)[i].data_fd;
4612 #endif
4613             if (!secure_mode) {
4614                 pmem_baseaddress = (unsigned char *)ion_map(pmem_fd, bytes);
4615                 if (pmem_baseaddress == MAP_FAILED) {
4616                     DEBUG_PRINT_ERROR("MMAP failed for Size %u",
4617                             (unsigned int)drv_ctx.op_buf.buffer_size);
4618 #ifdef USE_GBM
4619                     free_gbm_memory(&(*omx_op_buf_gbm_info)[i]);
4620 #elif defined USE_ION
4621                     free_ion_memory(&(*omx_op_buf_ion_info)[i]);
4622 #endif
4623                     return OMX_ErrorInsufficientResources;
4624                 }
4625             }
4626             (*omx_ptr_outputbuffer)[i].pmem_fd = pmem_fd;
4627 #ifdef USE_GBM
4628             m_pmem_info[i].pmeta_fd = pmeta_fd;
4629 #endif
4630             (*omx_ptr_outputbuffer)[i].offset = 0;
4631             (*omx_ptr_outputbuffer)[i].bufferaddr = pmem_baseaddress;
4632             (*omx_ptr_outputbuffer)[i].mmaped_size = bytes;
4633             (*omx_ptr_outputbuffer)[i].buffer_len = bytes;
4634             m_pmem_info[i].pmem_fd = pmem_fd;
4635             m_pmem_info[i].size = (*omx_ptr_outputbuffer)[i].buffer_len;
4636             m_pmem_info[i].mapped_size = (*omx_ptr_outputbuffer)[i].mmaped_size;
4637             m_pmem_info[i].buffer = (*omx_ptr_outputbuffer)[i].bufferaddr;
4638             m_pmem_info[i].offset = (*omx_ptr_outputbuffer)[i].offset;
4639 
4640             *bufferHdr = (*omx_base_address + i );
4641             if (secure_mode) {
4642 #ifdef USE_GBM
4643                 (*omx_ptr_outputbuffer)[i].bufferaddr =
4644                     (OMX_U8 *)(intptr_t)(*omx_op_buf_gbm_info)[i].bo_fd;
4645 #elif defined USE_ION
4646                 (*omx_ptr_outputbuffer)[i].bufferaddr =
4647                     (OMX_U8 *)(intptr_t)(*omx_op_buf_ion_info)[i].data_fd;
4648 #endif
4649             }
4650             if (intermediate == false &&
4651                 client_buffers.is_color_conversion_enabled()) {
4652                 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
4653                 eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
4654                                               port, appData,
4655                                               drv_ctx.op_buf.buffer_size,
4656                                               true, i);
4657             }
4658             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
4659                 enum v4l2_buf_type buf_type;
4660 
4661                 set_buffer_req(&drv_ctx.op_buf);
4662                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4663                 if (!client_buffers.is_color_conversion_enabled() ||
4664                     (client_buffers.is_color_conversion_enabled() && intermediate == true)) {
4665                     rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
4666                     if (rc) {
4667                         DEBUG_PRINT_ERROR("STREAMON(CAPTURE_MPLANE) Failed");
4668                         return OMX_ErrorInsufficientResources;
4669                     } else {
4670                         streaming[CAPTURE_PORT] = true;
4671                         DEBUG_PRINT_LOW("STREAMON(CAPTURE_MPLANE) Successful");
4672                     }
4673                 }
4674             }
4675 
4676             (*bufferHdr)->pBuffer = (OMX_U8*)(*omx_ptr_outputbuffer)[i].bufferaddr;
4677             (*bufferHdr)->pAppPrivate = appData;
4678             BITMASK_SET(&m_out_bm_count,i);
4679         } else {
4680             DEBUG_PRINT_ERROR("Faile to allocate output buffer (%d) maxcount %d",
4681                 i, drv_ctx.op_buf.actualcount);
4682             eRet = OMX_ErrorInsufficientResources;
4683         }
4684     }
4685 
4686     if (eRet == OMX_ErrorNone)
4687         DEBUG_PRINT_HIGH("Allocate_output_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d intermediate %d",
4688                          i, (*bufferHdr), (*bufferHdr)->pBuffer, (*bufferHdr)->nAllocLen,
4689                          (*bufferHdr)->nOffset, (*omx_ptr_outputbuffer)[i].pmem_fd,
4690                          intermediate);
4691     return eRet;
4692 }
4693 
4694 
4695 // AllocateBuffer  -- API Call
4696 /* ======================================================================
4697    FUNCTION
4698    omx_vdec::AllocateBuffer
4699 
4700    DESCRIPTION
4701    Returns zero if all the buffers released..
4702 
4703    PARAMETERS
4704    None.
4705 
4706    RETURN VALUE
4707    true/false
4708 
4709    ========================================================================== */
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)4710 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
4711         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4712         OMX_IN OMX_U32                        port,
4713         OMX_IN OMX_PTR                     appData,
4714         OMX_IN OMX_U32                       bytes)
4715 {
4716     unsigned i = 0;
4717     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
4718 
4719     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
4720     if (m_state == OMX_StateInvalid) {
4721         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
4722         return OMX_ErrorInvalidState;
4723     }
4724 
4725     if (port == OMX_CORE_INPUT_PORT_INDEX) {
4726         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
4727         // ensure that use-buffer was never called.
4728         // Mix-and-match of useBuffer and allocateBuffer is not allowed
4729         if (m_inp_mem_ptr && input_use_buffer) {
4730             DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
4731             return OMX_ErrorUndefined;
4732         }
4733         eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
4734     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4735         if (output_use_buffer) {
4736             DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
4737             return OMX_ErrorBadParameter;
4738         }
4739         eRet = allocate_output_buffer(hComp, bufferHdr, port, appData, bytes);
4740     } else {
4741         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
4742         eRet = OMX_ErrorBadPortIndex;
4743     }
4744     if (eRet == OMX_ErrorNone) {
4745         if (allocate_done()) {
4746             DEBUG_PRINT_HIGH("Allocated all buffers on port %d", port);
4747             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
4748                 // Send the callback now
4749                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4750                 post_event(OMX_CommandStateSet,OMX_StateIdle,
4751                         OMX_COMPONENT_GENERATE_EVENT);
4752             }
4753         }
4754         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
4755             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
4756                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4757                 post_event(OMX_CommandPortEnable,
4758                         OMX_CORE_INPUT_PORT_INDEX,
4759                         OMX_COMPONENT_GENERATE_EVENT);
4760             }
4761         }
4762         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
4763             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
4764                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4765                 post_event(OMX_CommandPortEnable,
4766                         OMX_CORE_OUTPUT_PORT_INDEX,
4767                         OMX_COMPONENT_GENERATE_EVENT);
4768             }
4769         }
4770     }
4771     return eRet;
4772 }
4773 
4774 // Free Buffer - API call
4775 /* ======================================================================
4776    FUNCTION
4777    omx_vdec::FreeBuffer
4778 
4779    DESCRIPTION
4780 
4781    PARAMETERS
4782    None.
4783 
4784    RETURN VALUE
4785    true/false
4786 
4787    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4788 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
4789         OMX_IN OMX_U32                 port,
4790         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4791 {
4792     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4793     unsigned int nPortIndex;
4794     (void) hComp;
4795 
4796     auto_lock l(buf_lock);
4797     if (m_state == OMX_StateIdle &&
4798             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4799         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
4800     } else if (m_state == OMX_StateIdle) {
4801         DEBUG_PRINT_LOW("Free buffer while Component in Idle");
4802     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
4803             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
4804         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
4805     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
4806                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
4807             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
4808              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
4809         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
4810     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
4811         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
4812         post_event(OMX_EventError,
4813                 OMX_ErrorPortUnpopulated,
4814                 OMX_COMPONENT_GENERATE_EVENT);
4815         m_buffer_error = true;
4816         return OMX_ErrorIncorrectStateOperation;
4817     } else if (m_state != OMX_StateInvalid) {
4818         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
4819         post_event(OMX_EventError,
4820                 OMX_ErrorPortUnpopulated,
4821                 OMX_COMPONENT_GENERATE_EVENT);
4822     }
4823 
4824     if (port == OMX_CORE_INPUT_PORT_INDEX) {
4825         if (!input_use_buffer)
4826             nPortIndex = buffer - m_inp_mem_ptr;
4827         else
4828             nPortIndex = buffer - m_inp_heap_ptr;
4829 
4830         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
4831         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
4832                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
4833             // Clear the bit associated with it.
4834             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
4835             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
4836             if (input_use_buffer == true) {
4837 
4838                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
4839                 if (m_phdr_pmem_ptr)
4840                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
4841             } else {
4842                 free_input_buffer(buffer);
4843             }
4844             m_inp_bPopulated = OMX_FALSE;
4845             /*Free the Buffer Header*/
4846             if (release_input_done()) {
4847                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
4848                 free_input_buffer_header();
4849             }
4850         } else {
4851             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
4852             eRet = OMX_ErrorBadPortIndex;
4853         }
4854 
4855         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
4856                 && release_input_done()) {
4857             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4858             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
4859             post_event(OMX_CommandPortDisable,
4860                     OMX_CORE_INPUT_PORT_INDEX,
4861                     OMX_COMPONENT_GENERATE_EVENT);
4862         }
4863     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4864         // check if the buffer is valid
4865         OMX_BUFFERHEADERTYPE  *omx_base_address =
4866             client_buffers.is_color_conversion_enabled()?
4867             m_intermediate_out_mem_ptr:m_out_mem_ptr;
4868         nPortIndex = buffer - m_out_mem_ptr;
4869         if (nPortIndex < drv_ctx.op_buf.actualcount &&
4870                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
4871             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
4872             // Clear the bit associated with it.
4873             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
4874             m_out_bPopulated = OMX_FALSE;
4875             free_output_buffer (buffer);
4876 
4877             if (release_output_done()) {
4878                 DEBUG_PRINT_HIGH("All output buffers released.");
4879                 free_output_buffer_header();
4880             }
4881         } else {
4882             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
4883             eRet = OMX_ErrorBadPortIndex;
4884         }
4885         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
4886                 && release_output_done()) {
4887             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4888             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
4889 #ifdef _ANDROID_ICS_
4890             if (m_enable_android_native_buffers) {
4891                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
4892                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
4893             }
4894 #endif
4895 
4896             post_event(OMX_CommandPortDisable,
4897                     OMX_CORE_OUTPUT_PORT_INDEX,
4898                     OMX_COMPONENT_GENERATE_EVENT);
4899         }
4900     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4901         nPortIndex = buffer - m_client_output_extradata_mem_ptr;
4902         DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
4903 
4904         BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
4905 
4906         if (release_output_extradata_done()) {
4907             free_output_extradata_buffer_header();
4908         }
4909     } else {
4910         eRet = OMX_ErrorBadPortIndex;
4911     }
4912     if ((eRet == OMX_ErrorNone) &&
4913             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4914         if (release_done()) {
4915             /*
4916              * Reset buffer requirements here to ensure setting buffer requirement
4917              * when component move to executing state from loaded state via idle.
4918              */
4919             drv_ctx.op_buf.buffer_size = 0;
4920             drv_ctx.op_buf.actualcount = 0;
4921 
4922             // Send the callback now
4923             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
4924             post_event(OMX_CommandStateSet, OMX_StateLoaded,
4925                     OMX_COMPONENT_GENERATE_EVENT);
4926             m_buffer_error = false;
4927         }
4928     }
4929     return eRet;
4930 }
4931 
4932 
4933 /* ======================================================================
4934    FUNCTION
4935    omx_vdec::EmptyThisBuffer
4936 
4937    DESCRIPTION
4938    This routine is used to push the encoded video frames to
4939    the video decoder.
4940 
4941    PARAMETERS
4942    None.
4943 
4944    RETURN VALUE
4945    OMX Error None if everything went successful.
4946 
4947    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4948 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
4949         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4950 {
4951     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
4952     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
4953 
4954     if (m_state != OMX_StateExecuting &&
4955             m_state != OMX_StatePause &&
4956             m_state != OMX_StateIdle) {
4957         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
4958         return OMX_ErrorInvalidState;
4959     }
4960 
4961     if (m_error_propogated) {
4962         DEBUG_PRINT_ERROR("Empty this buffer not allowed after error");
4963         return OMX_ErrorHardware;
4964     }
4965 
4966     if (buffer == NULL) {
4967         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
4968         return OMX_ErrorBadParameter;
4969     }
4970     print_omx_buffer("EmptyThisBuffer", buffer);
4971 
4972     if (!m_inp_bEnabled) {
4973         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
4974         return OMX_ErrorIncorrectStateOperation;
4975     }
4976 
4977     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4978         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
4979         return OMX_ErrorBadPortIndex;
4980     }
4981 
4982     if (perf_flag) {
4983         if (!latency) {
4984             dec_time.stop();
4985             latency = dec_time.processing_time_us();
4986             dec_time.start();
4987         }
4988     }
4989 
4990     if (input_use_buffer == true) {
4991         nBufferIndex = buffer - m_inp_heap_ptr;
4992         if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
4993             DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
4994             return OMX_ErrorBadParameter;
4995         }
4996         m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
4997         m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
4998         m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
4999         buffer = &m_inp_mem_ptr[nBufferIndex];
5000         DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
5001                 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
5002     } else {
5003         nBufferIndex = buffer - m_inp_mem_ptr;
5004     }
5005 
5006     if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
5007         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
5008         return OMX_ErrorBadParameter;
5009     }
5010 
5011     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
5012         codec_config_flag = true;
5013         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
5014     }
5015 
5016     if (m_input_pass_buffer_fd) {
5017         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
5018     }
5019 
5020     m_etb_count++;
5021     //To handle wrap around case. m_etb_count++ to ensure value is non-zero.
5022     if (!m_etb_count)
5023         m_etb_count++;
5024     m_etb_timestamp = buffer->nTimeStamp;
5025     DEBUG_PRINT_LOW("[ETB] nCnt(%u) BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
5026             m_etb_count, buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
5027     buffer->pMarkData = (OMX_PTR)(unsigned long)m_etb_count;
5028     post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
5029 
5030     time_stamp_dts.insert_timestamp(buffer);
5031     return OMX_ErrorNone;
5032 }
5033 
5034 /* ======================================================================
5035    FUNCTION
5036    omx_vdec::empty_this_buffer_proxy
5037 
5038    DESCRIPTION
5039    This routine is used to push the encoded video frames to
5040    the video decoder.
5041 
5042    PARAMETERS
5043    None.
5044 
5045    RETURN VALUE
5046    OMX Error None if everything went successful.
5047 
5048    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5049 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
5050         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5051 {
5052     VIDC_TRACE_NAME_HIGH("ETB");
5053     (void) hComp;
5054     int push_cnt = 0,i=0;
5055     unsigned nPortIndex = 0;
5056     OMX_ERRORTYPE ret = OMX_ErrorNone;
5057     struct vdec_bufferpayload *temp_buffer;
5058     bool port_setting_changed = true;
5059 
5060     /*Should we generate a Aync error event*/
5061     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
5062         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
5063         return OMX_ErrorBadParameter;
5064     }
5065 
5066     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
5067 
5068     if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
5069         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
5070                 nPortIndex);
5071         return OMX_ErrorBadParameter;
5072     }
5073 
5074     pending_input_buffers++;
5075     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
5076 
5077     /* return zero length and not an EOS buffer */
5078     if ((buffer->nFilledLen == 0) &&
5079             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
5080         DEBUG_PRINT_HIGH("return zero length buffer");
5081         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
5082                 OMX_COMPONENT_GENERATE_EBD);
5083         return OMX_ErrorNone;
5084     }
5085 
5086     if (input_flush_progress == true) {
5087         DEBUG_PRINT_LOW("Flush in progress return buffer ");
5088         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
5089                 OMX_COMPONENT_GENERATE_EBD);
5090         return OMX_ErrorNone;
5091     }
5092 
5093     if (m_error_propogated == true) {
5094         DEBUG_PRINT_LOW("Return buffer in error state");
5095         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
5096                 OMX_COMPONENT_GENERATE_EBD);
5097         return OMX_ErrorNone;
5098     }
5099 
5100     auto_lock l(buf_lock);
5101     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
5102 
5103     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
5104         return OMX_ErrorBadParameter;
5105     }
5106 
5107     if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
5108         DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
5109         return OMX_ErrorBadParameter;
5110     }
5111 
5112     VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
5113     VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
5114     /*for use buffer we need to memcpy the data*/
5115     temp_buffer->buffer_len = buffer->nFilledLen;
5116 
5117     if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
5118         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
5119             memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
5120                     buffer->nFilledLen);
5121         } else {
5122             return OMX_ErrorBadParameter;
5123         }
5124 
5125     }
5126 
5127     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
5128         DEBUG_PRINT_LOW("ETB: dmx enabled");
5129         if (m_demux_entries == 0) {
5130             extract_demux_addr_offsets(buffer);
5131         }
5132 
5133         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
5134         handle_demux_data(buffer);
5135     }
5136 
5137     log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len, buffer->nTimeStamp, temp_buffer->pmem_fd);
5138 
5139     if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
5140         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5141     }
5142 
5143     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5144         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
5145         nal_count = 0;
5146         frame_count = 0;
5147         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
5148         m_demux_entries = 0;
5149     }
5150     struct v4l2_buffer buf;
5151     struct v4l2_plane plane;
5152     memset( (void *)&buf, 0, sizeof(buf));
5153     memset( (void *)&plane, 0, sizeof(plane));
5154     int rc;
5155     unsigned long  print_count;
5156     if (temp_buffer->buffer_len == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5157         struct v4l2_decoder_cmd dec;
5158 
5159         if (!streaming[OUTPUT_PORT]) {
5160             enum v4l2_buf_type buf_type;
5161             int ret = 0;
5162 
5163             buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5164             DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
5165             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5166             if (!ret) {
5167                 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
5168                 streaming[OUTPUT_PORT] = true;
5169             } else {
5170                 DEBUG_PRINT_ERROR("Streamon failed before sending stop command");
5171                 return OMX_ErrorHardware;
5172             }
5173         }
5174 
5175         DEBUG_PRINT_HIGH("Input EOS reached. Converted to STOP command") ;
5176         memset(&dec, 0, sizeof(dec));
5177         dec.cmd = V4L2_DEC_CMD_STOP;
5178         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec);
5179         post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
5180             OMX_COMPONENT_GENERATE_EBD);
5181         if (rc < 0) {
5182             DEBUG_PRINT_ERROR("Decoder CMD failed");
5183             return OMX_ErrorHardware;
5184         }
5185         return OMX_ErrorNone;
5186     }
5187 
5188     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5189         DEBUG_PRINT_HIGH("Input EOS reached") ;
5190         buf.flags = V4L2_BUF_FLAG_EOS;
5191     }
5192 
5193     // update hdr10plusinfo list with cookie as pMarkData
5194     update_hdr10plusinfo_cookie_using_timestamp(buffer->pMarkData, buffer->nTimeStamp);
5195 
5196     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5197     buf.index = nPortIndex;
5198     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5199     buf.memory = V4L2_MEMORY_USERPTR;
5200     plane.bytesused = temp_buffer->buffer_len;
5201     plane.length = drv_ctx.ip_buf.buffer_size;
5202     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
5203         (unsigned long)temp_buffer->offset;
5204     plane.reserved[MSM_VIDC_BUFFER_FD] = temp_buffer->pmem_fd;
5205     plane.reserved[MSM_VIDC_DATA_OFFSET] = temp_buffer->offset;
5206     plane.reserved[MSM_VIDC_INPUT_TAG_1] = (unsigned long)buffer->pMarkData;
5207     plane.reserved[MSM_VIDC_INPUT_TAG_2] = (unsigned long)buffer->hMarkTargetComponent;
5208     plane.data_offset = 0;
5209     buf.m.planes = &plane;
5210     buf.length = 1;
5211     //assumption is that timestamp is in milliseconds
5212     buf.timestamp.tv_sec = buffer->nTimeStamp / 1000000;
5213     buf.timestamp.tv_usec = (buffer->nTimeStamp % 1000000);
5214     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_BUF_FLAG_CODECCONFIG: 0;
5215 
5216     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
5217         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
5218         android_atomic_inc(&m_queued_codec_config_count);
5219     }
5220 
5221     print_v4l2_buffer("QBUF-ETB", &buf);
5222     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5223     if (rc) {
5224         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
5225         print_v4l2_buffer("QBUF failed", &buf);
5226         print_omx_buffer("EBD on qbuf failed", buffer);
5227         m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
5228         return OMX_ErrorHardware;
5229     }
5230 
5231     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
5232         codec_config_flag = false;
5233     }
5234     if (!streaming[OUTPUT_PORT]) {
5235         enum v4l2_buf_type buf_type;
5236         int ret,r;
5237 
5238         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5239         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
5240         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5241         if (!ret) {
5242             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
5243             streaming[OUTPUT_PORT] = true;
5244         } else if (errno == EBUSY) {
5245             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
5246             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
5247                     OMX_COMPONENT_GENERATE_EBD);
5248             return OMX_ErrorInsufficientResources;
5249         } else {
5250             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
5251             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
5252             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
5253                     OMX_COMPONENT_GENERATE_EBD);
5254             return OMX_ErrorBadParameter;
5255         }
5256     }
5257 
5258     return ret;
5259 }
5260 
5261 /* ======================================================================
5262    FUNCTION
5263    omx_vdec::FillThisBuffer
5264 
5265    DESCRIPTION
5266    IL client uses this method to release the frame buffer
5267    after displaying them.
5268 
5269    PARAMETERS
5270    None.
5271 
5272    RETURN VALUE
5273    true/false
5274 
5275    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5276 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
5277         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5278 {
5279     if (m_state != OMX_StateExecuting &&
5280             m_state != OMX_StatePause &&
5281             m_state != OMX_StateIdle) {
5282         DEBUG_PRINT_ERROR("FTB in Invalid State");
5283         return OMX_ErrorInvalidState;
5284     }
5285 
5286     if (buffer == NULL || buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
5287         DEBUG_PRINT_ERROR("ERROR:FTB invalid buffer %p or PortIndex - %d",
5288              buffer, buffer ? (int)buffer->nOutputPortIndex : -1);
5289         return OMX_ErrorBadPortIndex;
5290     }
5291     print_omx_buffer("FillThisBuffer", buffer);
5292 
5293     if (m_error_propogated) {
5294         DEBUG_PRINT_ERROR("Fill this buffer not allowed after error");
5295         return OMX_ErrorHardware;
5296     }
5297 
5298     if (!m_out_bEnabled) {
5299         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
5300         return OMX_ErrorIncorrectStateOperation;
5301     }
5302 
5303     unsigned nPortIndex = buffer - m_out_mem_ptr;
5304     if (dynamic_buf_mode) {
5305         private_handle_t *handle = NULL;
5306         struct VideoDecoderOutputMetaData *meta = NULL;
5307 
5308         if (!buffer || !buffer->pBuffer) {
5309             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
5310             return OMX_ErrorBadParameter;
5311         }
5312 
5313         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
5314         handle = (private_handle_t *)meta->pHandle;
5315 
5316         //get the buffer type and fd info
5317         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ",
5318                         meta, meta->eType, meta->pHandle);
5319 
5320         if (!handle) {
5321             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
5322             return OMX_ErrorBadParameter;
5323         }
5324 
5325         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
5326         if (nPortIndex < drv_ctx.op_buf.actualcount &&
5327             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
5328             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
5329             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
5330 
5331             //Store private handle from GraphicBuffer
5332             native_buffer[nPortIndex].privatehandle = handle;
5333             native_buffer[nPortIndex].nativehandle = handle;
5334         } else {
5335             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
5336             return OMX_ErrorBadParameter;
5337         }
5338 
5339         buffer->nAllocLen = handle->size;
5340         DEBUG_PRINT_LOW("%s: buffer size = d-%d:b-%d",
5341                         __func__, (int)drv_ctx.op_buf.buffer_size, (int)handle->size);
5342 
5343         if (!client_buffers.is_color_conversion_enabled()) {
5344             drv_ctx.op_buf.buffer_size = handle->size;
5345         }
5346 
5347     }
5348 
5349     if (client_buffers.is_color_conversion_enabled()) {
5350         buffer = m_intermediate_out_mem_ptr + nPortIndex;
5351         buffer->nAllocLen = drv_ctx.op_buf.buffer_size;
5352     }
5353 
5354     //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
5355     //this with a more sane size so that we don't compensate in rest of code
5356     //We'll restore this size later on, so that it's transparent to client
5357     buffer->nFilledLen = 0;
5358 
5359     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
5360     return OMX_ErrorNone;
5361 }
5362 
5363 /* ======================================================================
5364    FUNCTION
5365    omx_vdec::fill_this_buffer_proxy
5366 
5367    DESCRIPTION
5368    IL client uses this method to release the frame buffer
5369    after displaying them.
5370 
5371    PARAMETERS
5372    None.
5373 
5374    RETURN VALUE
5375    true/false
5376 
5377    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)5378 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
5379         OMX_IN OMX_HANDLETYPE        hComp,
5380         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
5381 {
5382     VIDC_TRACE_NAME_HIGH("FTB");
5383     OMX_ERRORTYPE nRet = OMX_ErrorNone;
5384     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
5385     unsigned bufIndex = 0;
5386     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
5387     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
5388 
5389     auto_lock l(buf_lock);
5390     OMX_BUFFERHEADERTYPE  *omx_base_address =
5391         client_buffers.is_color_conversion_enabled()?
5392                            m_intermediate_out_mem_ptr:m_out_mem_ptr;
5393     vdec_bufferpayload *omx_ptr_outputbuffer =
5394         client_buffers.is_color_conversion_enabled()?
5395                     drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
5396     bufIndex = buffer-omx_base_address;
5397 
5398     if (bufferAdd == NULL || bufIndex >= drv_ctx.op_buf.actualcount) {
5399         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, bufIndex %u bufCount %u",
5400             bufIndex, drv_ctx.op_buf.actualcount);
5401         return OMX_ErrorBadParameter;
5402     }
5403 
5404     if (BITMASK_ABSENT(&m_out_bm_count, bufIndex) || m_buffer_error) {
5405         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, bufIndex %u", bufIndex);
5406         return OMX_ErrorBadParameter;
5407     }
5408 
5409     /*Return back the output buffer to client*/
5410     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
5411         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
5412         buffer->nFilledLen = 0;
5413         print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
5414         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
5415         return OMX_ErrorNone;
5416     }
5417     if (m_error_propogated == true) {
5418         DEBUG_PRINT_LOW("Return buffers in error state");
5419         buffer->nFilledLen = 0;
5420         print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
5421         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
5422         return OMX_ErrorNone;
5423     }
5424 
5425     if (dynamic_buf_mode) {
5426         omx_ptr_outputbuffer[bufIndex].offset = 0;
5427         omx_ptr_outputbuffer[bufIndex].buffer_len = buffer->nAllocLen;
5428         omx_ptr_outputbuffer[bufIndex].mmaped_size = buffer->nAllocLen;
5429     }
5430 
5431     pending_output_buffers++;
5432     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
5433     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
5434     if (ptr_respbuffer) {
5435         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
5436     }
5437 
5438     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
5439         DEBUG_PRINT_ERROR("Invalid ptr_respbuffer %p, ptr_outputbuffer %p",
5440             ptr_respbuffer, ptr_outputbuffer);
5441         buffer->nFilledLen = 0;
5442         print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
5443         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
5444         pending_output_buffers--;
5445         VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
5446         return OMX_ErrorBadParameter;
5447     }
5448 
5449     int rc = 0;
5450     struct v4l2_buffer buf;
5451     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5452     memset( (void *)&buf, 0, sizeof(buf));
5453     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
5454     unsigned int extra_idx = 0;
5455 
5456     buf.index = bufIndex;
5457     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5458     buf.memory = V4L2_MEMORY_USERPTR;
5459     plane[0].bytesused = buffer->nFilledLen;
5460     plane[0].length = buffer->nAllocLen;
5461     plane[0].m.userptr =
5462         (unsigned long)omx_ptr_outputbuffer[bufIndex].bufferaddr -
5463         (unsigned long)omx_ptr_outputbuffer[bufIndex].offset;
5464     plane[0].reserved[MSM_VIDC_BUFFER_FD] = omx_ptr_outputbuffer[bufIndex].pmem_fd;
5465     plane[0].reserved[MSM_VIDC_DATA_OFFSET] = omx_ptr_outputbuffer[bufIndex].offset;
5466     plane[0].data_offset = 0;
5467     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5468     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5469         plane[extra_idx].bytesused = drv_ctx.extradata_info.buffer_size;
5470         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5471         plane[extra_idx].m.userptr = (long unsigned int)drv_ctx.extradata_info.ion[bufIndex].uaddr;
5472 #ifdef USE_ION
5473         plane[extra_idx].reserved[MSM_VIDC_BUFFER_FD] = drv_ctx.extradata_info.ion[bufIndex].data_fd;
5474 #endif
5475         plane[extra_idx].reserved[MSM_VIDC_DATA_OFFSET] = 0;
5476         plane[extra_idx].data_offset = 0;
5477     } else if (extra_idx >= VIDEO_MAX_PLANES) {
5478         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
5479         return OMX_ErrorBadParameter;
5480     }
5481     buf.m.planes = plane;
5482     buf.length = drv_ctx.num_planes;
5483     print_v4l2_buffer("QBUF-FTB", &buf);
5484     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5485     if (rc) {
5486         buffer->nFilledLen = 0;
5487         DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
5488         print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
5489         m_cb.FillBufferDone(hComp, m_app_data, &m_out_mem_ptr[bufIndex]);
5490         return OMX_ErrorHardware;
5491     }
5492 
5493     return OMX_ErrorNone;
5494 }
5495 
5496 /* ======================================================================
5497    FUNCTION
5498    omx_vdec::SetCallbacks
5499 
5500    DESCRIPTION
5501    Set the callbacks.
5502 
5503    PARAMETERS
5504    None.
5505 
5506    RETURN VALUE
5507    OMX Error None if everything successful.
5508 
5509    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)5510 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
5511         OMX_IN OMX_CALLBACKTYPE* callbacks,
5512         OMX_IN OMX_PTR             appData)
5513 {
5514     (void) hComp;
5515 
5516     if (!callbacks)
5517         return OMX_ErrorBadParameter;
5518 
5519     m_cb       = *callbacks;
5520     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
5521             m_cb.EventHandler,m_cb.FillBufferDone);
5522     m_app_data =    appData;
5523     return OMX_ErrorNone;
5524 }
5525 
5526 /* ======================================================================
5527    FUNCTION
5528    omx_vdec::ComponentDeInit
5529 
5530    DESCRIPTION
5531    Destroys the component and release memory allocated to the heap.
5532 
5533    PARAMETERS
5534    <TBD>.
5535 
5536    RETURN VALUE
5537    OMX Error None if everything successful.
5538 
5539    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)5540 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
5541 {
5542    (void) hComp;
5543    OMX_ERRORTYPE nRet = OMX_ErrorNone;
5544    OMX_BUFFERHEADERTYPE *buffer;
5545 
5546     unsigned i = 0;
5547     if (OMX_StateLoaded != m_state) {
5548         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
5549                 m_state);
5550         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
5551     } else {
5552         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
5553     }
5554 
5555     /*Check if the output buffers have to be cleaned up*/
5556     buffer = m_out_mem_ptr;
5557     if (buffer) {
5558         DEBUG_PRINT_LOW("Freeing the Output Memory");
5559         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
5560             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
5561                 BITMASK_CLEAR(&m_out_bm_count, i);
5562                     nRet = free_output_buffer (buffer+i);
5563                     if (OMX_ErrorNone != nRet)
5564                         break;
5565             }
5566             if (release_output_done()) {
5567                 DEBUG_PRINT_HIGH("All output buffers are released");
5568                 break;
5569             }
5570         }
5571 #ifdef _ANDROID_ICS_
5572         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5573 #endif
5574     }
5575 
5576     /*Check if the input buffers have to be cleaned up*/
5577     if (m_inp_mem_ptr || m_inp_heap_ptr) {
5578         DEBUG_PRINT_LOW("Freeing the Input Memory");
5579         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
5580 
5581             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
5582                 BITMASK_CLEAR(&m_inp_bm_count, i);
5583                 if (m_inp_mem_ptr)
5584                     free_input_buffer (i,&m_inp_mem_ptr[i]);
5585                 else
5586                     free_input_buffer (i,NULL);
5587             }
5588 
5589             if (release_input_done()) {
5590                 DEBUG_PRINT_HIGH("All input buffers released");
5591                 break;
5592             }
5593        }
5594     }
5595     free_input_buffer_header();
5596     free_output_buffer_header();
5597 
5598     if (m_platform_list) {
5599         free(m_platform_list);
5600         m_platform_list = NULL;
5601     }
5602     if (m_vendor_config.pData) {
5603         free(m_vendor_config.pData);
5604         m_vendor_config.pData = NULL;
5605     }
5606 
5607     // Reset counters in mesg queues
5608     m_ftb_q.m_size=0;
5609     m_cmd_q.m_size=0;
5610     m_etb_q.m_size=0;
5611     m_ftb_q.m_read = m_ftb_q.m_write =0;
5612     m_cmd_q.m_read = m_cmd_q.m_write =0;
5613     m_etb_q.m_read = m_etb_q.m_write =0;
5614 
5615     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
5616     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
5617     // NULL);
5618     DEBUG_PRINT_HIGH("Close the driver instance");
5619 
5620     if (m_debug.infile) {
5621         fclose(m_debug.infile);
5622         m_debug.infile = NULL;
5623     }
5624     if (m_debug.outfile) {
5625         fclose(m_debug.outfile);
5626         m_debug.outfile = NULL;
5627     }
5628     if (m_debug.ccoutfile) {
5629         fclose(m_debug.ccoutfile);
5630         m_debug.ccoutfile = NULL;
5631     }
5632     if (m_debug.out_ymeta_file) {
5633         fclose(m_debug.out_ymeta_file);
5634         m_debug.out_ymeta_file = NULL;
5635     }
5636     if (m_debug.out_uvmeta_file) {
5637         fclose(m_debug.out_uvmeta_file);
5638         m_debug.out_uvmeta_file = NULL;
5639     }
5640 #ifdef OUTPUT_EXTRADATA_LOG
5641     if (outputExtradataFile)
5642         fclose (outputExtradataFile);
5643 #endif
5644     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
5645     return OMX_ErrorNone;
5646 }
5647 
5648 /* ======================================================================
5649    FUNCTION
5650    omx_vdec::UseEGLImage
5651 
5652    DESCRIPTION
5653    OMX Use EGL Image method implementation <TBD>.
5654 
5655    PARAMETERS
5656    <TBD>.
5657 
5658    RETURN VALUE
5659    Not Implemented error.
5660 
5661    ========================================================================== */
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)5662 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
5663         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5664         OMX_IN OMX_U32                        port,
5665         OMX_IN OMX_PTR                     appData,
5666         OMX_IN void*                      eglImage)
5667 {
5668     (void) appData;
5669     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
5670     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
5671     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
5672 
5673 #ifdef USE_EGL_IMAGE_GPU
5674     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
5675     EGLint fd = -1, offset = 0,pmemPtr = 0;
5676 #else
5677     int fd = -1, offset = 0;
5678 #endif
5679     DEBUG_PRINT_HIGH("use EGL image support for decoder");
5680     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
5681         DEBUG_PRINT_ERROR("Invalid EGL image");
5682     }
5683 #ifdef USE_EGL_IMAGE_GPU
5684     if (m_display_id == NULL) {
5685         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
5686         return OMX_ErrorInsufficientResources;
5687     }
5688     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
5689         eglGetProcAddress("eglQueryImageKHR");
5690     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
5691     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
5692     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
5693 #else //with OMX test app
5694     struct temp_egl {
5695         int pmem_fd;
5696         int offset;
5697     };
5698     struct temp_egl *temp_egl_id = NULL;
5699     void * pmemPtr = (void *) eglImage;
5700     temp_egl_id = (struct temp_egl *)eglImage;
5701     if (temp_egl_id != NULL) {
5702         fd = temp_egl_id->pmem_fd;
5703         offset = temp_egl_id->offset;
5704     }
5705 #endif
5706     if (fd < 0) {
5707         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
5708         return OMX_ErrorInsufficientResources;
5709     }
5710     pmem_info.pmem_fd = (OMX_U32) fd;
5711     pmem_info.offset = (OMX_U32) offset;
5712     pmem_entry.entry = (void *) &pmem_info;
5713     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
5714     pmem_list.entryList = &pmem_entry;
5715     pmem_list.nEntries = 1;
5716     ouput_egl_buffers = true;
5717     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
5718                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
5719                 (OMX_U8 *)pmemPtr)) {
5720         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
5721         return OMX_ErrorInsufficientResources;
5722     }
5723     return OMX_ErrorNone;
5724 }
5725 
5726 /* ======================================================================
5727    FUNCTION
5728    omx_vdec::ComponentRoleEnum
5729 
5730    DESCRIPTION
5731    OMX Component Role Enum method implementation.
5732 
5733    PARAMETERS
5734    <TBD>.
5735 
5736    RETURN VALUE
5737    OMX Error None if everything is successful.
5738    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)5739 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
5740         OMX_OUT OMX_U8*        role,
5741         OMX_IN OMX_U32        index)
5742 {
5743     (void) hComp;
5744     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5745 
5746     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
5747         if ((0 == index) && role) {
5748             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
5749             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5750         } else {
5751             eRet = OMX_ErrorNoMore;
5752         }
5753     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
5754         if ((0 == index) && role) {
5755             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
5756             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5757         } else {
5758             DEBUG_PRINT_LOW("No more roles");
5759             eRet = OMX_ErrorNoMore;
5760         }
5761     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
5762         if ((0 == index) && role) {
5763             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
5764             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
5765         } else {
5766             DEBUG_PRINT_LOW("No more roles");
5767             eRet = OMX_ErrorNoMore;
5768         }
5769     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
5770         if ((0 == index) && role) {
5771             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
5772             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5773         } else {
5774             DEBUG_PRINT_LOW("No more roles");
5775             eRet = OMX_ErrorNoMore;
5776         }
5777     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
5778         if ((0 == index) && role) {
5779             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
5780             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5781         } else {
5782             DEBUG_PRINT_LOW("No more roles");
5783             eRet = OMX_ErrorNoMore;
5784         }
5785     } else {
5786         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
5787         eRet = OMX_ErrorInvalidComponentName;
5788     }
5789     return eRet;
5790 }
5791 
5792 
5793 
5794 
5795 /* ======================================================================
5796    FUNCTION
5797    omx_vdec::AllocateDone
5798 
5799    DESCRIPTION
5800    Checks if entire buffer pool is allocated by IL Client or not.
5801    Need this to move to IDLE state.
5802 
5803    PARAMETERS
5804    None.
5805 
5806    RETURN VALUE
5807    true/false.
5808 
5809    ========================================================================== */
allocate_done(void)5810 bool omx_vdec::allocate_done(void)
5811 {
5812     bool bRet = false;
5813     bool bRet_In = false;
5814     bool bRet_Out = false;
5815     bool bRet_Out_Extra = false;
5816 
5817     bRet_In = allocate_input_done();
5818     bRet_Out = allocate_output_done();
5819     bRet_Out_Extra = allocate_output_extradata_done();
5820 
5821     if (bRet_In && bRet_Out && bRet_Out_Extra) {
5822         DEBUG_PRINT_HIGH("All ports buffers are allocated");
5823         bRet = true;
5824     }
5825 
5826     return bRet;
5827 }
5828 /* ======================================================================
5829    FUNCTION
5830    omx_vdec::AllocateInputDone
5831 
5832    DESCRIPTION
5833    Checks if I/P buffer pool is allocated by IL Client or not.
5834 
5835    PARAMETERS
5836    None.
5837 
5838    RETURN VALUE
5839    true/false.
5840 
5841    ========================================================================== */
allocate_input_done(void)5842 bool omx_vdec::allocate_input_done(void)
5843 {
5844     bool bRet = false;
5845     unsigned i=0;
5846 
5847     if (m_inp_mem_ptr == NULL) {
5848         return bRet;
5849     }
5850     if (m_inp_mem_ptr ) {
5851         for (; i<drv_ctx.ip_buf.actualcount; i++) {
5852             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
5853                 break;
5854             }
5855         }
5856     }
5857     if (i == drv_ctx.ip_buf.actualcount) {
5858         bRet = true;
5859     }
5860     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
5861         m_inp_bPopulated = OMX_TRUE;
5862     }
5863     return bRet;
5864 }
5865 /* ======================================================================
5866    FUNCTION
5867    omx_vdec::AllocateOutputDone
5868 
5869    DESCRIPTION
5870    Checks if entire O/P buffer pool is allocated by IL Client or not.
5871 
5872    PARAMETERS
5873    None.
5874 
5875    RETURN VALUE
5876    true/false.
5877 
5878    ========================================================================== */
allocate_output_done(void)5879 bool omx_vdec::allocate_output_done(void)
5880 {
5881     bool bRet = false;
5882     unsigned j=0;
5883 
5884     if (m_out_mem_ptr == NULL) {
5885         return bRet;
5886     }
5887 
5888     if (m_out_mem_ptr) {
5889         for (; j < drv_ctx.op_buf.actualcount; j++) {
5890             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
5891                 break;
5892             }
5893         }
5894     }
5895 
5896     if (j == drv_ctx.op_buf.actualcount) {
5897         bRet = true;
5898         if (m_out_bEnabled)
5899             m_out_bPopulated = OMX_TRUE;
5900     }
5901 
5902     return bRet;
5903 }
5904 
allocate_output_extradata_done(void)5905 bool omx_vdec::allocate_output_extradata_done(void)
5906 {
5907     bool bRet = false;
5908     unsigned j=0;
5909     unsigned nBufferCount = 0;
5910 
5911     nBufferCount = m_client_out_extradata_info.getBufferCount();
5912 
5913     if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
5914         return true;
5915     }
5916 
5917     if (m_client_output_extradata_mem_ptr) {
5918         for (; j < nBufferCount; j++) {
5919             if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
5920                 break;
5921             }
5922         }
5923 
5924         if (j == nBufferCount) {
5925             bRet = true;
5926             DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
5927         }
5928     }
5929 
5930     return bRet;
5931 }
5932 /* ======================================================================
5933    FUNCTION
5934    omx_vdec::ReleaseDone
5935 
5936    DESCRIPTION
5937    Checks if IL client has released all the buffers.
5938 
5939    PARAMETERS
5940    None.
5941 
5942    RETURN VALUE
5943    true/false
5944 
5945    ========================================================================== */
release_done(void)5946 bool omx_vdec::release_done(void)
5947 {
5948     bool bRet = false;
5949 
5950     if (release_input_done()) {
5951         if (release_output_done()) {
5952             if (release_output_extradata_done()) {
5953                 DEBUG_PRINT_HIGH("All ports buffers are released");
5954                 bRet = true;
5955             }
5956         }
5957     }
5958     return bRet;
5959 }
5960 
5961 
5962 /* ======================================================================
5963    FUNCTION
5964    omx_vdec::ReleaseOutputDone
5965 
5966    DESCRIPTION
5967    Checks if IL client has released all the buffers.
5968 
5969    PARAMETERS
5970    None.
5971 
5972    RETURN VALUE
5973    true/false
5974 
5975    ========================================================================== */
release_output_done(void)5976 bool omx_vdec::release_output_done(void)
5977 {
5978     bool bRet = false;
5979     unsigned i=0,j=0;
5980 
5981     if (m_out_mem_ptr) {
5982         for (; j < drv_ctx.op_buf.actualcount ; j++) {
5983             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
5984                 break;
5985             }
5986         }
5987         if (j == drv_ctx.op_buf.actualcount) {
5988             m_out_bm_count = 0;
5989             bRet = true;
5990         }
5991     } else {
5992         m_out_bm_count = 0;
5993         bRet = true;
5994     }
5995     return bRet;
5996 }
5997 /* ======================================================================
5998    FUNCTION
5999    omx_vdec::ReleaseInputDone
6000 
6001    DESCRIPTION
6002    Checks if IL client has released all the buffers.
6003 
6004    PARAMETERS
6005    None.
6006 
6007    RETURN VALUE
6008    true/false
6009 
6010    ========================================================================== */
release_input_done(void)6011 bool omx_vdec::release_input_done(void)
6012 {
6013     bool bRet = false;
6014     unsigned i=0,j=0;
6015 
6016     if (m_inp_mem_ptr) {
6017         for (; j<drv_ctx.ip_buf.actualcount; j++) {
6018             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
6019                 break;
6020             }
6021         }
6022         if (j==drv_ctx.ip_buf.actualcount) {
6023             bRet = true;
6024         }
6025     } else {
6026         bRet = true;
6027     }
6028     return bRet;
6029 }
6030 
release_output_extradata_done(void)6031 bool omx_vdec::release_output_extradata_done(void)
6032 {
6033     bool bRet = false;
6034     unsigned i=0,j=0, buffer_count=0;
6035 
6036     buffer_count = m_client_out_extradata_info.getBufferCount();
6037     DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
6038             m_client_output_extradata_mem_ptr, buffer_count);
6039 
6040     if (m_client_output_extradata_mem_ptr) {
6041         for (; j<buffer_count; j++) {
6042             if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
6043                 break;
6044             }
6045         }
6046         if (j == buffer_count) {
6047             bRet = true;
6048         }
6049     } else {
6050         bRet = true;
6051     }
6052     return bRet;
6053 }
6054 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6055 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
6056         OMX_BUFFERHEADERTYPE * buffer)
6057 {
6058     VIDC_TRACE_NAME_HIGH("FBD");
6059     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
6060     OMX_BUFFERHEADERTYPE  *omx_base_address =
6061         client_buffers.is_color_conversion_enabled()?
6062                               m_intermediate_out_mem_ptr:m_out_mem_ptr;
6063     vdec_bufferpayload *omx_ptr_outputbuffer =
6064         client_buffers.is_color_conversion_enabled()?
6065                     drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
6066 
6067     if (!buffer || (buffer - omx_base_address) >= (int)drv_ctx.op_buf.actualcount) {
6068         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
6069         return OMX_ErrorBadParameter;
6070     } else if (output_flush_progress) {
6071         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
6072         buffer->nFilledLen = 0;
6073         buffer->nTimeStamp = 0;
6074         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
6075         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6076         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
6077     }
6078 
6079     if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
6080         DEBUG_PRINT_HIGH("***************************************************");
6081         DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
6082         DEBUG_PRINT_HIGH("***************************************************");
6083     }
6084 
6085     if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
6086         DEBUG_PRINT_HIGH("***************************************************");
6087         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
6088         DEBUG_PRINT_HIGH("***************************************************");
6089     }
6090 
6091     pending_output_buffers --;
6092     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
6093 
6094     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
6095         DEBUG_PRINT_HIGH("Output EOS has been reached");
6096         if (!output_flush_progress)
6097             post_event((unsigned)NULL, (unsigned)NULL,
6098                     OMX_COMPONENT_GENERATE_EOS_DONE);
6099 
6100         if (psource_frame) {
6101             print_omx_buffer("EBD in FBD", psource_frame);
6102             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
6103             psource_frame = NULL;
6104         }
6105         if (pdest_frame) {
6106             pdest_frame->nFilledLen = 0;
6107             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
6108                     (unsigned)NULL);
6109             pdest_frame = NULL;
6110         }
6111     }
6112 
6113 #ifdef OUTPUT_EXTRADATA_LOG
6114     if (outputExtradataFile) {
6115         int buf_index = buffer - omx_base_address;
6116         if (buf_index < drv_ctx.extradata_info.count &&
6117                 drv_ctx.extradata_info.ion[buf_index].uaddr)
6118             fwrite (drv_ctx.extradata_info.ion[buf_index].uaddr, 1,
6119                 drv_ctx.extradata_info.buffer_size, outputExtradataFile);
6120     }
6121 #endif
6122 
6123     /* For use buffer we need to copy the data */
6124     if (!output_flush_progress) {
6125         /* This is the error check for non-recoverable errros */
6126         bool is_duplicate_ts_valid = true;
6127         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
6128 
6129         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
6130                 output_capability == V4L2_PIX_FMT_MPEG2)
6131             is_duplicate_ts_valid = false;
6132 
6133         time_stamp_dts.get_next_timestamp(buffer,
6134                 is_interlaced && is_duplicate_ts_valid && !is_mbaff);
6135 
6136     }
6137     VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
6138 
6139     if (m_cb.FillBufferDone) {
6140         if (buffer->nFilledLen > 0) {
6141             set_frame_rate(buffer->nTimeStamp);
6142 
6143             proc_frms++;
6144             if (perf_flag) {
6145                 if (1 == proc_frms) {
6146                     dec_time.stop();
6147                     latency = dec_time.processing_time_us() - latency;
6148                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
6149                     dec_time.start();
6150                     fps_metrics.start();
6151                 }
6152                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
6153                     OMX_U64 proc_time = 0;
6154                     fps_metrics.stop();
6155                     proc_time = fps_metrics.processing_time_us();
6156                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
6157                             (unsigned int)proc_frms, (float)proc_time / 1e6,
6158                             (float)(1e6 * proc_frms) / proc_time);
6159                 }
6160             }
6161         }
6162         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
6163             prev_ts = LLONG_MAX;
6164             proc_frms = 0;
6165         }
6166 
6167         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6168             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
6169              buffer->pPlatformPrivate)->entryList->entry;
6170         OMX_BUFFERHEADERTYPE *il_buffer;
6171         il_buffer = client_buffers.get_il_buf_hdr(buffer);
6172         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
6173 
6174         if (il_buffer && m_last_rendered_TS >= 0) {
6175             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
6176             // Convert fps into ms value. 1 sec = 1000000 ms.
6177             OMX_U64 target_ts_delta = m_dec_hfr_fps ? 1000000 / m_dec_hfr_fps : ts_delta;
6178 
6179             // Current frame can be send for rendering if
6180             // (a) current FPS is <=  60
6181             // (b) is the next frame after the frame with TS 0
6182             // (c) is the first frame after seek
6183             // (d) the delta TS b\w two consecutive frames is > 16 ms
6184             // (e) its TS is equal to previous frame TS
6185             // (f) if marked EOS
6186 
6187             if(current_framerate <= (OMX_U32)m_dec_hfr_fps || m_last_rendered_TS == 0 ||
6188                il_buffer->nTimeStamp == 0 || ts_delta >= (OMX_TICKS)target_ts_delta||
6189                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
6190                m_last_rendered_TS = il_buffer->nTimeStamp;
6191             } else {
6192                //mark for droping
6193                buffer->nFilledLen = 0;
6194             }
6195 
6196             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
6197                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
6198                               il_buffer->nTimeStamp,ts_delta);
6199 
6200             //above code makes sure that delta b\w two consecutive frames is not
6201             //greater than 16ms, slow-mo feature, so cap fps to max 60
6202             if (current_framerate > (OMX_U32)m_dec_hfr_fps ) {
6203                 current_framerate = m_dec_hfr_fps;
6204             }
6205         }
6206 
6207         // add current framerate to gralloc meta data
6208         if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && omx_base_address) {
6209             // If valid fps was received, consider the same if less than dec hfr rate
6210             // Otherwise, calculate fps using fbd timestamps
6211             float refresh_rate = (m_fps_received >> 16) ? (m_fps_received >> 16) : current_framerate;
6212 
6213             if (m_dec_hfr_fps)
6214                 refresh_rate = m_dec_hfr_fps;
6215 
6216             DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
6217             OMX_U32 buf_index = buffer - omx_base_address;
6218             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
6219                          UPDATE_REFRESH_RATE, (void*)&refresh_rate);
6220         }
6221 
6222         if (il_buffer) {
6223             log_output_buffers(buffer);
6224             log_cc_output_buffers(il_buffer);
6225             if (dynamic_buf_mode) {
6226                 unsigned int nPortIndex = 0;
6227                 nPortIndex = buffer-omx_base_address;
6228 
6229                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
6230                 // to size of the handle. Do it _after_ log_output_buffers which
6231                 // requires the respective sizes to be accurate.
6232 
6233                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
6234                 buffer->nFilledLen = buffer->nFilledLen ?
6235                         sizeof(struct VideoDecoderOutputMetaData) : 0;
6236 
6237                 //Clear graphic buffer handles in dynamic mode
6238                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
6239                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
6240                     native_buffer[nPortIndex].privatehandle = NULL;
6241                     native_buffer[nPortIndex].nativehandle = NULL;
6242                 } else {
6243                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
6244                     return OMX_ErrorBadParameter;
6245                 }
6246             }
6247             print_omx_buffer("FillBufferDone", buffer);
6248             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
6249         } else {
6250             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
6251             return OMX_ErrorBadParameter;
6252         }
6253     } else {
6254         DEBUG_PRINT_ERROR("NULL m_cb.FillBufferDone");
6255         return OMX_ErrorBadParameter;
6256     }
6257 
6258     return OMX_ErrorNone;
6259 }
6260 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6261 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
6262         OMX_BUFFERHEADERTYPE* buffer)
6263 {
6264     VIDC_TRACE_NAME_HIGH("EBD");
6265     int nBufferIndex = buffer - m_inp_mem_ptr;
6266 
6267     if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
6268         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
6269         return OMX_ErrorBadParameter;
6270     }
6271 
6272     pending_input_buffers--;
6273     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
6274 
6275     if (m_cb.EmptyBufferDone) {
6276         buffer->nFilledLen = 0;
6277         if (input_use_buffer == true) {
6278             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
6279         }
6280 
6281         /* Restore the FD that we over-wrote in ETB */
6282         if (m_input_pass_buffer_fd) {
6283             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
6284         }
6285 
6286         print_omx_buffer("EmptyBufferDone", buffer);
6287         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
6288     }
6289     return OMX_ErrorNone;
6290 }
6291 
async_message_process(void * context,void * message)6292 int omx_vdec::async_message_process (void *context, void* message)
6293 {
6294     omx_vdec* omx = NULL;
6295     struct vdec_msginfo *vdec_msg = NULL;
6296     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
6297     struct v4l2_buffer *v4l2_buf_ptr = NULL;
6298     struct v4l2_plane *plane = NULL;
6299     struct vdec_output_frameinfo *output_respbuf = NULL;
6300     int rc=1;
6301     bool reconfig_event_sent = false;
6302     if (context == NULL || message == NULL) {
6303         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
6304         return -1;
6305     }
6306     vdec_msg = (struct vdec_msginfo *)message;
6307 
6308     omx = reinterpret_cast<omx_vdec*>(context);
6309 
6310     switch (vdec_msg->msgcode) {
6311 
6312         case VDEC_MSG_EVT_HW_ERROR:
6313             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6314                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6315             break;
6316 
6317         case VDEC_MSG_EVT_HW_OVERLOAD:
6318             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6319                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
6320             break;
6321 
6322         case VDEC_MSG_EVT_HW_UNSUPPORTED:
6323             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6324                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
6325             break;
6326 
6327         case VDEC_MSG_RESP_START_DONE:
6328             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6329                     OMX_COMPONENT_GENERATE_START_DONE);
6330             break;
6331 
6332         case VDEC_MSG_RESP_STOP_DONE:
6333             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6334                     OMX_COMPONENT_GENERATE_STOP_DONE);
6335             break;
6336 
6337         case VDEC_MSG_RESP_RESUME_DONE:
6338             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6339                     OMX_COMPONENT_GENERATE_RESUME_DONE);
6340             break;
6341 
6342         case VDEC_MSG_RESP_PAUSE_DONE:
6343             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6344                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
6345             break;
6346 
6347         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
6348             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6349                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
6350             break;
6351         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
6352             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6353                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
6354             break;
6355         case VDEC_MSG_RESP_INPUT_FLUSHED:
6356         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
6357 
6358             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
6359                vdec_msg->msgdata.input_frame_clientdata; */
6360 
6361             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
6362             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
6363                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
6364                 omxhdr = NULL;
6365                 vdec_msg->status_code = VDEC_S_EFATAL;
6366                 break;
6367 
6368             }
6369             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
6370 
6371             if (v4l2_buf_ptr->flags & V4L2_BUF_INPUT_UNSUPPORTED) {
6372                 DEBUG_PRINT_HIGH("Unsupported input");
6373                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6374                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6375             }
6376             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
6377                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
6378                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
6379             }
6380             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6381 
6382                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
6383                 android_atomic_dec(&omx->m_queued_codec_config_count);
6384                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
6385                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
6386                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
6387                     sem_post(&omx->m_safe_flush);
6388                 }
6389             }
6390             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
6391                     OMX_COMPONENT_GENERATE_EBD);
6392             break;
6393         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
6394         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: {
6395            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
6396 
6397            OMX_BUFFERHEADERTYPE  *omx_base_address = omx->m_out_mem_ptr;
6398            vdec_bufferpayload *omx_ptr_outputbuffer = omx->drv_ctx.ptr_outputbuffer;
6399            vdec_output_frameinfo *omx_ptr_respbuffer = omx->drv_ctx.ptr_respbuffer;
6400 
6401            if (omx->client_buffers.is_color_conversion_enabled()) {
6402                omx_base_address = omx->m_intermediate_out_mem_ptr;
6403                omx_ptr_outputbuffer = omx->drv_ctx.ptr_intermediate_outputbuffer;
6404                omx_ptr_respbuffer = omx->drv_ctx.ptr_intermediate_respbuffer;
6405            }
6406 
6407            if (v4l2_buf_ptr == NULL || omx_base_address == NULL ||
6408                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
6409                omxhdr = NULL;
6410                vdec_msg->status_code = VDEC_S_EFATAL;
6411                break;
6412            }
6413            plane = v4l2_buf_ptr->m.planes;
6414            omxhdr = omx_base_address + v4l2_buf_ptr->index;
6415 
6416            if (omxhdr && omxhdr->pOutputPortPrivate &&
6417                ((omxhdr - omx_base_address) < (int)omx->drv_ctx.op_buf.actualcount) &&
6418                    (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
6419                      - omx_ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
6420 
6421                omxhdr->pMarkData = (OMX_PTR)(unsigned long)plane[0].reserved[MSM_VIDC_INPUT_TAG_1];
6422                omxhdr->hMarkTargetComponent = (OMX_HANDLETYPE)(unsigned long)plane[0].reserved[MSM_VIDC_INPUT_TAG_2];
6423 
6424                if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
6425                    omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
6426                    omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
6427                    omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
6428                    omxhdr->nFlags = 0;
6429 
6430                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_EOS) {
6431                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
6432                         //rc = -1;
6433                    }
6434                    if (omxhdr->nFilledLen) {
6435                        omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
6436                    }
6437                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_READONLY) {
6438                         omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
6439                         DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
6440                                         omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
6441                    }
6442 
6443                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
6444                        omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
6445                    }
6446 
6447                    output_respbuf = (struct vdec_output_frameinfo *)\
6448                             omxhdr->pOutputPortPrivate;
6449                    if (!output_respbuf) {
6450                      DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
6451                      return -1;
6452                    }
6453                    output_respbuf->len = vdec_msg->msgdata.output_frame.len;
6454                    output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
6455 
6456                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
6457                        output_respbuf->pic_type = PICTURE_TYPE_I;
6458                        omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
6459                    }
6460                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
6461                        output_respbuf->pic_type = PICTURE_TYPE_P;
6462                    }
6463                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
6464                        output_respbuf->pic_type = PICTURE_TYPE_B;
6465                        omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_BFRAME;
6466                    }
6467 
6468                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_CODECCONFIG)
6469                        omxhdr->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
6470 
6471                    if (vdec_msg->msgdata.output_frame.len) {
6472                        DEBUG_PRINT_LOW("Processing extradata");
6473                        reconfig_event_sent = omx->handle_extradata(omxhdr);
6474 
6475                        if (omx->m_extradata_misr.output_crop_updated) {
6476                            DEBUG_PRINT_LOW("Read FBD crop from output extra data");
6477                            vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_misr.output_crop_rect.nLeft;
6478                            vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_misr.output_crop_rect.nTop;
6479                            vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_misr.output_crop_rect.nWidth;
6480                            vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_misr.output_crop_rect.nHeight;
6481                            vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_misr.output_width;
6482                            vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_misr.output_height;
6483                        }
6484                    }
6485 
6486                    vdec_msg->msgdata.output_frame.bufferaddr =
6487                        omx_ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
6488 
6489                    DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
6490                            " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
6491                            omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
6492                            omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
6493                            vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
6494                            (unsigned int)vdec_msg->msgdata.output_frame.len,
6495                            vdec_msg->msgdata.output_frame.framesize.left,
6496                            vdec_msg->msgdata.output_frame.framesize.top,
6497                            vdec_msg->msgdata.output_frame.framesize.right,
6498                            vdec_msg->msgdata.output_frame.framesize.bottom);
6499 
6500                    /* Post event if resolution OR crop changed */
6501                    /* filled length will be changed if resolution changed */
6502                    /* Crop parameters can be changed even without resolution change */
6503                    if (omxhdr->nFilledLen
6504                        && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
6505                        || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
6506                        || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
6507                        || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
6508                        || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom) )) {
6509 
6510                        DEBUG_PRINT_HIGH("Parameters Changed From: Len: %u, L: %u, T: %u, R: %u, B: %u --> Len: %u, L: %u, T: %u, R: %u, B: %u",
6511                                omx->prev_n_filled_len,
6512                                omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
6513                                omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
6514                                omxhdr->nFilledLen,
6515                                vdec_msg->msgdata.output_frame.framesize.left,
6516                                vdec_msg->msgdata.output_frame.framesize.top,
6517                                vdec_msg->msgdata.output_frame.framesize.right,
6518                                vdec_msg->msgdata.output_frame.framesize.bottom);
6519 
6520                        memcpy(&omx->drv_ctx.frame_size,
6521                                &vdec_msg->msgdata.output_frame.framesize,
6522                                sizeof(struct vdec_framesize));
6523 
6524                        if(!reconfig_event_sent) {
6525                            omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
6526                                            OMX_IndexConfigCommonOutputCrop,
6527                                            OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6528                            reconfig_event_sent = true;
6529                        }
6530                        /* Update C2D with new resolution */
6531                        omx->m_progressive = omx->drv_ctx.interlace == VDEC_InterlaceFrameProgressive;
6532                        if (!omx->client_buffers.update_buffer_req()) {
6533                            DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
6534                        }
6535                    } else if (omxhdr->nFilledLen) {
6536                        /* Check whether interlaced info changed and update C2D */
6537                        int bProgressive = omx->drv_ctx.interlace == VDEC_InterlaceFrameProgressive;
6538                        if (omx->m_progressive != bProgressive) {
6539                            omx->m_progressive = bProgressive;
6540                            if (!omx->client_buffers.update_buffer_req()) {
6541                                DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
6542                            }
6543                        }
6544                    }
6545 
6546                    if (omxhdr->nFilledLen)
6547                        omx->prev_n_filled_len = omxhdr->nFilledLen;
6548 
6549                    if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
6550                        vdec_msg->msgdata.output_frame.bufferaddr)
6551                        memcpy ( omxhdr->pBuffer, (void *)
6552                                ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
6553                                 (unsigned long)vdec_msg->msgdata.output_frame.offset),
6554                                vdec_msg->msgdata.output_frame.len);
6555                } else {
6556                    DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
6557                            (unsigned int)vdec_msg->msgdata.output_frame.len,
6558                            omxhdr->nAllocLen, omx->prev_n_filled_len);
6559                    omxhdr->nFilledLen = 0;
6560                }
6561 
6562                omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
6563                         OMX_COMPONENT_GENERATE_FBD);
6564 
6565             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
6566                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
6567                         OMX_COMPONENT_GENERATE_EOS_DONE);
6568             } else {
6569                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
6570                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6571             }
6572             break;
6573         }
6574         case VDEC_MSG_EVT_CONFIG_CHANGED:
6575             DEBUG_PRINT_HIGH("Port settings changed");
6576             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
6577             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
6578             omx->isPortReconfigInsufficient = vdec_msg->msgdata.output_frame.flags;
6579             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
6580                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6581             break;
6582         default:
6583             break;
6584     }
6585     return rc;
6586 }
6587 
6588 #ifdef USE_GBM
alloc_map_gbm_memory(OMX_U32 w,OMX_U32 h,int dev_fd,struct vdec_gbm * op_buf_gbm_info,int flag)6589 bool omx_vdec::alloc_map_gbm_memory(OMX_U32 w,OMX_U32 h,int dev_fd,
6590                  struct vdec_gbm *op_buf_gbm_info, int flag)
6591 {
6592 
6593     uint32 flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
6594     struct gbm_device *gbm = NULL;
6595     struct gbm_bo *bo = NULL;
6596     int bo_fd = -1, meta_fd = -1;
6597     if (!op_buf_gbm_info || dev_fd < 0 ) {
6598         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
6599         return FALSE;
6600     }
6601 
6602     gbm = gbm_create_device(dev_fd);
6603     if (gbm == NULL) {
6604        DEBUG_PRINT_ERROR("create gbm device failed");
6605        return FALSE;
6606     } else {
6607        DEBUG_PRINT_LOW( "Successfully created gbm device");
6608     }
6609     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC)
6610        flags |= GBM_BO_USAGE_UBWC_ALIGNED_QTI;
6611 
6612     DEBUG_PRINT_LOW("create NV12 gbm_bo with width=%d, height=%d", w, h);
6613     bo = gbm_bo_create(gbm, w, h,GBM_FORMAT_NV12,
6614               flags);
6615 
6616     if (bo == NULL) {
6617       DEBUG_PRINT_ERROR("Create bo failed");
6618       gbm_device_destroy(gbm);
6619       return FALSE;
6620     }
6621 
6622     bo_fd = gbm_bo_get_fd(bo);
6623     if (bo_fd < 0) {
6624       DEBUG_PRINT_ERROR("Get bo fd failed");
6625       gbm_bo_destroy(bo);
6626       gbm_device_destroy(gbm);
6627       return FALSE;
6628     }
6629 
6630     gbm_perform(GBM_PERFORM_GET_METADATA_ION_FD, bo, &meta_fd);
6631     if (meta_fd < 0) {
6632       DEBUG_PRINT_ERROR("Get bo meta fd failed");
6633       gbm_bo_destroy(bo);
6634       gbm_device_destroy(gbm);
6635       return FALSE;
6636     }
6637     op_buf_gbm_info->gbm = gbm;
6638     op_buf_gbm_info->bo = bo;
6639     op_buf_gbm_info->bo_fd = bo_fd;
6640     op_buf_gbm_info->meta_fd = meta_fd;
6641 
6642     DEBUG_PRINT_LOW("allocate gbm bo fd meta fd  %p %d %d",bo,bo_fd,meta_fd);
6643     return TRUE;
6644 }
6645 
free_gbm_memory(struct vdec_gbm * buf_gbm_info)6646 void omx_vdec::free_gbm_memory(struct vdec_gbm *buf_gbm_info)
6647 {
6648     if(!buf_gbm_info) {
6649       DEBUG_PRINT_ERROR(" GBM: free called with invalid fd/allocdata");
6650       return;
6651     }
6652     DEBUG_PRINT_LOW("free gbm bo fd meta fd  %p %d %d",
6653            buf_gbm_info->bo,buf_gbm_info->bo_fd,buf_gbm_info->meta_fd);
6654 
6655     if (buf_gbm_info->bo)
6656        gbm_bo_destroy(buf_gbm_info->bo);
6657     buf_gbm_info->bo = NULL;
6658 
6659     if (buf_gbm_info->gbm)
6660        gbm_device_destroy(buf_gbm_info->gbm);
6661     buf_gbm_info->gbm = NULL;
6662 
6663     buf_gbm_info->bo_fd = -1;
6664     buf_gbm_info->meta_fd = -1;
6665 }
6666 #endif
6667 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)6668 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
6669         OMX_U32 alignment)
6670 {
6671     struct pmem_allocation allocation;
6672     allocation.size = buffer_size;
6673     allocation.align = clip2(alignment);
6674     if (allocation.align < 4096) {
6675         allocation.align = 4096;
6676     }
6677     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
6678         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
6679                 allocation.align, allocation.size);
6680         return false;
6681     }
6682     return true;
6683 }
6684 #endif
6685 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,vdec_ion * ion_info,int flag)6686 bool omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, vdec_ion *ion_info, int flag)
6687 
6688 {
6689     int rc = -EINVAL;
6690     int ion_dev_flag;
6691     struct vdec_ion ion_buf_info;
6692 
6693     if (!ion_info || buffer_size <= 0) {
6694         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
6695         return false;
6696     }
6697 
6698     ion_info->dev_fd = ion_open();
6699     if (ion_info->dev_fd < 0) {
6700         DEBUG_PRINT_ERROR("opening ion device failed with ion_fd = %d", ion_info->dev_fd);
6701         return false;
6702     }
6703 
6704     ion_info->alloc_data.flags = flag;
6705     ion_info->alloc_data.len = buffer_size;
6706 
6707     ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
6708     if (secure_mode && (ion_info->alloc_data.flags & ION_FLAG_SECURE)) {
6709         ion_info->alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID);
6710     }
6711 
6712     /* Use secure display cma heap for obvious reasons. */
6713     if (ion_info->alloc_data.flags & ION_FLAG_CP_BITSTREAM) {
6714         ion_info->alloc_data.heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
6715     }
6716 
6717     rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0,
6718                       ion_info->alloc_data.heap_id_mask, ion_info->alloc_data.flags,
6719                       &ion_info->data_fd);
6720 
6721     if (rc || ion_info->data_fd < 0) {
6722         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
6723         ion_close(ion_info->dev_fd);
6724         ion_info->data_fd = -1;
6725         ion_info->dev_fd = -1;
6726         return false;
6727     }
6728 
6729     DEBUG_PRINT_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
6730                      ion_info->dev_fd, ion_info->data_fd, (unsigned int)ion_info->alloc_data.len,
6731                      (unsigned int)ion_info->alloc_data.flags,
6732                      (unsigned int)ion_info->alloc_data.heap_id_mask);
6733 
6734     return true;
6735 }
6736 
free_ion_memory(struct vdec_ion * buf_ion_info)6737 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
6738 {
6739 
6740     if (!buf_ion_info) {
6741         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
6742         return;
6743     }
6744     DEBUG_PRINT_HIGH("Free ion memory: mmap fd %d ion_dev fd %d len %d flags %#x mask %#x",
6745         buf_ion_info->data_fd, buf_ion_info->dev_fd,
6746         (unsigned int)buf_ion_info->alloc_data.len,
6747         (unsigned int)buf_ion_info->alloc_data.flags,
6748         (unsigned int)buf_ion_info->alloc_data.heap_id_mask);
6749 
6750     if (buf_ion_info->data_fd >= 0) {
6751         close(buf_ion_info->data_fd);
6752         buf_ion_info->data_fd = -1;
6753     }
6754     if (buf_ion_info->dev_fd >= 0) {
6755         ion_close(buf_ion_info->dev_fd);
6756         buf_ion_info->dev_fd = -1;
6757     }
6758 }
6759 
6760 #endif
free_output_buffer_header(bool intermediate)6761 void omx_vdec::free_output_buffer_header(bool intermediate)
6762 {
6763     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
6764     output_use_buffer = false;
6765     ouput_egl_buffers = false;
6766 
6767     OMX_BUFFERHEADERTYPE  **omx_base_address =
6768         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
6769     vdec_bufferpayload **omx_ptr_outputbuffer =
6770         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
6771     vdec_output_frameinfo **omx_ptr_respbuffer =
6772         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
6773     vdec_ion **omx_op_buf_ion_info =
6774         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
6775 #ifdef USE_GBM
6776     vdec_gbm **omx_op_buf_gbm_info =
6777         intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
6778 #endif
6779 
6780     if (*omx_base_address) {
6781         free (*omx_base_address);
6782         *omx_base_address = NULL;
6783     }
6784 
6785     if (m_platform_list) {
6786         free(m_platform_list);
6787         m_platform_list = NULL;
6788     }
6789 
6790     if (*omx_ptr_respbuffer) {
6791         free (*omx_ptr_respbuffer);
6792         *omx_ptr_respbuffer = NULL;
6793     }
6794     if (*omx_ptr_outputbuffer) {
6795         free (*omx_ptr_outputbuffer);
6796         *omx_ptr_outputbuffer = NULL;
6797     }
6798 #ifdef USE_GBM
6799     if (*omx_op_buf_gbm_info) {
6800         DEBUG_PRINT_LOW("Free o/p gbm context");
6801         free(*omx_op_buf_gbm_info);
6802         *omx_op_buf_gbm_info = NULL;
6803     }
6804     if (drv_ctx.gbm_device_fd >= 0) {
6805        DEBUG_PRINT_LOW("Close gbm device");
6806        close(drv_ctx.gbm_device_fd);
6807        drv_ctx.gbm_device_fd = -1;
6808     }
6809 
6810 #elif defined USE_ION
6811     if (*omx_op_buf_ion_info) {
6812         DEBUG_PRINT_LOW("Free o/p ion context");
6813         free(*omx_op_buf_ion_info);
6814         *omx_op_buf_ion_info = NULL;
6815     }
6816 #endif
6817     if (intermediate == false && client_buffers.is_color_conversion_enabled()) {
6818         free_output_buffer_header(true);
6819     }
6820 }
6821 
free_input_buffer_header()6822 void omx_vdec::free_input_buffer_header()
6823 {
6824     input_use_buffer = false;
6825     if (m_inp_mem_ptr) {
6826         DEBUG_PRINT_LOW("Free input pmem Pointer area");
6827         free (m_inp_mem_ptr);
6828         m_inp_mem_ptr = NULL;
6829     }
6830     /* We just freed all the buffer headers, every thing in m_input_free_q,
6831      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
6832     while (m_input_free_q.m_size) {
6833         unsigned long address, p2, id;
6834         m_input_free_q.pop_entry(&address, &p2, &id);
6835     }
6836     while (m_input_pending_q.m_size) {
6837         unsigned long address, p2, id;
6838         m_input_pending_q.pop_entry(&address, &p2, &id);
6839     }
6840     pdest_frame = NULL;
6841     psource_frame = NULL;
6842     if (drv_ctx.ptr_inputbuffer) {
6843         DEBUG_PRINT_LOW("Free Driver Context pointer");
6844         free (drv_ctx.ptr_inputbuffer);
6845         drv_ctx.ptr_inputbuffer = NULL;
6846     }
6847 #ifdef USE_ION
6848     if (drv_ctx.ip_buf_ion_info) {
6849         DEBUG_PRINT_LOW("Free ion context");
6850         free(drv_ctx.ip_buf_ion_info);
6851         drv_ctx.ip_buf_ion_info = NULL;
6852     }
6853 #endif
6854 }
6855 
free_output_extradata_buffer_header()6856 void omx_vdec::free_output_extradata_buffer_header()
6857 {
6858     if (m_client_output_extradata_mem_ptr) {
6859         DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
6860         free(m_client_output_extradata_mem_ptr);
6861         m_client_output_extradata_mem_ptr = NULL;
6862     }
6863 }
6864 
stream_off(OMX_U32 port)6865 int omx_vdec::stream_off(OMX_U32 port)
6866 {
6867     enum v4l2_buf_type btype;
6868     int rc = 0;
6869     enum v4l2_ports v4l2_port = OUTPUT_PORT;
6870     struct v4l2_requestbuffers bufreq;
6871 
6872     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6873         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6874         v4l2_port = OUTPUT_PORT;
6875     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6876         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6877         v4l2_port = CAPTURE_PORT;
6878     } else if (port == OMX_ALL) {
6879         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
6880         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
6881 
6882         if (!rc_input)
6883             return rc_input;
6884         else
6885             return rc_output;
6886     }
6887 
6888     if (!streaming[v4l2_port]) {
6889         // already streamed off, warn and move on
6890         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
6891                 " which is already streamed off", v4l2_port);
6892         return 0;
6893     }
6894 
6895     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
6896 
6897     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
6898     if (rc) {
6899         /*TODO: How to handle this case */
6900         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
6901     } else {
6902         streaming[v4l2_port] = false;
6903     }
6904 
6905     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6906         bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6907     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6908         bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6909     }
6910 
6911     bufreq.memory = V4L2_MEMORY_USERPTR;
6912     bufreq.count = 0;
6913     rc = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6914     if (rc) {
6915         DEBUG_PRINT_ERROR("Failed to release buffers on %d Port", v4l2_port);
6916     }
6917     return rc;
6918 }
6919 
get_buffer_req(vdec_allocatorproperty * buffer_prop)6920 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
6921 {
6922     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6923     struct v4l2_control control;
6924     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
6925     unsigned int final_extra_data_size = 0;
6926     struct v4l2_format fmt;
6927     int ret = 0;
6928     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
6929             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
6930 
6931     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
6932         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6933         fmt.fmt.pix_mp.pixelformat = output_capability;
6934         control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
6935     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
6936         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6937         fmt.fmt.pix_mp.pixelformat = capture_capability;
6938         control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
6939     } else {
6940         eRet = OMX_ErrorBadParameter;
6941     }
6942     if (eRet == OMX_ErrorNone) {
6943         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control);
6944     }
6945     if (ret) {
6946         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
6947         /*TODO: How to handle this case */
6948         eRet = OMX_ErrorInsufficientResources;
6949         return eRet;
6950     }
6951     buffer_prop->actualcount = buffer_prop->mincount = control.value;
6952     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
6953             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
6954 
6955     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
6956 
6957     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
6958         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
6959     DEBUG_PRINT_HIGH("Buffer Size = %d, type = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.type);
6960 
6961     if (ret) {
6962         /*TODO: How to handle this case */
6963         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
6964         eRet = OMX_ErrorInsufficientResources;
6965     } else {
6966         int extra_idx = 0;
6967 
6968         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
6969         buf_size = buffer_prop->buffer_size;
6970         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6971         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6972             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
6973         } else if (extra_idx >= VIDEO_MAX_PLANES) {
6974             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
6975             return OMX_ErrorBadParameter;
6976         }
6977 
6978         default_extra_data_size = VENUS_EXTRADATA_SIZE(
6979                 drv_ctx.video_resolution.frame_height,
6980                 drv_ctx.video_resolution.frame_width);
6981         final_extra_data_size = extra_data_size > default_extra_data_size ?
6982             extra_data_size : default_extra_data_size;
6983 
6984         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
6985             (~(buffer_prop->alignment - 1));
6986 
6987         drv_ctx.extradata_info.count = buffer_prop->actualcount;
6988         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
6989         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
6990         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
6991                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
6992         if (extra_data_size)
6993             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: count(%d) size(%lu)",
6994                 drv_ctx.extradata_info.count, drv_ctx.extradata_info.buffer_size);
6995 
6996         if (in_reconfig) // BufReq will be set to driver when port is disabled
6997             buffer_prop->buffer_size = buf_size;
6998         else if (buf_size != buffer_prop->buffer_size) {
6999             buffer_prop->buffer_size = buf_size;
7000             eRet = set_buffer_req(buffer_prop);
7001         }
7002     }
7003     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
7004             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
7005     return eRet;
7006 }
7007 
set_buffer_req(vdec_allocatorproperty * buffer_prop)7008 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
7009 {
7010     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7011     unsigned buf_size = 0;
7012     struct v4l2_format fmt, c_fmt;
7013     struct v4l2_requestbuffers bufreq;
7014     int ret = 0;
7015     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
7016             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
7017     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7018     if (buf_size != buffer_prop->buffer_size) {
7019         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
7020                 (unsigned int)buffer_prop->buffer_size, buf_size);
7021         eRet = OMX_ErrorBadParameter;
7022     } else {
7023         memset(&fmt, 0x0, sizeof(struct v4l2_format));
7024         memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
7025         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7026         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7027         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
7028 
7029         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7030             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7031             fmt.fmt.pix_mp.pixelformat = output_capability;
7032             DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
7033                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
7034                 fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.pixelformat);
7035             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
7036         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7037             c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7038             c_fmt.fmt.pix_mp.pixelformat = capture_capability;
7039             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
7040             c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
7041             DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
7042                 c_fmt.type, c_fmt.fmt.pix_mp.width, c_fmt.fmt.pix_mp.height,
7043                 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage, c_fmt.fmt.pix_mp.pixelformat);
7044             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
7045         } else {
7046             eRet = OMX_ErrorBadParameter;
7047         }
7048         if (ret) {
7049             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
7050             eRet = OMX_ErrorInsufficientResources;
7051         }
7052 
7053         bufreq.memory = V4L2_MEMORY_USERPTR;
7054         bufreq.count = buffer_prop->actualcount;
7055         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7056             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7057         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7058             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7059         } else {
7060             eRet = OMX_ErrorBadParameter;
7061         }
7062 
7063         if (eRet == OMX_ErrorNone) {
7064             DEBUG_PRINT_LOW("REQBUFS: type %d count %d", bufreq.type, bufreq.count);
7065             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7066         }
7067 
7068         if (ret) {
7069             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
7070             /*TODO: How to handle this case */
7071             eRet = OMX_ErrorInsufficientResources;
7072         } else if (bufreq.count < buffer_prop->actualcount) {
7073             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
7074                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
7075                     buffer_prop->actualcount, bufreq.count);
7076             eRet = OMX_ErrorInsufficientResources;
7077         } else {
7078             if (!client_buffers.update_buffer_req()) {
7079                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
7080                 eRet = OMX_ErrorInsufficientResources;
7081             }
7082         }
7083     }
7084     return eRet;
7085 }
7086 
update_picture_resolution()7087 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
7088 {
7089     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7090     return eRet;
7091 }
7092 
fix_drv_output_format()7093 void omx_vdec::fix_drv_output_format()
7094 {
7095     bool is_dest_format_non_ubwc = (capture_capability != V4L2_PIX_FMT_NV12_UBWC &&
7096                                     capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC);
7097 
7098     if (is_dest_format_non_ubwc){
7099         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
7100             if(is_flexible_format){ // if flexible formats are expected, P010 is set for 10bit cases here
7101                 drv_ctx.output_format = VDEC_YUV_FORMAT_P010_VENUS;
7102                 capture_capability = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
7103             }
7104         } else {
7105             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
7106             capture_capability = V4L2_PIX_FMT_NV12;
7107         }
7108     } else {
7109         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
7110             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
7111             capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
7112         } else {
7113             // 8 bit depth uses the default.
7114             // from 10 bit to 8 bit resolution change case
7115             // we can't rely on default value. we need to re-init these
7116             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
7117             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
7118         }
7119     }
7120     DEBUG_PRINT_LOW("%s: Drv output format %#X Capture capability %#X",
7121                     __func__,
7122                     drv_ctx.output_format,
7123                     capture_capability);
7124 
7125 }
7126 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)7127 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
7128 {
7129     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7130     struct v4l2_format fmt;
7131     struct v4l2_control control;
7132     if (!portDefn) {
7133         DEBUG_PRINT_ERROR("update_portdef: invalid params");
7134         return OMX_ErrorBadParameter;
7135     }
7136     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
7137     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
7138     portDefn->eDomain    = OMX_PortDomainVideo;
7139     memset(&fmt, 0x0, sizeof(struct v4l2_format));
7140     if (0 == portDefn->nPortIndex) {
7141         int ret = 0;
7142         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7143         fmt.fmt.pix_mp.pixelformat = output_capability;
7144         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7145         if (ret) {
7146             DEBUG_PRINT_ERROR("Get Resolution failed");
7147             return OMX_ErrorHardware;
7148         }
7149         drv_ctx.ip_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
7150 
7151         control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
7152         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control);
7153         if (ret) {
7154             DEBUG_PRINT_ERROR("Get input buffer count failed");
7155             return OMX_ErrorHardware;
7156         }
7157         drv_ctx.ip_buf.mincount = control.value;
7158         drv_ctx.ip_buf.actualcount = control.value;
7159 
7160         portDefn->eDir =  OMX_DirInput;
7161         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
7162         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
7163         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
7164         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
7165         portDefn->format.video.eCompressionFormat = eCompressionFormat;
7166         //for input port, always report the fps value set by client,
7167         //to distinguish whether client got valid fps from parser.
7168         portDefn->format.video.xFramerate = m_fps_received;
7169         portDefn->bEnabled   = m_inp_bEnabled;
7170         portDefn->bPopulated = m_inp_bPopulated;
7171     } else if (1 == portDefn->nPortIndex) {
7172         unsigned int buf_size = 0;
7173         int ret = 0;
7174         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7175         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7176         /* Check the return value */
7177 
7178         fmt.fmt.pix_mp.pixelformat = capture_capability;
7179         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7180         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
7181         /* Check the return value */
7182 
7183         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7184         fmt.fmt.pix_mp.pixelformat = capture_capability;
7185         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7186         if (ret) {
7187             DEBUG_PRINT_ERROR("Get Resolution failed");
7188             return OMX_ErrorHardware;
7189         }
7190         drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
7191         if (!client_buffers.update_buffer_req()) {
7192             DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
7193             return OMX_ErrorHardware;
7194         }
7195 
7196         if (!client_buffers.get_buffer_req(buf_size)) {
7197             DEBUG_PRINT_ERROR("update buffer requirements");
7198             return OMX_ErrorHardware;
7199         }
7200         portDefn->nBufferSize = buf_size;
7201         portDefn->eDir =  OMX_DirOutput;
7202         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
7203         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
7204         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7205         if (drv_ctx.frame_rate.fps_denominator > 0)
7206             portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
7207                 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
7208         else {
7209             DEBUG_PRINT_ERROR("Error: Divide by zero");
7210             return OMX_ErrorBadParameter;
7211         }
7212         portDefn->bEnabled   = m_out_bEnabled;
7213         portDefn->bPopulated = m_out_bPopulated;
7214         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
7215             DEBUG_PRINT_ERROR("Error in getting color format");
7216             return OMX_ErrorHardware;
7217         }
7218         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7219         fmt.fmt.pix_mp.pixelformat = capture_capability;
7220     } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
7221         portDefn->nBufferSize = m_client_out_extradata_info.getSize();
7222         portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
7223         portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
7224         portDefn->eDir =  OMX_DirOutput;
7225         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
7226         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
7227         portDefn->format.video.nStride  = drv_ctx.video_resolution.stride;
7228         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
7229         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7230         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
7231         DEBUG_PRINT_LOW(" get_parameter: Port idx %d nBufSize %u nBufCnt %u",
7232                 (int)portDefn->nPortIndex,
7233                 (unsigned int)portDefn->nBufferSize,
7234                 (unsigned int)portDefn->nBufferCountActual);
7235         return eRet;
7236     } else {
7237         portDefn->eDir = OMX_DirMax;
7238         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
7239                 (int)portDefn->nPortIndex);
7240         eRet = OMX_ErrorBadPortIndex;
7241     }
7242     if (in_reconfig) {
7243         m_extradata_misr.output_crop_rect.nLeft = 0;
7244         m_extradata_misr.output_crop_rect.nTop = 0;
7245         m_extradata_misr.output_crop_rect.nWidth = fmt.fmt.pix_mp.width;
7246         m_extradata_misr.output_crop_rect.nHeight = fmt.fmt.pix_mp.height;
7247     }
7248     update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
7249         fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
7250 
7251     portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
7252     portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
7253     portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
7254     portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
7255 
7256     /* OMX client can do tone mapping/post processing, Hence, OMX should produce
7257        YUV buffers in case client needs it. */
7258     if (drv_ctx.idr_only_decoding && portDefn->format.video.eColorFormat == OMX_COLOR_Format16bitRGB565 &&
7259        ((dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10 && (m_thumbnail_yuv_output & THUMBNAIL_YUV420P_10BIT)) ||
7260         (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8 && (m_thumbnail_yuv_output & THUMBNAIL_YUV420P_8BIT)))) {
7261         DEBUG_PRINT_LOW("Change color format to YUV420 planar for thumbnail usecase");
7262         portDefn->format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
7263         if (!client_buffers.set_color_format(portDefn->format.video.eColorFormat)) {
7264             DEBUG_PRINT_ERROR("Set color format failed");
7265             eRet = OMX_ErrorBadParameter;
7266         }
7267     }
7268     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
7269        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
7270            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
7271            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
7272     } else if (portDefn->format.video.eColorFormat == OMX_COLOR_Format16bitRGB565) {
7273            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 32);
7274            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
7275     }
7276     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
7277             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
7278             (unsigned int)portDefn->nPortIndex,
7279             (unsigned int)portDefn->format.video.nFrameWidth,
7280             (unsigned int)portDefn->format.video.nFrameHeight,
7281             (int)portDefn->format.video.nStride,
7282             (unsigned int)portDefn->format.video.nSliceHeight,
7283             (unsigned int)portDefn->format.video.eColorFormat,
7284             (unsigned int)portDefn->nBufferSize,
7285             (unsigned int)portDefn->nBufferCountActual);
7286 
7287     return eRet;
7288 }
7289 
allocate_output_headers(bool intermediate)7290 OMX_ERRORTYPE omx_vdec::allocate_output_headers(bool intermediate)
7291 {
7292     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7293     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
7294     unsigned i = 0;
7295 
7296     OMX_BUFFERHEADERTYPE  **omx_base_address =
7297                       intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
7298     vdec_bufferpayload **omx_ptr_outputbuffer =
7299         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
7300     vdec_output_frameinfo **omx_ptr_respbuffer =
7301         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
7302     vdec_ion **omx_op_buf_ion_info =
7303         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
7304 
7305     if (!*omx_base_address) {
7306         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation, Cnt %d Sz %d",
7307             drv_ctx.op_buf.actualcount, (unsigned int)drv_ctx.op_buf.buffer_size);
7308         int nBufHdrSize        = 0;
7309         int nPlatformEntrySize = 0;
7310         int nPlatformListSize  = 0;
7311         int nPMEMInfoSize = 0;
7312         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
7313         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
7314         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
7315 
7316         nBufHdrSize        = drv_ctx.op_buf.actualcount *
7317             sizeof(OMX_BUFFERHEADERTYPE);
7318         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
7319             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
7320         nPlatformListSize  = drv_ctx.op_buf.actualcount *
7321             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
7322         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
7323             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
7324 
7325         *omx_base_address = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
7326         // Alloc mem for platform specific info
7327         char *pPtr=NULL;
7328         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7329                 nPMEMInfoSize,1);
7330         *omx_ptr_outputbuffer = (struct vdec_bufferpayload *)    \
7331                        calloc (sizeof(struct vdec_bufferpayload),
7332                                drv_ctx.op_buf.actualcount);
7333         *omx_ptr_respbuffer = (struct vdec_output_frameinfo  *)                         \
7334                      calloc (sizeof (struct vdec_output_frameinfo),
7335                              drv_ctx.op_buf.actualcount);
7336         if (!pPtr || !*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
7337             DEBUG_PRINT_ERROR("allocate_output_headers: allocation failed");
7338             free(pPtr); pPtr = NULL;
7339             free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
7340             free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
7341             return OMX_ErrorInsufficientResources;
7342         }
7343 
7344 #ifdef USE_ION
7345         *omx_op_buf_ion_info = (struct vdec_ion * ) \
7346                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
7347         if (!*omx_op_buf_ion_info) {
7348             DEBUG_PRINT_ERROR("Failed to alloc output buffer ion info");
7349             free(pPtr); pPtr = NULL;
7350             free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
7351             free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
7352             return OMX_ErrorInsufficientResources;
7353         }
7354 #endif
7355 
7356         if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
7357             && *omx_ptr_respbuffer) {
7358             bufHdr          =  *omx_base_address;
7359             if (m_platform_list) {
7360                 free(m_platform_list);
7361             }
7362             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7363             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7364                 (((char *) m_platform_list)  + nPlatformListSize);
7365             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7366                 (((char *) m_platform_entry) + nPlatformEntrySize);
7367             pPlatformList   = m_platform_list;
7368             pPlatformEntry  = m_platform_entry;
7369             pPMEMInfo       = m_pmem_info;
7370 
7371             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
7372 
7373             // Settting the entire storage nicely
7374             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
7375                             *omx_base_address,pPlatformEntry);
7376             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
7377             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
7378                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
7379                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
7380                 // Set the values when we determine the right HxW param
7381                 bufHdr->nAllocLen          = 0;
7382                 bufHdr->nFilledLen         = 0;
7383                 bufHdr->pAppPrivate        = NULL;
7384                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
7385                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7386                 pPlatformEntry->entry      = pPMEMInfo;
7387                 // Initialize the Platform List
7388                 pPlatformList->nEntries    = 1;
7389                 pPlatformList->entryList   = pPlatformEntry;
7390                 // Keep pBuffer NULL till vdec is opened
7391                 bufHdr->pBuffer            = NULL;
7392                 pPMEMInfo->offset          =  0;
7393                 pPMEMInfo->pmem_fd = -1;
7394                 bufHdr->pPlatformPrivate = pPlatformList;
7395                 (*omx_ptr_outputbuffer)[i].pmem_fd = -1;
7396 #ifdef USE_ION
7397                 (*omx_op_buf_ion_info)[i].data_fd = -1;
7398                 (*omx_op_buf_ion_info)[i].dev_fd = -1;
7399 #endif
7400                 /*Create a mapping between buffers*/
7401                 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
7402                 (*omx_ptr_respbuffer)[i].client_data = (void *) \
7403                     &(*omx_ptr_outputbuffer)[i];
7404                 // Move the buffer and buffer header pointers
7405                 bufHdr++;
7406                 pPMEMInfo++;
7407                 pPlatformEntry++;
7408                 pPlatformList++;
7409             }
7410         } else {
7411             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7412                               *omx_base_address, pPtr);
7413             if (*omx_base_address) {
7414                 free(*omx_base_address);
7415                 *omx_base_address = NULL;
7416             }
7417             if (pPtr) {
7418                 free(pPtr);
7419                 pPtr = NULL;
7420             }
7421             if (*omx_ptr_outputbuffer) {
7422                 free(*omx_ptr_outputbuffer);
7423                 *omx_ptr_outputbuffer = NULL;
7424             }
7425             if (*omx_ptr_respbuffer) {
7426                 free(*omx_ptr_respbuffer);
7427                 *omx_ptr_respbuffer = NULL;
7428             }
7429 #ifdef USE_ION
7430             if (*omx_op_buf_ion_info) {
7431                 DEBUG_PRINT_LOW("Free o/p ion context");
7432                 free(*omx_op_buf_ion_info);
7433                 *omx_op_buf_ion_info = NULL;
7434             }
7435 #endif
7436             eRet =  OMX_ErrorInsufficientResources;
7437         }
7438     } else {
7439         eRet =  OMX_ErrorInsufficientResources;
7440     }
7441 
7442     if (intermediate == false &&
7443         eRet == OMX_ErrorNone &&
7444         client_buffers.is_color_conversion_enabled()) {
7445         eRet = allocate_output_headers(true);
7446     }
7447 
7448     return eRet;
7449 }
7450 
complete_pending_buffer_done_cbs()7451 void omx_vdec::complete_pending_buffer_done_cbs()
7452 {
7453     unsigned long p1, p2, ident;
7454     omx_cmd_queue tmp_q, pending_bd_q;
7455     pthread_mutex_lock(&m_lock);
7456     // pop all pending GENERATE FDB from ftb queue
7457     while (m_ftb_q.m_size) {
7458         m_ftb_q.pop_entry(&p1,&p2,&ident);
7459         if (ident == OMX_COMPONENT_GENERATE_FBD) {
7460             pending_bd_q.insert_entry(p1,p2,ident);
7461         } else {
7462             tmp_q.insert_entry(p1,p2,ident);
7463         }
7464     }
7465     //return all non GENERATE FDB to ftb queue
7466     while (tmp_q.m_size) {
7467         tmp_q.pop_entry(&p1,&p2,&ident);
7468         m_ftb_q.insert_entry(p1,p2,ident);
7469     }
7470     // pop all pending GENERATE EDB from etb queue
7471     while (m_etb_q.m_size) {
7472         m_etb_q.pop_entry(&p1,&p2,&ident);
7473         if (ident == OMX_COMPONENT_GENERATE_EBD) {
7474             pending_bd_q.insert_entry(p1,p2,ident);
7475         } else {
7476             tmp_q.insert_entry(p1,p2,ident);
7477         }
7478     }
7479     //return all non GENERATE FDB to etb queue
7480     while (tmp_q.m_size) {
7481         tmp_q.pop_entry(&p1,&p2,&ident);
7482         m_etb_q.insert_entry(p1,p2,ident);
7483     }
7484     pthread_mutex_unlock(&m_lock);
7485     // process all pending buffer dones
7486     while (pending_bd_q.m_size) {
7487         pending_bd_q.pop_entry(&p1,&p2,&ident);
7488         switch (ident) {
7489             case OMX_COMPONENT_GENERATE_EBD:
7490                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
7491                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
7492                     omx_report_error ();
7493                 }
7494                 break;
7495 
7496             case OMX_COMPONENT_GENERATE_FBD:
7497                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
7498                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
7499                     omx_report_error ();
7500                 }
7501                 break;
7502         }
7503     }
7504 }
7505 
set_frame_rate(OMX_S64 act_timestamp)7506 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
7507 {
7508     OMX_U32 new_frame_interval = 0;
7509     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
7510             && (llabs(act_timestamp - prev_ts) > 2000 || frm_int == 0)) {
7511         new_frame_interval = client_set_fps ? frm_int : llabs(act_timestamp - prev_ts);
7512         if (new_frame_interval != frm_int || frm_int == 0) {
7513             frm_int = new_frame_interval;
7514             if (frm_int) {
7515                 drv_ctx.frame_rate.fps_numerator = 1e6;
7516                 drv_ctx.frame_rate.fps_denominator = frm_int;
7517                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
7518                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
7519                         (float)drv_ctx.frame_rate.fps_denominator);
7520                 /* We need to report the difference between this FBD and the previous FBD
7521                  * back to the driver for clock scaling purposes. */
7522                 struct v4l2_control control;
7523 
7524                 control.id =  V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
7525                 control.value = drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
7526                 control.value <<= 16;
7527                 control.value |= (0x0000FFFF | drv_ctx.frame_rate.fps_numerator % drv_ctx.frame_rate.fps_denominator);
7528                 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
7529                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7530                    DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
7531                             performance might be affected");
7532                 }
7533             }
7534         }
7535     }
7536     prev_ts = act_timestamp;
7537 }
7538 
convert_color_space_info(OMX_U32 primaries,OMX_U32 transfer,OMX_U32 matrix,ColorAspects * aspects)7539 void omx_vdec::convert_color_space_info(OMX_U32 primaries,
7540     OMX_U32 transfer, OMX_U32 matrix, ColorAspects *aspects)
7541 {
7542     switch (primaries) {
7543         case MSM_VIDC_BT709_5:
7544             aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
7545             break;
7546         case MSM_VIDC_BT470_6_M:
7547             aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
7548             break;
7549         case MSM_VIDC_BT601_6_625:
7550             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
7551             break;
7552         case MSM_VIDC_BT601_6_525:
7553             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
7554             break;
7555         case MSM_VIDC_GENERIC_FILM:
7556             aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
7557             break;
7558         case MSM_VIDC_BT2020:
7559             aspects->mPrimaries = ColorAspects::PrimariesBT2020;
7560             break;
7561         case MSM_VIDC_UNSPECIFIED:
7562             //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
7563         default:
7564             //aspects->mPrimaries = ColorAspects::PrimariesOther;
7565             aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
7566             break;
7567     }
7568 
7569     switch (transfer) {
7570         case MSM_VIDC_TRANSFER_BT709_5:
7571         case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
7572             aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7573             break;
7574         case MSM_VIDC_TRANSFER_BT_470_6_M:
7575             aspects->mTransfer = ColorAspects::TransferGamma22;
7576             break;
7577         case MSM_VIDC_TRANSFER_BT_470_6_BG:
7578             aspects->mTransfer = ColorAspects::TransferGamma28;
7579             break;
7580         case MSM_VIDC_TRANSFER_SMPTE_240M:
7581             aspects->mTransfer = ColorAspects::TransferSMPTE240M;
7582             break;
7583         case MSM_VIDC_TRANSFER_LINEAR:
7584             aspects->mTransfer = ColorAspects::TransferLinear;
7585             break;
7586         case MSM_VIDC_TRANSFER_IEC_61966:
7587             aspects->mTransfer = ColorAspects::TransferXvYCC;
7588             break;
7589         case MSM_VIDC_TRANSFER_BT_1361:
7590             aspects->mTransfer = ColorAspects::TransferBT1361;
7591             break;
7592         case MSM_VIDC_TRANSFER_SRGB:
7593             aspects->mTransfer = ColorAspects::TransferSRGB;
7594             break;
7595         case MSM_VIDC_TRANSFER_SMPTE_ST2084:
7596             aspects->mTransfer = ColorAspects::TransferST2084;
7597             break;
7598         case MSM_VIDC_TRANSFER_HLG:
7599             aspects->mTransfer = ColorAspects::TransferHLG;
7600             break;
7601         default:
7602             //aspects->mTransfer = ColorAspects::TransferOther;
7603             aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
7604             break;
7605     }
7606 
7607     switch (matrix) {
7608         case MSM_VIDC_MATRIX_BT_709_5:
7609             aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
7610             break;
7611         case MSM_VIDC_MATRIX_FCC_47:
7612             aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
7613             break;
7614         case MSM_VIDC_MATRIX_601_6_625:
7615         case MSM_VIDC_MATRIX_601_6_525:
7616             aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
7617             break;
7618         case MSM_VIDC_MATRIX_SMPTE_240M:
7619             aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
7620             break;
7621         case MSM_VIDC_MATRIX_BT_2020:
7622             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
7623             break;
7624         case MSM_VIDC_MATRIX_BT_2020_CONST:
7625             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
7626             break;
7627         default:
7628             //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
7629             aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
7630             break;
7631     }
7632 }
7633 
handle_color_space_info(void * data)7634 bool omx_vdec::handle_color_space_info(void *data)
7635 {
7636     ColorAspects tempAspects;
7637     memset(&tempAspects, 0x0, sizeof(ColorAspects));
7638     ColorAspects *aspects = &tempAspects;
7639 
7640     switch(output_capability) {
7641         case V4L2_PIX_FMT_MPEG2:
7642             {
7643                 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
7644                 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
7645 
7646                 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
7647                  * understand this code */
7648 
7649                 if (seqdisp_payload && seqdisp_payload->color_descp) {
7650 
7651                     convert_color_space_info(seqdisp_payload->color_primaries,
7652                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
7653                             aspects);
7654                     /* MPEG2 seqdisp payload doesn't give range info. Hence assing the value
7655                      * set by client */
7656                     aspects->mRange = m_client_color_space.sAspects.mRange;
7657                     m_disp_hor_size = seqdisp_payload->disp_width;
7658                     m_disp_vert_size = seqdisp_payload->disp_height;
7659                 }
7660             }
7661             break;
7662         case V4L2_PIX_FMT_H264:
7663         case V4L2_PIX_FMT_HEVC:
7664             {
7665                 struct msm_vidc_vui_display_info_payload *display_info_payload;
7666                 OMX_U32 range;
7667                 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
7668 
7669                 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
7670 
7671                 if (display_info_payload->video_signal_present_flag) {
7672                     range = display_info_payload->video_full_range_flag;
7673                     aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
7674                     if (display_info_payload->color_description_present_flag) {
7675                         convert_color_space_info(display_info_payload->color_primaries,
7676                                 display_info_payload->transfer_char,
7677                                 display_info_payload->matrix_coeffs,
7678                                 aspects);
7679                     }
7680                 }
7681             }
7682             break;
7683         case V4L2_PIX_FMT_VP8:
7684             {
7685                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
7686                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
7687                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
7688                  * to understand this code */
7689 
7690                 if (vpx_color_space_payload->color_space == 0) {
7691                     aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
7692                     aspects->mRange = ColorAspects::RangeLimited;
7693                     aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7694                     aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
7695                 } else {
7696                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
7697                     break;
7698                 }
7699             }
7700             break;
7701         case V4L2_PIX_FMT_VP9:
7702             {
7703                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
7704                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
7705                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
7706                  * to understand this code */
7707 
7708                 switch(vpx_color_space_payload->color_space) {
7709                     case MSM_VIDC_CS_BT_601:
7710                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
7711                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7712                         aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
7713                         aspects->mRange = m_client_color_space.sAspects.mRange;
7714                         break;
7715                     case MSM_VIDC_CS_BT_709:
7716                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
7717                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7718                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
7719                         aspects->mRange = m_client_color_space.sAspects.mRange;
7720                         break;
7721                     case MSM_VIDC_CS_SMPTE_170:
7722                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
7723                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7724                         aspects->mPrimaries =  ColorAspects::PrimariesBT601_6_525;
7725                         aspects->mRange = m_client_color_space.sAspects.mRange;
7726                         break;
7727                     case MSM_VIDC_CS_SMPTE_240:
7728                         aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
7729                         aspects->mTransfer = ColorAspects::TransferSMPTE240M;
7730                         aspects->mPrimaries =  ColorAspects::PrimariesBT601_6_525;
7731                         aspects->mRange = m_client_color_space.sAspects.mRange;
7732                         break;
7733                     case MSM_VIDC_CS_BT_2020:
7734                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
7735                         aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
7736                         aspects->mPrimaries = ColorAspects::PrimariesBT2020;
7737                         aspects->mRange = m_client_color_space.sAspects.mRange;
7738                         break;
7739                     case MSM_VIDC_CS_RESERVED:
7740                         aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
7741                         aspects->mTransfer = ColorAspects::TransferOther;
7742                         aspects->mPrimaries = ColorAspects::PrimariesOther;
7743                         aspects->mRange = m_client_color_space.sAspects.mRange;
7744                         break;
7745                     case MSM_VIDC_CS_RGB:
7746                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
7747                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
7748                         aspects->mPrimaries = ColorAspects::PrimariesOther;
7749                         aspects->mRange = m_client_color_space.sAspects.mRange;
7750                         break;
7751                     default:
7752                         break;
7753                 }
7754             }
7755             break;
7756         default:
7757             break;
7758     }
7759 
7760     print_debug_color_aspects(aspects, "Bitstream");
7761 
7762     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
7763             m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
7764             m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
7765             m_internal_color_space.sAspects.mRange != aspects->mRange) {
7766         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
7767 
7768         DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
7769         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
7770         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
7771 
7772         post_event(OMX_CORE_OUTPUT_PORT_INDEX,
7773                 OMX_QTIIndexConfigDescribeColorAspects,
7774                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
7775         return true;
7776     }
7777     return false;
7778 }
7779 
handle_content_light_level_info(void * data)7780 bool omx_vdec::handle_content_light_level_info(void* data)
7781 {
7782     struct msm_vidc_content_light_level_sei_payload *light_level_payload =
7783         (msm_vidc_content_light_level_sei_payload*)(data);
7784 
7785     if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
7786         (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
7787         m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
7788         m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
7789         return true;
7790     }
7791     return false;
7792 }
7793 
handle_mastering_display_color_info(void * data)7794 bool omx_vdec::handle_mastering_display_color_info(void* data)
7795 {
7796     struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
7797         (msm_vidc_mastering_display_colour_sei_payload*)(data);
7798     HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
7799     bool internal_disp_changed_flag = false;
7800 
7801     internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
7802         (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[0]);
7803     internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
7804         (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[1]);
7805     internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
7806         (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[2]);
7807 
7808     internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
7809         (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
7810 
7811     /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
7812        requires it in cd/m2, so dividing by 10000 and rounding the value after division
7813     */
7814     uint16_t max_display_luminance_cd_m2 =
7815         static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
7816     internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
7817         (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
7818 
7819     if (internal_disp_changed_flag) {
7820         hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[0];
7821         hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[0];
7822         hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[1];
7823         hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[1];
7824         hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[2];
7825         hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[2];
7826         hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
7827         hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
7828 
7829         hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
7830         hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
7831     }
7832 
7833     return internal_disp_changed_flag;
7834 }
7835 
convert_color_aspects_to_metadata(ColorAspects & aspects,ColorMetaData & color_mdata)7836 void omx_vdec::convert_color_aspects_to_metadata(ColorAspects& aspects, ColorMetaData &color_mdata)
7837 {
7838     PrimariesMap::const_iterator primary_it = mPrimariesMap.find(aspects.mPrimaries);
7839     TransferMap::const_iterator transfer_it = mTransferMap.find(aspects.mTransfer);
7840     MatrixCoeffMap::const_iterator matrix_it = mMatrixCoeffMap.find(aspects.mMatrixCoeffs);
7841     RangeMap::const_iterator range_it = mColorRangeMap.find(aspects.mRange);
7842 
7843     if (primary_it == mPrimariesMap.end()) {
7844         DEBUG_PRINT_LOW("No mapping for %d in PrimariesMap, defaulting to unspecified", aspects.mPrimaries);
7845         color_mdata.colorPrimaries = (ColorPrimaries)2;
7846     } else {
7847         color_mdata.colorPrimaries = primary_it->second;
7848     }
7849 
7850     if (transfer_it == mTransferMap.end()) {
7851         DEBUG_PRINT_LOW("No mapping for %d in TransferMap, defaulting to unspecified", aspects.mTransfer);
7852         color_mdata.transfer = (GammaTransfer)2;
7853     } else {
7854         color_mdata.transfer = transfer_it->second;
7855     }
7856 
7857     if (matrix_it == mMatrixCoeffMap.end()) {
7858         DEBUG_PRINT_LOW("No mapping for %d in MatrixCoeffMap, defaulting to unspecified", aspects.mMatrixCoeffs);
7859         color_mdata.matrixCoefficients = (MatrixCoEfficients)2;
7860     } else {
7861         color_mdata.matrixCoefficients = matrix_it->second;
7862     }
7863 
7864     if (range_it == mColorRangeMap.end()) {
7865         DEBUG_PRINT_LOW("No mapping for %d in ColorRangeMap, defaulting to limited range", aspects.mRange);
7866         color_mdata.range = Range_Limited;
7867     } else {
7868         color_mdata.range = range_it->second;
7869     }
7870 }
7871 
convert_hdr_info_to_metadata(HDRStaticInfo & hdr_info,ColorMetaData & color_mdata)7872 void omx_vdec::convert_hdr_info_to_metadata(HDRStaticInfo& hdr_info, ColorMetaData &color_mdata)
7873 {
7874     HDRStaticInfo::Type1 zero_hdr_info;
7875     MasteringDisplay& mastering_display = color_mdata.masteringDisplayInfo;
7876     ContentLightLevel& content_light = color_mdata.contentLightLevel;
7877     bool hdr_info_enabled = false;
7878     memset(&zero_hdr_info, 0, sizeof(HDRStaticInfo::Type1));
7879     hdr_info_enabled = (memcmp(&hdr_info, &zero_hdr_info, sizeof(HDRStaticInfo::Type1))!= 0);
7880 
7881     if (hdr_info_enabled) {
7882         mastering_display.colorVolumeSEIEnabled = true;
7883         mastering_display.primaries.rgbPrimaries[0][0] = hdr_info.sType1.mR.x;
7884         mastering_display.primaries.rgbPrimaries[0][1] = hdr_info.sType1.mR.y;
7885         mastering_display.primaries.rgbPrimaries[1][0] = hdr_info.sType1.mG.x;
7886         mastering_display.primaries.rgbPrimaries[1][1] = hdr_info.sType1.mG.y;
7887         mastering_display.primaries.rgbPrimaries[2][0] = hdr_info.sType1.mB.x;
7888         mastering_display.primaries.rgbPrimaries[2][1] = hdr_info.sType1.mB.y;
7889         mastering_display.primaries.whitePoint[0] = hdr_info.sType1.mW.x;
7890         mastering_display.primaries.whitePoint[1] = hdr_info.sType1.mW.y;
7891         mastering_display.maxDisplayLuminance = hdr_info.sType1.mMaxDisplayLuminance;
7892         mastering_display.minDisplayLuminance = hdr_info.sType1.mMinDisplayLuminance;
7893         content_light.lightLevelSEIEnabled = true;
7894         content_light.maxContentLightLevel = hdr_info.sType1.mMaxContentLightLevel;
7895         content_light.minPicAverageLightLevel = hdr_info.sType1.mMaxFrameAverageLightLevel;
7896     }
7897 
7898 }
7899 
get_preferred_color_aspects(ColorAspects & preferredColorAspects)7900 void omx_vdec::get_preferred_color_aspects(ColorAspects& preferredColorAspects)
7901 {
7902     // For VPX, use client-color if specified.
7903     // For the rest, try to use the stream-color if present
7904     bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
7905          output_capability == V4L2_PIX_FMT_VP9);
7906 
7907     const ColorAspects &preferredColor = preferClientColor ?
7908         m_client_color_space.sAspects : m_internal_color_space.sAspects;
7909     const ColorAspects &defaultColor = preferClientColor ?
7910         m_internal_color_space.sAspects : m_client_color_space.sAspects;
7911 
7912     if ((m_client_color_space.sAspects.mPrimaries == ColorAspects::PrimariesBT2020) && (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8)) {
7913         m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesBT709_5;
7914         m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5;
7915     }
7916 
7917     preferredColorAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
7918         preferredColor.mPrimaries : defaultColor.mPrimaries;
7919     preferredColorAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
7920         preferredColor.mTransfer : defaultColor.mTransfer;
7921     preferredColorAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
7922         preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
7923     preferredColorAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
7924         preferredColor.mRange : defaultColor.mRange;
7925 
7926 }
7927 
get_preferred_hdr_info(HDRStaticInfo & finalHDRInfo)7928 void omx_vdec::get_preferred_hdr_info(HDRStaticInfo& finalHDRInfo)
7929 {
7930     bool preferClientHDR = (output_capability == V4L2_PIX_FMT_VP9);
7931 
7932     const HDRStaticInfo &preferredHDRInfo = preferClientHDR ?
7933         m_client_hdr_info.sInfo : m_internal_hdr_info.sInfo;
7934     const HDRStaticInfo &defaultHDRInfo = preferClientHDR ?
7935         m_internal_hdr_info.sInfo : m_client_hdr_info.sInfo;
7936     finalHDRInfo.sType1.mR = ((preferredHDRInfo.sType1.mR.x != 0) && (preferredHDRInfo.sType1.mR.y != 0)) ?
7937         preferredHDRInfo.sType1.mR : defaultHDRInfo.sType1.mR;
7938     finalHDRInfo.sType1.mG = ((preferredHDRInfo.sType1.mG.x != 0) && (preferredHDRInfo.sType1.mG.y != 0)) ?
7939         preferredHDRInfo.sType1.mG : defaultHDRInfo.sType1.mG;
7940     finalHDRInfo.sType1.mB = ((preferredHDRInfo.sType1.mB.x != 0) && (preferredHDRInfo.sType1.mB.y != 0)) ?
7941         preferredHDRInfo.sType1.mB : defaultHDRInfo.sType1.mB;
7942     finalHDRInfo.sType1.mW = ((preferredHDRInfo.sType1.mW.x != 0) && (preferredHDRInfo.sType1.mW.y != 0)) ?
7943         preferredHDRInfo.sType1.mW : defaultHDRInfo.sType1.mW;
7944     finalHDRInfo.sType1.mMaxDisplayLuminance = (preferredHDRInfo.sType1.mMaxDisplayLuminance != 0) ?
7945         preferredHDRInfo.sType1.mMaxDisplayLuminance : defaultHDRInfo.sType1.mMaxDisplayLuminance;
7946     finalHDRInfo.sType1.mMinDisplayLuminance = (preferredHDRInfo.sType1.mMinDisplayLuminance != 0) ?
7947         preferredHDRInfo.sType1.mMinDisplayLuminance : defaultHDRInfo.sType1.mMinDisplayLuminance;
7948     finalHDRInfo.sType1.mMaxContentLightLevel = (preferredHDRInfo.sType1.mMaxContentLightLevel != 0) ?
7949         preferredHDRInfo.sType1.mMaxContentLightLevel : defaultHDRInfo.sType1.mMaxContentLightLevel;
7950     finalHDRInfo.sType1.mMaxFrameAverageLightLevel = (preferredHDRInfo.sType1.mMaxFrameAverageLightLevel != 0) ?
7951         preferredHDRInfo.sType1.mMaxFrameAverageLightLevel : defaultHDRInfo.sType1.mMaxFrameAverageLightLevel;
7952 }
7953 
set_histogram_metadata(private_handle_t * private_handle)7954 void omx_vdec::set_histogram_metadata(private_handle_t *private_handle)
7955 {
7956     if (m_hist_metadata.stat_len != VIDEO_HISTOGRAM_STATS_SIZE || !private_handle)
7957         return;
7958 
7959     m_hist_metadata.display_width = m_extradata_misr.output_crop_rect.nWidth;
7960     m_hist_metadata.display_height = m_extradata_misr.output_crop_rect.nHeight;
7961     m_hist_metadata.decode_width = m_extradata_misr.output_width;
7962     m_hist_metadata.decode_height = m_extradata_misr.output_height;
7963 
7964     if (setMetaData(private_handle, SET_VIDEO_HISTOGRAM_STATS, (void*)&m_hist_metadata))
7965         DEBUG_PRINT_HIGH("failed to set histogram video stats");
7966 
7967     m_hist_metadata.stat_len = 0;
7968 }
7969 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)7970 bool omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
7971 {
7972     OMX_OTHER_EXTRADATATYPE *p_client_extra = NULL;
7973     OMX_TICKS time_stamp = 0;
7974     unsigned long consumed_len = 0;
7975     OMX_U32 recovery_sei_flags = 1;
7976     int enable = OMX_InterlaceFrameProgressive;
7977     bool internal_hdr_info_changed_flag = false;
7978     bool reconfig_event_sent = false;
7979     char *p_extradata = NULL;
7980     OMX_OTHER_EXTRADATATYPE *data = NULL;
7981     ColorMetaData color_mdata;
7982     private_handle_t *private_handle = NULL;
7983 
7984     OMX_BUFFERHEADERTYPE  *omx_base_address =
7985         client_buffers.is_color_conversion_enabled()?
7986                             m_intermediate_out_mem_ptr:m_out_mem_ptr;
7987     memset(&color_mdata, 0, sizeof(color_mdata));
7988 
7989     int buf_index = p_buf_hdr - omx_base_address;
7990     if (buf_index >= drv_ctx.extradata_info.count) {
7991         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
7992                 buf_index, drv_ctx.extradata_info.count);
7993         return reconfig_event_sent;
7994     }
7995     if (m_enable_android_native_buffers)
7996         private_handle = (private_handle_t *)native_buffer[buf_index].privatehandle;
7997 
7998     if (!drv_ctx.extradata_info.ion[buf_index].uaddr) {
7999         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.ion[buf_index].uaddr");
8000         return reconfig_event_sent;
8001     }
8002 
8003     if (m_client_output_extradata_mem_ptr &&
8004         m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
8005         p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
8006     }
8007 
8008     p_extradata = drv_ctx.extradata_info.ion[buf_index].uaddr;
8009     if (p_extradata && p_client_extra) {
8010         memcpy(p_client_extra, p_extradata, drv_ctx.extradata_info.buffer_size);
8011         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
8012     }
8013 
8014     m_extradata_misr.output_crop_updated = OMX_FALSE;
8015     data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
8016     if (data) {
8017         bool is_hdr10_plus_info_found = false;
8018         while ((((consumed_len + sizeof(struct OMX_OTHER_EXTRADATATYPE)) <
8019                 drv_ctx.extradata_info.buffer_size) && ((consumed_len + data->nSize) <
8020                 drv_ctx.extradata_info.buffer_size))
8021                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
8022             DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
8023             switch ((unsigned long)data->eType) {
8024                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
8025                     struct msm_vidc_interlace_payload *payload;
8026                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
8027                     if (payload) {
8028                         DEBUG_PRINT_LOW("Interlace format %#x", payload->format);
8029                         enable = OMX_InterlaceFrameProgressive;
8030                         is_mbaff = payload->format & MSM_VIDC_INTERLACE_FRAME_MBAFF;
8031                         switch (payload->format & 0x1F) {
8032                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
8033                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
8034                                 break;
8035                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
8036                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
8037                                 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
8038                                 break;
8039                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
8040                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
8041                                 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
8042                                 break;
8043                             case MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST:
8044                                 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
8045                                 enable = OMX_InterlaceFrameTopFieldFirst;
8046                                 break;
8047                             case MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST:
8048                                 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
8049                                 enable = OMX_InterlaceFrameBottomFieldFirst;
8050                                 break;
8051                             default:
8052                                 DEBUG_PRINT_LOW("default case - set to progressive");
8053                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
8054                         }
8055                     }
8056 
8057                     if (m_enable_android_native_buffers) {
8058                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d",
8059                                         payload->format, enable);
8060 
8061                         setMetaData(private_handle, PP_PARAM_INTERLACED, (void*)&enable);
8062                     }
8063                     break;
8064                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
8065                     struct msm_vidc_ts_payload *time_stamp_payload;
8066                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
8067                     time_stamp = time_stamp_payload->timestamp_lo;
8068                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
8069                     p_buf_hdr->nTimeStamp = time_stamp;
8070                     break;
8071                 case MSM_VIDC_EXTRADATA_INDEX:
8072                     int *etype;
8073                     etype  = (int *)(void *)data->data;
8074                     if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
8075                         struct msm_vidc_output_crop_payload *output_crop_payload;
8076                         output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
8077                         if (output_crop_payload) {
8078                             m_extradata_misr.output_crop_rect.nLeft = output_crop_payload->left;
8079                             m_extradata_misr.output_crop_rect.nTop = output_crop_payload->top;
8080                             m_extradata_misr.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
8081                             m_extradata_misr.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
8082                             m_extradata_misr.output_width = output_crop_payload->width;
8083                             m_extradata_misr.output_height = output_crop_payload->height;
8084                             m_extradata_misr.output_crop_updated = OMX_TRUE;
8085                             for(unsigned int m=0; m<output_crop_payload->misr_info[0].misr_set; m++) {
8086                             DEBUG_PRINT_HIGH("MISR0: %x %x %x %x\n",
8087                                 output_crop_payload->misr_info[0].misr_dpb_luma[m],
8088                                 output_crop_payload->misr_info[0].misr_dpb_chroma[m],
8089                                 output_crop_payload->misr_info[0].misr_opb_luma[m],
8090                                 output_crop_payload->misr_info[0].misr_opb_chroma[m]);
8091                             }
8092                             for(unsigned int m=0; m< output_crop_payload->misr_info[1].misr_set; m++) {
8093                                 DEBUG_PRINT_HIGH("MISR1: %x %x %x %x\n",
8094                                                  output_crop_payload->misr_info[1].misr_dpb_luma[m],
8095                                                  output_crop_payload->misr_info[1].misr_dpb_chroma[m],
8096                                                  output_crop_payload->misr_info[1].misr_opb_luma[m],
8097                                                  output_crop_payload->misr_info[1].misr_opb_chroma[m]);
8098                             }
8099                             memcpy(m_extradata_misr.misr_info, output_crop_payload->misr_info, 2 * sizeof(msm_vidc_misr_info));
8100                         }
8101                     }
8102                     break;
8103                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
8104                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
8105                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
8106                     recovery_sei_flags = recovery_sei_payload->flags;
8107                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
8108                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8109                         DEBUG_PRINT_HIGH("***************************************************");
8110                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8111                         DEBUG_PRINT_HIGH("***************************************************");
8112                     }
8113                     break;
8114                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
8115                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
8116                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
8117                     reconfig_event_sent |= handle_color_space_info((void *)data->data);
8118                     break;
8119                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
8120                     if(output_capability == V4L2_PIX_FMT_HEVC) {
8121                         struct msm_vidc_stream_userdata_payload* userdata_payload = (struct msm_vidc_stream_userdata_payload*)data->data;
8122                         // Remove the size of type from msm_vidc_stream_userdata_payload
8123                         uint32_t payload_len = data->nDataSize - sizeof(userdata_payload->type);
8124                         if ((data->nDataSize < sizeof(userdata_payload->type)) ||
8125                             (payload_len > HDR_DYNAMIC_META_DATA_SZ)) {
8126                             DEBUG_PRINT_ERROR("Invalid User extradata size %u for HDR10+", data->nDataSize);
8127                         } else {
8128 #if HDR10_SETMETADATA_ENABLE
8129                             color_mdata.dynamicMetaDataValid = true;
8130                             color_mdata.dynamicMetaDataLen = payload_len;
8131                             memcpy(color_mdata.dynamicMetaDataPayload, userdata_payload->data, payload_len);
8132                             DEBUG_PRINT_HIGH("Copied %u bytes of HDR10+ extradata", payload_len);
8133 #else
8134                             if(!is_hdr10_plus_info_found) {
8135                                store_hevc_hdr10plusinfo(payload_len, userdata_payload);
8136                                is_hdr10_plus_info_found = true;
8137                             }
8138 #endif
8139                         }
8140                     }
8141                     break;
8142                 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
8143                     internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data);
8144                     break;
8145                 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
8146                     internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data);
8147                     break;
8148                 case MSM_VIDC_EXTRADATA_HDR_HIST:
8149                     if (data->nDataSize != VIDEO_HISTOGRAM_STATS_SIZE) {
8150                         DEBUG_PRINT_ERROR("Invalid HDR histogram extradata size %u", data->nDataSize);
8151                         m_hist_metadata.stat_len = 0;
8152                     } else {
8153                         memcpy(m_hist_metadata.stats_info, data->data, VIDEO_HISTOGRAM_STATS_SIZE);
8154                         m_hist_metadata.stat_len = VIDEO_HISTOGRAM_STATS_SIZE;
8155                         m_hist_metadata.frame_type = (p_buf_hdr->nFlags & OMX_BUFFERFLAG_SYNCFRAME) ? QD_SYNC_FRAME : 0;
8156                     }
8157                     break;
8158                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
8159                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
8160                 case MSM_VIDC_EXTRADATA_FRAME_QP:
8161                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
8162                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
8163                 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
8164                     // skip unused extra data
8165                     break;
8166                 default:
8167                     // skip unrecognized extra data instead of return error.
8168                     DEBUG_PRINT_LOW("Unrecognized extradata");
8169                     break;
8170             }
8171             consumed_len += data->nSize;
8172             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
8173         }
8174 
8175         if(internal_hdr_info_changed_flag) {
8176             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
8177             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
8178             if(!reconfig_event_sent) {
8179                 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
8180                 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8181                            OMX_QTIIndexConfigDescribeHDRColorInfo,
8182                            OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8183                 reconfig_event_sent = true;
8184             }
8185         }
8186 
8187         if (m_enable_android_native_buffers) {
8188                 ColorAspects final_color_aspects;
8189                 HDRStaticInfo final_hdr_info;
8190                 memset(&final_color_aspects, 0, sizeof(final_color_aspects));
8191                 memset(&final_hdr_info, 0, sizeof(final_hdr_info));
8192                 get_preferred_color_aspects(final_color_aspects);
8193 
8194                 /* For VP8, always set the metadata on gralloc handle to 601-LR */
8195                 if (output_capability == V4L2_PIX_FMT_VP8) {
8196                     final_color_aspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
8197                     final_color_aspects.mRange = ColorAspects::RangeLimited;
8198                     final_color_aspects.mTransfer = ColorAspects::TransferSMPTE170M;
8199                     final_color_aspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
8200                 }
8201                 get_preferred_hdr_info(final_hdr_info);
8202 #if HDR10_SETMETADATA_ENABLE
8203                 convert_hdr_info_to_metadata(final_hdr_info, color_mdata);
8204                 convert_hdr10plusinfo_to_metadata(p_buf_hdr->pMarkData, color_mdata);
8205                 remove_hdr10plusinfo_using_cookie(p_buf_hdr->pMarkData);
8206                 convert_color_aspects_to_metadata(final_color_aspects, color_mdata);
8207                 print_debug_hdr_color_info_mdata(&color_mdata);
8208                 print_debug_hdr10plus_metadata(color_mdata);
8209                 setMetaData(private_handle, COLOR_METADATA, (void*)&color_mdata);
8210 #endif
8211                 set_histogram_metadata(private_handle);
8212         }
8213 
8214     }
8215 
8216     return reconfig_event_sent;
8217 }
8218 
enable_extradata(OMX_U64 requested_extradata)8219 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata)
8220 {
8221     OMX_ERRORTYPE ret = OMX_ErrorNone;
8222     struct v4l2_control control;
8223     if (m_state != OMX_StateLoaded) {
8224         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
8225         return OMX_ErrorIncorrectStateOperation;
8226     }
8227     DEBUG_PRINT_HIGH("NOTE: requested[%u]", (unsigned int)requested_extradata);
8228 
8229 
8230     // Extradata default is enabled ib kernel by default
8231     control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
8232     control.value = requested_extradata;
8233     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
8234         DEBUG_PRINT_HIGH("Failed to enable extradata %#llX", requested_extradata);
8235     } else {
8236         DEBUG_PRINT_INFO("Extradata %#llX is enabled successfully.", requested_extradata);
8237     }
8238 
8239     ret = get_buffer_req(&drv_ctx.op_buf);
8240 
8241     return ret;
8242 }
8243 
allocate_desc_buffer(OMX_U32 index)8244 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
8245 {
8246     OMX_ERRORTYPE eRet = OMX_ErrorNone;
8247     if (index >= drv_ctx.ip_buf.actualcount) {
8248         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
8249         return OMX_ErrorInsufficientResources;
8250     }
8251     if (m_desc_buffer_ptr == NULL) {
8252         m_desc_buffer_ptr = (desc_buffer_hdr*) \
8253                     calloc( (sizeof(desc_buffer_hdr)),
8254                             drv_ctx.ip_buf.actualcount);
8255         if (m_desc_buffer_ptr == NULL) {
8256             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
8257             return OMX_ErrorInsufficientResources;
8258         }
8259     }
8260 
8261     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
8262     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
8263         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
8264         return OMX_ErrorInsufficientResources;
8265     }
8266 
8267     return eRet;
8268 }
8269 
insert_demux_addr_offset(OMX_U32 address_offset)8270 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
8271 {
8272     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
8273     if (m_demux_entries < 8192) {
8274         m_demux_offsets[m_demux_entries++] = address_offset;
8275     }
8276     return;
8277 }
8278 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)8279 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
8280 {
8281     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
8282     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
8283     OMX_U32 index = 0;
8284 
8285     m_demux_entries = 0;
8286 
8287     while (index < bytes_to_parse) {
8288         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8289                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
8290                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8291                  (buf[index+2] == 0x01)) ) {
8292             //Found start code, insert address offset
8293             insert_demux_addr_offset(index);
8294             if (buf[index+2] == 0x01) // 3 byte start code
8295                 index += 3;
8296             else                      //4 byte start code
8297                 index += 4;
8298         } else
8299             index++;
8300     }
8301     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
8302     return;
8303 }
8304 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)8305 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
8306 {
8307     //fix this, handle 3 byte start code, vc1 terminator entry
8308     OMX_U8 *p_demux_data = NULL;
8309     OMX_U32 desc_data = 0;
8310     OMX_U32 start_addr = 0;
8311     OMX_U32 nal_size = 0;
8312     OMX_U32 suffix_byte = 0;
8313     OMX_U32 demux_index = 0;
8314     OMX_U32 buffer_index = 0;
8315 
8316     if (m_desc_buffer_ptr == NULL) {
8317         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
8318         return OMX_ErrorBadParameter;
8319     }
8320 
8321     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
8322     if (buffer_index > drv_ctx.ip_buf.actualcount) {
8323         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
8324         return OMX_ErrorBadParameter;
8325     }
8326 
8327     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
8328 
8329     if ( ((OMX_U8*)p_demux_data == NULL) ||
8330             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
8331         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
8332         return OMX_ErrorBadParameter;
8333     } else {
8334         for (; demux_index < m_demux_entries; demux_index++) {
8335             desc_data = 0;
8336             start_addr = m_demux_offsets[demux_index];
8337             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
8338                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
8339             } else {
8340                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
8341             }
8342             if (demux_index < (m_demux_entries - 1)) {
8343                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
8344             } else {
8345                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
8346             }
8347             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
8348                     (unsigned int)start_addr,
8349                     (unsigned int)suffix_byte,
8350                     (unsigned int)nal_size,
8351                     (unsigned int)demux_index);
8352             desc_data = (start_addr >> 3) << 1;
8353             desc_data |= (start_addr & 7) << 21;
8354             desc_data |= suffix_byte << 24;
8355 
8356             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8357             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
8358             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8359             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8360 
8361             p_demux_data += 16;
8362         }
8363         //Add zero word to indicate end of descriptors
8364         memset(p_demux_data, 0, sizeof(OMX_U32));
8365 
8366         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
8367         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
8368     }
8369     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
8370     m_demux_entries = 0;
8371     DEBUG_PRINT_LOW("Demux table complete!");
8372     return OMX_ErrorNone;
8373 }
8374 
enable_color_conversion(bool enable)8375 void omx_vdec::allocate_color_convert_buf::enable_color_conversion(bool enable) {
8376     if (!omx) {
8377         DEBUG_PRINT_HIGH("Invalid omx_vdec");
8378         return;
8379     }
8380 
8381     if (!omx->in_reconfig)
8382         this->enabled = enable;
8383 
8384     omx->c2d_enable_pending = enable;
8385 }
8386 
allocate_color_convert_buf()8387 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
8388 {
8389     enabled = false;
8390     client_buffers_disabled = false;
8391     omx = NULL;
8392     init_members();
8393     ColorFormat = OMX_COLOR_FormatMax;
8394     dest_format = YCbCr420P;
8395     m_c2d_width = 0;
8396     m_c2d_height = 0;
8397 
8398     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][-1] =
8399                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
8400     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][VDEC_CODECTYPE_MVC] =
8401                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
8402     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_UBWC][-1] =
8403                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
8404     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_TP10_UBWC][-1] =
8405                      QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
8406     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_P010_VENUS][-1] =
8407                      QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus;
8408 
8409     mMapOutput2Convert.insert( {
8410             {VDEC_YUV_FORMAT_NV12, NV12_128m},
8411             {VDEC_YUV_FORMAT_NV12_UBWC, NV12_UBWC},
8412             {VDEC_YUV_FORMAT_NV12_TP10_UBWC, TP10_UBWC},
8413             {VDEC_YUV_FORMAT_P010_VENUS, YCbCr420_VENUS_P010},
8414         });
8415 }
8416 
set_vdec_client(void * client)8417 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
8418 {
8419     omx = reinterpret_cast<omx_vdec*>(client);
8420 }
8421 
init_members()8422 void omx_vdec::allocate_color_convert_buf::init_members()
8423 {
8424     allocated_count = 0;
8425     buffer_size_req = 0;
8426     buffer_alignment_req = 0;
8427     m_c2d_width = m_c2d_height = 0;
8428     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
8429     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
8430     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
8431     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
8432 #ifdef USE_ION
8433     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
8434 #endif
8435     for (int i = 0; i < MAX_COUNT; i++)
8436         pmem_fd[i] = -1;
8437 }
8438 
update_buffer_req()8439 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
8440 {
8441     bool status = true;
8442     unsigned int src_size = 0, destination_size = 0;
8443     unsigned int height, width;
8444     struct v4l2_format fmt;
8445     bool is_interlaced = false;
8446     OMX_COLOR_FORMATTYPE drv_color_format;
8447 
8448     if (!omx) {
8449         DEBUG_PRINT_ERROR("Invalid client in color convert");
8450         return false;
8451     }
8452     if (!enabled) {
8453         DEBUG_PRINT_HIGH("No color conversion required");
8454         return true;
8455     }
8456     pthread_mutex_lock(&omx->c_lock);
8457 
8458     ColorSubMapping::const_iterator
8459         found =  mMapOutput2Convert.find(omx->drv_ctx.output_format);
8460     if (found == mMapOutput2Convert.end()) {
8461         DEBUG_PRINT_HIGH("%s: Could not find the color conversion "
8462                          "mapping for %#X. Setting to default NV12",
8463                          __func__, omx->drv_ctx.output_format);
8464         src_format = NV12_128m;
8465     } else {
8466         src_format = (ColorConvertFormat) found->second;;
8467     }
8468 
8469     memset(&fmt, 0x0, sizeof(struct v4l2_format));
8470     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8471     fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
8472     ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
8473     width = fmt.fmt.pix_mp.width;
8474     height =  fmt.fmt.pix_mp.height;
8475 
8476     bool resolution_upgrade = (height > m_c2d_height ||
8477             width > m_c2d_width);
8478     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12)
8479         is_interlaced = omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
8480     if (resolution_upgrade) {
8481         // resolution upgraded ? ensure we are yet to allocate;
8482         // failing which, c2d buffers will never be reallocated and bad things will happen
8483         if (allocated_count > 0) {
8484             DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
8485                     allocated_count);
8486             status = false;
8487         }
8488     }
8489 
8490     if (status != false) {
8491         if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
8492             (ColorFormat != OMX_COLOR_FormatYUV420Planar &&
8493              ColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
8494              ColorFormat != OMX_COLOR_Format16bitRGB565 &&
8495              ColorFormat != (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)) {
8496             DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
8497             status = false;
8498         } else {
8499             ColorSubMapping::const_iterator
8500                 found =  mMapOutput2Convert.find(
8501                                                  omx->drv_ctx.output_format);
8502             if (found == mMapOutput2Convert.end()) {
8503                 src_format = NV12_128m;
8504             } else {
8505                 src_format = (ColorConvertFormat) found->second;;
8506             }
8507 
8508             if (c2dcc.isPropChanged(width, is_interlaced ? (height+1)/2 : height,
8509                                     width, height, src_format, dest_format, 0, 0)) {
8510                 DEBUG_PRINT_INFO("C2D: Set Resolution, Interlace(%s) Conversion(%#X -> %#X)"
8511                                  " src(%dX%d) dest(%dX%d)",
8512                                  is_interlaced ? "true": "false",
8513                                  src_format, dest_format, width,
8514                                  is_interlaced ? (height+1)/2 : height,
8515                                  width, height);
8516                 status = c2dcc.setResolution(width,
8517                                              is_interlaced ? (height+1)/2 : height,
8518                                              width, height,
8519                                              src_format, dest_format,
8520                                              0, 0);
8521                 if (status) {
8522                     src_size = c2dcc.getBuffSize(C2D_INPUT);
8523                     destination_size = c2dcc.getBuffSize(C2D_OUTPUT);
8524 
8525                     if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
8526                         !destination_size) {
8527                         DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
8528                                           "driver size %u destination size %d",
8529                                           src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
8530                                           destination_size);
8531                         buffer_size_req = 0;
8532                         // TODO: make this fatal. Driver is not supposed to quote size
8533                         //  smaller than what C2D needs !!
8534                     } else {
8535                         buffer_size_req = destination_size;
8536                         m_c2d_height = height;
8537                         m_c2d_width = width;
8538                     }
8539                 }
8540             }
8541         }
8542     }
8543     pthread_mutex_unlock(&omx->c_lock);
8544     return status;
8545 }
8546 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)8547 bool omx_vdec::allocate_color_convert_buf::set_color_format(
8548         OMX_COLOR_FORMATTYPE dest_color_format)
8549 {
8550     bool status = true, drv_colorformat_c2d_enable = false;
8551     bool dest_color_format_c2d_enable = false;
8552     OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
8553     if (!omx) {
8554         DEBUG_PRINT_ERROR("Invalid client in color convert");
8555         return false;
8556     }
8557     pthread_mutex_lock(&omx->c_lock);
8558     status = get_color_format (drv_color_format);
8559 
8560     drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
8561         (drv_color_format != (OMX_COLOR_FORMATTYPE)
8562                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
8563         (drv_color_format != (OMX_COLOR_FORMATTYPE)
8564                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed) &&
8565         (drv_color_format != (OMX_COLOR_FORMATTYPE)
8566                 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
8567 
8568     dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
8569             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
8570             (dest_color_format != (OMX_COLOR_FORMATTYPE)
8571                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
8572 
8573     if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
8574         DEBUG_PRINT_LOW("Enabling C2D");
8575         if (dest_color_format == OMX_COLOR_FormatYUV420Planar ||
8576             dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar ||
8577             dest_color_format == OMX_COLOR_Format16bitRGB565) {
8578             ColorFormat = dest_color_format;
8579             if (dest_color_format == OMX_COLOR_FormatYUV420Planar) {
8580                    dest_format = YCbCr420P;
8581             } else if( dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar) {
8582                     dest_format = YCbCr420SP;
8583             } else if(dest_color_format == OMX_COLOR_Format16bitRGB565) {
8584                     dest_format = RGB565;
8585             } else {
8586                    dest_format = NV12_128m;
8587             }
8588             enable_color_conversion(true);
8589         } else {
8590             DEBUG_PRINT_ERROR("Unsupported output color format for c2d (%d)",
8591                               dest_color_format);
8592             status = false;
8593             enable_color_conversion(false);
8594         }
8595     } else {
8596         enable_color_conversion(false);
8597     }
8598     pthread_mutex_unlock(&omx->c_lock);
8599     return status;
8600 }
8601 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)8602 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
8603 (OMX_BUFFERHEADERTYPE *bufadd)
8604 {
8605     if (!omx) {
8606         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8607         return NULL;
8608     }
8609     if (!is_color_conversion_enabled())
8610         return bufadd;
8611 
8612     OMX_BUFFERHEADERTYPE  *omx_base_address =
8613               is_color_conversion_enabled()?
8614                     omx->m_intermediate_out_mem_ptr:omx->m_out_mem_ptr;
8615 
8616     unsigned index = 0;
8617     index = bufadd - omx_base_address;
8618     if (index < omx->drv_ctx.op_buf.actualcount) {
8619         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
8620         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
8621 
8622         omx->m_out_mem_ptr[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
8623         omx->m_out_mem_ptr[index].nTimeStamp = bufadd->nTimeStamp;
8624         bool status = false;
8625         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
8626             pthread_mutex_lock(&omx->c_lock);
8627 
8628             DEBUG_PRINT_INFO("C2D: Start color convertion");
8629             cache_invalidate(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd);
8630             status = c2dcc.convertC2D(
8631                              omx->drv_ctx.ptr_intermediate_outputbuffer[index].pmem_fd,
8632                              bufadd->pBuffer, bufadd->pBuffer,
8633                              omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
8634                              omx->m_out_mem_ptr[index].pBuffer,
8635                              omx->m_out_mem_ptr[index].pBuffer);
8636             cache_invalidate(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd);
8637             if (!status) {
8638                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
8639                 m_out_mem_ptr_client[index].nFilledLen = 0;
8640                 omx->m_out_mem_ptr[index].nFilledLen = 0;
8641                 pthread_mutex_unlock(&omx->c_lock);
8642                 return &omx->m_out_mem_ptr[index];
8643             } else {
8644                 unsigned int filledLen = 0;
8645                 c2dcc.getBuffFilledLen(C2D_OUTPUT, filledLen);
8646                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
8647                 omx->m_out_mem_ptr[index].nFilledLen = filledLen;
8648             }
8649             pthread_mutex_unlock(&omx->c_lock);
8650         } else {
8651             m_out_mem_ptr_client[index].nFilledLen = 0;
8652             omx->m_out_mem_ptr[index].nFilledLen = 0;
8653         }
8654         return &omx->m_out_mem_ptr[index];
8655     }
8656     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
8657     return NULL;
8658 }
8659 
get_buffer_req(unsigned int & buffer_size)8660     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
8661 (unsigned int &buffer_size)
8662 {
8663     bool status = true;
8664     pthread_mutex_lock(&omx->c_lock);
8665      /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
8666         always uses VideoNativeMetadata and OMX recives buffer type as
8667         grallocsource via storeMetaDataInBuffers_l API. The buffer_size
8668         will be communicated to frameworks via IndexParamPortdefinition. */
8669     if (!enabled)
8670         buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
8671                       omx->drv_ctx.op_buf.buffer_size;
8672     else {
8673         buffer_size = c2dcc.getBuffSize(C2D_OUTPUT);
8674     }
8675     pthread_mutex_unlock(&omx->c_lock);
8676     return status;
8677 }
8678 
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)8679 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
8680         OMX_U32 buffer_size, OMX_U32 actual_count)
8681 {
8682     OMX_U32 expectedSize = enabled ? buffer_size_req : omx->dynamic_buf_mode ?
8683             sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
8684     if (buffer_size < expectedSize) {
8685         DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
8686                 buffer_size, expectedSize);
8687         return OMX_ErrorBadParameter;
8688     }
8689     if (actual_count < omx->drv_ctx.op_buf.mincount) {
8690         DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
8691                 actual_count, omx->drv_ctx.op_buf.mincount);
8692         return OMX_ErrorBadParameter;
8693     }
8694 
8695     if (enabled) {
8696         // disallow changing buffer size/count while we have active allocated buffers
8697         if (allocated_count > 0) {
8698             DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
8699                     buffer_size_req, buffer_size, allocated_count);
8700             return OMX_ErrorInvalidState;
8701         }
8702 
8703         buffer_size_req = buffer_size;
8704     } else {
8705         if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
8706             omx->drv_ctx.op_buf.buffer_size = buffer_size;
8707         }
8708     }
8709 
8710     omx->drv_ctx.op_buf.actualcount = actual_count;
8711     omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
8712 
8713     return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
8714 }
8715 
is_component_secure()8716 bool omx_vdec::is_component_secure()
8717 {
8718     return secure_mode;
8719 }
8720 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)8721 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
8722 {
8723     bool status = true;
8724     if (!enabled) {
8725         for (auto& x: mMapOutput2DriverColorFormat) {
8726             DecColorMapping::const_iterator
8727                 found = mMapOutput2DriverColorFormat.find(omx->drv_ctx.output_format);
8728             if (found == mMapOutput2DriverColorFormat.end()) {
8729                 status = false;
8730             } else {
8731                 ColorSubMapping::const_iterator
8732                     subFound = found->second.find(omx->drv_ctx.decoder_format);
8733                 if (subFound == found->second.end()) {
8734                     dest_color_format = (OMX_COLOR_FORMATTYPE)
8735                                              found->second.find(-1)->second;
8736                 } else {
8737                     dest_color_format = (OMX_COLOR_FORMATTYPE) subFound->second;
8738                 }
8739             }
8740         }
8741     } else {
8742         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
8743             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
8744             ColorFormat == OMX_COLOR_Format16bitRGB565 ||
8745             ColorFormat == (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
8746             dest_color_format = ColorFormat;
8747         } else {
8748             status = false;
8749         }
8750     }
8751     return status;
8752 }
8753 
send_codec_config()8754 void omx_vdec::send_codec_config()
8755 {
8756     if (codec_config_flag) {
8757         unsigned long p1 = 0, p2 = 0;
8758         unsigned long p3 = 0, p4 = 0;
8759         unsigned long ident = 0, ident2 = 0;
8760         pthread_mutex_lock(&m_lock);
8761         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
8762         while (m_etb_q.m_size) {
8763             m_etb_q.pop_entry(&p1,&p2,&ident);
8764             if (ident == OMX_COMPONENT_GENERATE_ETB) {
8765                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8766                     while (m_ftb_q.m_size) {
8767                         m_ftb_q.pop_entry(&p3,&p4,&ident2);
8768                         if (ident2 == OMX_COMPONENT_GENERATE_FTB) {
8769                             pthread_mutex_unlock(&m_lock);
8770                             if (fill_this_buffer_proxy((OMX_HANDLETYPE)p3,\
8771                                         (OMX_BUFFERHEADERTYPE *)p4) != OMX_ErrorNone) {
8772                                 DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
8773                                 omx_report_error ();
8774                             }
8775                             pthread_mutex_lock(&m_lock);
8776                         } else if (ident2 == OMX_COMPONENT_GENERATE_FBD) {
8777                             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p3);
8778                         }
8779                     }
8780                     pthread_mutex_unlock(&m_lock);
8781                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
8782                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
8783                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
8784                         omx_report_error ();
8785                     }
8786                     pthread_mutex_lock(&m_lock);
8787                 } else {
8788                     pending_input_buffers++;
8789                     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
8790                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
8791                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
8792                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
8793                 }
8794             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
8795                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
8796                         (OMX_BUFFERHEADERTYPE *)p1);
8797                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
8798             }
8799         }
8800         pthread_mutex_unlock(&m_lock);
8801     }
8802 }
8803 
perf_control()8804 omx_vdec::perf_control::perf_control()
8805 {
8806     m_perf_control_enable = 0;
8807     m_perf_lib = NULL;
8808     m_perf_handle = 0;
8809     m_perf_lock_acquire = NULL;
8810     m_perf_lock_release = NULL;
8811 }
8812 
~perf_control()8813 omx_vdec::perf_control::~perf_control()
8814 {
8815     if (!m_perf_control_enable)
8816         return;
8817 
8818     if (m_perf_handle && m_perf_lock_release) {
8819         m_perf_lock_release(m_perf_handle);
8820         DEBUG_PRINT_LOW("perflock released");
8821     }
8822     if (m_perf_lib) {
8823         dlclose(m_perf_lib);
8824     }
8825 }
8826 
perf_lock_acquire()8827 int omx_vdec::perf_control::perf_lock_acquire()
8828 {
8829     int arg[2];
8830     if (!m_perf_control_enable)
8831         return 0;
8832 
8833     if (!m_perf_lib) {
8834         DEBUG_PRINT_ERROR("no perf control library");
8835         return -1;
8836     }
8837     if (!m_perf_lock_acquire) {
8838         DEBUG_PRINT_ERROR("NULL perflock acquire");
8839         return -1;
8840     }
8841     if (m_perf_handle) {
8842         DEBUG_PRINT_LOW("perflock already acquired");
8843         return 0;
8844     }
8845     DEBUG_PRINT_HIGH("perflock acquire");
8846     arg[0] = MPCTLV3_VIDEO_DECODE_PB_HINT;
8847     arg[1] = 1;
8848     m_perf_handle = m_perf_lock_acquire(0, 0, arg, sizeof(arg) / sizeof(int));
8849     if (m_perf_handle < 0) {
8850         DEBUG_PRINT_ERROR("perflock acquire failed with error %d", m_perf_handle);
8851         m_perf_handle = 0;
8852         return -1;
8853     }
8854     return 0;
8855 }
8856 
perf_lock_release()8857 void omx_vdec::perf_control::perf_lock_release()
8858 {
8859     if (!m_perf_control_enable)
8860         return;
8861 
8862     if (!m_perf_lib) {
8863         DEBUG_PRINT_ERROR("no perf control library");
8864         return;
8865     }
8866     if (!m_perf_lock_release) {
8867         DEBUG_PRINT_ERROR("NULL perflock release");
8868         return;
8869     }
8870     if (!m_perf_handle) {
8871         DEBUG_PRINT_LOW("perflock already released");
8872         return;
8873     }
8874     DEBUG_PRINT_HIGH("perflock release");
8875     m_perf_lock_release(m_perf_handle);
8876     m_perf_handle = 0;
8877 }
8878 
load_perf_library()8879 bool omx_vdec::perf_control::load_perf_library()
8880 {
8881     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
8882 
8883     if (!m_perf_control_enable) {
8884         DEBUG_PRINT_HIGH("perf control is not enabled");
8885         return false;
8886     }
8887     if (m_perf_lib) {
8888         DEBUG_PRINT_HIGH("perf lib already opened");
8889         return true;
8890     }
8891 
8892     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
8893         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
8894         goto handle_err;
8895     }
8896 
8897     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
8898         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
8899         goto handle_err;
8900     } else {
8901         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
8902         if (m_perf_lock_acquire == NULL) {
8903             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
8904             goto handle_err;
8905         }
8906         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
8907         if (m_perf_lock_release == NULL) {
8908             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
8909             goto handle_err;
8910         }
8911     }
8912     return true;
8913 
8914 handle_err:
8915     if (m_perf_lib) {
8916         dlclose(m_perf_lib);
8917     }
8918     m_perf_lib = NULL;
8919     m_perf_lock_acquire = NULL;
8920     m_perf_lock_release = NULL;
8921     return false;
8922 }
8923 
8924 //static
describeColorFormat(OMX_PTR pParam)8925 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam)
8926 {
8927 #ifndef FLEXYUV_SUPPORTED
8928     return OMX_ErrorUndefined;
8929 #else
8930 
8931     if (pParam == NULL) {
8932         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
8933         return OMX_ErrorBadParameter;
8934     }
8935 
8936     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
8937 
8938     MediaImage *img = &(params->sMediaImage);
8939     switch(params->eColorFormat) {
8940         case static_cast <OMX_COLOR_FORMATTYPE> (QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m):
8941         {
8942             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
8943             img->mNumPlanes = 3;
8944             // mWidth and mHeight represent the W x H of the largest plane
8945             // In our case, this happens to be the Stride x Scanlines of Y plane
8946             img->mWidth = params->nFrameWidth;
8947             img->mHeight = params->nFrameHeight;
8948             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
8949             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
8950             img->mBitDepth = 8;
8951             //Plane 0 (Y)
8952             img->mPlane[MediaImage::Y].mOffset = 0;
8953             img->mPlane[MediaImage::Y].mColInc = 1;
8954             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
8955             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
8956             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
8957             //Plane 1 (U)
8958             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
8959             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
8960             img->mPlane[MediaImage::U].mRowInc =
8961                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
8962             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
8963             img->mPlane[MediaImage::U].mVertSubsampling = 2;
8964             //Plane 2 (V)
8965             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
8966             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
8967             img->mPlane[MediaImage::V].mRowInc =
8968                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
8969             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
8970             img->mPlane[MediaImage::V].mVertSubsampling = 2;
8971             break;
8972         }
8973 
8974         case OMX_COLOR_FormatYUV420Planar:
8975         case OMX_COLOR_FormatYUV420SemiPlanar:
8976             // We need not describe the standard OMX linear formats as these are
8977             // understood by client. Fail this deliberately to let client fill-in
8978             return OMX_ErrorUnsupportedSetting;
8979 
8980         default:
8981             // Rest all formats which are non-linear cannot be described
8982             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
8983             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
8984             return OMX_ErrorNone;
8985     };
8986 
8987     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
8988     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
8989     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
8990     for (size_t i = 0; i < img->mNumPlanes; ++i) {
8991         DEBUG_PRINT_LOW("  Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
8992                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
8993     }
8994     return OMX_ErrorNone;
8995 #endif //FLEXYUV_SUPPORTED
8996 }
8997 
prefetch_buffers(unsigned long prefetch_count,unsigned long prefetch_size,unsigned ioctl_code,unsigned ion_flag)8998 bool omx_vdec::prefetch_buffers(unsigned long prefetch_count,
8999         unsigned long prefetch_size, unsigned ioctl_code, unsigned ion_flag)
9000 {
9001     struct ion_prefetch_data prefetch_data;
9002     struct ion_prefetch_regions regions;
9003     __u64 sizes[prefetch_count];
9004     int rc, ion_fd = ion_open();
9005     if (ion_fd < 0) {
9006         DEBUG_PRINT_ERROR("%s: Ion fd open failed : %d", __func__, ion_fd);
9007         return false;
9008     }
9009 
9010     DEBUG_PRINT_HIGH("%s: prefetch_count : %lu, prefetch_size : %lu, ioctl : %u",
9011             __func__, prefetch_count, prefetch_size, ioctl_code);
9012     for (uint32_t i = 0; i < prefetch_count; i++) {
9013         sizes[i] = prefetch_size;
9014     }
9015 
9016     regions.nr_sizes = prefetch_count;
9017     regions.sizes = (__u64) sizes;
9018     regions.vmid = ion_flag;
9019 
9020     prefetch_data.nr_regions = 1;
9021     prefetch_data.regions = (__u64) &regions;
9022     prefetch_data.heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
9023 
9024     rc = ioctl(ion_fd, ioctl_code, &prefetch_data);
9025     if (rc) {
9026         DEBUG_PRINT_ERROR("%s: Prefetch ioctl failed ioctl : %u, rc : %d, errno : %d",
9027                 __func__, ioctl_code, rc, errno);
9028         rc = false;
9029     } else {
9030         rc = true;
9031     }
9032 
9033     close(ion_fd);
9034     return rc;
9035 }
9036 
store_vp9_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)9037 bool omx_vdec::store_vp9_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
9038 {
9039     struct hdr10plusInfo metadata;
9040 
9041     if (!hdr10plusdata) {
9042         DEBUG_PRINT_ERROR("hdr10plus info not present");
9043         return false;
9044     }
9045 
9046     if (hdr10plusdata->nParamSize > MAX_HDR10PLUSINFO_SIZE ||
9047             hdr10plusdata->nParamSize < 1) {
9048         DEBUG_PRINT_ERROR("Invalid hdr10plus metadata size %u", hdr10plusdata->nParamSize);
9049         return false;
9050     }
9051 
9052     if (output_capability != V4L2_PIX_FMT_VP9) {
9053         DEBUG_PRINT_ERROR("DescribeHDR10PlusInfoParams is not supported for %d codec",
9054             output_capability);
9055         return false;
9056     }
9057 
9058     memset(&metadata, 0, sizeof(struct hdr10plusInfo));
9059     metadata.nSize = hdr10plusdata->nSize;
9060     metadata.nVersion = hdr10plusdata->nVersion;
9061     metadata.nPortIndex = hdr10plusdata->nPortIndex;
9062     metadata.nParamSize = hdr10plusdata->nParamSize;
9063     metadata.nParamSizeUsed = hdr10plusdata->nParamSizeUsed;
9064     memcpy(metadata.payload, hdr10plusdata->nValue , hdr10plusdata->nParamSizeUsed);
9065     metadata.is_new = true;
9066 
9067     /*
9068      * For the first setconfig, set the timestamp as zero. For
9069      * the remaining, set the timestamp equal to previous
9070      * etb timestamp + 1 to know this hdr10plus data arrived
9071      * after previous etb.
9072      */
9073     if (m_etb_count) {
9074         metadata.timestamp = m_etb_timestamp + 1;
9075     }
9076 
9077     pthread_mutex_lock(&m_hdr10pluslock);
9078     DEBUG_PRINT_LOW("add hdr10plus info to the list with timestamp %lld and size %u",
9079         metadata.timestamp, metadata.nParamSizeUsed);
9080     m_hdr10pluslist.push_back(metadata);
9081     pthread_mutex_unlock(&m_hdr10pluslock);
9082 
9083     return true;
9084 }
9085 
store_hevc_hdr10plusinfo(uint32_t payload_size,msm_vidc_stream_userdata_payload * hdr10plusdata)9086 bool omx_vdec::store_hevc_hdr10plusinfo(uint32_t payload_size,
9087     msm_vidc_stream_userdata_payload *hdr10plusdata)
9088 {
9089     struct hdr10plusInfo metadata;
9090 
9091     if (!hdr10plusdata) {
9092         DEBUG_PRINT_ERROR("hdr10plus info not present");
9093         return false;
9094     }
9095 
9096     if (payload_size > MAX_HDR10PLUSINFO_SIZE ||
9097             payload_size < 1) {
9098         DEBUG_PRINT_ERROR("Invalid hdr10plus metadata size %u", payload_size);
9099         return false;
9100     }
9101 
9102     if (output_capability != V4L2_PIX_FMT_HEVC) {
9103         DEBUG_PRINT_ERROR("msm_vidc_stream_userdata_payload is not supported for %d codec",
9104             output_capability);
9105         return false;
9106     }
9107 
9108     memset(&metadata, 0, sizeof(struct hdr10plusInfo));
9109     metadata.nParamSizeUsed = payload_size;
9110     memcpy(metadata.payload, hdr10plusdata->data , payload_size);
9111     metadata.is_new = false;
9112     if (m_etb_count) {
9113         metadata.timestamp = m_etb_timestamp + 1;
9114     }
9115 
9116     pthread_mutex_lock(&m_hdr10pluslock);
9117     DEBUG_PRINT_LOW("add hevc hdr10plus info to the list with size %u", payload_size);
9118     m_hdr10pluslist.push_back(metadata);
9119     pthread_mutex_unlock(&m_hdr10pluslock);
9120 
9121     return true;
9122 }
9123 
update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR markdata,OMX_TICKS timestamp)9124 void omx_vdec::update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR markdata, OMX_TICKS timestamp)
9125 {
9126     std::list<hdr10plusInfo>::reverse_iterator iter;
9127     unsigned int found = 0;
9128     unsigned int cookie = (unsigned int)(unsigned long)markdata;
9129     bool is_list_empty = false;
9130 
9131     if (output_capability != V4L2_PIX_FMT_VP9 &&
9132         output_capability != V4L2_PIX_FMT_HEVC)
9133         return;
9134 
9135     pthread_mutex_lock(&m_hdr10pluslock);
9136     is_list_empty = m_hdr10pluslist.empty();
9137     pthread_mutex_unlock(&m_hdr10pluslock);
9138 
9139     if (is_list_empty) {
9140         DEBUG_PRINT_HIGH("update_hdr10plusinfo_cookie_using_timestamp: hdr10plusinfo list is empty!");
9141         return;
9142     }
9143     /*
9144      * look for the hdr10plus data which has timestamp nearest and
9145      * lower than the etb timestamp, we should not take the
9146      * hdr10plus data which has the timestamp greater than etb timestamp.
9147      */
9148     pthread_mutex_lock(&m_hdr10pluslock);
9149     iter = m_hdr10pluslist.rbegin();
9150     while (iter != m_hdr10pluslist.rend()) {
9151         if (iter->timestamp <= timestamp && iter->is_new) {
9152             found++;
9153             if (found == 1) {
9154                 iter->cookie = cookie;
9155                 iter->is_new = false;
9156                 DEBUG_PRINT_LOW("Cookie value %u stored in hdr10plus list with timestamp %lld, size %u",
9157                     iter->cookie, iter->timestamp, iter->nParamSizeUsed);
9158             }
9159         }
9160         iter++;
9161     }
9162     pthread_mutex_unlock(&m_hdr10pluslock);
9163 
9164     if(found > 1)
9165         DEBUG_PRINT_HIGH("Multiple hdr10plus data not expected. Continue with the latest");
9166 }
9167 
convert_hdr10plusinfo_to_metadata(OMX_PTR markdata,ColorMetaData & colorData)9168 void omx_vdec::convert_hdr10plusinfo_to_metadata(OMX_PTR markdata, ColorMetaData &colorData)
9169 {
9170     std::list<hdr10plusInfo>::iterator iter;
9171     unsigned int cookie = (unsigned int)(unsigned long)markdata;
9172     bool is_list_empty = false;
9173 
9174     if (output_capability != V4L2_PIX_FMT_VP9 &&
9175         output_capability != V4L2_PIX_FMT_HEVC)
9176         return;
9177 
9178     pthread_mutex_lock(&m_hdr10pluslock);
9179     is_list_empty = m_hdr10pluslist.empty();
9180     pthread_mutex_unlock(&m_hdr10pluslock);
9181 
9182     if (is_list_empty) {
9183         DEBUG_PRINT_HIGH("convert_hdr10plusinfo_to_metadata: hdr10plusinfo list is empty!");
9184         return;
9185     }
9186 
9187     pthread_mutex_lock(&m_hdr10pluslock);
9188     iter = m_hdr10pluslist.begin();
9189     while (iter != m_hdr10pluslist.end()) {
9190         if (iter->cookie == cookie && !iter->is_new) {
9191             colorData.dynamicMetaDataValid = true;
9192             colorData.dynamicMetaDataLen = iter->nParamSizeUsed;
9193             memcpy(colorData.dynamicMetaDataPayload, iter->payload,
9194                 iter->nParamSizeUsed);
9195             DEBUG_PRINT_LOW("found hdr10plus metadata for cookie %u with timestamp %lld, size %u",
9196                 cookie, iter->timestamp, colorData.dynamicMetaDataLen);
9197             break;
9198         }
9199         iter++;
9200     }
9201     pthread_mutex_unlock(&m_hdr10pluslock);
9202 }
9203 
remove_hdr10plusinfo_using_cookie(OMX_PTR markdata)9204 void omx_vdec::remove_hdr10plusinfo_using_cookie(OMX_PTR markdata)
9205 {
9206     std::list<hdr10plusInfo>::iterator iter;
9207     unsigned int cookie = (unsigned int)(unsigned long)markdata;
9208     bool is_list_empty = false;
9209 
9210     if (output_capability != V4L2_PIX_FMT_VP9 &&
9211         output_capability != V4L2_PIX_FMT_HEVC)
9212         return;
9213 
9214     pthread_mutex_lock(&m_hdr10pluslock);
9215     is_list_empty = m_hdr10pluslist.empty();
9216     pthread_mutex_unlock(&m_hdr10pluslock);
9217 
9218     if (is_list_empty) {
9219         DEBUG_PRINT_HIGH("remove_hdr10plusinfo_using_cookie: hdr10plusinfo list is empty!");
9220         return;
9221     }
9222 
9223     pthread_mutex_lock(&m_hdr10pluslock);
9224     iter = m_hdr10pluslist.begin();
9225     while (iter != m_hdr10pluslist.end()) {
9226         if (iter->cookie == cookie && !iter->is_new) {
9227             iter = m_hdr10pluslist.erase(iter);
9228             DEBUG_PRINT_LOW("removed hdr10plusinfo from the list for the cookie %u", cookie);
9229             break;
9230         }
9231         iter++;
9232     }
9233     pthread_mutex_unlock(&m_hdr10pluslock);
9234 }
9235 
clear_hdr10plusinfo()9236 void omx_vdec::clear_hdr10plusinfo()
9237 {
9238     bool is_list_empty = false;
9239 
9240     if (output_capability != V4L2_PIX_FMT_VP9 &&
9241         output_capability != V4L2_PIX_FMT_HEVC)
9242         return;
9243 
9244     pthread_mutex_lock(&m_hdr10pluslock);
9245     is_list_empty = m_hdr10pluslist.empty();
9246     pthread_mutex_unlock(&m_hdr10pluslock);
9247 
9248     if (is_list_empty) {
9249         DEBUG_PRINT_HIGH("clear_hdr10plusinfo: hdr10plusinfo list is empty!");
9250         return;
9251     }
9252 
9253     pthread_mutex_lock(&m_hdr10pluslock);
9254     m_hdr10pluslist.clear();
9255     pthread_mutex_unlock(&m_hdr10pluslock);
9256 }
9257 
get_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)9258 void omx_vdec::get_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
9259 {
9260     bool is_list_empty = false;
9261 
9262     if (output_capability != V4L2_PIX_FMT_VP9 &&
9263         output_capability != V4L2_PIX_FMT_HEVC)
9264         return;
9265 
9266     pthread_mutex_lock(&m_hdr10pluslock);
9267     is_list_empty = m_hdr10pluslist.empty();
9268     pthread_mutex_unlock(&m_hdr10pluslock);
9269 
9270     if (is_list_empty) {
9271         DEBUG_PRINT_HIGH("get_hdr10plusinfo: hdr10plusinfo list is empty!");
9272         return;
9273     }
9274 
9275     pthread_mutex_lock(&m_hdr10pluslock);
9276     hdr10plusInfo item = m_hdr10pluslist.front();
9277     hdr10plusdata->nParamSizeUsed = item.nParamSizeUsed;
9278     memcpy(hdr10plusdata->nValue, item.payload,item.nParamSizeUsed);
9279     DEBUG_PRINT_LOW("found hdr10plus metadata with timestamp %lld, size %u",
9280         item.timestamp, item.nParamSizeUsed);
9281     m_hdr10pluslist.pop_front();
9282     pthread_mutex_unlock(&m_hdr10pluslock);
9283 }
9284 
print_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)9285 void omx_vdec::print_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
9286 {
9287          DEBUG_PRINT_LOW("HDR10+ frameworks path valid data length: %d", hdr10plusdata->nParamSizeUsed);
9288         for (uint32_t i = 0 ; i < hdr10plusdata->nParamSizeUsed && i+3 < 1024; i=i+4) {
9289             DEBUG_PRINT_LOW("HDR10+ mdata: %02X %02X %02X %02X", hdr10plusdata->nValue[i],
9290             hdr10plusdata->nValue[i+1],
9291             hdr10plusdata->nValue[i+2],
9292             hdr10plusdata->nValue[i+3]);
9293     }
9294 }
9295 
start()9296 void perf_metrics::start()
9297 {
9298     if (!active) {
9299         start_time = get_act_time();
9300         active = true;
9301     }
9302 }
9303 
stop()9304 void perf_metrics::stop()
9305 {
9306     OMX_U64 stop_time = get_act_time();
9307     if (active) {
9308         proc_time += (stop_time - start_time);
9309         active = false;
9310     }
9311 }
9312 
end(OMX_U32 units_cntr)9313 void perf_metrics::end(OMX_U32 units_cntr)
9314 {
9315     stop();
9316     DEBUG_PRINT_LOW("--> Processing time : [%.2f] Sec", (float)proc_time / 1e6);
9317     if (units_cntr) {
9318         DEBUG_PRINT_LOW("--> Avrg proc time  : [%.2f] mSec", proc_time / (float)(units_cntr * 1e3));
9319     }
9320 }
9321 
reset()9322 void perf_metrics::reset()
9323 {
9324     start_time = 0;
9325     proc_time = 0;
9326     active = false;
9327 }
9328 
get_act_time()9329 OMX_U64 perf_metrics::get_act_time()
9330 {
9331     struct timeval act_time = {0, 0};
9332     gettimeofday(&act_time, NULL);
9333     return (act_time.tv_usec + act_time.tv_sec * 1e6);
9334 }
9335 
processing_time_us()9336 OMX_U64 perf_metrics::processing_time_us()
9337 {
9338     return proc_time;
9339 }
9340 
9341 // No code beyond this !
9342 
9343 // inline import of vendor-extensions implementation
9344 #include "omx_vdec_extensions.hpp"
9345