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