• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 /*============================================================================
30                             O p e n M A X   w r a p p e r s
31                              O p e n  M A X   C o r e
32 
33   This module contains the implementation of the OpenMAX core & component.
34 
35 *//*========================================================================*/
36 
37 //////////////////////////////////////////////////////////////////////////////
38 //                             Include Files
39 //////////////////////////////////////////////////////////////////////////////
40 
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43 
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <media/hardware/HardwareAPI.h>
55 #include <media/msm_media_info.h>
56 #include <sys/eventfd.h>
57 
58 #ifndef _ANDROID_
59 #include <sys/ioctl.h>
60 #include <sys/mman.h>
61 #endif //_ANDROID_
62 
63 #ifdef _ANDROID_
64 #include <cutils/properties.h>
65 #undef USE_EGL_IMAGE_GPU
66 #endif
67 
68 #include <qdMetaData.h>
69 
70 #ifdef ANDROID_JELLYBEAN_MR2
71 #include "QComOMXMetadata.h"
72 #endif
73 
74 #ifdef USE_EGL_IMAGE_GPU
75 #include <EGL/egl.h>
76 #include <EGL/eglQCOM.h>
77 #define EGL_BUFFER_HANDLE 0x4F00
78 #define EGL_BUFFER_OFFSET 0x4F01
79 #endif
80 
81 #define BUFFER_LOG_LOC "/data/misc/media"
82 
83 #ifdef OUTPUT_EXTRADATA_LOG
84 FILE *outputExtradataFile;
85 char output_extradata_filename [] = "/data/misc/media/extradata";
86 #endif
87 
88 #define DEFAULT_FPS 30
89 #define MAX_SUPPORTED_FPS 120
90 #define DEFAULT_WIDTH_ALIGNMENT 128
91 #define DEFAULT_HEIGHT_ALIGNMENT 32
92 
93 #define VC1_SP_MP_START_CODE        0xC5000000
94 #define VC1_SP_MP_START_CODE_MASK   0xFF000000
95 #define VC1_AP_SEQ_START_CODE       0x0F010000
96 #define VC1_STRUCT_C_PROFILE_MASK   0xF0
97 #define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
98 #define VC1_SIMPLE_PROFILE          0
99 #define VC1_MAIN_PROFILE            1
100 #define VC1_ADVANCE_PROFILE         3
101 #define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
102 #define VC1_SIMPLE_PROFILE_MED_LEVEL  2
103 #define VC1_STRUCT_C_LEN            4
104 #define VC1_STRUCT_C_POS            8
105 #define VC1_STRUCT_A_POS            12
106 #define VC1_STRUCT_B_POS            24
107 #define VC1_SEQ_LAYER_SIZE          36
108 #define POLL_TIMEOUT 0x7fffffff
109 
110 #define MEM_DEVICE "/dev/ion"
111 
112 #ifdef _ANDROID_
113 extern "C" {
114 #include<utils/Log.h>
115 }
116 #endif//_ANDROID_
117 
118 #define SZ_4K 0x1000
119 #define SZ_1M 0x100000
120 
121 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
122 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
123 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
124 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
125 
126 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA)
127 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
128 
129 #ifndef ION_FLAG_CP_BITSTREAM
130 #define ION_FLAG_CP_BITSTREAM 0
131 #endif
132 
133 #ifndef ION_FLAG_CP_PIXEL
134 #define ION_FLAG_CP_PIXEL 0
135 #endif
136 
137 #ifdef MASTER_SIDE_CP
138 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
139 #define SECURE_ALIGN SZ_4K
140 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
141 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
142 #else //SLAVE_SIDE_CP
143 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
144 #define SECURE_ALIGN SZ_1M
145 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
146 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
147 #endif
148 
149 static OMX_U32 maxSmoothStreamingWidth = 1920;
150 static OMX_U32 maxSmoothStreamingHeight = 1088;
151 
async_message_thread(void * input)152 void* async_message_thread (void *input)
153 {
154     OMX_BUFFERHEADERTYPE *buffer;
155     struct v4l2_plane plane[VIDEO_MAX_PLANES];
156     struct pollfd pfds[2];
157     struct v4l2_buffer v4l2_buf;
158     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
159     struct v4l2_event dqevent;
160     omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
161     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
162     pfds[1].events = POLLIN | POLLERR;
163     pfds[0].fd = omx->drv_ctx.video_driver_fd;
164     pfds[1].fd = omx->m_poll_efd;
165     int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
166     DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
167     prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
168     while (!omx->async_thread_force_stop) {
169         rc = poll(pfds, 2, POLL_TIMEOUT);
170         if (!rc) {
171             DEBUG_PRINT_ERROR("Poll timedout");
172             break;
173         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
174             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
175             break;
176         }
177         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
178             DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
179             break;
180         }
181         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
182             struct vdec_msginfo vdec_msg;
183             memset(&vdec_msg, 0, sizeof(vdec_msg));
184             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
185             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
186             v4l2_buf.length = omx->drv_ctx.num_planes;
187             v4l2_buf.m.planes = plane;
188             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
189                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
190                 vdec_msg.status_code=VDEC_S_SUCCESS;
191                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
192                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
193                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
194                 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
195                     (uint64_t)v4l2_buf.timestamp.tv_usec;
196                 if (vdec_msg.msgdata.output_frame.len) {
197                     vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
198                     vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
199                     vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
200                     vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
201                     vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
202                     vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
203                 }
204                 if (omx->async_message_process(input,&vdec_msg) < 0) {
205                     DEBUG_PRINT_HIGH("async_message_thread Exited");
206                     break;
207                 }
208             }
209         }
210         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
211             struct vdec_msginfo vdec_msg;
212             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
213             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
214             v4l2_buf.length = 1;
215             v4l2_buf.m.planes = plane;
216             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
217                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
218                 vdec_msg.status_code=VDEC_S_SUCCESS;
219                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
220                 if (omx->async_message_process(input,&vdec_msg) < 0) {
221                     DEBUG_PRINT_HIGH("async_message_thread Exited");
222                     break;
223                 }
224             }
225         }
226         if (pfds[0].revents & POLLPRI) {
227             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
228             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
229                 struct vdec_msginfo vdec_msg;
230                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
231 
232                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
233                 vdec_msg.status_code=VDEC_S_SUCCESS;
234                 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
235                 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
236                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
237                 if (omx->async_message_process(input,&vdec_msg) < 0) {
238                     DEBUG_PRINT_HIGH("async_message_thread Exited");
239                     break;
240                 }
241             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT ) {
242                 struct vdec_msginfo vdec_msg;
243                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
244                 vdec_msg.status_code=VDEC_S_SUCCESS;
245                 omx->dpb_bit_depth = dqevent.u.data[0];
246                 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", dqevent.u.data[0]);
247                 if (omx->async_message_process(input,&vdec_msg) < 0) {
248                     DEBUG_PRINT_HIGH("async_message_thread Exited");
249                     break;
250                 }
251             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
252                 struct vdec_msginfo vdec_msg;
253                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
254                 vdec_msg.status_code=VDEC_S_SUCCESS;
255                 DEBUG_PRINT_HIGH("VIDC Input 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                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
261                 vdec_msg.status_code=VDEC_S_SUCCESS;
262                 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
263                 if (omx->async_message_process(input,&vdec_msg) < 0) {
264                     DEBUG_PRINT_HIGH("async_message_thread Exited");
265                     break;
266                 }
267             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
268                 struct vdec_msginfo vdec_msg;
269                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
270                 vdec_msg.status_code=VDEC_S_SUCCESS;
271                 DEBUG_PRINT_ERROR("HW Overload received");
272                 if (omx->async_message_process(input,&vdec_msg) < 0) {
273                     DEBUG_PRINT_HIGH("async_message_thread Exited");
274                     break;
275                 }
276             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
277                 struct vdec_msginfo vdec_msg;
278                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
279                 vdec_msg.status_code=VDEC_S_SUCCESS;
280                 DEBUG_PRINT_ERROR("HW Unsupported received");
281                 if (omx->async_message_process(input,&vdec_msg) < 0) {
282                     DEBUG_PRINT_HIGH("async_message_thread Exited");
283                     break;
284                 }
285             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
286                 struct vdec_msginfo vdec_msg;
287                 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
288                 vdec_msg.status_code = VDEC_S_SUCCESS;
289                 DEBUG_PRINT_HIGH("SYS Error Recieved");
290                 if (omx->async_message_process(input,&vdec_msg) < 0) {
291                     DEBUG_PRINT_HIGH("async_message_thread Exited");
292                     break;
293                 }
294             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
295                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
296 
297                 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
298             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
299                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
300                 struct vdec_msginfo vdec_msg;
301 
302                 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
303 
304                 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
305                 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
306                 v4l2_buf.length = omx->drv_ctx.num_planes;
307                 v4l2_buf.m.planes = plane;
308                 v4l2_buf.index = ptr[5];
309                 v4l2_buf.flags = 0;
310 
311                 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
312                 vdec_msg.status_code = VDEC_S_SUCCESS;
313                 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
314                 vdec_msg.msgdata.output_frame.len = 0;
315                 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
316                 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
317                     (uint64_t)ptr[4];
318                 if (omx->async_message_process(input,&vdec_msg) < 0) {
319                     DEBUG_PRINT_HIGH("async_message_thread Exitedn");
320                     break;
321                 }
322             } else {
323                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
324                 continue;
325             }
326         }
327     }
328     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
329     return NULL;
330 }
331 
message_thread(void * input)332 void* message_thread(void *input)
333 {
334     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
335     unsigned char id;
336     int n;
337 
338     fd_set readFds;
339     int res = 0;
340     struct timeval tv;
341 
342     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
343     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
344     while (!omx->message_thread_stop) {
345 
346         tv.tv_sec = 2;
347         tv.tv_usec = 0;
348 
349         FD_ZERO(&readFds);
350         FD_SET(omx->m_pipe_in, &readFds);
351 
352         res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
353         if (res < 0) {
354             DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
355             continue;
356         } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
357             continue;
358         }
359 
360         n = read(omx->m_pipe_in, &id, 1);
361 
362         if (0 == n) {
363             break;
364         }
365 
366         if (1 == n) {
367             omx->process_event_cb(omx, id);
368         }
369 
370         if ((n < 0) && (errno != EINTR)) {
371             DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
372             break;
373         }
374     }
375     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
376     return 0;
377 }
378 
post_message(omx_vdec * omx,unsigned char id)379 void post_message(omx_vdec *omx, unsigned char id)
380 {
381     int ret_value;
382     DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
383     ret_value = write(omx->m_pipe_out, &id, 1);
384     if (ret_value <= 0) {
385         DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
386     } else {
387         DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
388     }
389 }
390 
391 // omx_cmd_queue destructor
~omx_cmd_queue()392 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
393 {
394     // Nothing to do
395 }
396 
397 // omx cmd queue constructor
omx_cmd_queue()398 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
399 {
400     memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
401 }
402 
403 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)404 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
405 {
406     bool ret = true;
407     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
408         m_q[m_write].id       = id;
409         m_q[m_write].param1   = p1;
410         m_q[m_write].param2   = p2;
411         m_write++;
412         m_size ++;
413         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
414             m_write = 0;
415         }
416     } else {
417         ret = false;
418         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
419     }
420     return ret;
421 }
422 
423 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)424 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
425 {
426     bool ret = true;
427     if (m_size > 0) {
428         *id = m_q[m_read].id;
429         *p1 = m_q[m_read].param1;
430         *p2 = m_q[m_read].param2;
431         // Move the read pointer ahead
432         ++m_read;
433         --m_size;
434         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
435             m_read = 0;
436         }
437     } else {
438         ret = false;
439     }
440     return ret;
441 }
442 
443 // Retrieve the first mesg type in the queue
get_q_msg_type()444 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
445 {
446     return m_q[m_read].id;
447 }
448 
449 #ifdef _ANDROID_
ts_arr_list()450 omx_vdec::ts_arr_list::ts_arr_list()
451 {
452     //initialize timestamps array
453     memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
454 }
~ts_arr_list()455 omx_vdec::ts_arr_list::~ts_arr_list()
456 {
457     //free m_ts_arr_list?
458 }
459 
insert_ts(OMX_TICKS ts)460 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
461 {
462     bool ret = true;
463     bool duplicate_ts = false;
464     int idx = 0;
465 
466     //insert at the first available empty location
467     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
468         if (!m_ts_arr_list[idx].valid) {
469             //found invalid or empty entry, save timestamp
470             m_ts_arr_list[idx].valid = true;
471             m_ts_arr_list[idx].timestamp = ts;
472             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
473                     ts, idx);
474             break;
475         }
476     }
477 
478     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
479         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
480         ret = false;
481     }
482     return ret;
483 }
484 
pop_min_ts(OMX_TICKS & ts)485 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
486 {
487     bool ret = true;
488     int min_idx = -1;
489     OMX_TICKS min_ts = 0;
490     int idx = 0;
491 
492     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
493 
494         if (m_ts_arr_list[idx].valid) {
495             //found valid entry, save index
496             if (min_idx < 0) {
497                 //first valid entry
498                 min_ts = m_ts_arr_list[idx].timestamp;
499                 min_idx = idx;
500             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
501                 min_ts = m_ts_arr_list[idx].timestamp;
502                 min_idx = idx;
503             }
504         }
505 
506     }
507 
508     if (min_idx < 0) {
509         //no valid entries found
510         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
511         ts = 0;
512         ret = false;
513     } else {
514         ts = m_ts_arr_list[min_idx].timestamp;
515         m_ts_arr_list[min_idx].valid = false;
516         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
517                 ts, min_idx);
518     }
519 
520     return ret;
521 
522 }
523 
524 
reset_ts_list()525 bool omx_vdec::ts_arr_list::reset_ts_list()
526 {
527     bool ret = true;
528     int idx = 0;
529 
530     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
531     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
532         m_ts_arr_list[idx].valid = false;
533     }
534     return ret;
535 }
536 #endif
537 
538 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)539 void *get_omx_component_factory_fn(void)
540 {
541     return (new omx_vdec);
542 }
543 
544 #ifdef _ANDROID_
545 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,ion_user_handle_t handle,int ionMapfd)546 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
547         ion_user_handle_t handle, int ionMapfd)
548 {
549     (void) devicefd;
550     (void) size;
551     (void) base;
552     (void) handle;
553     (void) ionMapfd;
554     //    ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
555 }
556 #else
VideoHeap(int fd,size_t size,void * base)557 VideoHeap::VideoHeap(int fd, size_t size, void* base)
558 {
559     // dup file descriptor, map once, use pmem
560     init(dup(fd), base, size, 0 , MEM_DEVICE);
561 }
562 #endif
563 #endif // _ANDROID_
564 /* ======================================================================
565    FUNCTION
566    omx_vdec::omx_vdec
567 
568    DESCRIPTION
569    Constructor
570 
571    PARAMETERS
572    None
573 
574    RETURN VALUE
575    None.
576    ========================================================================== */
omx_vdec()577 omx_vdec::omx_vdec(): m_error_propogated(false),
578     m_state(OMX_StateInvalid),
579     m_app_data(NULL),
580     m_inp_mem_ptr(NULL),
581     m_out_mem_ptr(NULL),
582     input_flush_progress (false),
583     output_flush_progress (false),
584     input_use_buffer (false),
585     output_use_buffer (false),
586     ouput_egl_buffers(false),
587     m_use_output_pmem(OMX_FALSE),
588     m_out_mem_region_smi(OMX_FALSE),
589     m_out_pvt_entry_pmem(OMX_FALSE),
590     pending_input_buffers(0),
591     pending_output_buffers(0),
592     m_out_bm_count(0),
593     m_inp_bm_count(0),
594     m_inp_bPopulated(OMX_FALSE),
595     m_out_bPopulated(OMX_FALSE),
596     m_flags(0),
597 #ifdef _ANDROID_
598     m_heap_ptr(NULL),
599 #endif
600     m_inp_bEnabled(OMX_TRUE),
601     m_out_bEnabled(OMX_TRUE),
602     m_in_alloc_cnt(0),
603     m_platform_list(NULL),
604     m_platform_entry(NULL),
605     m_pmem_info(NULL),
606     h264_parser(NULL),
607     arbitrary_bytes (true),
608     psource_frame (NULL),
609     pdest_frame (NULL),
610     m_inp_heap_ptr (NULL),
611     m_phdr_pmem_ptr(NULL),
612     m_heap_inp_bm_count (0),
613     codec_type_parse ((codec_type)0),
614     first_frame_meta (true),
615     frame_count (0),
616     nal_count (0),
617     nal_length(0),
618     look_ahead_nal (false),
619     first_frame(0),
620     first_buffer(NULL),
621     first_frame_size (0),
622     m_device_file_ptr(NULL),
623     m_vc1_profile((vc1_profile_type)0),
624     h264_last_au_ts(LLONG_MAX),
625     h264_last_au_flags(0),
626     m_disp_hor_size(0),
627     m_disp_vert_size(0),
628     prev_ts(LLONG_MAX),
629     prev_ts_actual(LLONG_MAX),
630     rst_prev_ts(true),
631     frm_int(0),
632     in_reconfig(false),
633     m_display_id(NULL),
634     client_extradata(0),
635     m_reject_avc_1080p_mp (0),
636 #ifdef _ANDROID_
637     m_enable_android_native_buffers(OMX_FALSE),
638     m_use_android_native_buffers(OMX_FALSE),
639 #endif
640     m_desc_buffer_ptr(NULL),
641     secure_mode(false),
642     allocate_native_handle(false),
643     m_other_extradata(NULL),
644     m_profile(0),
645     client_set_fps(false),
646     m_last_rendered_TS(-1),
647     m_queued_codec_config_count(0),
648     current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
649     secure_scaling_to_non_secure_opb(false),
650     m_force_compressed_for_dpb(false)
651 {
652     m_pipe_in = -1;
653     m_pipe_out = -1;
654     m_poll_efd = -1;
655     drv_ctx.video_driver_fd = -1;
656     drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
657     /* Assumption is that , to begin with , we have all the frames with decoder */
658     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
659     memset(&m_debug,0,sizeof(m_debug));
660 #ifdef _ANDROID_
661     char property_value[PROPERTY_VALUE_MAX] = {0};
662     property_get("vidc.debug.level", property_value, "1");
663     debug_level = atoi(property_value);
664     property_value[0] = '\0';
665 
666     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
667 
668     property_get("vidc.dec.debug.perf", property_value, "0");
669     perf_flag = atoi(property_value);
670     if (perf_flag) {
671         DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
672         dec_time.start();
673         proc_frms = latency = 0;
674     }
675     prev_n_filled_len = 0;
676     property_value[0] = '\0';
677     property_get("vidc.dec.debug.ts", property_value, "0");
678     m_debug_timestamp = atoi(property_value);
679     DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
680     if (m_debug_timestamp) {
681         time_stamp_dts.set_timestamp_reorder_mode(true);
682         time_stamp_dts.enable_debug_print(true);
683     }
684 
685     property_value[0] = '\0';
686     property_get("vidc.dec.debug.concealedmb", property_value, "0");
687     m_debug_concealedmb = atoi(property_value);
688     DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
689 
690     property_value[0] = '\0';
691     property_get("vidc.dec.profile.check", property_value, "0");
692     m_reject_avc_1080p_mp = atoi(property_value);
693     DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
694 
695     property_value[0] = '\0';
696     property_get("vidc.dec.log.in", property_value, "0");
697     m_debug.in_buffer_log = atoi(property_value);
698 
699     property_value[0] = '\0';
700     property_get("vidc.dec.log.out", property_value, "0");
701     m_debug.out_buffer_log = atoi(property_value);
702     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
703 
704     property_value[0] = '\0';
705     property_get("vidc.dec.meta.log.out", property_value, "0");
706     m_debug.out_meta_buffer_log = atoi(property_value);
707     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
708 
709     property_value[0] = '\0';
710     property_get("vidc.log.loc", property_value, "");
711     if (*property_value)
712         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
713 
714     property_value[0] = '\0';
715     property_get("vidc.dec.120fps.enabled", property_value, "0");
716 
717     //if this feature is not enabled then reset this value -ve
718     if(atoi(property_value)) {
719         DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
720         m_last_rendered_TS = 0;
721     }
722 
723     property_value[0] = '\0';
724     property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
725     m_disable_dynamic_buf_mode = atoi(property_value);
726     DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
727 
728 #ifdef _UBWC_
729     property_value[0] = '\0';
730     property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
731     m_disable_ubwc_mode = atoi(property_value);
732     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
733 #else
734     m_disable_ubwc_mode = true;
735 #endif
736 #endif
737     memset(&m_cmp,0,sizeof(m_cmp));
738     memset(&m_cb,0,sizeof(m_cb));
739     memset (&drv_ctx,0,sizeof(drv_ctx));
740     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
741     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
742     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
743     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
744     memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
745     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
746     m_demux_entries = 0;
747     msg_thread_id = 0;
748     async_thread_id = 0;
749     msg_thread_created = false;
750     async_thread_created = false;
751     async_thread_force_stop = false;
752     message_thread_stop = false;
753 #ifdef _ANDROID_ICS_
754     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
755 #endif
756     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
757 
758     /* invalidate m_frame_pack_arrangement */
759     memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
760     m_frame_pack_arrangement.cancel_flag = 1;
761 
762     drv_ctx.timestamp_adjust = false;
763     m_vendor_config.pData = NULL;
764     pthread_mutex_init(&m_lock, NULL);
765     pthread_mutex_init(&c_lock, NULL);
766     pthread_mutex_init(&buf_lock, NULL);
767     sem_init(&m_cmd_lock,0,0);
768     sem_init(&m_safe_flush, 0, 0);
769     streaming[CAPTURE_PORT] =
770         streaming[OUTPUT_PORT] = false;
771 #ifdef _ANDROID_
772     char extradata_value[PROPERTY_VALUE_MAX] = {0};
773     property_get("vidc.dec.debug.extradata", extradata_value, "0");
774     m_debug_extradata = atoi(extradata_value);
775     DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
776 #endif
777     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
778     client_buffers.set_vdec_client(this);
779     dynamic_buf_mode = false;
780     out_dynamic_list = NULL;
781     is_down_scalar_enabled = false;
782     m_downscalar_width = 0;
783     m_downscalar_height = 0;
784     m_force_down_scalar = 0;
785     m_reconfig_height = 0;
786     m_reconfig_width = 0;
787     m_smoothstreaming_mode = false;
788     m_smoothstreaming_width = 0;
789     m_smoothstreaming_height = 0;
790     is_q6_platform = false;
791     m_perf_control.send_hint_to_mpctl(true);
792     m_input_pass_buffer_fd = false;
793     m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
794     m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
795     m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
796     m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
797     m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
798 
799     m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
800     m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
801     m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
802     m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
803     m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
804     m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
805 }
806 
807 static const int event_type[] = {
808     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
809     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
810     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
811     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
812     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
813     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
814     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
815     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
816     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
817 };
818 
subscribe_to_events(int fd)819 static OMX_ERRORTYPE subscribe_to_events(int fd)
820 {
821     OMX_ERRORTYPE eRet = OMX_ErrorNone;
822     struct v4l2_event_subscription sub;
823     int array_sz = sizeof(event_type)/sizeof(int);
824     int i,rc;
825     if (fd < 0) {
826         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
827         return OMX_ErrorBadParameter;
828     }
829 
830     for (i = 0; i < array_sz; ++i) {
831         memset(&sub, 0, sizeof(sub));
832         sub.type = event_type[i];
833         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
834         if (rc) {
835             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
836             break;
837         }
838     }
839     if (i < array_sz) {
840         for (--i; i >=0 ; i--) {
841             memset(&sub, 0, sizeof(sub));
842             sub.type = event_type[i];
843             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
844             if (rc)
845                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
846         }
847         eRet = OMX_ErrorNotImplemented;
848     }
849     return eRet;
850 }
851 
852 
unsubscribe_to_events(int fd)853 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
854 {
855     OMX_ERRORTYPE eRet = OMX_ErrorNone;
856     struct v4l2_event_subscription sub;
857     int array_sz = sizeof(event_type)/sizeof(int);
858     int i,rc;
859     if (fd < 0) {
860         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
861         return OMX_ErrorBadParameter;
862     }
863 
864     for (i = 0; i < array_sz; ++i) {
865         memset(&sub, 0, sizeof(sub));
866         sub.type = event_type[i];
867         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
868         if (rc) {
869             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
870             break;
871         }
872     }
873     return eRet;
874 }
875 
876 /* ======================================================================
877    FUNCTION
878    omx_vdec::~omx_vdec
879 
880    DESCRIPTION
881    Destructor
882 
883    PARAMETERS
884    None
885 
886    RETURN VALUE
887    None.
888    ========================================================================== */
~omx_vdec()889 omx_vdec::~omx_vdec()
890 {
891     m_pmem_info = NULL;
892     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
893     if (msg_thread_created) {
894         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
895         message_thread_stop = true;
896         post_message(this, OMX_COMPONENT_CLOSE_MSG);
897         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
898         pthread_join(msg_thread_id,NULL);
899     }
900     close(m_pipe_in);
901     close(m_pipe_out);
902     m_pipe_in = -1;
903     m_pipe_out = -1;
904     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
905     if(eventfd_write(m_poll_efd, 1)) {
906          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
907          async_thread_force_stop = true;
908     }
909 
910     if (async_thread_created)
911         pthread_join(async_thread_id,NULL);
912     unsubscribe_to_events(drv_ctx.video_driver_fd);
913     close(m_poll_efd);
914     close(drv_ctx.video_driver_fd);
915     pthread_mutex_destroy(&m_lock);
916     pthread_mutex_destroy(&c_lock);
917     pthread_mutex_destroy(&buf_lock);
918     sem_destroy(&m_cmd_lock);
919     if (perf_flag) {
920         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
921         dec_time.end();
922     }
923     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
924     m_perf_control.send_hint_to_mpctl(false);
925 }
926 
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)927 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
928 {
929     struct v4l2_requestbuffers bufreq;
930     int rc = 0;
931     if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
932         bufreq.memory = V4L2_MEMORY_USERPTR;
933         bufreq.count = 0;
934         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
935         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
936     } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
937         bufreq.memory = V4L2_MEMORY_USERPTR;
938         bufreq.count = 0;
939         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
940         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
941     }
942     return rc;
943 }
944 
set_dpb(bool is_split_mode,int dpb_color_format)945 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
946 {
947     int rc = 0;
948     struct v4l2_ext_control ctrl[2];
949     struct v4l2_ext_controls controls;
950 
951     DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
952          is_split_mode ? "split" : "combined",
953          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
954          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
955          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
956          "unknown",
957          capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
958          capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
959          "unknown");
960 
961     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
962     if (is_split_mode) {
963         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
964     } else {
965         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
966     }
967 
968     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
969     ctrl[1].value = dpb_color_format;
970 
971     controls.count = 2;
972     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
973     controls.controls = ctrl;
974 
975     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
976     if (rc) {
977         DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
978         return OMX_ErrorUnsupportedSetting;
979     }
980     return OMX_ErrorNone;
981 }
982 
983 
decide_dpb_buffer_mode(bool force_split_mode)984 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
985 {
986     OMX_ERRORTYPE eRet = OMX_ErrorNone;
987 
988     bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC;
989 
990     bool is_res_above_1080p = (drv_ctx.video_resolution.frame_width > 1920 &&
991             drv_ctx.video_resolution.frame_height > 1088) ||
992             (drv_ctx.video_resolution.frame_height > 1088 &&
993              drv_ctx.video_resolution.frame_width > 1920);
994 
995     if (cpu_access) {
996         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
997             if ((m_force_compressed_for_dpb || is_res_above_1080p) &&
998                 !force_split_mode) {
999                 //split DPB-OPB
1000                 //DPB -> UBWC , OPB -> Linear
1001                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1002             } else if (force_split_mode) {
1003                         //DPB -> Linear, OPB -> Linear
1004                         eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1005             } else {
1006                         //DPB-OPB combined linear
1007                         eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1008            }
1009         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1010             //split DPB-OPB
1011             //DPB -> UBWC, OPB -> Linear
1012             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1013         }
1014     } else { //no cpu access
1015         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1016             if (force_split_mode) {
1017                 //split DPB-OPB
1018                 //DPB -> UBWC, OPB -> UBWC
1019                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1020             } else {
1021                 //DPB-OPB combined UBWC
1022                 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1023             }
1024         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1025             //split DPB-OPB
1026             //DPB -> UBWC, OPB -> UBWC
1027             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1028         }
1029     }
1030     if (eRet) {
1031         DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1032     }
1033     return eRet;
1034 }
1035 
enable_downscalar()1036 int omx_vdec::enable_downscalar()
1037 {
1038     int rc = 0;
1039     struct v4l2_control control;
1040     struct v4l2_format fmt;
1041 
1042     if (is_down_scalar_enabled) {
1043         DEBUG_PRINT_LOW("%s: already enabled", __func__);
1044         return 0;
1045     }
1046 
1047     DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1048     rc = decide_dpb_buffer_mode(true);
1049     if (rc) {
1050         DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1051         return rc;
1052     }
1053     is_down_scalar_enabled = true;
1054 
1055     memset(&control, 0x0, sizeof(struct v4l2_control));
1056     control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1057     control.value = 1;
1058     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1059     if (rc) {
1060         DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1061         return rc;
1062     }
1063 
1064     return 0;
1065 }
1066 
disable_downscalar()1067 int omx_vdec::disable_downscalar()
1068 {
1069     int rc = 0;
1070     struct v4l2_control control;
1071 
1072     if (!is_down_scalar_enabled) {
1073         DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1074         return 0;
1075     }
1076 
1077     rc = decide_dpb_buffer_mode(false);
1078     if (rc < 0) {
1079         DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1080         return rc;
1081     }
1082     is_down_scalar_enabled = false;
1083 
1084     return rc;
1085 }
1086 
decide_downscalar()1087 int omx_vdec::decide_downscalar()
1088 {
1089     int rc = 0;
1090     struct v4l2_format fmt;
1091     enum color_fmts color_format;
1092 
1093     if  (!m_downscalar_width || !m_downscalar_height) {
1094         DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1095         return 0;
1096     }
1097 
1098     if (m_force_down_scalar) {
1099         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1100         return 0;
1101     }
1102 
1103     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1104     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1105     fmt.fmt.pix_mp.pixelformat = capture_capability;
1106     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1107     if (rc < 0) {
1108        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1109        return rc;
1110     }
1111 
1112     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__,
1113         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height);
1114 
1115     if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) {
1116         rc = enable_downscalar();
1117         if (rc < 0) {
1118             DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1119             return rc;
1120         }
1121 
1122         OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1123                             fmt.fmt.pix_mp.width : m_downscalar_width;
1124         OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1125                             fmt.fmt.pix_mp.height : m_downscalar_height;
1126         switch (capture_capability) {
1127             case V4L2_PIX_FMT_NV12:
1128                 color_format = COLOR_FMT_NV12;
1129                 break;
1130             case V4L2_PIX_FMT_NV12_UBWC:
1131                 color_format = COLOR_FMT_NV12_UBWC;
1132                 break;
1133             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1134                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1135                 break;
1136             default:
1137                 DEBUG_PRINT_ERROR("Color format not recognized\n");
1138                 rc = OMX_ErrorUndefined;
1139                 return rc;
1140         }
1141 
1142         rc = update_resolution(width, height,
1143                 VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height));
1144         if (rc < 0) {
1145             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height);
1146             return rc;
1147         }
1148     } else {
1149 
1150         rc = disable_downscalar();
1151         if (rc < 0) {
1152             DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1153             return rc;
1154         }
1155 
1156         rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1157                 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
1158         if (rc < 0) {
1159             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width,
1160                 fmt.fmt.pix_mp.height);
1161             return rc;
1162         }
1163     }
1164 
1165     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1166     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1167     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1168     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1169     fmt.fmt.pix_mp.pixelformat = capture_capability;
1170     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1171     if (rc) {
1172         DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1173         return rc;
1174     }
1175 
1176     rc = get_buffer_req(&drv_ctx.op_buf);
1177     if (rc) {
1178         DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1179         return rc;
1180     }
1181 
1182     return rc;
1183 }
1184 
1185 /* ======================================================================
1186    FUNCTION
1187    omx_vdec::OMXCntrlProcessMsgCb
1188 
1189    DESCRIPTION
1190    IL Client callbacks are generated through this routine. The decoder
1191    provides the thread context for this routine.
1192 
1193    PARAMETERS
1194    ctxt -- Context information related to the self.
1195    id   -- Event identifier. This could be any of the following:
1196    1. Command completion event
1197    2. Buffer done callback event
1198    3. Frame done callback event
1199 
1200    RETURN VALUE
1201    None.
1202 
1203    ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1204 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1205 {
1206     unsigned long p1; // Parameter - 1
1207     unsigned long p2; // Parameter - 2
1208     unsigned long ident;
1209     unsigned qsize=0; // qsize
1210     omx_vdec *pThis = (omx_vdec *) ctxt;
1211 
1212     if (!pThis) {
1213         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1214                 __func__);
1215         return;
1216     }
1217 
1218     // Protect the shared queue data structure
1219     do {
1220         /*Read the message id's from the queue*/
1221         pthread_mutex_lock(&pThis->m_lock);
1222         qsize = pThis->m_cmd_q.m_size;
1223         if (qsize) {
1224             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1225         }
1226 
1227         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1228             qsize = pThis->m_ftb_q.m_size;
1229             if (qsize) {
1230                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1231             }
1232         }
1233 
1234         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1235             qsize = pThis->m_etb_q.m_size;
1236             if (qsize) {
1237                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1238             }
1239         }
1240         pthread_mutex_unlock(&pThis->m_lock);
1241 
1242         /*process message if we have one*/
1243         if (qsize > 0) {
1244             id = ident;
1245             switch (id) {
1246                 case OMX_COMPONENT_GENERATE_EVENT:
1247                     if (pThis->m_cb.EventHandler) {
1248                         switch (p1) {
1249                             case OMX_CommandStateSet:
1250                                 pThis->m_state = (OMX_STATETYPE) p2;
1251                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1252                                         pThis->m_state);
1253                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1254                                         OMX_EventCmdComplete, p1, p2, NULL);
1255                                 break;
1256 
1257                             case OMX_EventError:
1258                                 if (p2 == OMX_StateInvalid) {
1259                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1260                                     pThis->m_state = (OMX_STATETYPE) p2;
1261                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1262                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1263                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1264                                     pThis->omx_report_error();
1265                                 } else {
1266                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1267                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
1268                                 }
1269                                 break;
1270 
1271                             case OMX_CommandPortDisable:
1272                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1273                                 if (BITMASK_PRESENT(&pThis->m_flags,
1274                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1275                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1276                                     break;
1277                                 }
1278                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1279                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1280                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1281                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1282                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
1283                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1284                                     pThis->in_reconfig = false;
1285                                     if (eRet !=  OMX_ErrorNone) {
1286                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1287                                         pThis->omx_report_error();
1288                                         break;
1289                                     }
1290                                 }
1291                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1292                                         OMX_EventCmdComplete, p1, p2, NULL );
1293                                 break;
1294                             case OMX_CommandPortEnable:
1295                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1296                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1297                                         OMX_EventCmdComplete, p1, p2, NULL );
1298                                 break;
1299 
1300                             default:
1301                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1302                                         OMX_EventCmdComplete, p1, p2, NULL );
1303                                 break;
1304 
1305                         }
1306                     } else {
1307                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1308                     }
1309                     break;
1310                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1311                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1312                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1313                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1314                         pThis->omx_report_error ();
1315                     }
1316                     break;
1317                 case OMX_COMPONENT_GENERATE_ETB: {
1318                         OMX_ERRORTYPE iret;
1319                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1320                         if (iret == OMX_ErrorInsufficientResources) {
1321                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1322                             pThis->omx_report_hw_overload ();
1323                         } else if (iret != OMX_ErrorNone) {
1324                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1325                             pThis->omx_report_error ();
1326                         }
1327                     }
1328                     break;
1329 
1330                 case OMX_COMPONENT_GENERATE_FTB:
1331                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1332                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1333                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1334                         pThis->omx_report_error ();
1335                     }
1336                     break;
1337 
1338                 case OMX_COMPONENT_GENERATE_COMMAND:
1339                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1340                             (OMX_U32)p2,(OMX_PTR)NULL);
1341                     break;
1342 
1343                 case OMX_COMPONENT_GENERATE_EBD:
1344 
1345                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1346                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1347                         pThis->omx_report_error ();
1348                     } else {
1349                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1350                             pThis->time_stamp_dts.remove_time_stamp(
1351                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1352                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1353                                     ?true:false);
1354                         }
1355 
1356                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1357                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1358                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1359                             pThis->omx_report_error ();
1360                         }
1361                     }
1362                     break;
1363                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1364                                             int64_t *timestamp = (int64_t *)(intptr_t)p1;
1365                                             if (p1) {
1366                                                 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1367                                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1368                                                         ?true:false);
1369                                                 free(timestamp);
1370                                             }
1371                                         }
1372                                         break;
1373                 case OMX_COMPONENT_GENERATE_FBD:
1374                                         if (p2 != VDEC_S_SUCCESS) {
1375                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1376                                             pThis->omx_report_error ();
1377                                         } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1378                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1379                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
1380                                             pThis->omx_report_error ();
1381                                         }
1382                                         break;
1383 
1384                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1385                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1386                                         if (!pThis->input_flush_progress) {
1387                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1388                                         } else {
1389                                             pThis->execute_input_flush();
1390                                             if (pThis->m_cb.EventHandler) {
1391                                                 if (p2 != VDEC_S_SUCCESS) {
1392                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1393                                                     pThis->omx_report_error ();
1394                                                 } else {
1395                                                     /*Check if we need generate event for Flush done*/
1396                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1397                                                                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
1398                                                         BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
1399                                                         DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
1400                                                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1401                                                                 OMX_EventCmdComplete,OMX_CommandFlush,
1402                                                                 OMX_CORE_INPUT_PORT_INDEX,NULL );
1403                                                     }
1404                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1405                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1406                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1407                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1408                                                             pThis->omx_report_error ();
1409                                                         } else {
1410                                                             pThis->streaming[OUTPUT_PORT] = false;
1411                                                         }
1412                                                         if (!pThis->output_flush_progress) {
1413                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1414                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1415                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1416                                                         }
1417                                                     }
1418                                                 }
1419                                             } else {
1420                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1421                                             }
1422                                         }
1423                                         break;
1424 
1425                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1426                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1427                                         if (!pThis->output_flush_progress) {
1428                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1429                                         } else {
1430                                             pThis->execute_output_flush();
1431                                             if (pThis->m_cb.EventHandler) {
1432                                                 if (p2 != VDEC_S_SUCCESS) {
1433                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1434                                                     pThis->omx_report_error ();
1435                                                 } else {
1436                                                     /*Check if we need generate event for Flush done*/
1437                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1438                                                                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
1439                                                         DEBUG_PRINT_LOW("Notify Output Flush done");
1440                                                         BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1441                                                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1442                                                                 OMX_EventCmdComplete,OMX_CommandFlush,
1443                                                                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1444                                                     }
1445                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1446                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1447                                                         DEBUG_PRINT_LOW("Internal flush complete");
1448                                                         BITMASK_CLEAR (&pThis->m_flags,
1449                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1450                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1451                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1452                                                             pThis->post_event(OMX_CommandPortDisable,
1453                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1454                                                                     OMX_COMPONENT_GENERATE_EVENT);
1455                                                             BITMASK_CLEAR (&pThis->m_flags,
1456                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1457                                                             BITMASK_CLEAR (&pThis->m_flags,
1458                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1459 
1460                                                         }
1461                                                     }
1462 
1463                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1464                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1465                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1466                                                             pThis->omx_report_error ();
1467                                                             break;
1468                                                         }
1469                                                         pThis->streaming[CAPTURE_PORT] = false;
1470                                                         if (!pThis->input_flush_progress) {
1471                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1472                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1473                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1474                                                         }
1475                                                     }
1476                                                 }
1477                                             } else {
1478                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1479                                             }
1480                                         }
1481                                         break;
1482 
1483                 case OMX_COMPONENT_GENERATE_START_DONE:
1484                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1485 
1486                                         if (pThis->m_cb.EventHandler) {
1487                                             if (p2 != VDEC_S_SUCCESS) {
1488                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1489                                                 pThis->omx_report_error ();
1490                                             } else {
1491                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1492                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1493                                                     DEBUG_PRINT_LOW("Move to executing");
1494                                                     // Send the callback now
1495                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1496                                                     pThis->m_state = OMX_StateExecuting;
1497                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1498                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1499                                                             OMX_StateExecuting, NULL);
1500                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1501                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1502                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1503                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1504                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1505                                                         pThis->omx_report_error ();
1506                                                     }
1507                                                 }
1508                                             }
1509                                         } else {
1510                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1511                                         }
1512                                         break;
1513 
1514                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1515                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1516                                         if (pThis->m_cb.EventHandler) {
1517                                             if (p2 != VDEC_S_SUCCESS) {
1518                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1519                                                 pThis->omx_report_error ();
1520                                             } else {
1521                                                 pThis->complete_pending_buffer_done_cbs();
1522                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1523                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1524                                                     //Send the callback now
1525                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1526                                                     pThis->m_state = OMX_StatePause;
1527                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1528                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1529                                                             OMX_StatePause, NULL);
1530                                                 }
1531                                             }
1532                                         } else {
1533                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1534                                         }
1535 
1536                                         break;
1537 
1538                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1539                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1540                                         if (pThis->m_cb.EventHandler) {
1541                                             if (p2 != VDEC_S_SUCCESS) {
1542                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1543                                                 pThis->omx_report_error ();
1544                                             } else {
1545                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1546                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1547                                                     // Send the callback now
1548                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1549                                                     pThis->m_state = OMX_StateExecuting;
1550                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1551                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1552                                                             OMX_StateExecuting,NULL);
1553                                                 }
1554                                             }
1555                                         } else {
1556                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1557                                         }
1558 
1559                                         break;
1560 
1561                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1562                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1563                                         if (pThis->m_cb.EventHandler) {
1564                                             if (p2 != VDEC_S_SUCCESS) {
1565                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1566                                                 pThis->omx_report_error ();
1567                                             } else {
1568                                                 pThis->complete_pending_buffer_done_cbs();
1569                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1570                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1571                                                     // Send the callback now
1572                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1573                                                     pThis->m_state = OMX_StateIdle;
1574                                                     DEBUG_PRINT_LOW("Move to Idle State");
1575                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1576                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1577                                                             OMX_StateIdle,NULL);
1578                                                 }
1579                                             }
1580                                         } else {
1581                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1582                                         }
1583 
1584                                         break;
1585 
1586                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1587                                         if (p2 == OMX_IndexParamPortDefinition) {
1588                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1589                                             pThis->in_reconfig = true;
1590                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1591                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1592 
1593                                             /* Check if resolution is changed in smooth streaming mode */
1594                                             if (pThis->m_smoothstreaming_mode &&
1595                                                 (pThis->framesize.nWidth !=
1596                                                     pThis->drv_ctx.video_resolution.frame_width) ||
1597                                                 (pThis->framesize.nHeight !=
1598                                                     pThis->drv_ctx.video_resolution.frame_height)) {
1599 
1600                                                 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1601                                                         pThis->framesize.nWidth,
1602                                                         pThis->framesize.nHeight,
1603                                                         pThis->drv_ctx.video_resolution.frame_width,
1604                                                         pThis->drv_ctx.video_resolution.frame_height);
1605 
1606                                                 /* Update new resolution */
1607                                                 pThis->framesize.nWidth =
1608                                                        pThis->drv_ctx.video_resolution.frame_width;
1609                                                 pThis->framesize.nHeight =
1610                                                        pThis->drv_ctx.video_resolution.frame_height;
1611 
1612                                                 /* Update C2D with new resolution */
1613                                                 if (!pThis->client_buffers.update_buffer_req()) {
1614                                                     DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1615                                                 }
1616                                             }
1617 
1618                                             /* Update new crop information */
1619                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1620                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1621                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1622                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1623 
1624                                             /* Validate the new crop information */
1625                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1626                                                 pThis->drv_ctx.video_resolution.frame_width) {
1627 
1628                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1629                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1630                                                         pThis->drv_ctx.video_resolution.frame_width);
1631                                                 pThis->rectangle.nLeft = 0;
1632 
1633                                                 if (pThis->rectangle.nWidth >
1634                                                     pThis->drv_ctx.video_resolution.frame_width) {
1635 
1636                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1637                                                             pThis->rectangle.nWidth,
1638                                                             pThis->drv_ctx.video_resolution.frame_width);
1639                                                     pThis->rectangle.nWidth =
1640                                                         pThis->drv_ctx.video_resolution.frame_width;
1641                                                 }
1642                                             }
1643                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1644                                                 pThis->drv_ctx.video_resolution.frame_height) {
1645 
1646                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1647                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1648                                                     pThis->drv_ctx.video_resolution.frame_height);
1649                                                 pThis->rectangle.nTop = 0;
1650 
1651                                                 if (pThis->rectangle.nHeight >
1652                                                     pThis->drv_ctx.video_resolution.frame_height) {
1653 
1654                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1655                                                         pThis->rectangle.nHeight,
1656                                                         pThis->drv_ctx.video_resolution.frame_height);
1657                                                     pThis->rectangle.nHeight =
1658                                                         pThis->drv_ctx.video_resolution.frame_height;
1659                                                 }
1660                                             }
1661                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1662                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1663                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1664                                         } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1665                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1666                                         } else {
1667                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1668                                             break;
1669                                         }
1670                                         if (pThis->m_debug.outfile) {
1671                                             fclose(pThis->m_debug.outfile);
1672                                             pThis->m_debug.outfile = NULL;
1673                                         }
1674                                         if (pThis->m_debug.out_ymeta_file) {
1675                                             fclose(pThis->m_debug.out_ymeta_file);
1676                                             pThis->m_debug.out_ymeta_file = NULL;
1677                                         }
1678                                         if (pThis->m_debug.out_uvmeta_file) {
1679                                             fclose(pThis->m_debug.out_uvmeta_file);
1680                                             pThis->m_debug.out_uvmeta_file = NULL;
1681                                         }
1682 
1683                                         if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1684                                             pThis->prefetchNewBuffers();
1685                                         }
1686 
1687                                         if (pThis->m_cb.EventHandler) {
1688                                             uint32_t frame_data[2];
1689                                             frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1690                                                 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1691                                             frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1692                                                 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1693                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1694                                                     OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1695                                         } else {
1696                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1697                                         }
1698                                         break;
1699 
1700                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1701                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1702                                         if (pThis->m_cb.EventHandler) {
1703                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1704                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1705                                         } else {
1706                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1707                                         }
1708                                         pThis->prev_ts = LLONG_MAX;
1709                                         pThis->rst_prev_ts = true;
1710                                         break;
1711 
1712                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1713                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1714                                         pThis->omx_report_error();
1715                                         break;
1716 
1717                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1718                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1719                                         pThis->omx_report_unsupported_setting();
1720                                         break;
1721 
1722                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1723                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1724                                         pThis->omx_report_hw_overload();
1725                                         break;
1726 
1727                 default:
1728                                         break;
1729             }
1730         }
1731         pthread_mutex_lock(&pThis->m_lock);
1732         qsize = pThis->m_cmd_q.m_size;
1733         if (pThis->m_state != OMX_StatePause)
1734             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1735         pthread_mutex_unlock(&pThis->m_lock);
1736     } while (qsize>0);
1737 
1738 }
1739 
update_resolution(int width,int height,int stride,int scan_lines)1740 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1741 {
1742     int format_changed = 0;
1743     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1744             (width != (int)drv_ctx.video_resolution.frame_width)) {
1745         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1746                 width, drv_ctx.video_resolution.frame_width,
1747                 height,drv_ctx.video_resolution.frame_height);
1748         format_changed = 1;
1749     }
1750     drv_ctx.video_resolution.frame_height = height;
1751     drv_ctx.video_resolution.frame_width = width;
1752     drv_ctx.video_resolution.scan_lines = scan_lines;
1753     drv_ctx.video_resolution.stride = stride;
1754     if(!is_down_scalar_enabled) {
1755         rectangle.nLeft = 0;
1756         rectangle.nTop = 0;
1757         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1758         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1759     }
1760     return format_changed;
1761 }
1762 
is_video_session_supported()1763 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1764 {
1765     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1766                 OMX_MAX_STRINGNAME_SIZE) &&
1767             (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1768         m_decoder_capability.max_width = 1280;
1769         m_decoder_capability.max_height = 720;
1770         DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1771     }
1772 
1773     if ((drv_ctx.video_resolution.frame_width *
1774                 drv_ctx.video_resolution.frame_height >
1775                 m_decoder_capability.max_width *
1776                 m_decoder_capability.max_height) ||
1777             (drv_ctx.video_resolution.frame_width*
1778              drv_ctx.video_resolution.frame_height <
1779              m_decoder_capability.min_width *
1780              m_decoder_capability.min_height)) {
1781         DEBUG_PRINT_ERROR(
1782                 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1783                 drv_ctx.video_resolution.frame_width,
1784                 drv_ctx.video_resolution.frame_height,
1785                 m_decoder_capability.min_width,
1786                 m_decoder_capability.min_height,
1787                 m_decoder_capability.max_width,
1788                 m_decoder_capability.max_height);
1789         return OMX_ErrorUnsupportedSetting;
1790     }
1791     DEBUG_PRINT_HIGH("video session supported");
1792     return OMX_ErrorNone;
1793 }
1794 
log_input_buffers(const char * buffer_addr,int buffer_len)1795 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1796 {
1797     if (m_debug.in_buffer_log && !m_debug.infile) {
1798         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1799            snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1800                    m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1801         } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1802                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1803                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1804         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
1805                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
1806                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1807         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1808                     !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1809                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
1810                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1811         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1812                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1813                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1814         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
1815                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1816                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1817         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
1818                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1819                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1820         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1821                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1822                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1823         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1824                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1825                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1826         } else {
1827                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
1828                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1829         }
1830         m_debug.infile = fopen (m_debug.infile_name, "ab");
1831         if (!m_debug.infile) {
1832             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1833             m_debug.infile_name[0] = '\0';
1834             return -1;
1835         }
1836         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1837                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1838             struct ivf_file_header {
1839                 OMX_U8 signature[4]; //='DKIF';
1840                 OMX_U8 version         ; //= 0;
1841                 OMX_U8 headersize      ; //= 32;
1842                 OMX_U32 FourCC;
1843                 OMX_U8 width;
1844                 OMX_U8 height;
1845                 OMX_U32 rate;
1846                 OMX_U32 scale;
1847                 OMX_U32 length;
1848                 OMX_U8 unused[4];
1849             } file_header;
1850 
1851             memset((void *)&file_header,0,sizeof(file_header));
1852             file_header.signature[0] = 'D';
1853             file_header.signature[1] = 'K';
1854             file_header.signature[2] = 'I';
1855             file_header.signature[3] = 'F';
1856             file_header.version = 0;
1857             file_header.headersize = 32;
1858             switch (drv_ctx.decoder_format) {
1859                 case VDEC_CODECTYPE_VP8:
1860                     file_header.FourCC = 0x30385056;
1861                     break;
1862                 case VDEC_CODECTYPE_VP9:
1863                     file_header.FourCC = 0x30395056;
1864                     break;
1865                 default:
1866                     DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
1867                     break;
1868             }
1869             fwrite((const char *)&file_header,
1870                     sizeof(file_header),1,m_debug.infile);
1871          }
1872     }
1873     if (m_debug.infile && buffer_addr && buffer_len) {
1874         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1875                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1876             struct vpx_ivf_frame_header {
1877                 OMX_U32 framesize;
1878                 OMX_U32 timestamp_lo;
1879                 OMX_U32 timestamp_hi;
1880             } vpx_frame_header;
1881             vpx_frame_header.framesize = buffer_len;
1882             /* Currently FW doesn't use timestamp values */
1883             vpx_frame_header.timestamp_lo = 0;
1884             vpx_frame_header.timestamp_hi = 0;
1885             fwrite((const char *)&vpx_frame_header,
1886                     sizeof(vpx_frame_header),1,m_debug.infile);
1887         }
1888         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1889     }
1890     return 0;
1891 }
1892 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1893 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
1894     int buf_index = 0;
1895     char *temp = NULL;
1896 
1897     if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
1898         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
1899                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1900         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1901         if (!m_debug.outfile) {
1902             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1903             m_debug.outfile_name[0] = '\0';
1904             return -1;
1905         }
1906     }
1907 
1908     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
1909         && buffer->nFilledLen) {
1910         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
1911                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1912         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
1913                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1914         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
1915         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
1916         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
1917             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
1918             m_debug.out_ymetafile_name[0] = '\0';
1919             m_debug.out_uvmetafile_name[0] = '\0';
1920             return -1;
1921         }
1922     }
1923 
1924     if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
1925         return 0;
1926 
1927     buf_index = buffer - m_out_mem_ptr;
1928     temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1929 
1930     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
1931         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
1932             drv_ctx.video_resolution.frame_width,
1933             drv_ctx.video_resolution.frame_height);
1934 
1935         if (m_debug.outfile)
1936             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
1937 
1938         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
1939             unsigned int width = 0, height = 0;
1940             unsigned int y_plane, y_meta_plane;
1941             int y_stride = 0, y_sclines = 0;
1942             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
1943             int color_fmt = COLOR_FMT_NV12_UBWC;
1944             int i;
1945             int bytes_written = 0;
1946 
1947             width = drv_ctx.video_resolution.frame_width;
1948             height = drv_ctx.video_resolution.frame_height;
1949             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
1950             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
1951             y_stride = VENUS_Y_STRIDE(color_fmt, width);
1952             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
1953             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
1954             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
1955 
1956             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
1957             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
1958 
1959             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1960             for (i = 0; i < y_meta_scanlines; i++) {
1961                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
1962                  temp += y_meta_stride;
1963             }
1964 
1965             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
1966             for(i = 0; i < uv_meta_scanlines; i++) {
1967                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
1968                 temp += uv_meta_stride;
1969             }
1970         }
1971     } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) {
1972         int stride = drv_ctx.video_resolution.stride;
1973         int scanlines = drv_ctx.video_resolution.scan_lines;
1974         if (m_smoothstreaming_mode) {
1975             stride = drv_ctx.video_resolution.frame_width;
1976             scanlines = drv_ctx.video_resolution.frame_height;
1977             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
1978             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
1979         }
1980         unsigned i;
1981         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1982             drv_ctx.video_resolution.frame_width,
1983             drv_ctx.video_resolution.frame_height, stride, scanlines);
1984         int bytes_written = 0;
1985         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1986              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1987              temp += stride;
1988         }
1989         temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
1990         int stride_c = stride;
1991         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1992             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1993             temp += stride_c;
1994         }
1995     }
1996     return 0;
1997 }
1998 
1999 /* ======================================================================
2000    FUNCTION
2001    omx_vdec::ComponentInit
2002 
2003    DESCRIPTION
2004    Initialize the component.
2005 
2006    PARAMETERS
2007    ctxt -- Context information related to the self.
2008    id   -- Event identifier. This could be any of the following:
2009    1. Command completion event
2010    2. Buffer done callback event
2011    3. Frame done callback event
2012 
2013    RETURN VALUE
2014    None.
2015 
2016    ========================================================================== */
component_init(OMX_STRING role)2017 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2018 {
2019 
2020     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2021     struct v4l2_fmtdesc fdesc;
2022     struct v4l2_format fmt;
2023     struct v4l2_requestbuffers bufreq;
2024     struct v4l2_control control;
2025     struct v4l2_frmsizeenum frmsize;
2026     unsigned int   alignment = 0,buffer_size = 0;
2027     int fds[2];
2028     int r,ret=0;
2029     bool codec_ambiguous = false;
2030     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2031     char property_value[PROPERTY_VALUE_MAX] = {0};
2032     FILE *soc_file = NULL;
2033     char buffer[10];
2034 
2035 #ifdef _ANDROID_
2036     char platform_name[PROPERTY_VALUE_MAX];
2037     property_get("ro.board.platform", platform_name, "0");
2038     if (!strncmp(platform_name, "msm8610", 7)) {
2039         device_name = (OMX_STRING)"/dev/video/q6_dec";
2040         is_q6_platform = true;
2041         maxSmoothStreamingWidth = 1280;
2042         maxSmoothStreamingHeight = 720;
2043     }
2044 #endif
2045 
2046     is_thulium_v1 = false;
2047     soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2048     if (soc_file) {
2049         fread(buffer, 1, 4, soc_file);
2050         fclose(soc_file);
2051         if (atoi(buffer) == 246) {
2052             soc_file = fopen("/sys/devices/soc0/revision", "r");
2053             if (soc_file) {
2054                 fread(buffer, 1, 4, soc_file);
2055                 fclose(soc_file);
2056                 if (atoi(buffer) == 1) {
2057                     is_thulium_v1 = true;
2058                     DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2059                 }
2060             }
2061         }
2062     }
2063 
2064 #ifdef _ANDROID_
2065     /*
2066      * turn off frame parsing for Android by default.
2067      * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2068      */
2069     arbitrary_bytes = false;
2070     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2071     if (atoi(property_value)) {
2072         DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2073         arbitrary_bytes = true;
2074     }
2075 #endif
2076 
2077     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2078                 OMX_MAX_STRINGNAME_SIZE)) {
2079         secure_mode = true;
2080         arbitrary_bytes = false;
2081         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2082     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2083                 OMX_MAX_STRINGNAME_SIZE)) {
2084         secure_mode = true;
2085         arbitrary_bytes = false;
2086         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2087     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2088                 OMX_MAX_STRINGNAME_SIZE)) {
2089         secure_mode = true;
2090         arbitrary_bytes = false;
2091         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2092     } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2093                 OMX_MAX_STRINGNAME_SIZE)) {
2094         secure_mode = true;
2095         arbitrary_bytes = false;
2096         role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2097     } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2098                 OMX_MAX_STRINGNAME_SIZE)) {
2099         secure_mode = true;
2100         arbitrary_bytes = false;
2101         role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2102     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2103                 OMX_MAX_STRINGNAME_SIZE)) {
2104         secure_mode = true;
2105         arbitrary_bytes = false;
2106         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2107     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2108                 OMX_MAX_STRINGNAME_SIZE)) {
2109         secure_mode = true;
2110         arbitrary_bytes = false;
2111         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2112     }
2113 
2114     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2115 
2116     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2117 
2118     if (drv_ctx.video_driver_fd < 0) {
2119         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2120         return OMX_ErrorInsufficientResources;
2121     }
2122     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2123     drv_ctx.frame_rate.fps_denominator = 1;
2124     m_poll_efd = eventfd(0, 0);
2125     if (m_poll_efd < 0) {
2126         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2127         return OMX_ErrorInsufficientResources;
2128     }
2129     ret = subscribe_to_events(drv_ctx.video_driver_fd);
2130     if (!ret) {
2131         async_thread_created = true;
2132         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2133     }
2134     if (ret) {
2135         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2136         async_thread_created = false;
2137         return OMX_ErrorInsufficientResources;
2138     }
2139 
2140 #ifdef OUTPUT_EXTRADATA_LOG
2141     outputExtradataFile = fopen (output_extradata_filename, "ab");
2142 #endif
2143 
2144     // Copy the role information which provides the decoder kind
2145     strlcpy(drv_ctx.kind,role,128);
2146 
2147     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2148                 OMX_MAX_STRINGNAME_SIZE)) {
2149         strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2150                 OMX_MAX_STRINGNAME_SIZE);
2151         drv_ctx.timestamp_adjust = true;
2152         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2153         eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2154         output_capability=V4L2_PIX_FMT_MPEG4;
2155         /*Initialize Start Code for MPEG4*/
2156         codec_type_parse = CODEC_TYPE_MPEG4;
2157         m_frame_parser.init_start_codes(codec_type_parse);
2158     } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2159                 OMX_MAX_STRINGNAME_SIZE)) {
2160         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2161                 OMX_MAX_STRINGNAME_SIZE);
2162         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2163         output_capability = V4L2_PIX_FMT_MPEG2;
2164         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2165         /*Initialize Start Code for MPEG2*/
2166         codec_type_parse = CODEC_TYPE_MPEG2;
2167         m_frame_parser.init_start_codes(codec_type_parse);
2168     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2169                 OMX_MAX_STRINGNAME_SIZE)) {
2170         strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2171         DEBUG_PRINT_LOW("H263 Decoder selected");
2172         drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2173         eCompressionFormat = OMX_VIDEO_CodingH263;
2174         output_capability = V4L2_PIX_FMT_H263;
2175         codec_type_parse = CODEC_TYPE_H263;
2176         m_frame_parser.init_start_codes(codec_type_parse);
2177     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2178                 OMX_MAX_STRINGNAME_SIZE)) {
2179         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2180         DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2181         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2182         output_capability = V4L2_PIX_FMT_DIVX_311;
2183         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2184         codec_type_parse = CODEC_TYPE_DIVX;
2185         m_frame_parser.init_start_codes(codec_type_parse);
2186 
2187     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2188                 OMX_MAX_STRINGNAME_SIZE)) {
2189         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2190         DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2191         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2192         output_capability = V4L2_PIX_FMT_DIVX;
2193         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2194         codec_type_parse = CODEC_TYPE_DIVX;
2195         codec_ambiguous = true;
2196         m_frame_parser.init_start_codes(codec_type_parse);
2197 
2198     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2199                 OMX_MAX_STRINGNAME_SIZE)) {
2200         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2201         DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2202         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2203         output_capability = V4L2_PIX_FMT_DIVX;
2204         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2205         codec_type_parse = CODEC_TYPE_DIVX;
2206         codec_ambiguous = true;
2207         m_frame_parser.init_start_codes(codec_type_parse);
2208 
2209     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2210                 OMX_MAX_STRINGNAME_SIZE)) {
2211         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2212         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2213         output_capability=V4L2_PIX_FMT_H264;
2214         eCompressionFormat = OMX_VIDEO_CodingAVC;
2215         codec_type_parse = CODEC_TYPE_H264;
2216         m_frame_parser.init_start_codes(codec_type_parse);
2217         m_frame_parser.init_nal_length(nal_length);
2218         if (is_thulium_v1) {
2219             arbitrary_bytes = true;
2220             DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2221         }
2222     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2223                 OMX_MAX_STRINGNAME_SIZE)) {
2224         strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2225         drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2226         output_capability = V4L2_PIX_FMT_H264_MVC;
2227         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2228         codec_type_parse = CODEC_TYPE_H264;
2229         m_frame_parser.init_start_codes(codec_type_parse);
2230         m_frame_parser.init_nal_length(nal_length);
2231     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2232                 OMX_MAX_STRINGNAME_SIZE)) {
2233         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2234         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2235         output_capability = V4L2_PIX_FMT_HEVC;
2236         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2237         codec_type_parse = CODEC_TYPE_HEVC;
2238         m_frame_parser.init_start_codes(codec_type_parse);
2239         m_frame_parser.init_nal_length(nal_length);
2240     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2241                 OMX_MAX_STRINGNAME_SIZE)) {
2242         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2243         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2244         eCompressionFormat = OMX_VIDEO_CodingWMV;
2245         codec_type_parse = CODEC_TYPE_VC1;
2246         output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2247         m_frame_parser.init_start_codes(codec_type_parse);
2248     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2249                 OMX_MAX_STRINGNAME_SIZE)) {
2250         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2251         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2252         eCompressionFormat = OMX_VIDEO_CodingWMV;
2253         codec_type_parse = CODEC_TYPE_VC1;
2254         output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2255         m_frame_parser.init_start_codes(codec_type_parse);
2256     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2257                 OMX_MAX_STRINGNAME_SIZE)) {
2258         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2259         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2260         output_capability = V4L2_PIX_FMT_VP8;
2261         eCompressionFormat = OMX_VIDEO_CodingVP8;
2262         codec_type_parse = CODEC_TYPE_VP8;
2263         arbitrary_bytes = false;
2264     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2265                 OMX_MAX_STRINGNAME_SIZE)) {
2266         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2267         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2268         output_capability = V4L2_PIX_FMT_VP9;
2269         eCompressionFormat = OMX_VIDEO_CodingVP9;
2270         codec_type_parse = CODEC_TYPE_VP9;
2271         arbitrary_bytes = false;
2272     } else {
2273         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2274         eRet = OMX_ErrorInvalidComponentName;
2275     }
2276 
2277     if (eRet == OMX_ErrorNone) {
2278         OMX_COLOR_FORMATTYPE dest_color_format;
2279         if (m_disable_ubwc_mode) {
2280             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2281         } else {
2282             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2283         }
2284         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2285             dest_color_format = (OMX_COLOR_FORMATTYPE)
2286                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2287         else
2288             dest_color_format = (OMX_COLOR_FORMATTYPE)
2289                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2290         if (!client_buffers.set_color_format(dest_color_format)) {
2291             DEBUG_PRINT_ERROR("Setting color format failed");
2292             eRet = OMX_ErrorInsufficientResources;
2293         }
2294 
2295         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2296 
2297         if (m_disable_ubwc_mode) {
2298             capture_capability = V4L2_PIX_FMT_NV12;
2299         } else {
2300             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2301         }
2302 
2303         struct v4l2_capability cap;
2304         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2305         if (ret) {
2306             DEBUG_PRINT_ERROR("Failed to query capabilities");
2307             /*TODO: How to handle this case */
2308         } else {
2309             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2310                 " version = %d, capabilities = %x", cap.driver, cap.card,
2311                 cap.bus_info, cap.version, cap.capabilities);
2312         }
2313         ret=0;
2314         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2315         fdesc.index=0;
2316         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2317             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2318                     fdesc.pixelformat, fdesc.flags);
2319             fdesc.index++;
2320         }
2321         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2322         fdesc.index=0;
2323         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2324 
2325             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2326                     fdesc.pixelformat, fdesc.flags);
2327             fdesc.index++;
2328         }
2329         update_resolution(320, 240, 320, 240);
2330         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2331         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2332         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2333         fmt.fmt.pix_mp.pixelformat = output_capability;
2334         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2335         if (ret) {
2336             /*TODO: How to handle this case */
2337             DEBUG_PRINT_ERROR("Failed to set format on output port");
2338             return OMX_ErrorInsufficientResources;
2339         }
2340         DEBUG_PRINT_HIGH("Set Format was successful");
2341         if (codec_ambiguous) {
2342             if (output_capability == V4L2_PIX_FMT_DIVX) {
2343                 struct v4l2_control divx_ctrl;
2344 
2345                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2346                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2347                 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2348                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2349                 } else {
2350                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2351                 }
2352 
2353                 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2354                 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2355                 if (ret) {
2356                     DEBUG_PRINT_ERROR("Failed to set divx version");
2357                 }
2358             } else {
2359                 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2360             }
2361         }
2362 
2363         property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2364         m_conceal_color= atoi(property_value);
2365         DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2366         control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2367         control.value = m_conceal_color;
2368         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2369         if (ret) {
2370             DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2371         }
2372 
2373         //Get the hardware capabilities
2374         memset((void *)&frmsize,0,sizeof(frmsize));
2375         frmsize.index = 0;
2376         frmsize.pixel_format = output_capability;
2377         ret = ioctl(drv_ctx.video_driver_fd,
2378                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2379         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2380             DEBUG_PRINT_ERROR("Failed to get framesizes");
2381             return OMX_ErrorHardware;
2382         }
2383 
2384         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2385             m_decoder_capability.min_width = frmsize.stepwise.min_width;
2386             m_decoder_capability.max_width = frmsize.stepwise.max_width;
2387             m_decoder_capability.min_height = frmsize.stepwise.min_height;
2388             m_decoder_capability.max_height = frmsize.stepwise.max_height;
2389         }
2390 
2391         memset(&fmt, 0x0, sizeof(struct v4l2_format));
2392         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2393         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2394         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2395         fmt.fmt.pix_mp.pixelformat = capture_capability;
2396         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2397         if (ret) {
2398             /*TODO: How to handle this case */
2399             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2400         }
2401         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2402         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2403         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2404 
2405         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2406         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2407         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2408 
2409         DEBUG_PRINT_HIGH("Set Format was successful");
2410         if (secure_mode) {
2411             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2412             control.value = 1;
2413             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2414             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2415             if (ret) {
2416                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2417                 return OMX_ErrorInsufficientResources;
2418             }
2419         }
2420         if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2421             control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2422             control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2423             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2424             if (ret) {
2425                 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2426                 return OMX_ErrorInsufficientResources;
2427             }
2428         }
2429 
2430         if (is_thulium_v1) {
2431             eRet = enable_smoothstreaming();
2432             if (eRet != OMX_ErrorNone) {
2433                DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2434                return eRet;
2435             }
2436         }
2437 
2438         /*Get the Buffer requirements for input and output ports*/
2439         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2440         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2441 
2442         if (secure_mode) {
2443             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2444             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2445         } else {
2446             drv_ctx.op_buf.alignment = SZ_4K;
2447             drv_ctx.ip_buf.alignment = SZ_4K;
2448         }
2449 
2450         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2451         drv_ctx.extradata = 0;
2452         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2453         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2454         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2455         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2456         drv_ctx.idr_only_decoding = 0;
2457 
2458 #ifdef _ANDROID_
2459         property_get("vidc.dec.downscalar_width",property_value,"0");
2460         if (atoi(property_value)) {
2461             m_downscalar_width = atoi(property_value);
2462         }
2463         property_get("vidc.dec.downscalar_height",property_value,"0");
2464         if (atoi(property_value)) {
2465             m_downscalar_height = atoi(property_value);
2466         }
2467 
2468         if (m_downscalar_width < m_decoder_capability.min_width ||
2469             m_downscalar_height < m_decoder_capability.min_height) {
2470             m_downscalar_width = 0;
2471             m_downscalar_height = 0;
2472         }
2473 
2474         DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2475             m_downscalar_width, m_downscalar_height);
2476 #endif
2477         m_state = OMX_StateLoaded;
2478 #ifdef DEFAULT_EXTRADATA
2479         if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",
2480                     OMX_MAX_STRINGNAME_SIZE) &&
2481                 strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",
2482                         OMX_MAX_STRINGNAME_SIZE)) &&
2483                 (eRet == OMX_ErrorNone))
2484                 enable_extradata(DEFAULT_EXTRADATA, true, true);
2485 #endif
2486         eRet = get_buffer_req(&drv_ctx.ip_buf);
2487         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2488         get_buffer_req(&drv_ctx.op_buf);
2489         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2490                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2491                 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2492                     h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2493                     h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2494                     h264_scratch.nFilledLen = 0;
2495                     h264_scratch.nOffset = 0;
2496 
2497                     if (h264_scratch.pBuffer == NULL) {
2498                         DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2499                         return OMX_ErrorInsufficientResources;
2500                     }
2501         }
2502         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2503             drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2504             if (m_frame_parser.mutils == NULL) {
2505                 m_frame_parser.mutils = new H264_Utils();
2506                 if (m_frame_parser.mutils == NULL) {
2507                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2508                     eRet = OMX_ErrorInsufficientResources;
2509                 } else {
2510                     m_frame_parser.mutils->initialize_frame_checking_environment();
2511                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2512                 }
2513             }
2514 
2515             h264_parser = new h264_stream_parser();
2516             if (!h264_parser) {
2517                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2518                 eRet = OMX_ErrorInsufficientResources;
2519             }
2520         }
2521 
2522         if (pipe(fds)) {
2523             DEBUG_PRINT_ERROR("pipe creation failed");
2524             eRet = OMX_ErrorInsufficientResources;
2525         } else {
2526             m_pipe_in = fds[0];
2527             m_pipe_out = fds[1];
2528             msg_thread_created = true;
2529             r = pthread_create(&msg_thread_id,0,message_thread,this);
2530 
2531             if (r < 0) {
2532                 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
2533                 msg_thread_created = false;
2534                 eRet = OMX_ErrorInsufficientResources;
2535             }
2536         }
2537     }
2538 
2539     if (eRet != OMX_ErrorNone) {
2540         DEBUG_PRINT_ERROR("Component Init Failed");
2541     } else {
2542         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2543                 drv_ctx.video_driver_fd);
2544     }
2545     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2546     return eRet;
2547 }
2548 
2549 /* ======================================================================
2550    FUNCTION
2551    omx_vdec::GetComponentVersion
2552 
2553    DESCRIPTION
2554    Returns the component version.
2555 
2556    PARAMETERS
2557    TBD.
2558 
2559    RETURN VALUE
2560    OMX_ErrorNone.
2561 
2562    ========================================================================== */
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)2563 OMX_ERRORTYPE  omx_vdec::get_component_version
2564 (
2565  OMX_IN OMX_HANDLETYPE hComp,
2566  OMX_OUT OMX_STRING componentName,
2567  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2568  OMX_OUT OMX_VERSIONTYPE* specVersion,
2569  OMX_OUT OMX_UUIDTYPE* componentUUID
2570  )
2571 {
2572     (void) hComp;
2573     (void) componentName;
2574     (void) componentVersion;
2575     (void) componentUUID;
2576     if (m_state == OMX_StateInvalid) {
2577         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2578         return OMX_ErrorInvalidState;
2579     }
2580     /* TBD -- Return the proper version */
2581     if (specVersion) {
2582         specVersion->nVersion = OMX_SPEC_VERSION;
2583     }
2584     return OMX_ErrorNone;
2585 }
2586 /* ======================================================================
2587    FUNCTION
2588    omx_vdec::SendCommand
2589 
2590    DESCRIPTION
2591    Returns zero if all the buffers released..
2592 
2593    PARAMETERS
2594    None.
2595 
2596    RETURN VALUE
2597    true/false
2598 
2599    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2600 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2601         OMX_IN OMX_COMMANDTYPE cmd,
2602         OMX_IN OMX_U32 param1,
2603         OMX_IN OMX_PTR cmdData
2604         )
2605 {
2606     (void) hComp;
2607     (void) cmdData;
2608     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2609     if (m_state == OMX_StateInvalid) {
2610         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2611         return OMX_ErrorInvalidState;
2612     }
2613     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2614             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2615         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2616                 "to invalid port: %u", (unsigned int)param1);
2617         return OMX_ErrorBadPortIndex;
2618     }
2619 
2620     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2621     sem_wait(&m_cmd_lock);
2622     DEBUG_PRINT_LOW("send_command: Command Processed");
2623     return OMX_ErrorNone;
2624 }
2625 
2626 /* ======================================================================
2627    FUNCTION
2628    omx_vdec::SendCommand
2629 
2630    DESCRIPTION
2631    Returns zero if all the buffers released..
2632 
2633    PARAMETERS
2634    None.
2635 
2636    RETURN VALUE
2637    true/false
2638 
2639    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2640 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2641         OMX_IN OMX_COMMANDTYPE cmd,
2642         OMX_IN OMX_U32 param1,
2643         OMX_IN OMX_PTR cmdData
2644         )
2645 {
2646     (void) hComp;
2647     (void) cmdData;
2648     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2649     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2650     int bFlag = 1,sem_posted = 0,ret=0;
2651 
2652     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2653     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2654             m_state, eState);
2655 
2656     if (cmd == OMX_CommandStateSet) {
2657         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2658         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2659         /***************************/
2660         /* Current State is Loaded */
2661         /***************************/
2662         if (m_state == OMX_StateLoaded) {
2663             if (eState == OMX_StateIdle) {
2664                 //if all buffers are allocated or all ports disabled
2665                 if (allocate_done() ||
2666                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2667                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2668                 } else {
2669                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2670                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2671                     // Skip the event notification
2672                     bFlag = 0;
2673                 }
2674             }
2675             /* Requesting transition from Loaded to Loaded */
2676             else if (eState == OMX_StateLoaded) {
2677                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2678                 post_event(OMX_EventError,OMX_ErrorSameState,\
2679                         OMX_COMPONENT_GENERATE_EVENT);
2680                 eRet = OMX_ErrorSameState;
2681             }
2682             /* Requesting transition from Loaded to WaitForResources */
2683             else if (eState == OMX_StateWaitForResources) {
2684                 /* Since error is None , we will post an event
2685                    at the end of this function definition */
2686                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2687             }
2688             /* Requesting transition from Loaded to Executing */
2689             else if (eState == OMX_StateExecuting) {
2690                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2691                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2692                         OMX_COMPONENT_GENERATE_EVENT);
2693                 eRet = OMX_ErrorIncorrectStateTransition;
2694             }
2695             /* Requesting transition from Loaded to Pause */
2696             else if (eState == OMX_StatePause) {
2697                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2698                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2699                         OMX_COMPONENT_GENERATE_EVENT);
2700                 eRet = OMX_ErrorIncorrectStateTransition;
2701             }
2702             /* Requesting transition from Loaded to Invalid */
2703             else if (eState == OMX_StateInvalid) {
2704                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2705                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2706                 eRet = OMX_ErrorInvalidState;
2707             } else {
2708                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2709                         eState);
2710                 eRet = OMX_ErrorBadParameter;
2711             }
2712         }
2713 
2714         /***************************/
2715         /* Current State is IDLE */
2716         /***************************/
2717         else if (m_state == OMX_StateIdle) {
2718             if (eState == OMX_StateLoaded) {
2719                 if (release_done()) {
2720                     /*
2721                        Since error is None , we will post an event at the end
2722                        of this function definition
2723                      */
2724                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2725                 } else {
2726                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2727                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2728                     // Skip the event notification
2729                     bFlag = 0;
2730                 }
2731             }
2732             /* Requesting transition from Idle to Executing */
2733             else if (eState == OMX_StateExecuting) {
2734                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2735                 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2736                 bFlag = 1;
2737                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2738                 m_state=OMX_StateExecuting;
2739                 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2740             }
2741             /* Requesting transition from Idle to Idle */
2742             else if (eState == OMX_StateIdle) {
2743                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2744                 post_event(OMX_EventError,OMX_ErrorSameState,\
2745                         OMX_COMPONENT_GENERATE_EVENT);
2746                 eRet = OMX_ErrorSameState;
2747             }
2748             /* Requesting transition from Idle to WaitForResources */
2749             else if (eState == OMX_StateWaitForResources) {
2750                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2751                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2752                         OMX_COMPONENT_GENERATE_EVENT);
2753                 eRet = OMX_ErrorIncorrectStateTransition;
2754             }
2755             /* Requesting transition from Idle to Pause */
2756             else if (eState == OMX_StatePause) {
2757                 /*To pause the Video core we need to start the driver*/
2758                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2759                       NULL) < */0) {
2760                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2761                     omx_report_error ();
2762                     eRet = OMX_ErrorHardware;
2763                 } else {
2764                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2765                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2766                     bFlag = 0;
2767                 }
2768             }
2769             /* Requesting transition from Idle to Invalid */
2770             else if (eState == OMX_StateInvalid) {
2771                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2772                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2773                 eRet = OMX_ErrorInvalidState;
2774             } else {
2775                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2776                 eRet = OMX_ErrorBadParameter;
2777             }
2778         }
2779 
2780         /******************************/
2781         /* Current State is Executing */
2782         /******************************/
2783         else if (m_state == OMX_StateExecuting) {
2784             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2785             /* Requesting transition from Executing to Idle */
2786             if (eState == OMX_StateIdle) {
2787                 /* Since error is None , we will post an event
2788                    at the end of this function definition
2789                  */
2790                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2791                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2792                 if (!sem_posted) {
2793                     sem_posted = 1;
2794                     sem_post (&m_cmd_lock);
2795                     execute_omx_flush(OMX_ALL);
2796                 }
2797                 bFlag = 0;
2798             }
2799             /* Requesting transition from Executing to Paused */
2800             else if (eState == OMX_StatePause) {
2801                 DEBUG_PRINT_LOW("PAUSE Command Issued");
2802                 m_state = OMX_StatePause;
2803                 bFlag = 1;
2804             }
2805             /* Requesting transition from Executing to Loaded */
2806             else if (eState == OMX_StateLoaded) {
2807                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2808                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2809                         OMX_COMPONENT_GENERATE_EVENT);
2810                 eRet = OMX_ErrorIncorrectStateTransition;
2811             }
2812             /* Requesting transition from Executing to WaitForResources */
2813             else if (eState == OMX_StateWaitForResources) {
2814                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2815                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2816                         OMX_COMPONENT_GENERATE_EVENT);
2817                 eRet = OMX_ErrorIncorrectStateTransition;
2818             }
2819             /* Requesting transition from Executing to Executing */
2820             else if (eState == OMX_StateExecuting) {
2821                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2822                 post_event(OMX_EventError,OMX_ErrorSameState,\
2823                         OMX_COMPONENT_GENERATE_EVENT);
2824                 eRet = OMX_ErrorSameState;
2825             }
2826             /* Requesting transition from Executing to Invalid */
2827             else if (eState == OMX_StateInvalid) {
2828                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2829                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2830                 eRet = OMX_ErrorInvalidState;
2831             } else {
2832                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2833                 eRet = OMX_ErrorBadParameter;
2834             }
2835         }
2836         /***************************/
2837         /* Current State is Pause  */
2838         /***************************/
2839         else if (m_state == OMX_StatePause) {
2840             /* Requesting transition from Pause to Executing */
2841             if (eState == OMX_StateExecuting) {
2842                 DEBUG_PRINT_LOW("Pause --> Executing");
2843                 m_state = OMX_StateExecuting;
2844                 bFlag = 1;
2845             }
2846             /* Requesting transition from Pause to Idle */
2847             else if (eState == OMX_StateIdle) {
2848                 /* Since error is None , we will post an event
2849                    at the end of this function definition */
2850                 DEBUG_PRINT_LOW("Pause --> Idle");
2851                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2852                 if (!sem_posted) {
2853                     sem_posted = 1;
2854                     sem_post (&m_cmd_lock);
2855                     execute_omx_flush(OMX_ALL);
2856                 }
2857                 bFlag = 0;
2858             }
2859             /* Requesting transition from Pause to loaded */
2860             else if (eState == OMX_StateLoaded) {
2861                 DEBUG_PRINT_ERROR("Pause --> loaded");
2862                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2863                         OMX_COMPONENT_GENERATE_EVENT);
2864                 eRet = OMX_ErrorIncorrectStateTransition;
2865             }
2866             /* Requesting transition from Pause to WaitForResources */
2867             else if (eState == OMX_StateWaitForResources) {
2868                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2869                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2870                         OMX_COMPONENT_GENERATE_EVENT);
2871                 eRet = OMX_ErrorIncorrectStateTransition;
2872             }
2873             /* Requesting transition from Pause to Pause */
2874             else if (eState == OMX_StatePause) {
2875                 DEBUG_PRINT_ERROR("Pause --> Pause");
2876                 post_event(OMX_EventError,OMX_ErrorSameState,\
2877                         OMX_COMPONENT_GENERATE_EVENT);
2878                 eRet = OMX_ErrorSameState;
2879             }
2880             /* Requesting transition from Pause to Invalid */
2881             else if (eState == OMX_StateInvalid) {
2882                 DEBUG_PRINT_ERROR("Pause --> Invalid");
2883                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2884                 eRet = OMX_ErrorInvalidState;
2885             } else {
2886                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2887                 eRet = OMX_ErrorBadParameter;
2888             }
2889         }
2890         /***************************/
2891         /* Current State is WaitForResources  */
2892         /***************************/
2893         else if (m_state == OMX_StateWaitForResources) {
2894             /* Requesting transition from WaitForResources to Loaded */
2895             if (eState == OMX_StateLoaded) {
2896                 /* Since error is None , we will post an event
2897                    at the end of this function definition */
2898                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2899             }
2900             /* Requesting transition from WaitForResources to WaitForResources */
2901             else if (eState == OMX_StateWaitForResources) {
2902                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2903                 post_event(OMX_EventError,OMX_ErrorSameState,
2904                         OMX_COMPONENT_GENERATE_EVENT);
2905                 eRet = OMX_ErrorSameState;
2906             }
2907             /* Requesting transition from WaitForResources to Executing */
2908             else if (eState == OMX_StateExecuting) {
2909                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2910                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2911                         OMX_COMPONENT_GENERATE_EVENT);
2912                 eRet = OMX_ErrorIncorrectStateTransition;
2913             }
2914             /* Requesting transition from WaitForResources to Pause */
2915             else if (eState == OMX_StatePause) {
2916                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2917                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2918                         OMX_COMPONENT_GENERATE_EVENT);
2919                 eRet = OMX_ErrorIncorrectStateTransition;
2920             }
2921             /* Requesting transition from WaitForResources to Invalid */
2922             else if (eState == OMX_StateInvalid) {
2923                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2924                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2925                 eRet = OMX_ErrorInvalidState;
2926             }
2927             /* Requesting transition from WaitForResources to Loaded -
2928                is NOT tested by Khronos TS */
2929 
2930         } else {
2931             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2932             eRet = OMX_ErrorBadParameter;
2933         }
2934     }
2935     /********************************/
2936     /* Current State is Invalid */
2937     /*******************************/
2938     else if (m_state == OMX_StateInvalid) {
2939         /* State Transition from Inavlid to any state */
2940         if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
2941                     || OMX_StateIdle || OMX_StateExecuting
2942                     || OMX_StatePause || OMX_StateInvalid)) {
2943             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2944             post_event(OMX_EventError,OMX_ErrorInvalidState,\
2945                     OMX_COMPONENT_GENERATE_EVENT);
2946             eRet = OMX_ErrorInvalidState;
2947         }
2948     } else if (cmd == OMX_CommandFlush) {
2949         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2950                 "with param1: %u", (unsigned int)param1);
2951 #ifdef _MSM8974_
2952         send_codec_config();
2953 #endif
2954         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2955                     param1 == OMX_ALL)) {
2956             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2957                struct timespec ts;
2958 
2959                clock_gettime(CLOCK_REALTIME, &ts);
2960                ts.tv_sec += 2;
2961                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2962                        m_queued_codec_config_count);
2963                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2964                if (sem_timedwait(&m_safe_flush, &ts)) {
2965                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2966                }
2967                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2968             }
2969         }
2970 
2971         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2972             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2973         }
2974         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2975             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2976         }
2977         if (!sem_posted) {
2978             sem_posted = 1;
2979             DEBUG_PRINT_LOW("Set the Semaphore");
2980             sem_post (&m_cmd_lock);
2981             execute_omx_flush(param1);
2982         }
2983         bFlag = 0;
2984     } else if ( cmd == OMX_CommandPortEnable) {
2985         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2986                 "with param1: %u", (unsigned int)param1);
2987         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2988             m_inp_bEnabled = OMX_TRUE;
2989 
2990             if ( (m_state == OMX_StateLoaded &&
2991                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2992                     || allocate_input_done()) {
2993                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2994                         OMX_COMPONENT_GENERATE_EVENT);
2995             } else {
2996                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2997                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2998                 // Skip the event notification
2999                 bFlag = 0;
3000             }
3001         }
3002         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3003             DEBUG_PRINT_LOW("Enable output Port command recieved");
3004             m_out_bEnabled = OMX_TRUE;
3005 
3006             if ( (m_state == OMX_StateLoaded &&
3007                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3008                     || (allocate_output_done())) {
3009                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3010                         OMX_COMPONENT_GENERATE_EVENT);
3011 
3012             } else {
3013                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3014                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3015                 // Skip the event notification
3016                 bFlag = 0;
3017                 /* enable/disable downscaling if required */
3018                 ret = decide_downscalar();
3019                 if (ret) {
3020                     DEBUG_PRINT_LOW("decide_downscalar failed\n");
3021                 }
3022             }
3023         }
3024     } else if (cmd == OMX_CommandPortDisable) {
3025         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3026                 "with param1: %u", (unsigned int)param1);
3027         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3028             codec_config_flag = false;
3029             m_inp_bEnabled = OMX_FALSE;
3030             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3031                     && release_input_done()) {
3032                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3033                         OMX_COMPONENT_GENERATE_EVENT);
3034             } else {
3035                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3036                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3037                     if (!sem_posted) {
3038                         sem_posted = 1;
3039                         sem_post (&m_cmd_lock);
3040                     }
3041                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3042                 }
3043 
3044                 // Skip the event notification
3045                 bFlag = 0;
3046             }
3047         }
3048         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3049             m_out_bEnabled = OMX_FALSE;
3050             DEBUG_PRINT_LOW("Disable output Port command recieved");
3051             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3052                     && release_output_done()) {
3053                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3054                         OMX_COMPONENT_GENERATE_EVENT);
3055             } else {
3056                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3057                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3058                     if (!sem_posted) {
3059                         sem_posted = 1;
3060                         sem_post (&m_cmd_lock);
3061                     }
3062                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3063                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3064                 }
3065                 // Skip the event notification
3066                 bFlag = 0;
3067 
3068             }
3069         }
3070     } else {
3071         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3072         eRet = OMX_ErrorNotImplemented;
3073     }
3074     if (eRet == OMX_ErrorNone && bFlag) {
3075         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3076     }
3077     if (!sem_posted) {
3078         sem_post(&m_cmd_lock);
3079     }
3080 
3081     return eRet;
3082 }
3083 
3084 /* ======================================================================
3085    FUNCTION
3086    omx_vdec::ExecuteOmxFlush
3087 
3088    DESCRIPTION
3089    Executes the OMX flush.
3090 
3091    PARAMETERS
3092    flushtype - input flush(1)/output flush(0)/ both.
3093 
3094    RETURN VALUE
3095    true/false
3096 
3097    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3098 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3099 {
3100     bool bRet = false;
3101     struct v4l2_plane plane;
3102     struct v4l2_buffer v4l2_buf;
3103     struct v4l2_decoder_cmd dec;
3104     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3105     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3106     dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3107 
3108     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3109 
3110     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3111         output_flush_progress = true;
3112         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3113     } else {
3114         /* XXX: The driver/hardware does not support flushing of individual ports
3115          * in all states. So we pretty much need to flush both ports internally,
3116          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3117          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3118          * we automatically omit sending the FLUSH done for the "opposite" port. */
3119         input_flush_progress = true;
3120         output_flush_progress = true;
3121         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3122         request_perf_level(VIDC_TURBO);
3123     }
3124 
3125     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3126         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3127         bRet = false;
3128     }
3129 
3130     return bRet;
3131 }
3132 /*=========================================================================
3133 FUNCTION : execute_output_flush
3134 
3135 DESCRIPTION
3136 Executes the OMX flush at OUTPUT PORT.
3137 
3138 PARAMETERS
3139 None.
3140 
3141 RETURN VALUE
3142 true/false
3143 ==========================================================================*/
execute_output_flush()3144 bool omx_vdec::execute_output_flush()
3145 {
3146     unsigned long p1 = 0; // Parameter - 1
3147     unsigned long p2 = 0; // Parameter - 2
3148     unsigned long ident = 0;
3149     bool bRet = true;
3150 
3151     /*Generate FBD for all Buffers in the FTBq*/
3152     pthread_mutex_lock(&m_lock);
3153     DEBUG_PRINT_LOW("Initiate Output Flush");
3154 
3155     //reset last render TS
3156     if(m_last_rendered_TS > 0) {
3157         m_last_rendered_TS = 0;
3158     }
3159 
3160     while (m_ftb_q.m_size) {
3161         DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3162                 m_ftb_q.m_size,pending_output_buffers);
3163         m_ftb_q.pop_entry(&p1,&p2,&ident);
3164         DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3165         if (ident == m_fill_output_msg ) {
3166             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3167         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3168             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3169         }
3170     }
3171     pthread_mutex_unlock(&m_lock);
3172     output_flush_progress = false;
3173 
3174     if (arbitrary_bytes) {
3175         prev_ts = LLONG_MAX;
3176         rst_prev_ts = true;
3177     }
3178     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3179     return bRet;
3180 }
3181 /*=========================================================================
3182 FUNCTION : execute_input_flush
3183 
3184 DESCRIPTION
3185 Executes the OMX flush at INPUT PORT.
3186 
3187 PARAMETERS
3188 None.
3189 
3190 RETURN VALUE
3191 true/false
3192 ==========================================================================*/
execute_input_flush()3193 bool omx_vdec::execute_input_flush()
3194 {
3195     unsigned       i =0;
3196     unsigned long p1 = 0; // Parameter - 1
3197     unsigned long p2 = 0; // Parameter - 2
3198     unsigned long ident = 0;
3199     bool bRet = true;
3200 
3201     /*Generate EBD for all Buffers in the ETBq*/
3202     DEBUG_PRINT_LOW("Initiate Input Flush");
3203 
3204     pthread_mutex_lock(&m_lock);
3205     DEBUG_PRINT_LOW("Check if the Queue is empty");
3206     while (m_etb_q.m_size) {
3207         m_etb_q.pop_entry(&p1,&p2,&ident);
3208 
3209         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3210             DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3211             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3212         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3213             pending_input_buffers++;
3214             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3215                     (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3216             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3217         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3218             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3219                     (OMX_BUFFERHEADERTYPE *)p1);
3220             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3221         }
3222     }
3223     time_stamp_dts.flush_timestamp();
3224     /*Check if Heap Buffers are to be flushed*/
3225     if (arbitrary_bytes && !(codec_config_flag)) {
3226         DEBUG_PRINT_LOW("Reset all the variables before flusing");
3227         h264_scratch.nFilledLen = 0;
3228         nal_count = 0;
3229         look_ahead_nal = false;
3230         frame_count = 0;
3231         h264_last_au_ts = LLONG_MAX;
3232         h264_last_au_flags = 0;
3233         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3234         m_demux_entries = 0;
3235         DEBUG_PRINT_LOW("Initialize parser");
3236         if (m_frame_parser.mutils) {
3237             m_frame_parser.mutils->initialize_frame_checking_environment();
3238         }
3239 
3240         while (m_input_pending_q.m_size) {
3241             m_input_pending_q.pop_entry(&p1,&p2,&ident);
3242             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3243         }
3244 
3245         if (psource_frame) {
3246             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3247             psource_frame = NULL;
3248         }
3249 
3250         if (pdest_frame) {
3251             pdest_frame->nFilledLen = 0;
3252             m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3253                     (unsigned int)NULL);
3254             pdest_frame = NULL;
3255         }
3256         m_frame_parser.flush();
3257     } else if (codec_config_flag) {
3258         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3259                 "is not sent to the driver yet");
3260     }
3261     pthread_mutex_unlock(&m_lock);
3262     input_flush_progress = false;
3263     if (!arbitrary_bytes) {
3264         prev_ts = LLONG_MAX;
3265         rst_prev_ts = true;
3266     }
3267 #ifdef _ANDROID_
3268     if (m_debug_timestamp) {
3269         m_timestamp_list.reset_ts_list();
3270     }
3271 #endif
3272     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3273     return bRet;
3274 }
3275 
3276 
3277 /* ======================================================================
3278    FUNCTION
3279    omx_vdec::SendCommandEvent
3280 
3281    DESCRIPTION
3282    Send the event to decoder pipe.  This is needed to generate the callbacks
3283    in decoder thread context.
3284 
3285    PARAMETERS
3286    None.
3287 
3288    RETURN VALUE
3289    true/false
3290 
3291    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3292 bool omx_vdec::post_event(unsigned long p1,
3293         unsigned long p2,
3294         unsigned long id)
3295 {
3296     bool bRet = false;
3297 
3298     /* Just drop messages typically generated by hardware (w/o client request),
3299      * if we've reported an error to client. */
3300     if (m_error_propogated) {
3301         switch (id) {
3302             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3303             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3304                 DEBUG_PRINT_ERROR("Dropping message %lx "
3305                         "since client expected to be in error state", id);
3306                 return false;
3307             default:
3308                 /* whatever */
3309                 break;
3310         }
3311     }
3312 
3313     pthread_mutex_lock(&m_lock);
3314 
3315     if (id == m_fill_output_msg ||
3316             id == OMX_COMPONENT_GENERATE_FBD ||
3317             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3318             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3319         m_ftb_q.insert_entry(p1,p2,id);
3320     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3321             id == OMX_COMPONENT_GENERATE_EBD ||
3322             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3323             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3324         m_etb_q.insert_entry(p1,p2,id);
3325     } else {
3326         m_cmd_q.insert_entry(p1,p2,id);
3327     }
3328 
3329     bRet = true;
3330     DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3331     post_message(this, id);
3332 
3333     pthread_mutex_unlock(&m_lock);
3334 
3335     return bRet;
3336 }
3337 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3338 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3339 {
3340     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3341     if (!profileLevelType)
3342         return OMX_ErrorBadParameter;
3343 
3344     if (profileLevelType->nPortIndex == 0) {
3345         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3346             if (profileLevelType->nProfileIndex == 0) {
3347                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3348                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3349 
3350             } else if (profileLevelType->nProfileIndex == 1) {
3351                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3352                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3353             } else if (profileLevelType->nProfileIndex == 2) {
3354                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3355                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3356             } else {
3357                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3358                         (unsigned int)profileLevelType->nProfileIndex);
3359                 eRet = OMX_ErrorNoMore;
3360             }
3361         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3362             if (profileLevelType->nProfileIndex == 0) {
3363                 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3364                 profileLevelType->eLevel   = QOMX_VIDEO_MVCLevel51;
3365             } else {
3366                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3367                                 (unsigned int)profileLevelType->nProfileIndex);
3368                 eRet = OMX_ErrorNoMore;
3369             }
3370         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3371             if (profileLevelType->nProfileIndex == 0) {
3372                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3373                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3374             } else if (profileLevelType->nProfileIndex == 1) {
3375                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3376                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3377             } else {
3378                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3379                         (unsigned int)profileLevelType->nProfileIndex);
3380                 eRet = OMX_ErrorNoMore;
3381             }
3382         } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3383             if (profileLevelType->nProfileIndex == 0) {
3384                 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3385                 profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
3386             } else {
3387                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3388                                 (unsigned int)profileLevelType->nProfileIndex);
3389                 eRet = OMX_ErrorNoMore;
3390             }
3391         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3392             if (profileLevelType->nProfileIndex == 0) {
3393                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3394                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3395             } else if (profileLevelType->nProfileIndex == 1) {
3396                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3397                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3398             } else {
3399                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3400                                 (unsigned int)profileLevelType->nProfileIndex);
3401                 eRet = OMX_ErrorNoMore;
3402             }
3403         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3404                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3405             eRet = OMX_ErrorNoMore;
3406         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3407             if (profileLevelType->nProfileIndex == 0) {
3408                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3409                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3410             } else if (profileLevelType->nProfileIndex == 1) {
3411                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3412                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3413             } else {
3414                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3415                                 (unsigned int)profileLevelType->nProfileIndex);
3416                 eRet = OMX_ErrorNoMore;
3417             }
3418         } else {
3419             DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3420             eRet = OMX_ErrorNoMore;
3421         }
3422     } else {
3423         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3424                           (unsigned int)profileLevelType->nPortIndex);
3425         eRet = OMX_ErrorBadPortIndex;
3426     }
3427     return eRet;
3428 }
3429 
3430 /* ======================================================================
3431    FUNCTION
3432    omx_vdec::GetParameter
3433 
3434    DESCRIPTION
3435    OMX Get Parameter method implementation
3436 
3437    PARAMETERS
3438    <TBD>.
3439 
3440    RETURN VALUE
3441    Error None if successful.
3442 
3443    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3444 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3445         OMX_IN OMX_INDEXTYPE paramIndex,
3446         OMX_INOUT OMX_PTR     paramData)
3447 {
3448     (void) hComp;
3449     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3450 
3451     DEBUG_PRINT_LOW("get_parameter:");
3452     if (m_state == OMX_StateInvalid) {
3453         DEBUG_PRINT_ERROR("Get Param in Invalid State");
3454         return OMX_ErrorInvalidState;
3455     }
3456     if (paramData == NULL) {
3457         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3458         return OMX_ErrorBadParameter;
3459     }
3460     switch ((unsigned long)paramIndex) {
3461         case OMX_IndexParamPortDefinition: {
3462                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3463                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3464                                    (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3465                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3466                                decide_dpb_buffer_mode(is_down_scalar_enabled);
3467                                eRet = update_portdef(portDefn);
3468                                if (eRet == OMX_ErrorNone)
3469                                    m_port_def = *portDefn;
3470                                break;
3471                            }
3472         case OMX_IndexParamVideoInit: {
3473                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3474                               OMX_PORT_PARAM_TYPE *portParamType =
3475                                   (OMX_PORT_PARAM_TYPE *) paramData;
3476                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3477 
3478                               portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3479                               portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3480                               portParamType->nPorts           = 2;
3481                               portParamType->nStartPortNumber = 0;
3482                               break;
3483                           }
3484         case OMX_IndexParamVideoPortFormat: {
3485                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3486                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3487                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3488                                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3489 
3490                                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3491                                 portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3492 
3493                                 if (0 == portFmt->nPortIndex) {
3494                                     if (0 == portFmt->nIndex) {
3495                                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3496                                         portFmt->eCompressionFormat = eCompressionFormat;
3497                                     } else {
3498                                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3499                                                 " NoMore compression formats");
3500                                         eRet =  OMX_ErrorNoMore;
3501                                     }
3502                                 } else if (1 == portFmt->nPortIndex) {
3503                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3504 
3505                                     // Distinguish non-surface mode from normal playback use-case based on
3506                                     // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3507                                     // For non-android, use the default list
3508                                     // Also use default format-list if FLEXIBLE YUV is supported,
3509                                     // as the client negotiates the standard color-format if it needs to
3510                                     bool useNonSurfaceMode = false;
3511 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3512                                     useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3513 #endif
3514                                     if (is_thulium_v1) {
3515                                         portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3516                                     } else {
3517                                         portFmt->eColorFormat = useNonSurfaceMode ?
3518                                             getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3519                                             getPreferredColorFormatDefaultMode(portFmt->nIndex);
3520                                     }
3521 
3522                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3523                                         eRet = OMX_ErrorNoMore;
3524                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3525                                                 " NoMore Color formats");
3526                                     }
3527                                     DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3528                                 } else {
3529                                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3530                                             (int)portFmt->nPortIndex);
3531                                     eRet = OMX_ErrorBadPortIndex;
3532                                 }
3533                                 break;
3534                             }
3535                             /*Component should support this port definition*/
3536         case OMX_IndexParamAudioInit: {
3537                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3538                               OMX_PORT_PARAM_TYPE *audioPortParamType =
3539                                   (OMX_PORT_PARAM_TYPE *) paramData;
3540                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3541                               audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3542                               audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3543                               audioPortParamType->nPorts           = 0;
3544                               audioPortParamType->nStartPortNumber = 0;
3545                               break;
3546                           }
3547                           /*Component should support this port definition*/
3548         case OMX_IndexParamImageInit: {
3549                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3550                               OMX_PORT_PARAM_TYPE *imagePortParamType =
3551                                   (OMX_PORT_PARAM_TYPE *) paramData;
3552                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3553                               imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3554                               imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3555                               imagePortParamType->nPorts           = 0;
3556                               imagePortParamType->nStartPortNumber = 0;
3557                               break;
3558 
3559                           }
3560                           /*Component should support this port definition*/
3561         case OMX_IndexParamOtherInit: {
3562                               DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3563                                       paramIndex);
3564                               eRet =OMX_ErrorUnsupportedIndex;
3565                               break;
3566                           }
3567         case OMX_IndexParamStandardComponentRole: {
3568                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3569                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
3570                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3571                                   comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3572                                   comp_role->nSize = sizeof(*comp_role);
3573 
3574                                   DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3575                                           paramIndex);
3576                                   strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3577                                           OMX_MAX_STRINGNAME_SIZE);
3578                                   break;
3579                               }
3580                               /* Added for parameter test */
3581         case OMX_IndexParamPriorityMgmt: {
3582                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3583                              OMX_PRIORITYMGMTTYPE *priorityMgmType =
3584                                  (OMX_PRIORITYMGMTTYPE *) paramData;
3585                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3586                              priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3587                              priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3588 
3589                              break;
3590                          }
3591                          /* Added for parameter test */
3592         case OMX_IndexParamCompBufferSupplier: {
3593                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3594                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3595                                        (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3596                                    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3597 
3598                                    bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3599                                    bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3600                                    if (0 == bufferSupplierType->nPortIndex)
3601                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3602                                    else if (1 == bufferSupplierType->nPortIndex)
3603                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3604                                    else
3605                                        eRet = OMX_ErrorBadPortIndex;
3606 
3607 
3608                                    break;
3609                                }
3610         case OMX_IndexParamVideoAvc: {
3611                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3612                                      paramIndex);
3613                              break;
3614                          }
3615         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3616                              DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3617                                      paramIndex);
3618                              break;
3619                          }
3620         case OMX_IndexParamVideoH263: {
3621                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3622                                       paramIndex);
3623                               break;
3624                           }
3625         case OMX_IndexParamVideoMpeg4: {
3626                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3627                                        paramIndex);
3628                                break;
3629                            }
3630         case OMX_IndexParamVideoMpeg2: {
3631                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3632                                        paramIndex);
3633                                break;
3634                            }
3635         case OMX_IndexParamVideoProfileLevelQuerySupported: {
3636                                         VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3637                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3638                                         OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3639                                             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3640                                         eRet = get_supported_profile_level(profileLevelType);
3641                                         break;
3642                                     }
3643 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3644         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3645                                         VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3646                                         DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3647                                         GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3648                                         if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3649 
3650                                             if (secure_mode && !secure_scaling_to_non_secure_opb) {
3651                                                 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3652                                                         GRALLOC_USAGE_PRIVATE_UNCACHED);
3653                                             } else {
3654                                                 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3655                                             }
3656                                         } else {
3657                                             DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3658                                             eRet = OMX_ErrorBadParameter;
3659                                         }
3660                                     }
3661                                     break;
3662 #endif
3663 
3664 #ifdef FLEXYUV_SUPPORTED
3665         case OMX_QcomIndexFlexibleYUVDescription: {
3666                 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3667                 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3668                 eRet = describeColorFormat(paramData);
3669                 break;
3670             }
3671 #endif
3672         case OMX_IndexParamVideoProfileLevelCurrent: {
3673              VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3674              OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3675              struct v4l2_control profile_control, level_control;
3676 
3677              switch (drv_ctx.decoder_format) {
3678                  case VDEC_CODECTYPE_H264:
3679                      profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3680                      level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3681                      break;
3682                  default:
3683                      DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3684                      eRet = OMX_ErrorNotImplemented;
3685                      break;
3686              }
3687 
3688              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3689                 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3690                     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3691                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3692                         pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3693                         break;
3694                     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3695                         pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3696                         break;
3697                     case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3698                         pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3699                         break;
3700                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3701                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3702                         break;
3703                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3704                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3705                         break;
3706                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3707                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3708                         break;
3709                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3710                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3711                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3712                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3713                     case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3714                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3715                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3716                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3717                     case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3718                     case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3719                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3720                         eRet = OMX_ErrorUnsupportedIndex;
3721                         break;
3722                 }
3723              } else {
3724                  eRet = OMX_ErrorUnsupportedIndex;
3725              }
3726 
3727 
3728              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3729                 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3730                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3731                         pParam->eLevel = OMX_VIDEO_AVCLevel1;
3732                         break;
3733                     case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3734                         pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3735                         break;
3736                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3737                         pParam->eLevel = OMX_VIDEO_AVCLevel11;
3738                         break;
3739                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3740                         pParam->eLevel = OMX_VIDEO_AVCLevel12;
3741                         break;
3742                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3743                         pParam->eLevel = OMX_VIDEO_AVCLevel13;
3744                         break;
3745                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3746                         pParam->eLevel = OMX_VIDEO_AVCLevel2;
3747                         break;
3748                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3749                         pParam->eLevel = OMX_VIDEO_AVCLevel21;
3750                         break;
3751                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3752                         pParam->eLevel = OMX_VIDEO_AVCLevel22;
3753                         break;
3754                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
3755                         pParam->eLevel = OMX_VIDEO_AVCLevel3;
3756                         break;
3757                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
3758                         pParam->eLevel = OMX_VIDEO_AVCLevel31;
3759                         break;
3760                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
3761                         pParam->eLevel = OMX_VIDEO_AVCLevel32;
3762                         break;
3763                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
3764                         pParam->eLevel = OMX_VIDEO_AVCLevel4;
3765                         break;
3766                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
3767                         pParam->eLevel = OMX_VIDEO_AVCLevel41;
3768                         break;
3769                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
3770                         pParam->eLevel = OMX_VIDEO_AVCLevel42;
3771                         break;
3772                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
3773                         pParam->eLevel = OMX_VIDEO_AVCLevel5;
3774                         break;
3775                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
3776                         pParam->eLevel = OMX_VIDEO_AVCLevel51;
3777                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
3778                         pParam->eLevel = OMX_VIDEO_AVCLevel52;
3779                         break;
3780                 }
3781              } else {
3782                  eRet = OMX_ErrorUnsupportedIndex;
3783              }
3784 
3785              break;
3786 
3787          }
3788         default: {
3789                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3790                  eRet =OMX_ErrorUnsupportedIndex;
3791              }
3792 
3793     }
3794 
3795     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3796             drv_ctx.video_resolution.frame_width,
3797             drv_ctx.video_resolution.frame_height,
3798             drv_ctx.video_resolution.stride,
3799             drv_ctx.video_resolution.scan_lines);
3800 
3801     return eRet;
3802 }
3803 
3804 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3805 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3806 {
3807     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3808     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3809     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3810 
3811     if ((params == NULL) ||
3812             (params->nativeBuffer == NULL) ||
3813             (params->nativeBuffer->handle == NULL) ||
3814             !m_enable_android_native_buffers)
3815         return OMX_ErrorBadParameter;
3816     m_use_android_native_buffers = OMX_TRUE;
3817     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3818     private_handle_t *handle = (private_handle_t *)nBuf->handle;
3819     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3820         OMX_U8 *buffer = NULL;
3821         if (!secure_mode) {
3822             buffer = (OMX_U8*)mmap(0, handle->size,
3823                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3824             if (buffer == MAP_FAILED) {
3825                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3826                 return OMX_ErrorInsufficientResources;
3827             }
3828         }
3829         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3830     } else {
3831         eRet = OMX_ErrorBadParameter;
3832     }
3833     return eRet;
3834 }
3835 #endif
3836 
enable_smoothstreaming()3837 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3838     struct v4l2_control control;
3839     struct v4l2_format fmt;
3840     control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3841     control.value = 1;
3842     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3843     if (rc < 0) {
3844         DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3845         return OMX_ErrorHardware;
3846     }
3847     m_smoothstreaming_mode = true;
3848     return OMX_ErrorNone;
3849 }
3850 
3851 /* ======================================================================
3852    FUNCTION
3853    omx_vdec::Setparameter
3854 
3855    DESCRIPTION
3856    OMX Set Parameter method implementation.
3857 
3858    PARAMETERS
3859    <TBD>.
3860 
3861    RETURN VALUE
3862    OMX Error None if successful.
3863 
3864    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3865 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3866         OMX_IN OMX_INDEXTYPE paramIndex,
3867         OMX_IN OMX_PTR        paramData)
3868 {
3869     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3870     int ret=0;
3871     struct v4l2_format fmt;
3872 #ifdef _ANDROID_
3873     char property_value[PROPERTY_VALUE_MAX] = {0};
3874 #endif
3875     if (m_state == OMX_StateInvalid) {
3876         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3877         return OMX_ErrorInvalidState;
3878     }
3879     if (paramData == NULL) {
3880         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
3881         return OMX_ErrorBadParameter;
3882     }
3883     if ((m_state != OMX_StateLoaded) &&
3884             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
3885             (m_out_bEnabled == OMX_TRUE) &&
3886             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
3887             (m_inp_bEnabled == OMX_TRUE)) {
3888         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3889         return OMX_ErrorIncorrectStateOperation;
3890     }
3891     switch ((unsigned long)paramIndex) {
3892         case OMX_IndexParamPortDefinition: {
3893                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3894                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3895                                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3896                                //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
3897                                //been called.
3898                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
3899                                        (int)portDefn->format.video.nFrameHeight,
3900                                        (int)portDefn->format.video.nFrameWidth);
3901 
3902                                if (portDefn->nBufferCountActual >= MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3903                                    DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
3904                                                           portDefn->nBufferCountActual);
3905                                    eRet = OMX_ErrorBadParameter;
3906                                    break;
3907                                }
3908                                if (OMX_DirOutput == portDefn->eDir) {
3909                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
3910                                    bool port_format_changed = false;
3911                                    m_display_id = portDefn->format.video.pNativeWindow;
3912                                    unsigned int buffer_size;
3913                                    /* update output port resolution with client supplied dimensions
3914                                       in case scaling is enabled, else it follows input resolution set
3915                                    */
3916                                    decide_dpb_buffer_mode(is_down_scalar_enabled);
3917                                    if (is_down_scalar_enabled) {
3918                                        DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
3919                                                (unsigned int)portDefn->format.video.nFrameWidth,
3920                                                (unsigned int)portDefn->format.video.nFrameHeight);
3921                                        if (portDefn->format.video.nFrameHeight != 0x0 &&
3922                                                portDefn->format.video.nFrameWidth != 0x0) {
3923                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3924                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3925                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3926                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
3927                                            if (ret) {
3928                                                DEBUG_PRINT_ERROR("Get Resolution failed");
3929                                                eRet = OMX_ErrorHardware;
3930                                                break;
3931                                            }
3932                                            if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
3933                                                (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
3934                                                    port_format_changed = true;
3935                                            }
3936                                            update_resolution(portDefn->format.video.nFrameWidth,
3937                                                    portDefn->format.video.nFrameHeight,
3938                                                    portDefn->format.video.nFrameWidth,
3939                                                    portDefn->format.video.nFrameHeight);
3940 
3941                                            /* set crop info */
3942                                            rectangle.nLeft = 0;
3943                                            rectangle.nTop = 0;
3944                                            rectangle.nWidth = portDefn->format.video.nFrameWidth;
3945                                            rectangle.nHeight = portDefn->format.video.nFrameHeight;
3946 
3947                                            eRet = is_video_session_supported();
3948                                            if (eRet)
3949                                                break;
3950                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3951                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3952                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3953                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3954                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3955                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
3956                                                fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
3957                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3958                                            if (ret) {
3959                                                DEBUG_PRINT_ERROR("Set Resolution failed");
3960                                                eRet = OMX_ErrorUnsupportedSetting;
3961                                            } else
3962                                                eRet = get_buffer_req(&drv_ctx.op_buf);
3963                                        }
3964 
3965                                        if (eRet) {
3966                                            break;
3967                                        }
3968 
3969                                        if (secure_mode) {
3970                                            struct v4l2_control control;
3971                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
3972                                            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
3973                                                DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
3974                                                eRet = OMX_ErrorHardware;
3975                                            } else {
3976                                                /* This is a workaround for a bug in fw which uses stride
3977                                                 * and slice instead of width and height to check against
3978                                                 * the threshold.
3979                                                 */
3980                                                OMX_U32 stride, slice;
3981                                                if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
3982                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
3983                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
3984                                                } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
3985                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
3986                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
3987                                                } else {
3988                                                    stride = portDefn->format.video.nFrameWidth;
3989                                                    slice = portDefn->format.video.nFrameHeight;
3990                                                }
3991 
3992                                                DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
3993                                                DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
3994 
3995                                                if (stride * slice <= (OMX_U32)control.value) {
3996                                                    secure_scaling_to_non_secure_opb = true;
3997                                                    DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
3998                                                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
3999                                                    control.value = 1;
4000                                                    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4001                                                        DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4002                                                        eRet = OMX_ErrorUnsupportedSetting;
4003                                                    }
4004                                                }
4005                                            }
4006                                        }
4007                                    }
4008 
4009                                    if (eRet) {
4010                                        break;
4011                                    }
4012 
4013                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4014                                        DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4015                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4016                                        eRet = OMX_ErrorBadParameter;
4017                                    } else if (!client_buffers.get_buffer_req(buffer_size)) {
4018                                        DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4019                                        eRet = OMX_ErrorBadParameter;
4020                                    } else if (!port_format_changed) {
4021 
4022                                        // Buffer count can change only when port is disabled
4023                                        if (!release_output_done()) {
4024                                            DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4025                                            eRet = OMX_ErrorInvalidState;
4026                                            break;
4027                                        }
4028 
4029                                        if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
4030                                                portDefn->nBufferSize >=  drv_ctx.op_buf.buffer_size ) {
4031                                            drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
4032                                            drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
4033                                            drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount;
4034                                            drv_ctx.extradata_info.size = drv_ctx.extradata_info.count *
4035                                                drv_ctx.extradata_info.buffer_size;
4036                                            eRet = set_buffer_req(&drv_ctx.op_buf);
4037                                            if (eRet == OMX_ErrorNone)
4038                                                m_port_def = *portDefn;
4039                                        } else {
4040                                            DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4041                                                    drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size,
4042                                                    (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4043                                            eRet = OMX_ErrorBadParameter;
4044                                        }
4045                                    }
4046                                } else if (OMX_DirInput == portDefn->eDir) {
4047                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4048                                    bool port_format_changed = false;
4049                                    if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4050                                            (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4051                                        // Frame rate only should be set if this is a "known value" or to
4052                                        // activate ts prediction logic (arbitrary mode only) sending input
4053                                        // timestamps with max value (LLONG_MAX).
4054                                        DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4055                                                (unsigned int)portDefn->format.video.xFramerate >> 16);
4056                                        Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4057                                                drv_ctx.frame_rate.fps_denominator);
4058                                        if (!drv_ctx.frame_rate.fps_numerator) {
4059                                            DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4060                                            drv_ctx.frame_rate.fps_numerator = 30;
4061                                        }
4062                                        if (drv_ctx.frame_rate.fps_denominator)
4063                                            drv_ctx.frame_rate.fps_numerator = (int)
4064                                                drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4065                                        drv_ctx.frame_rate.fps_denominator = 1;
4066                                        frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4067                                            drv_ctx.frame_rate.fps_numerator;
4068                                        DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4069                                                (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4070                                                (float)drv_ctx.frame_rate.fps_denominator);
4071 
4072                                        struct v4l2_outputparm oparm;
4073                                        /*XXX: we're providing timing info as seconds per frame rather than frames
4074                                         * per second.*/
4075                                        oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4076                                        oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4077 
4078                                        struct v4l2_streamparm sparm;
4079                                        sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4080                                        sparm.parm.output = oparm;
4081                                        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4082                                            DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4083                                            eRet = OMX_ErrorHardware;
4084                                            break;
4085                                        }
4086                                        m_perf_control.request_cores(frm_int);
4087                                    }
4088 
4089                                    if (drv_ctx.video_resolution.frame_height !=
4090                                            portDefn->format.video.nFrameHeight ||
4091                                            drv_ctx.video_resolution.frame_width  !=
4092                                            portDefn->format.video.nFrameWidth) {
4093                                        DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4094                                                (unsigned int)portDefn->format.video.nFrameWidth,
4095                                                (unsigned int)portDefn->format.video.nFrameHeight);
4096                                        port_format_changed = true;
4097                                        OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4098                                        OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4099                                        if (frameHeight != 0x0 && frameWidth != 0x0) {
4100                                            if (m_smoothstreaming_mode &&
4101                                                    ((frameWidth * frameHeight) <
4102                                                    (m_smoothstreaming_width * m_smoothstreaming_height))) {
4103                                                frameWidth = m_smoothstreaming_width;
4104                                                frameHeight = m_smoothstreaming_height;
4105                                                DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4106                                                        "for adaptive-playback/smooth-streaming",
4107                                                        (unsigned int)frameWidth, (unsigned int)frameHeight);
4108                                            }
4109                                            update_resolution(frameWidth, frameHeight,
4110                                                    frameWidth, frameHeight);
4111                                            eRet = is_video_session_supported();
4112                                            if (eRet)
4113                                                break;
4114                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4115                                            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4116                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4117                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4118                                            fmt.fmt.pix_mp.pixelformat = output_capability;
4119                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4120                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4121                                            if (ret) {
4122                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4123                                                eRet = OMX_ErrorUnsupportedSetting;
4124                                            } else {
4125                                                if (!is_down_scalar_enabled)
4126                                                    eRet = get_buffer_req(&drv_ctx.op_buf);
4127                                            }
4128                                        }
4129                                    }
4130                                    if (m_custom_buffersize.input_buffersize
4131                                         && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4132                                        DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4133                                                m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4134                                        eRet = OMX_ErrorBadParameter;
4135                                        break;
4136                                    }
4137                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4138                                        DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4139                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4140                                        eRet = OMX_ErrorBadParameter;
4141                                        break;
4142                                    }
4143                                    // Buffer count can change only when port is disabled
4144                                    if (!release_input_done()) {
4145                                        DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4146                                        eRet = OMX_ErrorInvalidState;
4147                                        break;
4148                                    }
4149 
4150                                    if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4151                                            || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4152                                        port_format_changed = true;
4153                                        vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4154                                        drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4155                                        drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4156                                            (~(buffer_prop->alignment - 1));
4157                                        eRet = set_buffer_req(buffer_prop);
4158                                    }
4159                                    if (false == port_format_changed) {
4160                                        DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4161                                                drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4162                                                (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4163                                        eRet = OMX_ErrorBadParameter;
4164                                    }
4165                                } else if (portDefn->eDir ==  OMX_DirMax) {
4166                                    DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4167                                            (int)portDefn->nPortIndex);
4168                                    eRet = OMX_ErrorBadPortIndex;
4169                                }
4170                            }
4171                            break;
4172         case OMX_IndexParamVideoPortFormat: {
4173                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4174                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4175                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4176                                 int ret=0;
4177                                 struct v4l2_format fmt;
4178                                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4179                                         portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4180 
4181                                 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4182                                 if (1 == portFmt->nPortIndex) {
4183                                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4184                                     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4185                                     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4186                                     enum vdec_output_fromat op_format;
4187                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4188                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4189                                             portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4190                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4191                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4192                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4193                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4194                                     } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4195                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4196                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4197                                     } else
4198                                         eRet = OMX_ErrorBadParameter;
4199 
4200                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4201                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4202                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4203                                     } else {
4204                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4205                                     }
4206 
4207                                     if (eRet == OMX_ErrorNone) {
4208                                         drv_ctx.output_format = op_format;
4209                                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4210                                         if (ret) {
4211                                             DEBUG_PRINT_ERROR("Set output format failed");
4212                                             eRet = OMX_ErrorUnsupportedSetting;
4213                                             /*TODO: How to handle this case */
4214                                         } else {
4215                                             eRet = get_buffer_req(&drv_ctx.op_buf);
4216                                         }
4217                                     }
4218                                     if (eRet == OMX_ErrorNone) {
4219                                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4220                                             DEBUG_PRINT_ERROR("Set color format failed");
4221                                             eRet = OMX_ErrorBadParameter;
4222                                         }
4223                                     }
4224                                 }
4225                             }
4226                             break;
4227 
4228         case OMX_QcomIndexPortDefn: {
4229                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4230                             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4231                                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4232                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4233                                     (unsigned int)portFmt->nFramePackingFormat);
4234 
4235                             /* Input port */
4236                             if (portFmt->nPortIndex == 0) {
4237                                 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4238                                     if (secure_mode || m_input_pass_buffer_fd) {
4239                                         arbitrary_bytes = false;
4240                                         DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4241                                         eRet = OMX_ErrorUnsupportedSetting;
4242                                     } else {
4243                                         arbitrary_bytes = true;
4244                                     }
4245                                 } else if (portFmt->nFramePackingFormat ==
4246                                         OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4247                                     arbitrary_bytes = false;
4248 #ifdef _ANDROID_
4249                                     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4250                                     if (atoi(property_value)) {
4251                                         DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4252                                         arbitrary_bytes = true;
4253                                     }
4254 #endif
4255                                 } else {
4256                                     DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4257                                             (unsigned int)portFmt->nFramePackingFormat);
4258                                     eRet = OMX_ErrorUnsupportedSetting;
4259                                 }
4260                             } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4261                                 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4262                                 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4263                                             portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4264                                         portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4265                                     m_out_mem_region_smi = OMX_TRUE;
4266                                     if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4267                                         DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4268                                         m_use_output_pmem = OMX_TRUE;
4269                                     }
4270                                 }
4271                             }
4272                         }
4273                         if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4274                                     OMX_MAX_STRINGNAME_SIZE)) {
4275                             arbitrary_bytes = true;
4276                             DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4277                         }
4278                         break;
4279 
4280         case OMX_IndexParamStandardComponentRole: {
4281                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4282                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
4283                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4284                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4285                                           comp_role->cRole);
4286 
4287                                   if ((m_state == OMX_StateLoaded)&&
4288                                           !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4289                                       DEBUG_PRINT_LOW("Set Parameter called in valid state");
4290                                   } else {
4291                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4292                                       return OMX_ErrorIncorrectStateOperation;
4293                                   }
4294 
4295                                   if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4296                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4297                                           strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4298                                       } else {
4299                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4300                                           eRet =OMX_ErrorUnsupportedSetting;
4301                                       }
4302                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4303                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4304                                           strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4305                                       } else {
4306                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4307                                           eRet = OMX_ErrorUnsupportedSetting;
4308                                       }
4309                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4310                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4311                                           strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4312                                       } else {
4313                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4314                                           eRet = OMX_ErrorUnsupportedSetting;
4315                                       }
4316                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4317                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4318                                           strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4319                                       } else {
4320                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4321                                           eRet =OMX_ErrorUnsupportedSetting;
4322                                       }
4323                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4324                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4325                                           strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4326                                       } else {
4327                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4328                                           eRet = OMX_ErrorUnsupportedSetting;
4329                                       }
4330                                   } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4331                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4332                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4333                                         ) {
4334                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4335                                           strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4336                                       } else {
4337                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4338                                           eRet =OMX_ErrorUnsupportedSetting;
4339                                       }
4340                                   } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4341                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4342                                         ) {
4343                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4344                                           strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4345                                       } else {
4346                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4347                                           eRet =OMX_ErrorUnsupportedSetting;
4348                                       }
4349                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4350                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4351                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4352                                           strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4353                                       } else {
4354                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4355                                           eRet = OMX_ErrorUnsupportedSetting;
4356                                       }
4357                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4358                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4359                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4360                                           strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4361                                       } else {
4362                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4363                                           eRet = OMX_ErrorUnsupportedSetting;
4364                                       }
4365                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4366                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4367                                           strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4368                                       } else {
4369                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4370                                           eRet = OMX_ErrorUnsupportedSetting;
4371                                       }
4372                                   } else {
4373                                       DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4374                                       eRet = OMX_ErrorInvalidComponentName;
4375                                   }
4376                                   break;
4377                               }
4378 
4379         case OMX_IndexParamPriorityMgmt: {
4380                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4381                              if (m_state != OMX_StateLoaded) {
4382                                  DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4383                                  return OMX_ErrorIncorrectStateOperation;
4384                              }
4385                              OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4386                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4387                                      (unsigned int)priorityMgmtype->nGroupID);
4388 
4389                              DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4390                                      (unsigned int)priorityMgmtype->nGroupPriority);
4391 
4392                              m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4393                              m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4394 
4395                              break;
4396                          }
4397 
4398         case OMX_IndexParamCompBufferSupplier: {
4399                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4400                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4401                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4402                                            bufferSupplierType->eBufferSupplier);
4403                                    if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4404                                        m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4405 
4406                                    else
4407 
4408                                        eRet = OMX_ErrorBadPortIndex;
4409 
4410                                    break;
4411 
4412                                }
4413         case OMX_IndexParamVideoAvc: {
4414                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4415                                      paramIndex);
4416                              break;
4417                          }
4418         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4419                             DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4420                                      paramIndex);
4421                              break;
4422                         }
4423         case OMX_IndexParamVideoH263: {
4424                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4425                                       paramIndex);
4426                               break;
4427                           }
4428         case OMX_IndexParamVideoMpeg4: {
4429                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4430                                        paramIndex);
4431                                break;
4432                            }
4433         case OMX_IndexParamVideoMpeg2: {
4434                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4435                                        paramIndex);
4436                                break;
4437                            }
4438         case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4439                                      VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4440                                      QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4441                                          (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4442                                      struct v4l2_control control;
4443                                      int pic_order,rc=0;
4444                                      DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4445                                              pictureOrder->eOutputPictureOrder);
4446                                      if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4447                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4448                                      } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4449                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4450                                          time_stamp_dts.set_timestamp_reorder_mode(false);
4451                                      } else
4452                                          eRet = OMX_ErrorBadParameter;
4453                                      if (eRet == OMX_ErrorNone) {
4454                                          control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4455                                          control.value = pic_order;
4456                                          rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4457                                          if (rc) {
4458                                              DEBUG_PRINT_ERROR("Set picture order failed");
4459                                              eRet = OMX_ErrorUnsupportedSetting;
4460                                          }
4461                                      }
4462                                      break;
4463                                  }
4464         case OMX_QcomIndexParamConcealMBMapExtraData:
4465                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4466                                eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4467                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4468                                break;
4469         case OMX_QcomIndexParamFrameInfoExtraData:
4470                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4471                                eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4472                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4473                                break;
4474         case OMX_ExtraDataFrameDimension:
4475                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4476                                eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4477                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4478                                break;
4479         case OMX_QcomIndexParamInterlaceExtraData:
4480                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4481                                eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4482                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4483                                break;
4484         case OMX_QcomIndexParamH264TimeInfo:
4485                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4486                                eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4487                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4488                                break;
4489         case OMX_QcomIndexParamVideoFramePackingExtradata:
4490                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4491                                eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4492                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4493                                break;
4494         case OMX_QcomIndexParamVideoQPExtraData:
4495                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4496                                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4497                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4498                                break;
4499         case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4500                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4501                                eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4502                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4503                                break;
4504         case OMX_QcomIndexEnableExtnUserData:
4505                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4506                                 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4507                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4508                                 break;
4509         case OMX_QTIIndexParamVQZipSEIExtraData:
4510                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4511                                 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4512                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4513                                 break;
4514         case OMX_QcomIndexParamVideoDivx: {
4515                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4516                           }
4517                           break;
4518         case OMX_QcomIndexPlatformPvt: {
4519                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4520                                DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4521                                OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4522                                if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4523                                    DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4524                                    eRet = OMX_ErrorUnsupportedSetting;
4525                                } else {
4526                                    m_out_pvt_entry_pmem = OMX_TRUE;
4527                                    if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4528                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4529                                        m_use_output_pmem = OMX_TRUE;
4530                                    }
4531                                }
4532 
4533                            }
4534                            break;
4535         case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4536                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4537                                        DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4538                                        struct v4l2_control control;
4539                                        int rc;
4540                                        drv_ctx.idr_only_decoding = 1;
4541                                        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4542                                        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4543                                        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4544                                        if (rc) {
4545                                            DEBUG_PRINT_ERROR("Set picture order failed");
4546                                            eRet = OMX_ErrorUnsupportedSetting;
4547                                        } else {
4548                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4549                                            control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4550                                            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4551                                            if (rc) {
4552                                                DEBUG_PRINT_ERROR("Sync frame setting failed");
4553                                                eRet = OMX_ErrorUnsupportedSetting;
4554                                            }
4555                                            /*Setting sync frame decoding on driver might change buffer
4556                                             * requirements so update them here*/
4557                                            if (get_buffer_req(&drv_ctx.ip_buf)) {
4558                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4559                                                eRet = OMX_ErrorUnsupportedSetting;
4560                                            }
4561                                            if (get_buffer_req(&drv_ctx.op_buf)) {
4562                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4563                                                eRet = OMX_ErrorUnsupportedSetting;
4564                                            }
4565                                        }
4566                                    }
4567                                    break;
4568 
4569         case OMX_QcomIndexParamIndexExtraDataType: {
4570                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4571                                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4572                                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4573                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4574                                             (extradataIndexType->nPortIndex == 1)) {
4575                                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4576                                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4577 
4578                                     }
4579                                 }
4580                                 break;
4581         case OMX_QcomIndexParamEnableSmoothStreaming: {
4582 #ifndef SMOOTH_STREAMING_DISABLED
4583                                       eRet = enable_smoothstreaming();
4584 #else
4585                                       eRet = OMX_ErrorUnsupportedSetting;
4586 #endif
4587                                   }
4588                                   break;
4589 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4590                                   /* Need to allow following two set_parameters even in Idle
4591                                    * state. This is ANDROID architecture which is not in sync
4592                                    * with openmax standard. */
4593         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4594                                            VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4595                                            EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4596                                            if (enableNativeBuffers) {
4597                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
4598                                            }
4599 #if !defined(FLEXYUV_SUPPORTED)
4600                                            if (m_enable_android_native_buffers) {
4601                                                // Use the most-preferred-native-color-format as surface-mode is hinted here
4602                                                if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4603                                                    DEBUG_PRINT_ERROR("Failed to set native color format!");
4604                                                    eRet = OMX_ErrorUnsupportedSetting;
4605                                                }
4606                                            }
4607 #endif
4608                                        }
4609                                        break;
4610         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4611                                        VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4612                                        eRet = use_android_native_buffer(hComp, paramData);
4613                                    }
4614                                    break;
4615         case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4616                 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4617                 if (allocateNativeHandleParams != NULL) {
4618                     allocate_native_handle = allocateNativeHandleParams->enable;
4619                 }
4620             }
4621             break;
4622 #endif
4623         case OMX_QcomIndexParamEnableTimeStampReorder: {
4624                                        VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4625                                        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4626                                        if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4627                                            if (reorder->bEnable == OMX_TRUE) {
4628                                                frm_int =0;
4629                                                time_stamp_dts.set_timestamp_reorder_mode(true);
4630                                            } else
4631                                                time_stamp_dts.set_timestamp_reorder_mode(false);
4632                                        } else {
4633                                            time_stamp_dts.set_timestamp_reorder_mode(false);
4634                                            if (reorder->bEnable == OMX_TRUE) {
4635                                                eRet = OMX_ErrorUnsupportedSetting;
4636                                            }
4637                                        }
4638                                    }
4639                                    break;
4640         case OMX_IndexParamVideoProfileLevelCurrent: {
4641                                      VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4642                                      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4643                                          (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4644                                      if (pParam) {
4645                                          m_profile_lvl.eProfile = pParam->eProfile;
4646                                          m_profile_lvl.eLevel = pParam->eLevel;
4647                                      }
4648                                      break;
4649 
4650                                  }
4651         case OMX_QcomIndexParamVideoMetaBufferMode:
4652         {
4653             VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4654             StoreMetaDataInBuffersParams *metabuffer =
4655                 (StoreMetaDataInBuffersParams *)paramData;
4656             if (!metabuffer) {
4657                 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4658                 eRet = OMX_ErrorBadParameter;
4659                 break;
4660             }
4661             if (m_disable_dynamic_buf_mode) {
4662                 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4663                 eRet = OMX_ErrorUnsupportedSetting;
4664                 break;
4665             }
4666             if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4667                     //set property dynamic buffer mode to driver.
4668                     struct v4l2_control control;
4669                     struct v4l2_format fmt;
4670                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
4671                     if (metabuffer->bStoreMetaData == true) {
4672                         control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
4673                     } else {
4674                         control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
4675                     }
4676                     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4677                     if (!rc) {
4678                         DEBUG_PRINT_HIGH("%s buffer mode",
4679                            (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4680                                dynamic_buf_mode = metabuffer->bStoreMetaData;
4681                     } else {
4682                         DEBUG_PRINT_ERROR("Failed to %s buffer mode",
4683                            (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
4684                         eRet = OMX_ErrorUnsupportedSetting;
4685                     }
4686                 } else {
4687                     DEBUG_PRINT_ERROR(
4688                        "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4689                        (unsigned int)metabuffer->nPortIndex);
4690                     eRet = OMX_ErrorUnsupportedSetting;
4691                 }
4692                 break;
4693         }
4694         case OMX_QcomIndexParamVideoDownScalar:
4695         {
4696             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4697             QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4698             struct v4l2_control control;
4699             int rc;
4700             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
4701 
4702             if (pParam && pParam->bEnable) {
4703                 rc = enable_downscalar();
4704                 if (rc < 0) {
4705                     DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
4706                     return OMX_ErrorUnsupportedSetting;
4707                 }
4708                 m_force_down_scalar = pParam->bEnable;
4709             } else {
4710                 rc = disable_downscalar();
4711                 if (rc < 0) {
4712                     DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
4713                     return OMX_ErrorUnsupportedSetting;
4714                 }
4715                 m_force_down_scalar = pParam->bEnable;
4716             }
4717             break;
4718         }
4719 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4720         case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4721         {
4722             VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4723             DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4724             PrepareForAdaptivePlaybackParams* pParams =
4725                     (PrepareForAdaptivePlaybackParams *) paramData;
4726             if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4727                 if (!pParams->bEnable) {
4728                     return OMX_ErrorNone;
4729                 }
4730                 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4731                         || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4732                     DEBUG_PRINT_ERROR(
4733                             "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4734                              (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4735                              (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4736                     eRet = OMX_ErrorBadParameter;
4737                 } else {
4738                     eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4739                 }
4740             } else {
4741                 DEBUG_PRINT_ERROR(
4742                         "Prepare for adaptive playback supported only on output port");
4743                 eRet = OMX_ErrorBadParameter;
4744             }
4745             break;
4746         }
4747 
4748         case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
4749         {
4750             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4751             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
4752             m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4753             if (m_disable_dynamic_buf_mode) {
4754                 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
4755             }
4756             break;
4757         }
4758 #endif
4759         case OMX_QcomIndexParamVideoCustomBufferSize:
4760         {
4761             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4762             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4763             QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4764             if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4765                 struct v4l2_control control;
4766                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4767                 control.value = pParam->nBufferSize;
4768                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4769                     DEBUG_PRINT_ERROR("Failed to set input buffer size");
4770                     eRet = OMX_ErrorUnsupportedSetting;
4771                 } else {
4772                     eRet = get_buffer_req(&drv_ctx.ip_buf);
4773                     if (eRet == OMX_ErrorNone) {
4774                         m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4775                         DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4776                             m_custom_buffersize.input_buffersize);
4777                     } else {
4778                         DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4779                     }
4780                 }
4781             } else {
4782                 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4783                 eRet = OMX_ErrorBadParameter;
4784             }
4785             break;
4786         }
4787         case OMX_QTIIndexParamVQZIPSEIType:
4788         {
4789             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
4790             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
4791             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
4792                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
4793                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
4794             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4795                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4796             if (eRet != OMX_ErrorNone) {
4797                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
4798                 eRet = OMX_ErrorBadParameter;
4799                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4800             } else {
4801                 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4802                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4803                 if (eRet != OMX_ErrorNone) {
4804                     DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
4805                     eRet = OMX_ErrorBadParameter;
4806                     client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4807                     client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4808                 }
4809             }
4810             break;
4811         }
4812 
4813         case OMX_QTIIndexParamPassInputBufferFd:
4814         {
4815             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4816             if (arbitrary_bytes) {
4817                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
4818                 eRet = OMX_ErrorUnsupportedSetting;
4819                 break;
4820             }
4821 
4822             m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4823             if (m_input_pass_buffer_fd)
4824                 DEBUG_PRINT_LOW("Enable passing input buffer FD");
4825             break;
4826         }
4827         case OMX_QTIIndexParamForceCompressedForDPB:
4828         {
4829             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
4830             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
4831             OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
4832                 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
4833             if (m_disable_ubwc_mode) {
4834                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
4835                 eRet = OMX_ErrorUnsupportedSetting;
4836                 break;
4837             }
4838             if (!paramData) {
4839                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
4840                eRet = OMX_ErrorBadParameter;
4841                break;
4842             }
4843 
4844             m_force_compressed_for_dpb = pParam->bEnable;
4845             break;
4846         }
4847         case OMX_QTIIndexParamForceUnCompressedForOPB:
4848         {
4849             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE);
4850             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
4851             OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
4852                 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
4853             if (!paramData) {
4854                 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
4855                 eRet = OMX_ErrorBadParameter;
4856                 break;
4857             }
4858             m_disable_ubwc_mode = pParam->bEnable;
4859             DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
4860             break;
4861         }
4862 
4863 
4864         default: {
4865                  DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4866                  eRet = OMX_ErrorUnsupportedIndex;
4867              }
4868     }
4869     if (eRet != OMX_ErrorNone)
4870         DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4871     return eRet;
4872 }
4873 
4874 /* ======================================================================
4875    FUNCTION
4876    omx_vdec::GetConfig
4877 
4878    DESCRIPTION
4879    OMX Get Config Method implementation.
4880 
4881    PARAMETERS
4882    <TBD>.
4883 
4884    RETURN VALUE
4885    OMX Error None if successful.
4886 
4887    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4888 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
4889         OMX_IN OMX_INDEXTYPE configIndex,
4890         OMX_INOUT OMX_PTR     configData)
4891 {
4892     (void) hComp;
4893     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4894 
4895     if (m_state == OMX_StateInvalid) {
4896         DEBUG_PRINT_ERROR("Get Config in Invalid State");
4897         return OMX_ErrorInvalidState;
4898     }
4899 
4900     switch ((unsigned long)configIndex) {
4901         case OMX_QcomIndexConfigInterlaced: {
4902                                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
4903                                 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
4904                                     (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
4905                                 if (configFmt->nPortIndex == 1) {
4906                                     if (configFmt->nIndex == 0) {
4907                                         configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
4908                                     } else if (configFmt->nIndex == 1) {
4909                                         configFmt->eInterlaceType =
4910                                             OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
4911                                     } else if (configFmt->nIndex == 2) {
4912                                         configFmt->eInterlaceType =
4913                                             OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
4914                                     } else {
4915                                         DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
4916                                                 " NoMore Interlaced formats");
4917                                         eRet = OMX_ErrorNoMore;
4918                                     }
4919 
4920                                 } else {
4921                                     DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
4922                                             (int)configFmt->nPortIndex);
4923                                     eRet = OMX_ErrorBadPortIndex;
4924                                 }
4925                                 break;
4926                             }
4927         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
4928                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
4929                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
4930                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
4931                                      decoderinstances->nNumOfInstances = 16;
4932                                      /*TODO: How to handle this case */
4933                                      break;
4934                                  }
4935         case OMX_QcomIndexConfigVideoFramePackingArrangement: {
4936                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
4937                                               VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
4938                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
4939                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
4940                                               memcpy(configFmt, &m_frame_pack_arrangement,
4941                                                   sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
4942                                           } else {
4943                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
4944                                           }
4945                                           break;
4946                                       }
4947         case OMX_IndexConfigCommonOutputCrop: {
4948                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
4949                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
4950                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
4951                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
4952                                         rectangle.nLeft, rectangle.nTop,
4953                                         rectangle.nWidth, rectangle.nHeight);
4954                                   break;
4955                               }
4956         case OMX_QcomIndexConfigPerfLevel: {
4957                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
4958                 struct v4l2_control control;
4959                 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
4960                         (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
4961 
4962                 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
4963                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4964                     DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
4965                     eRet = OMX_ErrorHardware;
4966                 }
4967 
4968                 if (eRet == OMX_ErrorNone) {
4969                     switch (control.value) {
4970                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
4971                             perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
4972                             break;
4973                         default:
4974                             DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
4975                             /* Fall through */
4976                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
4977                             perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
4978                             break;
4979                     }
4980                 }
4981 
4982                 break;
4983         }
4984         case OMX_QcomIndexConfigH264EntropyCodingCabac: {
4985             VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
4986             QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
4987             struct v4l2_control control;
4988 
4989             if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
4990                 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
4991                 eRet = OMX_ErrorNotImplemented;
4992                 break;
4993             }
4994 
4995             control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
4996             if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
4997                 coding->bCabac = (OMX_BOOL)
4998                     (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
4999                 /* We can't query driver at the moment for the cabac mode, so
5000                  * just use 0xff...f as a place holder for future improvement */
5001                 coding->nCabacInitIdc = ~0;
5002             } else {
5003                 eRet = OMX_ErrorUnsupportedIndex;
5004             }
5005 
5006             break;
5007         }
5008         case OMX_QTIIndexConfigDescribeColorAspects:
5009         {
5010             VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5011             DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5012 
5013             print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5014             print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5015 
5016             if (params->bRequestingDataSpace) {
5017                 DEBUG_PRINT_ERROR("Does not handle dataspace request");
5018                 return OMX_ErrorUnsupportedSetting;
5019             }
5020             if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) {
5021                 DEBUG_PRINT_LOW("Updating Client's color aspects with internal");
5022                 memcpy(&(m_client_color_space.sAspects),
5023                         &(m_internal_color_space.sAspects), sizeof(ColorAspects));
5024                 m_internal_color_space.bDataSpaceChanged = OMX_FALSE;
5025             }
5026             memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects));
5027 
5028             break;
5029         }
5030         default: {
5031                  DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5032                  eRet = OMX_ErrorBadParameter;
5033              }
5034 
5035     }
5036 
5037     return eRet;
5038 }
5039 
5040 /* ======================================================================
5041    FUNCTION
5042    omx_vdec::SetConfig
5043 
5044    DESCRIPTION
5045    OMX Set Config method implementation
5046 
5047    PARAMETERS
5048    <TBD>.
5049 
5050    RETURN VALUE
5051    OMX Error None if successful.
5052    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5053 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5054         OMX_IN OMX_INDEXTYPE configIndex,
5055         OMX_IN OMX_PTR        configData)
5056 {
5057     (void) hComp;
5058     if (m_state == OMX_StateInvalid) {
5059         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5060         return OMX_ErrorInvalidState;
5061     }
5062 
5063     OMX_ERRORTYPE ret = OMX_ErrorNone;
5064     OMX_VIDEO_CONFIG_NALSIZE *pNal;
5065 
5066     DEBUG_PRINT_LOW("Set Config Called");
5067 
5068     if (configIndex == OMX_IndexConfigVideoNalSize) {
5069         struct v4l2_control temp;
5070         temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5071 
5072         VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5073         pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5074         switch (pNal->nNaluBytes) {
5075             case 0:
5076                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5077                 break;
5078             case 2:
5079                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5080                 break;
5081             case 4:
5082                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5083                 break;
5084             default:
5085                 return OMX_ErrorUnsupportedSetting;
5086         }
5087 
5088         if (!arbitrary_bytes) {
5089             /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5090              * with start code, so only need to notify driver in frame by frame mode */
5091             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5092                 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5093                 return OMX_ErrorHardware;
5094             }
5095         }
5096 
5097         nal_length = pNal->nNaluBytes;
5098         m_frame_parser.init_nal_length(nal_length);
5099 
5100         DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5101         return ret;
5102     } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5103         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5104         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5105 
5106         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5107             if (config->bEnabled) {
5108                 if ((config->nFps >> 16) > 0) {
5109                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5110                             (unsigned int)config->nFps >> 16);
5111                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5112                             drv_ctx.frame_rate.fps_denominator);
5113 
5114                     if (!drv_ctx.frame_rate.fps_numerator) {
5115                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5116                         drv_ctx.frame_rate.fps_numerator = 30;
5117                     }
5118 
5119                     if (drv_ctx.frame_rate.fps_denominator) {
5120                         drv_ctx.frame_rate.fps_numerator = (int)
5121                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5122                     }
5123 
5124                     drv_ctx.frame_rate.fps_denominator = 1;
5125                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5126                         drv_ctx.frame_rate.fps_numerator;
5127 
5128                     struct v4l2_outputparm oparm;
5129                     /*XXX: we're providing timing info as seconds per frame rather than frames
5130                      * per second.*/
5131                     oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5132                     oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5133 
5134                     struct v4l2_streamparm sparm;
5135                     sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5136                     sparm.parm.output = oparm;
5137                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5138                         DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5139                                 performance might be affected");
5140                         ret = OMX_ErrorHardware;
5141                     }
5142                     client_set_fps = true;
5143                 } else {
5144                     DEBUG_PRINT_ERROR("Frame rate not supported.");
5145                     ret = OMX_ErrorUnsupportedSetting;
5146                 }
5147             } else {
5148                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5149                 client_set_fps = false;
5150             }
5151         } else {
5152             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5153                     (int)config->nPortIndex);
5154             ret = OMX_ErrorBadPortIndex;
5155         }
5156 
5157         return ret;
5158     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5159         OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5160             (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5161         struct v4l2_control control;
5162 
5163         DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5164 
5165         control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5166 
5167         switch (perf->ePerfLevel) {
5168             case OMX_QCOM_PerfLevelNominal:
5169                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5170                 break;
5171             case OMX_QCOM_PerfLevelTurbo:
5172                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5173                 break;
5174             default:
5175                 ret = OMX_ErrorUnsupportedSetting;
5176                 break;
5177         }
5178 
5179         if (ret == OMX_ErrorNone) {
5180             ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5181                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5182         }
5183 
5184         return ret;
5185     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5186         OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5187             (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5188         struct v4l2_control control;
5189         DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5190         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5191 
5192         switch (config->eDecodeType) {
5193             case OMX_QCOM_PictypeDecode_I:
5194                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5195                 break;
5196             case OMX_QCOM_PictypeDecode_IPB:
5197             default:
5198                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5199                 break;
5200         }
5201 
5202         ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5203                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5204         if (ret)
5205             DEBUG_PRINT_ERROR("Failed to set picture type decode");
5206 
5207         return ret;
5208     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5209         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5210         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5211 
5212         struct v4l2_control control;
5213 
5214         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5215         if (priority->nU32 == 0)
5216             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5217         else
5218             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5219 
5220         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5221             DEBUG_PRINT_ERROR("Failed to set Priority");
5222             ret = OMX_ErrorUnsupportedSetting;
5223         }
5224         return ret;
5225     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5226         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5227         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5228 
5229         struct v4l2_control control;
5230 
5231         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5232         control.value = rate->nU32;
5233 
5234         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5235             ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5236                     OMX_ErrorUnsupportedSetting;
5237             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5238                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5239         }
5240         return ret;
5241 
5242     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5243         VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5244         DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5245         if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5246             enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5247         }
5248 
5249         print_debug_color_aspects(&(params->sAspects), "Set Config");
5250         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5251         return ret;
5252     }
5253 
5254     return OMX_ErrorNotImplemented;
5255 }
5256 
5257 #define extn_equals(param, extn) (!strcmp(param, extn))
5258 
5259 /* ======================================================================
5260    FUNCTION
5261    omx_vdec::GetExtensionIndex
5262 
5263    DESCRIPTION
5264    OMX GetExtensionIndex method implementaion.  <TBD>
5265 
5266    PARAMETERS
5267    <TBD>.
5268 
5269    RETURN VALUE
5270    OMX Error None if everything successful.
5271 
5272    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5273 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5274         OMX_IN OMX_STRING      paramName,
5275         OMX_OUT OMX_INDEXTYPE* indexType)
5276 {
5277     (void) hComp;
5278     if (m_state == OMX_StateInvalid) {
5279         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5280         return OMX_ErrorInvalidState;
5281     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5282         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5283     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5284         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5285     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5286         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5287     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5288         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5289     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5290         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5291     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5292         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5293     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5294         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5295     }
5296 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5297     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5298         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5299     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5300         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5301     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5302         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5303         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5304     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5305         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5306     } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5307         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5308     }
5309 #endif
5310     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5311         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5312     }
5313 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5314     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5315         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5316     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5317         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5318     }
5319 #endif
5320 #ifdef FLEXYUV_SUPPORTED
5321     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5322         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5323     }
5324 #endif
5325     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5326         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5327     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5328         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5329     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5330         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5331     } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5332         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5333     } else {
5334         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5335         return OMX_ErrorNotImplemented;
5336     }
5337     return OMX_ErrorNone;
5338 }
5339 
5340 /* ======================================================================
5341    FUNCTION
5342    omx_vdec::GetState
5343 
5344    DESCRIPTION
5345    Returns the state information back to the caller.<TBD>
5346 
5347    PARAMETERS
5348    <TBD>.
5349 
5350    RETURN VALUE
5351    Error None if everything is successful.
5352    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5353 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5354         OMX_OUT OMX_STATETYPE* state)
5355 {
5356     (void) hComp;
5357     *state = m_state;
5358     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5359     return OMX_ErrorNone;
5360 }
5361 
5362 /* ======================================================================
5363    FUNCTION
5364    omx_vdec::ComponentTunnelRequest
5365 
5366    DESCRIPTION
5367    OMX Component Tunnel Request method implementation. <TBD>
5368 
5369    PARAMETERS
5370    None.
5371 
5372    RETURN VALUE
5373    OMX Error None if everything successful.
5374 
5375    ========================================================================== */
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)5376 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5377         OMX_IN OMX_U32                        port,
5378         OMX_IN OMX_HANDLETYPE        peerComponent,
5379         OMX_IN OMX_U32                    peerPort,
5380         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5381 {
5382     (void) hComp;
5383     (void) port;
5384     (void) peerComponent;
5385     (void) peerPort;
5386     (void) tunnelSetup;
5387     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5388     return OMX_ErrorNotImplemented;
5389 }
5390 
5391 /* ======================================================================
5392    FUNCTION
5393    omx_vdec::UseOutputBuffer
5394 
5395    DESCRIPTION
5396    Helper function for Use buffer in the input pin
5397 
5398    PARAMETERS
5399    None.
5400 
5401    RETURN VALUE
5402    true/false
5403 
5404    ========================================================================== */
allocate_extradata()5405 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5406 {
5407 #ifdef USE_ION
5408     if (drv_ctx.extradata_info.buffer_size) {
5409         if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5410             munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5411             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5412             free_ion_memory(&drv_ctx.extradata_info.ion);
5413         }
5414         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5415         drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5416                 drv_ctx.extradata_info.size, 4096,
5417                 &drv_ctx.extradata_info.ion.ion_alloc_data,
5418                 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5419         if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5420             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5421             return OMX_ErrorInsufficientResources;
5422         }
5423         drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5424                 drv_ctx.extradata_info.size,
5425                 PROT_READ|PROT_WRITE, MAP_SHARED,
5426                 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5427         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5428             DEBUG_PRINT_ERROR("Failed to map extradata memory");
5429             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5430             free_ion_memory(&drv_ctx.extradata_info.ion);
5431             return OMX_ErrorInsufficientResources;
5432         }
5433     }
5434 #endif
5435     if (!m_other_extradata) {
5436         m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5437         if (!m_other_extradata) {
5438             DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5439             return OMX_ErrorInsufficientResources;
5440         }
5441     }
5442     return OMX_ErrorNone;
5443 }
5444 
free_extradata()5445 void omx_vdec::free_extradata()
5446 {
5447 #ifdef USE_ION
5448     if (drv_ctx.extradata_info.uaddr) {
5449         munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5450         close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5451         free_ion_memory(&drv_ctx.extradata_info.ion);
5452     }
5453     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
5454 #endif
5455     if (m_other_extradata) {
5456         free(m_other_extradata);
5457         m_other_extradata = NULL;
5458     }
5459 }
5460 
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)5461 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5462         OMX_IN OMX_HANDLETYPE            hComp,
5463         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5464         OMX_IN OMX_U32                   port,
5465         OMX_IN OMX_PTR                   appData,
5466         OMX_IN OMX_U32                   bytes,
5467         OMX_IN OMX_U8*                   buffer)
5468 {
5469     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5470     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5471     unsigned                         i= 0; // Temporary counter
5472     struct vdec_setbuffer_cmd setbuffers;
5473     OMX_PTR privateAppData = NULL;
5474     private_handle_t *handle = NULL;
5475     OMX_U8 *buff = buffer;
5476     struct v4l2_buffer buf;
5477     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5478     int extra_idx = 0;
5479     (void) hComp;
5480     (void) port;
5481 
5482     if (!m_out_mem_ptr) {
5483         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5484         eRet = allocate_output_headers();
5485         if (eRet == OMX_ErrorNone)
5486             eRet = allocate_extradata();
5487     }
5488 
5489     if (eRet == OMX_ErrorNone) {
5490         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5491             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5492                 break;
5493             }
5494         }
5495     }
5496 
5497     if (i >= drv_ctx.op_buf.actualcount) {
5498         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5499         eRet = OMX_ErrorInsufficientResources;
5500     }
5501 
5502     if (eRet != OMX_ErrorNone)
5503        return eRet;
5504 
5505     if (dynamic_buf_mode) {
5506         *bufferHdr = (m_out_mem_ptr + i );
5507         (*bufferHdr)->pBuffer = NULL;
5508         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5509             enum v4l2_buf_type buf_type;
5510             int rr = 0;
5511             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5512             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5513                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5514                 return OMX_ErrorInsufficientResources;
5515             } else {
5516                 streaming[CAPTURE_PORT] = true;
5517                 DEBUG_PRINT_LOW("STREAMON Successful");
5518             }
5519 
5520             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5521             request_perf_level(VIDC_TURBO);
5522         }
5523         BITMASK_SET(&m_out_bm_count,i);
5524         (*bufferHdr)->pAppPrivate = appData;
5525         (*bufferHdr)->pBuffer = buffer;
5526         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5527         return eRet;
5528     }
5529 
5530     if (eRet == OMX_ErrorNone) {
5531 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5532         if (m_enable_android_native_buffers) {
5533             if (m_use_android_native_buffers) {
5534                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5535                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5536                 handle = (private_handle_t *)nBuf->handle;
5537                 privateAppData = params->pAppPrivate;
5538             } else {
5539                 handle = (private_handle_t *)buff;
5540                 privateAppData = appData;
5541             }
5542             if (!handle) {
5543                 DEBUG_PRINT_ERROR("handle is invalid");
5544                 return OMX_ErrorBadParameter;
5545             }
5546 
5547             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5548                 if (secure_mode && secure_scaling_to_non_secure_opb) {
5549                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5550                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5551                 } else {
5552                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5553                             " expected %u, got %u",
5554                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5555                     return OMX_ErrorBadParameter;
5556                 }
5557             }
5558 
5559             drv_ctx.op_buf.buffer_size = handle->size;
5560 
5561             if (!m_use_android_native_buffers) {
5562                 if (!secure_mode) {
5563                     buff =  (OMX_U8*)mmap(0, handle->size,
5564                             PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
5565                     if (buff == MAP_FAILED) {
5566                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5567                         return OMX_ErrorInsufficientResources;
5568                     }
5569                 }
5570             }
5571 #if defined(_ANDROID_ICS_)
5572             native_buffer[i].nativehandle = handle;
5573             native_buffer[i].privatehandle = handle;
5574 #endif
5575             if (!handle) {
5576                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5577                 return OMX_ErrorBadParameter;
5578             }
5579             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5580             drv_ctx.ptr_outputbuffer[i].offset = 0;
5581             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5582             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5583             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5584         } else
5585 #endif
5586 
5587             if (!ouput_egl_buffers && !m_use_output_pmem) {
5588 #ifdef USE_ION
5589                 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5590                         drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
5591                         &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
5592                         &drv_ctx.op_buf_ion_info[i].fd_ion_data,
5593                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5594                 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
5595                     DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
5596                     return OMX_ErrorInsufficientResources;
5597                 }
5598                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5599                                       drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5600 #else
5601                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5602                                       open (MEM_DEVICE,O_RDWR);
5603 
5604                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5605                     DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5606                     return OMX_ErrorInsufficientResources;
5607                 }
5608 
5609                 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
5610                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
5611                     drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5612                                           open (MEM_DEVICE,O_RDWR);
5613                     if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5614                         DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5615                         return OMX_ErrorInsufficientResources;
5616                     }
5617                 }
5618 
5619                 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5620                             drv_ctx.op_buf.buffer_size,
5621                             drv_ctx.op_buf.alignment)) {
5622                     DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5623                     close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5624                     return OMX_ErrorInsufficientResources;
5625                 }
5626 #endif
5627                 if (!secure_mode) {
5628                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
5629                         (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
5630                                 PROT_READ|PROT_WRITE, MAP_SHARED,
5631                                 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
5632                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5633                         close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5634 #ifdef USE_ION
5635                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5636 #endif
5637                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5638                         return OMX_ErrorInsufficientResources;
5639                     }
5640                 }
5641                 drv_ctx.ptr_outputbuffer[i].offset = 0;
5642                 privateAppData = appData;
5643             } else {
5644 
5645                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5646                 if (!appData || !bytes ) {
5647                     if (!secure_mode && !buffer) {
5648                         DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
5649                         return OMX_ErrorBadParameter;
5650                     }
5651                 }
5652 
5653                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
5654                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
5655                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
5656                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
5657                         !pmem_list->nEntries ||
5658                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
5659                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
5660                     return OMX_ErrorBadParameter;
5661                 }
5662                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5663                     pmem_list->entryList->entry;
5664                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
5665                         pmem_info->pmem_fd);
5666                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
5667                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
5668                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5669                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
5670                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5671                 privateAppData = appData;
5672             }
5673         m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5674         m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5675         m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5676         m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5677         m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5678 
5679         *bufferHdr = (m_out_mem_ptr + i );
5680         if (secure_mode)
5681             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5682         //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5683         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
5684                 sizeof (vdec_bufferpayload));
5685 
5686         DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
5687                 drv_ctx.ptr_outputbuffer[i].bufferaddr,
5688                 drv_ctx.ptr_outputbuffer[i].pmem_fd );
5689 
5690         buf.index = i;
5691         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5692         buf.memory = V4L2_MEMORY_USERPTR;
5693         plane[0].length = drv_ctx.op_buf.buffer_size;
5694         plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
5695             (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
5696         plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5697         plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
5698         plane[0].data_offset = 0;
5699         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5700         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5701             plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5702             plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
5703 #ifdef USE_ION
5704             plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5705 #endif
5706             plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
5707             plane[extra_idx].data_offset = 0;
5708         } else if  (extra_idx >= VIDEO_MAX_PLANES) {
5709             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
5710             return OMX_ErrorBadParameter;
5711         }
5712         buf.m.planes = plane;
5713         buf.length = drv_ctx.num_planes;
5714 
5715         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
5716             DEBUG_PRINT_ERROR("Failed to prepare bufs");
5717             /*TODO: How to handle this case */
5718             return OMX_ErrorInsufficientResources;
5719         }
5720 
5721         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
5722             enum v4l2_buf_type buf_type;
5723             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5724             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
5725                 return OMX_ErrorInsufficientResources;
5726             } else {
5727                 streaming[CAPTURE_PORT] = true;
5728                 DEBUG_PRINT_LOW("STREAMON Successful");
5729             }
5730 
5731             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5732             request_perf_level(VIDC_TURBO);
5733         }
5734 
5735         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
5736         if (m_enable_android_native_buffers) {
5737             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
5738             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
5739         } else {
5740             (*bufferHdr)->pBuffer = buff;
5741         }
5742         (*bufferHdr)->pAppPrivate = privateAppData;
5743         BITMASK_SET(&m_out_bm_count,i);
5744     }
5745     return eRet;
5746 }
5747 
5748 /* ======================================================================
5749    FUNCTION
5750    omx_vdec::use_input_heap_buffers
5751 
5752    DESCRIPTION
5753    OMX Use Buffer Heap allocation method implementation.
5754 
5755    PARAMETERS
5756    <TBD>.
5757 
5758    RETURN VALUE
5759    OMX Error None , if everything successful.
5760 
5761    ========================================================================== */
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)5762 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
5763         OMX_IN OMX_HANDLETYPE            hComp,
5764         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5765         OMX_IN OMX_U32                   port,
5766         OMX_IN OMX_PTR                   appData,
5767         OMX_IN OMX_U32                   bytes,
5768         OMX_IN OMX_U8*                   buffer)
5769 {
5770     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5771     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5772     if (!m_inp_heap_ptr)
5773         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5774             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5775                     drv_ctx.ip_buf.actualcount);
5776     if (!m_phdr_pmem_ptr)
5777         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5778             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5779                     drv_ctx.ip_buf.actualcount);
5780     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5781         DEBUG_PRINT_ERROR("Insufficent memory");
5782         eRet = OMX_ErrorInsufficientResources;
5783     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5784         input_use_buffer = true;
5785         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5786         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5787         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5788         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5789         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5790         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5791         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5792         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5793         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5794         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5795                     (unsigned)NULL, (unsigned)NULL)) {
5796             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5797             return OMX_ErrorInsufficientResources;
5798         }
5799         m_in_alloc_cnt++;
5800     } else {
5801         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5802         eRet = OMX_ErrorInsufficientResources;
5803     }
5804     return eRet;
5805 }
5806 
5807 /* ======================================================================
5808    FUNCTION
5809    omx_vdec::UseBuffer
5810 
5811    DESCRIPTION
5812    OMX Use Buffer method implementation.
5813 
5814    PARAMETERS
5815    <TBD>.
5816 
5817    RETURN VALUE
5818    OMX Error None , if everything successful.
5819 
5820    ========================================================================== */
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)5821 OMX_ERRORTYPE  omx_vdec::use_buffer(
5822         OMX_IN OMX_HANDLETYPE            hComp,
5823         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5824         OMX_IN OMX_U32                   port,
5825         OMX_IN OMX_PTR                   appData,
5826         OMX_IN OMX_U32                   bytes,
5827         OMX_IN OMX_U8*                   buffer)
5828 {
5829     OMX_ERRORTYPE error = OMX_ErrorNone;
5830     struct vdec_setbuffer_cmd setbuffers;
5831 
5832     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5833             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5834             return OMX_ErrorBadParameter;
5835     }
5836     if (m_state == OMX_StateInvalid) {
5837         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5838         return OMX_ErrorInvalidState;
5839     }
5840     if (port == OMX_CORE_INPUT_PORT_INDEX)
5841         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5842     else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
5843         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5844     else {
5845         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5846         error = OMX_ErrorBadPortIndex;
5847     }
5848     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5849     if (error == OMX_ErrorNone) {
5850         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5851             // Send the callback now
5852             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5853             post_event(OMX_CommandStateSet,OMX_StateIdle,
5854                     OMX_COMPONENT_GENERATE_EVENT);
5855         }
5856         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5857                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5858             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5859             post_event(OMX_CommandPortEnable,
5860                     OMX_CORE_INPUT_PORT_INDEX,
5861                     OMX_COMPONENT_GENERATE_EVENT);
5862         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
5863                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5864             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5865             post_event(OMX_CommandPortEnable,
5866                     OMX_CORE_OUTPUT_PORT_INDEX,
5867                     OMX_COMPONENT_GENERATE_EVENT);
5868         }
5869     }
5870     return error;
5871 }
5872 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)5873 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
5874         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
5875 {
5876     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
5877         if (m_inp_heap_ptr[bufferindex].pBuffer)
5878             free(m_inp_heap_ptr[bufferindex].pBuffer);
5879         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
5880     }
5881     if (pmem_bufferHdr)
5882         free_input_buffer(pmem_bufferHdr);
5883     return OMX_ErrorNone;
5884 }
5885 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5886 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5887 {
5888     unsigned int index = 0;
5889     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
5890         return OMX_ErrorBadParameter;
5891     }
5892 
5893     index = bufferHdr - m_inp_mem_ptr;
5894     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5895 
5896     auto_lock l(buf_lock);
5897     bufferHdr->pInputPortPrivate = NULL;
5898 
5899     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
5900         DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5901         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
5902             struct vdec_setbuffer_cmd setbuffers;
5903             setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
5904             memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
5905                     sizeof (vdec_bufferpayload));
5906             if (!secure_mode) {
5907                 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
5908                         drv_ctx.ptr_inputbuffer[index].pmem_fd);
5909                 DEBUG_PRINT_LOW("unmap the input buffer size=%u  address = %p",
5910                         (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
5911                         drv_ctx.ptr_inputbuffer[index].bufferaddr);
5912                 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
5913                         drv_ctx.ptr_inputbuffer[index].mmaped_size);
5914                 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
5915             } else if (allocate_native_handle){
5916                 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
5917                 native_handle_close(nh);
5918                 native_handle_delete(nh);
5919             }
5920             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
5921             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
5922                 free(m_desc_buffer_ptr[index].buf_addr);
5923                 m_desc_buffer_ptr[index].buf_addr = NULL;
5924                 m_desc_buffer_ptr[index].desc_data_size = 0;
5925             }
5926 #ifdef USE_ION
5927             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
5928 #endif
5929         }
5930     }
5931 
5932     return OMX_ErrorNone;
5933 }
5934 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5935 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5936 {
5937     unsigned int index = 0;
5938 
5939     if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
5940         return OMX_ErrorBadParameter;
5941     }
5942 
5943     index = bufferHdr - m_out_mem_ptr;
5944     DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
5945 
5946     if (index < drv_ctx.op_buf.actualcount
5947             && drv_ctx.ptr_outputbuffer) {
5948         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
5949                 drv_ctx.ptr_outputbuffer[index].bufferaddr);
5950 
5951         struct vdec_setbuffer_cmd setbuffers;
5952         setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5953         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
5954                 sizeof (vdec_bufferpayload));
5955 
5956         if (!dynamic_buf_mode) {
5957             if (streaming[CAPTURE_PORT] &&
5958                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
5959                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
5960                     DEBUG_PRINT_ERROR("STREAMOFF Failed");
5961                 } else {
5962                     DEBUG_PRINT_LOW("STREAMOFF Successful");
5963                 }
5964             }
5965 #ifdef _ANDROID_
5966             if (m_enable_android_native_buffers) {
5967                 if (!secure_mode) {
5968                     if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
5969                         munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
5970                                 drv_ctx.ptr_outputbuffer[index].mmaped_size);
5971                     }
5972                 }
5973                 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
5974             } else {
5975 #endif
5976                 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
5977                     if (!secure_mode) {
5978                         DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
5979                                 drv_ctx.ptr_outputbuffer[0].pmem_fd);
5980                         DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
5981                                 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
5982                                 drv_ctx.ptr_outputbuffer[0].bufferaddr);
5983                         munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
5984                                 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
5985                     }
5986                     close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
5987                     drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
5988 #ifdef USE_ION
5989                     free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
5990 #endif
5991                 }
5992 #ifdef _ANDROID_
5993             }
5994 #endif
5995         } //!dynamic_buf_mode
5996         if (release_output_done()) {
5997             free_extradata();
5998         }
5999     }
6000 
6001     return OMX_ErrorNone;
6002 
6003 }
6004 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6005 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
6006         OMX_BUFFERHEADERTYPE **bufferHdr,
6007         OMX_U32              port,
6008         OMX_PTR              appData,
6009         OMX_U32              bytes)
6010 {
6011     OMX_BUFFERHEADERTYPE *input = NULL;
6012     unsigned char *buf_addr = NULL;
6013     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6014     unsigned   i = 0;
6015 
6016     /* Sanity Check*/
6017     if (bufferHdr == NULL) {
6018         return OMX_ErrorBadParameter;
6019     }
6020 
6021     if (m_inp_heap_ptr == NULL) {
6022         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6023                  calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6024                          drv_ctx.ip_buf.actualcount);
6025         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6026                   calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6027                           drv_ctx.ip_buf.actualcount);
6028 
6029         if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6030             DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6031             return OMX_ErrorInsufficientResources;
6032         }
6033     }
6034 
6035     /*Find a Free index*/
6036     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6037         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6038             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6039             break;
6040         }
6041     }
6042 
6043     if (i < drv_ctx.ip_buf.actualcount) {
6044         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6045 
6046         if (buf_addr == NULL) {
6047             return OMX_ErrorInsufficientResources;
6048         }
6049 
6050         *bufferHdr = (m_inp_heap_ptr + i);
6051         input = *bufferHdr;
6052         BITMASK_SET(&m_heap_inp_bm_count,i);
6053 
6054         input->pBuffer           = (OMX_U8 *)buf_addr;
6055         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6056         input->nVersion.nVersion = OMX_SPEC_VERSION;
6057         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6058         input->pAppPrivate       = appData;
6059         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6060         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6061         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6062         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6063         /*Add the Buffers to freeq*/
6064         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6065                     (unsigned)NULL, (unsigned)NULL)) {
6066             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6067             return OMX_ErrorInsufficientResources;
6068         }
6069     } else {
6070         return OMX_ErrorBadParameter;
6071     }
6072 
6073     return eRet;
6074 
6075 }
6076 
6077 
6078 /* ======================================================================
6079    FUNCTION
6080    omx_vdec::AllocateInputBuffer
6081 
6082    DESCRIPTION
6083    Helper function for allocate buffer in the input pin
6084 
6085    PARAMETERS
6086    None.
6087 
6088    RETURN VALUE
6089    true/false
6090 
6091    ========================================================================== */
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)6092 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6093         OMX_IN OMX_HANDLETYPE            hComp,
6094         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6095         OMX_IN OMX_U32                   port,
6096         OMX_IN OMX_PTR                   appData,
6097         OMX_IN OMX_U32                   bytes)
6098 {
6099     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6100     struct vdec_setbuffer_cmd setbuffers;
6101     OMX_BUFFERHEADERTYPE *input = NULL;
6102     unsigned   i = 0;
6103     unsigned char *buf_addr = NULL;
6104     int pmem_fd = -1;
6105 
6106     (void) hComp;
6107     (void) port;
6108 
6109 
6110     if (bytes != drv_ctx.ip_buf.buffer_size) {
6111         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6112                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6113         return OMX_ErrorBadParameter;
6114     }
6115 
6116     if (!m_inp_mem_ptr) {
6117         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6118                 drv_ctx.ip_buf.actualcount,
6119                 (unsigned int)drv_ctx.ip_buf.buffer_size);
6120 
6121         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6122                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6123 
6124         if (m_inp_mem_ptr == NULL) {
6125             return OMX_ErrorInsufficientResources;
6126         }
6127 
6128         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6129                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6130 
6131         if (drv_ctx.ptr_inputbuffer == NULL) {
6132             return OMX_ErrorInsufficientResources;
6133         }
6134 #ifdef USE_ION
6135         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6136                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6137 
6138         if (drv_ctx.ip_buf_ion_info == NULL) {
6139             return OMX_ErrorInsufficientResources;
6140         }
6141 #endif
6142 
6143         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6144             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6145 #ifdef USE_ION
6146             drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6147 #endif
6148         }
6149     }
6150 
6151     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6152         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6153             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6154             break;
6155         }
6156     }
6157 
6158     if (i < drv_ctx.ip_buf.actualcount) {
6159         struct v4l2_buffer buf;
6160         struct v4l2_plane plane;
6161         int rc;
6162         DEBUG_PRINT_LOW("Allocate input Buffer");
6163 #ifdef USE_ION
6164         drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6165                 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
6166                 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6167                 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6168                 SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6169         if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6170             return OMX_ErrorInsufficientResources;
6171         }
6172         pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6173 #else
6174         pmem_fd = open (MEM_DEVICE,O_RDWR);
6175 
6176         if (pmem_fd < 0) {
6177             DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6178             return OMX_ErrorInsufficientResources;
6179         }
6180 
6181         if (pmem_fd == 0) {
6182             pmem_fd = open (MEM_DEVICE,O_RDWR);
6183 
6184             if (pmem_fd < 0) {
6185                 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6186                 return OMX_ErrorInsufficientResources;
6187             }
6188         }
6189 
6190         if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6191                     drv_ctx.ip_buf.alignment)) {
6192             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6193             close(pmem_fd);
6194             return OMX_ErrorInsufficientResources;
6195         }
6196 #endif
6197         if (!secure_mode) {
6198             buf_addr = (unsigned char *)mmap(NULL,
6199                     drv_ctx.ip_buf.buffer_size,
6200                     PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6201 
6202             if (buf_addr == MAP_FAILED) {
6203                 close(pmem_fd);
6204 #ifdef USE_ION
6205                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6206 #endif
6207                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6208                 return OMX_ErrorInsufficientResources;
6209             }
6210         }
6211         *bufferHdr = (m_inp_mem_ptr + i);
6212         if (secure_mode)
6213             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6214         else
6215             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6216         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6217         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6218         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6219         drv_ctx.ptr_inputbuffer [i].offset = 0;
6220 
6221 
6222         buf.index = i;
6223         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6224         buf.memory = V4L2_MEMORY_USERPTR;
6225         plane.bytesused = 0;
6226         plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6227         plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6228         plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6229         plane.reserved[1] = 0;
6230         plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6231         buf.m.planes = &plane;
6232         buf.length = 1;
6233 
6234         DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6235                 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6236 
6237         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6238 
6239         if (rc) {
6240             DEBUG_PRINT_ERROR("Failed to prepare bufs");
6241             /*TODO: How to handle this case */
6242             return OMX_ErrorInsufficientResources;
6243         }
6244 
6245         input = *bufferHdr;
6246         BITMASK_SET(&m_inp_bm_count,i);
6247         DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6248         if (allocate_native_handle) {
6249             native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6250             nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6251             input->pBuffer = (OMX_U8 *)nh;
6252         } else if (secure_mode || m_input_pass_buffer_fd) {
6253             /*Legacy method, pass ion fd stashed directly in pBuffer*/
6254             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6255         } else {
6256             input->pBuffer           = (OMX_U8 *)buf_addr;
6257         }
6258         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6259         input->nVersion.nVersion = OMX_SPEC_VERSION;
6260         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6261         input->pAppPrivate       = appData;
6262         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6263         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6264 
6265         if (drv_ctx.disable_dmx) {
6266             eRet = allocate_desc_buffer(i);
6267         }
6268     } else {
6269         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6270         eRet = OMX_ErrorInsufficientResources;
6271     }
6272     return eRet;
6273 }
6274 
6275 
6276 /* ======================================================================
6277    FUNCTION
6278    omx_vdec::AllocateOutputBuffer
6279 
6280    DESCRIPTION
6281    Helper fn for AllocateBuffer in the output pin
6282 
6283    PARAMETERS
6284    <TBD>.
6285 
6286    RETURN VALUE
6287    OMX Error None if everything went well.
6288 
6289    ========================================================================== */
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)6290 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6291         OMX_IN OMX_HANDLETYPE            hComp,
6292         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6293         OMX_IN OMX_U32                   port,
6294         OMX_IN OMX_PTR                   appData,
6295         OMX_IN OMX_U32                   bytes)
6296 {
6297     (void)hComp;
6298     (void)port;
6299     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6300     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6301     unsigned                         i= 0; // Temporary counter
6302     struct vdec_setbuffer_cmd setbuffers;
6303     int extra_idx = 0;
6304 #ifdef USE_ION
6305     int ion_device_fd =-1;
6306     struct ion_allocation_data ion_alloc_data;
6307     struct ion_fd_data fd_ion_data;
6308 #endif
6309     if (!m_out_mem_ptr) {
6310         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6311                 drv_ctx.op_buf.actualcount,
6312                 (unsigned int)drv_ctx.op_buf.buffer_size);
6313         int nBufHdrSize        = 0;
6314         int nPlatformEntrySize = 0;
6315         int nPlatformListSize  = 0;
6316         int nPMEMInfoSize = 0;
6317         int pmem_fd = -1;
6318         unsigned char *pmem_baseaddress = NULL;
6319 
6320         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6321         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6322         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6323 
6324         DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6325                 drv_ctx.op_buf.actualcount);
6326         nBufHdrSize        = drv_ctx.op_buf.actualcount *
6327             sizeof(OMX_BUFFERHEADERTYPE);
6328 
6329         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6330             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6331         nPlatformListSize  = drv_ctx.op_buf.actualcount *
6332             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6333         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6334             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6335 
6336         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6337                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6338                 nPMEMInfoSize,
6339                 nPlatformListSize);
6340         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6341                 drv_ctx.op_buf.actualcount);
6342 #ifdef USE_ION
6343         // Allocate output buffers as cached to improve performance of software-reading
6344         // of the YUVs. Output buffers are cache-invalidated in driver.
6345         // If color-conversion is involved, Only the C2D output buffers are cached, no
6346         // need to cache the decoder's output buffers
6347         int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6348         ion_device_fd = alloc_map_ion_memory(
6349                 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
6350                 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6351                 &ion_alloc_data, &fd_ion_data,
6352                 (secure_mode && !secure_scaling_to_non_secure_opb) ?
6353                 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6354         if (ion_device_fd < 0) {
6355             return OMX_ErrorInsufficientResources;
6356         }
6357         pmem_fd = fd_ion_data.fd;
6358 #else
6359         pmem_fd = open (MEM_DEVICE,O_RDWR);
6360 
6361         if (pmem_fd < 0) {
6362             DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6363                     drv_ctx.op_buf.buffer_size);
6364             return OMX_ErrorInsufficientResources;
6365         }
6366 
6367         if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
6368                     drv_ctx.op_buf.actualcount,
6369                     drv_ctx.op_buf.alignment)) {
6370             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6371             close(pmem_fd);
6372             return OMX_ErrorInsufficientResources;
6373         }
6374 #endif
6375         if (!secure_mode) {
6376             pmem_baseaddress = (unsigned char *)mmap(NULL,
6377                     (drv_ctx.op_buf.buffer_size *
6378                      drv_ctx.op_buf.actualcount),
6379                     PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
6380             if (pmem_baseaddress == MAP_FAILED) {
6381                 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6382                         (unsigned int)drv_ctx.op_buf.buffer_size);
6383                 close(pmem_fd);
6384 #ifdef USE_ION
6385                 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6386 #endif
6387                 return OMX_ErrorInsufficientResources;
6388             }
6389         }
6390         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
6391         // Alloc mem for platform specific info
6392         char *pPtr=NULL;
6393         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6394                 nPMEMInfoSize,1);
6395         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6396                        calloc (sizeof(struct vdec_bufferpayload),
6397                                drv_ctx.op_buf.actualcount);
6398         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
6399                      calloc (sizeof (struct vdec_output_frameinfo),
6400                              drv_ctx.op_buf.actualcount);
6401         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6402             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6403             return OMX_ErrorInsufficientResources;
6404         }
6405 
6406 #ifdef USE_ION
6407         drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6408                       calloc (sizeof(struct vdec_ion),
6409                               drv_ctx.op_buf.actualcount);
6410         if (!drv_ctx.op_buf_ion_info) {
6411             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6412             return OMX_ErrorInsufficientResources;
6413         }
6414 #endif
6415 
6416         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6417                 && drv_ctx.ptr_respbuffer) {
6418             drv_ctx.ptr_outputbuffer[0].mmaped_size =
6419                 (drv_ctx.op_buf.buffer_size *
6420                  drv_ctx.op_buf.actualcount);
6421             bufHdr          =  m_out_mem_ptr;
6422             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6423             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6424                 (((char *) m_platform_list)  + nPlatformListSize);
6425             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6426                 (((char *) m_platform_entry) + nPlatformEntrySize);
6427             pPlatformList   = m_platform_list;
6428             pPlatformEntry  = m_platform_entry;
6429             pPMEMInfo       = m_pmem_info;
6430 
6431             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6432 
6433             // Settting the entire storage nicely
6434             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
6435             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
6436             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6437                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6438                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6439                 // Set the values when we determine the right HxW param
6440                 bufHdr->nAllocLen          = bytes;
6441                 bufHdr->nFilledLen         = 0;
6442                 bufHdr->pAppPrivate        = appData;
6443                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
6444                 // Platform specific PMEM Information
6445                 // Initialize the Platform Entry
6446                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6447                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6448                 pPlatformEntry->entry      = pPMEMInfo;
6449                 // Initialize the Platform List
6450                 pPlatformList->nEntries    = 1;
6451                 pPlatformList->entryList   = pPlatformEntry;
6452                 // Keep pBuffer NULL till vdec is opened
6453                 bufHdr->pBuffer            = NULL;
6454                 bufHdr->nOffset            = 0;
6455 
6456                 pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
6457                 pPMEMInfo->pmem_fd = -1;
6458                 bufHdr->pPlatformPrivate = pPlatformList;
6459 
6460                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
6461                 m_pmem_info[i].pmem_fd = pmem_fd;
6462 #ifdef USE_ION
6463                 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
6464                 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
6465                 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
6466 #endif
6467 
6468                 /*Create a mapping between buffers*/
6469                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
6470                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
6471                                     &drv_ctx.ptr_outputbuffer[i];
6472                 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
6473                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6474                     pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
6475                 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6476                 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6477                 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6478 
6479                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
6480                         pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
6481                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
6482                 // Move the buffer and buffer header pointers
6483                 bufHdr++;
6484                 pPMEMInfo++;
6485                 pPlatformEntry++;
6486                 pPlatformList++;
6487             }
6488         } else {
6489             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6490                     m_out_mem_ptr, pPtr);
6491             if (m_out_mem_ptr) {
6492                 free(m_out_mem_ptr);
6493                 m_out_mem_ptr = NULL;
6494             }
6495             if (pPtr) {
6496                 free(pPtr);
6497                 pPtr = NULL;
6498             }
6499             if (drv_ctx.ptr_outputbuffer) {
6500                 free(drv_ctx.ptr_outputbuffer);
6501                 drv_ctx.ptr_outputbuffer = NULL;
6502             }
6503             if (drv_ctx.ptr_respbuffer) {
6504                 free(drv_ctx.ptr_respbuffer);
6505                 drv_ctx.ptr_respbuffer = NULL;
6506             }
6507 #ifdef USE_ION
6508             if (drv_ctx.op_buf_ion_info) {
6509                 DEBUG_PRINT_LOW("Free o/p ion context");
6510                 free(drv_ctx.op_buf_ion_info);
6511                 drv_ctx.op_buf_ion_info = NULL;
6512             }
6513 #endif
6514             eRet =  OMX_ErrorInsufficientResources;
6515         }
6516         if (eRet == OMX_ErrorNone)
6517             eRet = allocate_extradata();
6518     }
6519 
6520     for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6521         if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6522             DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
6523             break;
6524         }
6525     }
6526 
6527     if (eRet == OMX_ErrorNone) {
6528         if (i < drv_ctx.op_buf.actualcount) {
6529             struct v4l2_buffer buf;
6530             struct v4l2_plane plane[VIDEO_MAX_PLANES];
6531             int rc;
6532             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6533 
6534             drv_ctx.ptr_outputbuffer[i].buffer_len =
6535                 drv_ctx.op_buf.buffer_size;
6536 
6537             *bufferHdr = (m_out_mem_ptr + i );
6538             if (secure_mode) {
6539 #ifdef USE_ION
6540                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6541                     (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6542 #else
6543                 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6544 #endif
6545             }
6546             drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6547 
6548             buf.index = i;
6549             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6550             buf.memory = V4L2_MEMORY_USERPTR;
6551             plane[0].length = drv_ctx.op_buf.buffer_size;
6552             plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6553                 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6554 #ifdef USE_ION
6555             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6556 #endif
6557             plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6558             plane[0].data_offset = 0;
6559             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6560             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6561                 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6562                 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6563 #ifdef USE_ION
6564                 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6565 #endif
6566                 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6567                 plane[extra_idx].data_offset = 0;
6568             } else if (extra_idx >= VIDEO_MAX_PLANES) {
6569                 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
6570                 return OMX_ErrorBadParameter;
6571             }
6572             buf.m.planes = plane;
6573             buf.length = drv_ctx.num_planes;
6574             DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
6575             rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6576             if (rc) {
6577                 /*TODO: How to handle this case */
6578                 return OMX_ErrorInsufficientResources;
6579             }
6580 
6581             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6582                 enum v4l2_buf_type buf_type;
6583                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6584                 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6585                 if (rc) {
6586                     return OMX_ErrorInsufficientResources;
6587                 } else {
6588                     streaming[CAPTURE_PORT] = true;
6589                     DEBUG_PRINT_LOW("STREAMON Successful");
6590                 }
6591 
6592                 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6593                 request_perf_level(VIDC_TURBO);
6594             }
6595 
6596             (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
6597             (*bufferHdr)->pAppPrivate = appData;
6598             BITMASK_SET(&m_out_bm_count,i);
6599         } else {
6600             DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
6601             eRet = OMX_ErrorInsufficientResources;
6602         }
6603     }
6604 
6605     return eRet;
6606 }
6607 
6608 
6609 // AllocateBuffer  -- API Call
6610 /* ======================================================================
6611    FUNCTION
6612    omx_vdec::AllocateBuffer
6613 
6614    DESCRIPTION
6615    Returns zero if all the buffers released..
6616 
6617    PARAMETERS
6618    None.
6619 
6620    RETURN VALUE
6621    true/false
6622 
6623    ========================================================================== */
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)6624 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
6625         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6626         OMX_IN OMX_U32                        port,
6627         OMX_IN OMX_PTR                     appData,
6628         OMX_IN OMX_U32                       bytes)
6629 {
6630     unsigned i = 0;
6631     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
6632 
6633     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
6634     if (m_state == OMX_StateInvalid) {
6635         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
6636         return OMX_ErrorInvalidState;
6637     }
6638 
6639     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6640         if (arbitrary_bytes) {
6641             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
6642         } else {
6643             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
6644         }
6645     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6646         eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
6647                 appData,bytes);
6648     } else {
6649         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6650         eRet = OMX_ErrorBadPortIndex;
6651     }
6652     DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
6653     if (eRet == OMX_ErrorNone) {
6654         if (allocate_done()) {
6655             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6656                 // Send the callback now
6657                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6658                 post_event(OMX_CommandStateSet,OMX_StateIdle,
6659                         OMX_COMPONENT_GENERATE_EVENT);
6660             }
6661         }
6662         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
6663             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6664                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6665                 post_event(OMX_CommandPortEnable,
6666                         OMX_CORE_INPUT_PORT_INDEX,
6667                         OMX_COMPONENT_GENERATE_EVENT);
6668             }
6669         }
6670         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
6671             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6672                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6673                 post_event(OMX_CommandPortEnable,
6674                         OMX_CORE_OUTPUT_PORT_INDEX,
6675                         OMX_COMPONENT_GENERATE_EVENT);
6676             }
6677         }
6678     }
6679     DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
6680     return eRet;
6681 }
6682 
6683 // Free Buffer - API call
6684 /* ======================================================================
6685    FUNCTION
6686    omx_vdec::FreeBuffer
6687 
6688    DESCRIPTION
6689 
6690    PARAMETERS
6691    None.
6692 
6693    RETURN VALUE
6694    true/false
6695 
6696    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6697 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6698         OMX_IN OMX_U32                 port,
6699         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6700 {
6701     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6702     unsigned int nPortIndex;
6703     (void) hComp;
6704     DEBUG_PRINT_LOW("In for decoder free_buffer");
6705 
6706     if (m_state == OMX_StateIdle &&
6707             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6708         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
6709     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
6710             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
6711         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
6712     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
6713                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
6714             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
6715              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
6716         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
6717     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
6718         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
6719         post_event(OMX_EventError,
6720                 OMX_ErrorPortUnpopulated,
6721                 OMX_COMPONENT_GENERATE_EVENT);
6722 
6723         return OMX_ErrorIncorrectStateOperation;
6724     } else if (m_state != OMX_StateInvalid) {
6725         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6726         post_event(OMX_EventError,
6727                 OMX_ErrorPortUnpopulated,
6728                 OMX_COMPONENT_GENERATE_EVENT);
6729     }
6730 
6731     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6732         /*Check if arbitrary bytes*/
6733         if (!arbitrary_bytes && !input_use_buffer)
6734             nPortIndex = buffer - m_inp_mem_ptr;
6735         else
6736             nPortIndex = buffer - m_inp_heap_ptr;
6737 
6738         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6739         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6740                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6741             // Clear the bit associated with it.
6742             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6743             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6744             if (input_use_buffer == true) {
6745 
6746                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6747                 if (m_phdr_pmem_ptr)
6748                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6749             } else {
6750                 if (arbitrary_bytes) {
6751                     if (m_phdr_pmem_ptr)
6752                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
6753                     else
6754                         free_input_buffer(nPortIndex,NULL);
6755                 } else
6756                     free_input_buffer(buffer);
6757             }
6758             m_inp_bPopulated = OMX_FALSE;
6759             if(release_input_done())
6760                 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
6761             /*Free the Buffer Header*/
6762             if (release_input_done()) {
6763                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6764                 free_input_buffer_header();
6765             }
6766         } else {
6767             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6768             eRet = OMX_ErrorBadPortIndex;
6769         }
6770 
6771         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6772                 && release_input_done()) {
6773             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6774             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6775             post_event(OMX_CommandPortDisable,
6776                     OMX_CORE_INPUT_PORT_INDEX,
6777                     OMX_COMPONENT_GENERATE_EVENT);
6778         }
6779     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6780         // check if the buffer is valid
6781         nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6782         if (nPortIndex < drv_ctx.op_buf.actualcount &&
6783                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6784             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6785             // Clear the bit associated with it.
6786             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6787             m_out_bPopulated = OMX_FALSE;
6788             client_buffers.free_output_buffer (buffer);
6789 
6790             if(release_output_done()) {
6791                 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
6792             }
6793             if (release_output_done()) {
6794                 free_output_buffer_header();
6795             }
6796         } else {
6797             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6798             eRet = OMX_ErrorBadPortIndex;
6799         }
6800         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6801                 && release_output_done()) {
6802             DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
6803 
6804             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6805             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6806 #ifdef _ANDROID_ICS_
6807             if (m_enable_android_native_buffers) {
6808                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6809                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6810             }
6811 #endif
6812 
6813             post_event(OMX_CommandPortDisable,
6814                     OMX_CORE_OUTPUT_PORT_INDEX,
6815                     OMX_COMPONENT_GENERATE_EVENT);
6816         }
6817     } else {
6818         eRet = OMX_ErrorBadPortIndex;
6819     }
6820     if ((eRet == OMX_ErrorNone) &&
6821             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6822         if (release_done()) {
6823             // Send the callback now
6824             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6825             post_event(OMX_CommandStateSet, OMX_StateLoaded,
6826                     OMX_COMPONENT_GENERATE_EVENT);
6827         }
6828     }
6829     return eRet;
6830 }
6831 
6832 
6833 /* ======================================================================
6834    FUNCTION
6835    omx_vdec::EmptyThisBuffer
6836 
6837    DESCRIPTION
6838    This routine is used to push the encoded video frames to
6839    the video decoder.
6840 
6841    PARAMETERS
6842    None.
6843 
6844    RETURN VALUE
6845    OMX Error None if everything went successful.
6846 
6847    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6848 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6849         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6850 {
6851     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6852     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6853 
6854     if (m_state != OMX_StateExecuting &&
6855             m_state != OMX_StatePause &&
6856             m_state != OMX_StateIdle) {
6857         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6858         return OMX_ErrorInvalidState;
6859     }
6860 
6861     if (buffer == NULL) {
6862         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6863         return OMX_ErrorBadParameter;
6864     }
6865 
6866     if (!m_inp_bEnabled) {
6867         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
6868         return OMX_ErrorIncorrectStateOperation;
6869     }
6870 
6871     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
6872         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
6873         return OMX_ErrorBadPortIndex;
6874     }
6875 
6876     if (perf_flag) {
6877         if (!latency) {
6878             dec_time.stop();
6879             latency = dec_time.processing_time_us();
6880             dec_time.start();
6881         }
6882     }
6883 
6884     if (arbitrary_bytes) {
6885         nBufferIndex = buffer - m_inp_heap_ptr;
6886     } else {
6887         if (input_use_buffer == true) {
6888             nBufferIndex = buffer - m_inp_heap_ptr;
6889             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
6890             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
6891             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
6892             buffer = &m_inp_mem_ptr[nBufferIndex];
6893             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
6894                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
6895         } else {
6896             nBufferIndex = buffer - m_inp_mem_ptr;
6897         }
6898     }
6899 
6900     if (nBufferIndex > drv_ctx.ip_buf.actualcount ) {
6901         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
6902         return OMX_ErrorBadParameter;
6903     }
6904 
6905     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6906         codec_config_flag = true;
6907         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
6908     }
6909 
6910     /* The client should not set this when codec is in arbitrary bytes mode */
6911     if (m_input_pass_buffer_fd) {
6912         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
6913     }
6914 
6915     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
6916             buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
6917     if (arbitrary_bytes) {
6918         post_event ((unsigned long)hComp,(unsigned long)buffer,
6919                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
6920     } else {
6921         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
6922     }
6923     time_stamp_dts.insert_timestamp(buffer);
6924     return OMX_ErrorNone;
6925 }
6926 
6927 /* ======================================================================
6928    FUNCTION
6929    omx_vdec::empty_this_buffer_proxy
6930 
6931    DESCRIPTION
6932    This routine is used to push the encoded video frames to
6933    the video decoder.
6934 
6935    PARAMETERS
6936    None.
6937 
6938    RETURN VALUE
6939    OMX Error None if everything went successful.
6940 
6941    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6942 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
6943         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6944 {
6945     (void) hComp;
6946     int push_cnt = 0,i=0;
6947     unsigned nPortIndex = 0;
6948     OMX_ERRORTYPE ret = OMX_ErrorNone;
6949     struct vdec_input_frameinfo frameinfo;
6950     struct vdec_bufferpayload *temp_buffer;
6951     struct vdec_seqheader seq_header;
6952     bool port_setting_changed = true;
6953 
6954     /*Should we generate a Aync error event*/
6955     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
6956         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
6957         return OMX_ErrorBadParameter;
6958     }
6959 
6960     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
6961 
6962     if (nPortIndex > drv_ctx.ip_buf.actualcount) {
6963         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
6964                 nPortIndex);
6965         return OMX_ErrorBadParameter;
6966     }
6967 
6968     pending_input_buffers++;
6969 
6970     /* return zero length and not an EOS buffer */
6971     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
6972             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
6973         DEBUG_PRINT_HIGH("return zero legth buffer");
6974         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6975                 OMX_COMPONENT_GENERATE_EBD);
6976         return OMX_ErrorNone;
6977     }
6978 
6979     if (input_flush_progress == true) {
6980         DEBUG_PRINT_LOW("Flush in progress return buffer ");
6981         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6982                 OMX_COMPONENT_GENERATE_EBD);
6983         return OMX_ErrorNone;
6984     }
6985 
6986     auto_lock l(buf_lock);
6987     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
6988 
6989     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
6990         return OMX_ErrorBadParameter;
6991     }
6992     /* If its first frame, H264 codec and reject is true, then parse the nal
6993        and get the profile. Based on this, reject the clip playback */
6994     if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
6995             m_reject_avc_1080p_mp) {
6996         first_frame = 1;
6997         DEBUG_PRINT_ERROR("Parse nal to get the profile");
6998         h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
6999                 NALU_TYPE_SPS);
7000         m_profile = h264_parser->get_profile();
7001         ret = is_video_session_supported();
7002         if (ret) {
7003             post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7004             post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7005             /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7006             m_state = OMX_StateInvalid;
7007             return OMX_ErrorNone;
7008         }
7009     }
7010 
7011     DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7012     /*for use buffer we need to memcpy the data*/
7013     temp_buffer->buffer_len = buffer->nFilledLen;
7014 
7015     if (input_use_buffer && temp_buffer->bufferaddr) {
7016         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7017             if (arbitrary_bytes) {
7018                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7019             } else {
7020                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7021                         buffer->nFilledLen);
7022             }
7023         } else {
7024             return OMX_ErrorBadParameter;
7025         }
7026 
7027     }
7028 
7029     frameinfo.bufferaddr = temp_buffer->bufferaddr;
7030     frameinfo.client_data = (void *) buffer;
7031     frameinfo.datalen = temp_buffer->buffer_len;
7032     frameinfo.flags = 0;
7033     frameinfo.offset = buffer->nOffset;
7034     frameinfo.pmem_fd = temp_buffer->pmem_fd;
7035     frameinfo.pmem_offset = temp_buffer->offset;
7036     frameinfo.timestamp = buffer->nTimeStamp;
7037     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7038         DEBUG_PRINT_LOW("ETB: dmx enabled");
7039         if (m_demux_entries == 0) {
7040             extract_demux_addr_offsets(buffer);
7041         }
7042 
7043         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7044         handle_demux_data(buffer);
7045         frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7046         frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7047     } else {
7048         frameinfo.desc_addr = NULL;
7049         frameinfo.desc_size = 0;
7050     }
7051     if (!arbitrary_bytes) {
7052         frameinfo.flags |= buffer->nFlags;
7053     }
7054 
7055 #ifdef _ANDROID_
7056     if (m_debug_timestamp) {
7057         if (arbitrary_bytes) {
7058             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7059             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7060         } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7061             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7062             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7063         }
7064     }
7065 #endif
7066 
7067     log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7068 
7069 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7070         frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7071         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7072     }
7073 
7074     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7075         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7076         frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7077         h264_scratch.nFilledLen = 0;
7078         nal_count = 0;
7079         look_ahead_nal = false;
7080         frame_count = 0;
7081         if (m_frame_parser.mutils)
7082             m_frame_parser.mutils->initialize_frame_checking_environment();
7083         m_frame_parser.flush();
7084         h264_last_au_ts = LLONG_MAX;
7085         h264_last_au_flags = 0;
7086         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7087         m_demux_entries = 0;
7088     }
7089     struct v4l2_buffer buf;
7090     struct v4l2_plane plane;
7091     memset( (void *)&buf, 0, sizeof(buf));
7092     memset( (void *)&plane, 0, sizeof(plane));
7093     int rc;
7094     unsigned long  print_count;
7095     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7096         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7097         DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7098     }
7099     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7100     buf.index = nPortIndex;
7101     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7102     buf.memory = V4L2_MEMORY_USERPTR;
7103     plane.bytesused = temp_buffer->buffer_len;
7104     plane.length = drv_ctx.ip_buf.buffer_size;
7105     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7106         (unsigned long)temp_buffer->offset;
7107     plane.reserved[0] = temp_buffer->pmem_fd;
7108     plane.reserved[1] = temp_buffer->offset;
7109     plane.data_offset = 0;
7110     buf.m.planes = &plane;
7111     buf.length = 1;
7112     if (frameinfo.timestamp >= LLONG_MAX) {
7113         buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7114     }
7115     //assumption is that timestamp is in milliseconds
7116     buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7117     buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7118     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7119     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7120 
7121     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7122         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7123         android_atomic_inc(&m_queued_codec_config_count);
7124     }
7125 
7126     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7127     if (rc) {
7128         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
7129         return OMX_ErrorHardware;
7130     }
7131 
7132     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7133         codec_config_flag = false;
7134     }
7135     if (!streaming[OUTPUT_PORT]) {
7136         enum v4l2_buf_type buf_type;
7137         int ret,r;
7138 
7139         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7140         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7141         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7142         if (!ret) {
7143             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7144             streaming[OUTPUT_PORT] = true;
7145         } else if (errno == EBUSY) {
7146             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7147             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7148                     OMX_COMPONENT_GENERATE_EBD);
7149             return OMX_ErrorInsufficientResources;
7150         } else {
7151             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7152             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7153             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7154                     OMX_COMPONENT_GENERATE_EBD);
7155             return OMX_ErrorBadParameter;
7156         }
7157     }
7158     DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7159             frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7160             (unsigned int)frameinfo.datalen);
7161 
7162     return ret;
7163 }
7164 
7165 /* ======================================================================
7166    FUNCTION
7167    omx_vdec::FillThisBuffer
7168 
7169    DESCRIPTION
7170    IL client uses this method to release the frame buffer
7171    after displaying them.
7172 
7173    PARAMETERS
7174    None.
7175 
7176    RETURN VALUE
7177    true/false
7178 
7179    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7180 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7181         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7182 {
7183     if (m_state != OMX_StateExecuting &&
7184             m_state != OMX_StatePause &&
7185             m_state != OMX_StateIdle) {
7186         DEBUG_PRINT_ERROR("FTB in Invalid State");
7187         return OMX_ErrorInvalidState;
7188     }
7189 
7190     if (!m_out_bEnabled) {
7191         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7192         return OMX_ErrorIncorrectStateOperation;
7193     }
7194 
7195     unsigned nPortIndex = 0;
7196     if (dynamic_buf_mode) {
7197         private_handle_t *handle = NULL;
7198         struct VideoDecoderOutputMetaData *meta;
7199         unsigned int nPortIndex = 0;
7200 
7201         if (!buffer || !buffer->pBuffer) {
7202             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7203             return OMX_ErrorBadParameter;
7204         }
7205 
7206         //get the buffer type and fd info
7207         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7208         handle = (private_handle_t *)meta->pHandle;
7209         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7210 
7211         if (!handle) {
7212             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7213             return OMX_ErrorBadParameter;
7214         }
7215         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7216         nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7217         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7218             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7219             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7220             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7221 
7222            //Store private handle from GraphicBuffer
7223             native_buffer[nPortIndex].privatehandle = handle;
7224             native_buffer[nPortIndex].nativehandle = handle;
7225         } else {
7226             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7227             return OMX_ErrorBadParameter;
7228         }
7229 
7230         //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7231         //this with a more sane size so that we don't compensate in rest of code
7232         //We'll restore this size later on, so that it's transparent to client
7233         buffer->nFilledLen = 0;
7234         buffer->nAllocLen = handle->size;
7235         drv_ctx.op_buf.buffer_size = handle->size;
7236     }
7237 
7238     nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7239     if (buffer == NULL ||
7240             (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7241         DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7242             nPortIndex, drv_ctx.op_buf.actualcount);
7243         return OMX_ErrorBadParameter;
7244     }
7245 
7246     if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7247         DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7248         return OMX_ErrorBadPortIndex;
7249     }
7250 
7251     DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7252     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7253     return OMX_ErrorNone;
7254 }
7255 /* ======================================================================
7256    FUNCTION
7257    omx_vdec::fill_this_buffer_proxy
7258 
7259    DESCRIPTION
7260    IL client uses this method to release the frame buffer
7261    after displaying them.
7262 
7263    PARAMETERS
7264    None.
7265 
7266    RETURN VALUE
7267    true/false
7268 
7269    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7270 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
7271         OMX_IN OMX_HANDLETYPE        hComp,
7272         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7273 {
7274     OMX_ERRORTYPE nRet = OMX_ErrorNone;
7275     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7276     unsigned nPortIndex = 0;
7277     struct vdec_fillbuffer_cmd fillbuffer;
7278     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
7279     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
7280 
7281     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7282 
7283     if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) {
7284         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7285             nPortIndex, drv_ctx.op_buf.actualcount);
7286         return OMX_ErrorBadParameter;
7287     }
7288 
7289     DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
7290             bufferAdd, bufferAdd->pBuffer);
7291     /*Return back the output buffer to client*/
7292     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
7293         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7294         buffer->nFilledLen = 0;
7295         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7296         return OMX_ErrorNone;
7297     }
7298 
7299     if (dynamic_buf_mode) {
7300         drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7301         drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7302         buf_ref_add(nPortIndex);
7303         drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7304     }
7305 
7306     pending_output_buffers++;
7307     buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7308     if (!buffer) {
7309        DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7310        return OMX_ErrorBadParameter;
7311     }
7312     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7313     if (ptr_respbuffer) {
7314         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7315     }
7316 
7317     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7318         DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
7319         buffer->nFilledLen = 0;
7320         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7321         pending_output_buffers--;
7322         return OMX_ErrorBadParameter;
7323     }
7324 
7325     int rc = 0;
7326     struct v4l2_buffer buf;
7327     struct v4l2_plane plane[VIDEO_MAX_PLANES];
7328     memset( (void *)&buf, 0, sizeof(buf));
7329     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7330     unsigned int extra_idx = 0;
7331 
7332     buf.index = nPortIndex;
7333     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7334     buf.memory = V4L2_MEMORY_USERPTR;
7335     plane[0].bytesused = buffer->nFilledLen;
7336     plane[0].length = buffer->nAllocLen;
7337     plane[0].m.userptr =
7338         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7339         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7340     plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7341     plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7342     plane[0].data_offset = 0;
7343     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7344     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7345         plane[extra_idx].bytesused = 0;
7346         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7347         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7348 #ifdef USE_ION
7349         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7350 #endif
7351         plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7352         plane[extra_idx].data_offset = 0;
7353     } else if (extra_idx >= VIDEO_MAX_PLANES) {
7354         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7355         return OMX_ErrorBadParameter;
7356     }
7357     buf.m.planes = plane;
7358     buf.length = drv_ctx.num_planes;
7359     DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
7360              plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
7361 
7362     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7363     if (rc) {
7364         /*TODO: How to handle this case */
7365         DEBUG_PRINT_ERROR("Failed to qbuf to driver");
7366     }
7367 return OMX_ErrorNone;
7368 }
7369 
7370 /* ======================================================================
7371    FUNCTION
7372    omx_vdec::SetCallbacks
7373 
7374    DESCRIPTION
7375    Set the callbacks.
7376 
7377    PARAMETERS
7378    None.
7379 
7380    RETURN VALUE
7381    OMX Error None if everything successful.
7382 
7383    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7384 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
7385         OMX_IN OMX_CALLBACKTYPE* callbacks,
7386         OMX_IN OMX_PTR             appData)
7387 {
7388     (void) hComp;
7389     m_cb       = *callbacks;
7390     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7391             m_cb.EventHandler,m_cb.FillBufferDone);
7392     m_app_data =    appData;
7393     return OMX_ErrorNotImplemented;
7394 }
7395 
7396 /* ======================================================================
7397    FUNCTION
7398    omx_vdec::ComponentDeInit
7399 
7400    DESCRIPTION
7401    Destroys the component and release memory allocated to the heap.
7402 
7403    PARAMETERS
7404    <TBD>.
7405 
7406    RETURN VALUE
7407    OMX Error None if everything successful.
7408 
7409    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7410 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7411 {
7412    (void) hComp;
7413 
7414     unsigned i = 0;
7415     if (OMX_StateLoaded != m_state) {
7416         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7417                 m_state);
7418         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7419     } else {
7420         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7421     }
7422 
7423     /*Check if the output buffers have to be cleaned up*/
7424     if (m_out_mem_ptr) {
7425         DEBUG_PRINT_LOW("Freeing the Output Memory");
7426         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7427             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7428                 BITMASK_CLEAR(&m_out_bm_count, i);
7429                 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
7430             }
7431 
7432             if (release_output_done()) {
7433                 break;
7434             }
7435         }
7436 #ifdef _ANDROID_ICS_
7437         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7438 #endif
7439     }
7440 
7441     /*Check if the input buffers have to be cleaned up*/
7442     if (m_inp_mem_ptr || m_inp_heap_ptr) {
7443         DEBUG_PRINT_LOW("Freeing the Input Memory");
7444         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7445 
7446             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7447                 BITMASK_CLEAR(&m_inp_bm_count, i);
7448                 if (m_inp_mem_ptr)
7449                     free_input_buffer (i,&m_inp_mem_ptr[i]);
7450                 else
7451                     free_input_buffer (i,NULL);
7452             }
7453 
7454             if (release_input_done()) {
7455                 break;
7456             }
7457        }
7458     }
7459     free_input_buffer_header();
7460     free_output_buffer_header();
7461     if (h264_scratch.pBuffer) {
7462         free(h264_scratch.pBuffer);
7463         h264_scratch.pBuffer = NULL;
7464     }
7465 
7466     if (h264_parser) {
7467         delete h264_parser;
7468         h264_parser = NULL;
7469     }
7470 
7471     if (m_frame_parser.mutils) {
7472         DEBUG_PRINT_LOW("Free utils parser");
7473         delete (m_frame_parser.mutils);
7474         m_frame_parser.mutils = NULL;
7475     }
7476 
7477     if (m_platform_list) {
7478         free(m_platform_list);
7479         m_platform_list = NULL;
7480     }
7481     if (m_vendor_config.pData) {
7482         free(m_vendor_config.pData);
7483         m_vendor_config.pData = NULL;
7484     }
7485 
7486     // Reset counters in mesg queues
7487     m_ftb_q.m_size=0;
7488     m_cmd_q.m_size=0;
7489     m_etb_q.m_size=0;
7490     m_ftb_q.m_read = m_ftb_q.m_write =0;
7491     m_cmd_q.m_read = m_cmd_q.m_write =0;
7492     m_etb_q.m_read = m_etb_q.m_write =0;
7493 #ifdef _ANDROID_
7494     if (m_debug_timestamp) {
7495         m_timestamp_list.reset_ts_list();
7496     }
7497 #endif
7498 
7499     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7500     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7501     // NULL);
7502     DEBUG_PRINT_HIGH("Close the driver instance");
7503 
7504     if (m_debug.infile) {
7505         fclose(m_debug.infile);
7506         m_debug.infile = NULL;
7507     }
7508     if (m_debug.outfile) {
7509         fclose(m_debug.outfile);
7510         m_debug.outfile = NULL;
7511     }
7512     if (m_debug.out_ymeta_file) {
7513         fclose(m_debug.out_ymeta_file);
7514         m_debug.out_ymeta_file = NULL;
7515     }
7516     if (m_debug.out_uvmeta_file) {
7517         fclose(m_debug.out_uvmeta_file);
7518         m_debug.out_uvmeta_file = NULL;
7519     }
7520 #ifdef OUTPUT_EXTRADATA_LOG
7521     if (outputExtradataFile)
7522         fclose (outputExtradataFile);
7523 #endif
7524     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
7525     return OMX_ErrorNone;
7526 }
7527 
7528 /* ======================================================================
7529    FUNCTION
7530    omx_vdec::UseEGLImage
7531 
7532    DESCRIPTION
7533    OMX Use EGL Image method implementation <TBD>.
7534 
7535    PARAMETERS
7536    <TBD>.
7537 
7538    RETURN VALUE
7539    Not Implemented error.
7540 
7541    ========================================================================== */
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)7542 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
7543         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7544         OMX_IN OMX_U32                        port,
7545         OMX_IN OMX_PTR                     appData,
7546         OMX_IN void*                      eglImage)
7547 {
7548     (void) appData;
7549     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
7550     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
7551     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
7552 
7553 #ifdef USE_EGL_IMAGE_GPU
7554     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
7555     EGLint fd = -1, offset = 0,pmemPtr = 0;
7556 #else
7557     int fd = -1, offset = 0;
7558 #endif
7559     DEBUG_PRINT_HIGH("use EGL image support for decoder");
7560     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
7561         DEBUG_PRINT_ERROR("Invalid EGL image");
7562     }
7563 #ifdef USE_EGL_IMAGE_GPU
7564     if (m_display_id == NULL) {
7565         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
7566         return OMX_ErrorInsufficientResources;
7567     }
7568     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
7569         eglGetProcAddress("eglQueryImageKHR");
7570     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
7571     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
7572     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
7573 #else //with OMX test app
7574     struct temp_egl {
7575         int pmem_fd;
7576         int offset;
7577     };
7578     struct temp_egl *temp_egl_id = NULL;
7579     void * pmemPtr = (void *) eglImage;
7580     temp_egl_id = (struct temp_egl *)eglImage;
7581     if (temp_egl_id != NULL) {
7582         fd = temp_egl_id->pmem_fd;
7583         offset = temp_egl_id->offset;
7584     }
7585 #endif
7586     if (fd < 0) {
7587         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
7588         return OMX_ErrorInsufficientResources;
7589     }
7590     pmem_info.pmem_fd = (OMX_U32) fd;
7591     pmem_info.offset = (OMX_U32) offset;
7592     pmem_entry.entry = (void *) &pmem_info;
7593     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7594     pmem_list.entryList = &pmem_entry;
7595     pmem_list.nEntries = 1;
7596     ouput_egl_buffers = true;
7597     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
7598                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
7599                 (OMX_U8 *)pmemPtr)) {
7600         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
7601         return OMX_ErrorInsufficientResources;
7602     }
7603     return OMX_ErrorNone;
7604 }
7605 
7606 /* ======================================================================
7607    FUNCTION
7608    omx_vdec::ComponentRoleEnum
7609 
7610    DESCRIPTION
7611    OMX Component Role Enum method implementation.
7612 
7613    PARAMETERS
7614    <TBD>.
7615 
7616    RETURN VALUE
7617    OMX Error None if everything is successful.
7618    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)7619 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
7620         OMX_OUT OMX_U8*        role,
7621         OMX_IN OMX_U32        index)
7622 {
7623     (void) hComp;
7624     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7625 
7626     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
7627         if ((0 == index) && role) {
7628             strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
7629             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7630         } else {
7631             eRet = OMX_ErrorNoMore;
7632         }
7633     }
7634     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
7635         if ((0 == index) && role) {
7636             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
7637             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7638         } else {
7639             eRet = OMX_ErrorNoMore;
7640         }
7641     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
7642         if ((0 == index) && role) {
7643             strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
7644             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7645         } else {
7646             DEBUG_PRINT_LOW("No more roles");
7647             eRet = OMX_ErrorNoMore;
7648         }
7649     }
7650 
7651     else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
7652             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
7653         if ((0 == index) && role) {
7654             strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
7655             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7656         } else {
7657             DEBUG_PRINT_LOW("No more roles");
7658             eRet = OMX_ErrorNoMore;
7659         }
7660     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
7661         if ((0 == index) && role) {
7662             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
7663             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7664         } else {
7665             DEBUG_PRINT_LOW("No more roles");
7666             eRet = OMX_ErrorNoMore;
7667         }
7668     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
7669         if ((0 == index) && role) {
7670             strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
7671             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7672         } else {
7673             DEBUG_PRINT_LOW("No more roles");
7674             eRet = OMX_ErrorNoMore;
7675         }
7676     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
7677         if ((0 == index) && role) {
7678             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
7679             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
7680         } else {
7681             DEBUG_PRINT_LOW("No more roles");
7682             eRet = OMX_ErrorNoMore;
7683         }
7684     } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
7685             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
7686           ) {
7687         if ((0 == index) && role) {
7688             strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
7689             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7690         } else {
7691             DEBUG_PRINT_LOW("No more roles");
7692             eRet = OMX_ErrorNoMore;
7693         }
7694     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7695         if ((0 == index) && role) {
7696             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7697             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7698         } else {
7699             DEBUG_PRINT_LOW("No more roles");
7700             eRet = OMX_ErrorNoMore;
7701         }
7702     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
7703         if ((0 == index) && role) {
7704             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
7705             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7706         } else {
7707             DEBUG_PRINT_LOW("No more roles");
7708             eRet = OMX_ErrorNoMore;
7709         }
7710     } else {
7711         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7712         eRet = OMX_ErrorInvalidComponentName;
7713     }
7714     return eRet;
7715 }
7716 
7717 
7718 
7719 
7720 /* ======================================================================
7721    FUNCTION
7722    omx_vdec::AllocateDone
7723 
7724    DESCRIPTION
7725    Checks if entire buffer pool is allocated by IL Client or not.
7726    Need this to move to IDLE state.
7727 
7728    PARAMETERS
7729    None.
7730 
7731    RETURN VALUE
7732    true/false.
7733 
7734    ========================================================================== */
allocate_done(void)7735 bool omx_vdec::allocate_done(void)
7736 {
7737     bool bRet = false;
7738     bool bRet_In = false;
7739     bool bRet_Out = false;
7740 
7741     bRet_In = allocate_input_done();
7742     bRet_Out = allocate_output_done();
7743 
7744     if (bRet_In && bRet_Out) {
7745         bRet = true;
7746     }
7747 
7748     return bRet;
7749 }
7750 /* ======================================================================
7751    FUNCTION
7752    omx_vdec::AllocateInputDone
7753 
7754    DESCRIPTION
7755    Checks if I/P buffer pool is allocated by IL Client or not.
7756 
7757    PARAMETERS
7758    None.
7759 
7760    RETURN VALUE
7761    true/false.
7762 
7763    ========================================================================== */
allocate_input_done(void)7764 bool omx_vdec::allocate_input_done(void)
7765 {
7766     bool bRet = false;
7767     unsigned i=0;
7768 
7769     if (m_inp_mem_ptr == NULL) {
7770         return bRet;
7771     }
7772     if (m_inp_mem_ptr ) {
7773         for (; i<drv_ctx.ip_buf.actualcount; i++) {
7774             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7775                 break;
7776             }
7777         }
7778     }
7779     if (i == drv_ctx.ip_buf.actualcount) {
7780         bRet = true;
7781         DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
7782     }
7783     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7784         m_inp_bPopulated = OMX_TRUE;
7785     }
7786     return bRet;
7787 }
7788 /* ======================================================================
7789    FUNCTION
7790    omx_vdec::AllocateOutputDone
7791 
7792    DESCRIPTION
7793    Checks if entire O/P buffer pool is allocated by IL Client or not.
7794 
7795    PARAMETERS
7796    None.
7797 
7798    RETURN VALUE
7799    true/false.
7800 
7801    ========================================================================== */
allocate_output_done(void)7802 bool omx_vdec::allocate_output_done(void)
7803 {
7804     bool bRet = false;
7805     unsigned j=0;
7806 
7807     if (m_out_mem_ptr == NULL) {
7808         return bRet;
7809     }
7810 
7811     if (m_out_mem_ptr) {
7812         for (; j < drv_ctx.op_buf.actualcount; j++) {
7813             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7814                 break;
7815             }
7816         }
7817     }
7818 
7819     if (j == drv_ctx.op_buf.actualcount) {
7820         bRet = true;
7821         DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
7822         if (m_out_bEnabled)
7823             m_out_bPopulated = OMX_TRUE;
7824     }
7825 
7826     return bRet;
7827 }
7828 
7829 /* ======================================================================
7830    FUNCTION
7831    omx_vdec::ReleaseDone
7832 
7833    DESCRIPTION
7834    Checks if IL client has released all the buffers.
7835 
7836    PARAMETERS
7837    None.
7838 
7839    RETURN VALUE
7840    true/false
7841 
7842    ========================================================================== */
release_done(void)7843 bool omx_vdec::release_done(void)
7844 {
7845     bool bRet = false;
7846 
7847     if (release_input_done()) {
7848         if (release_output_done()) {
7849             bRet = true;
7850         }
7851     }
7852     return bRet;
7853 }
7854 
7855 
7856 /* ======================================================================
7857    FUNCTION
7858    omx_vdec::ReleaseOutputDone
7859 
7860    DESCRIPTION
7861    Checks if IL client has released all the buffers.
7862 
7863    PARAMETERS
7864    None.
7865 
7866    RETURN VALUE
7867    true/false
7868 
7869    ========================================================================== */
release_output_done(void)7870 bool omx_vdec::release_output_done(void)
7871 {
7872     bool bRet = false;
7873     unsigned i=0,j=0;
7874 
7875     DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
7876     if (m_out_mem_ptr) {
7877         for (; j < drv_ctx.op_buf.actualcount ; j++) {
7878             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
7879                 break;
7880             }
7881         }
7882         if (j == drv_ctx.op_buf.actualcount) {
7883             m_out_bm_count = 0;
7884             bRet = true;
7885         }
7886     } else {
7887         m_out_bm_count = 0;
7888         bRet = true;
7889     }
7890     return bRet;
7891 }
7892 /* ======================================================================
7893    FUNCTION
7894    omx_vdec::ReleaseInputDone
7895 
7896    DESCRIPTION
7897    Checks if IL client has released all the buffers.
7898 
7899    PARAMETERS
7900    None.
7901 
7902    RETURN VALUE
7903    true/false
7904 
7905    ========================================================================== */
release_input_done(void)7906 bool omx_vdec::release_input_done(void)
7907 {
7908     bool bRet = false;
7909     unsigned i=0,j=0;
7910 
7911     DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
7912     if (m_inp_mem_ptr) {
7913         for (; j<drv_ctx.ip_buf.actualcount; j++) {
7914             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
7915                 break;
7916             }
7917         }
7918         if (j==drv_ctx.ip_buf.actualcount) {
7919             bRet = true;
7920         }
7921     } else {
7922         bRet = true;
7923     }
7924     return bRet;
7925 }
7926 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7927 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
7928         OMX_BUFFERHEADERTYPE * buffer)
7929 {
7930     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
7931     if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
7932         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
7933         return OMX_ErrorBadParameter;
7934     } else if (output_flush_progress) {
7935         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
7936         buffer->nFilledLen = 0;
7937         buffer->nTimeStamp = 0;
7938         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
7939         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7940         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
7941     }
7942 
7943     if (m_debug_extradata) {
7944         if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7945             DEBUG_PRINT_HIGH("***************************************************");
7946             DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
7947             DEBUG_PRINT_HIGH("***************************************************");
7948         }
7949 
7950         if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
7951             DEBUG_PRINT_HIGH("***************************************************");
7952             DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
7953             DEBUG_PRINT_HIGH("***************************************************");
7954         }
7955     }
7956 
7957 
7958     DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
7959             buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
7960     pending_output_buffers --;
7961 
7962     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7963         DEBUG_PRINT_HIGH("Output EOS has been reached");
7964         if (!output_flush_progress)
7965             post_event((unsigned)NULL, (unsigned)NULL,
7966                     OMX_COMPONENT_GENERATE_EOS_DONE);
7967 
7968         if (psource_frame) {
7969             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
7970             psource_frame = NULL;
7971         }
7972         if (pdest_frame) {
7973             pdest_frame->nFilledLen = 0;
7974             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
7975                     (unsigned)NULL);
7976             pdest_frame = NULL;
7977         }
7978     }
7979 
7980     if (!output_flush_progress && (buffer->nFilledLen > 0)) {
7981         // set the default colorspace advised by client, since the bitstream may be
7982         // devoid of colorspace-info.
7983         if (m_enable_android_native_buffers) {
7984             ColorSpace_t color_space = ITU_R_601;
7985 
7986         // Disabled ?
7987         // WA for VP8. Vp8 encoder does not embed color-info (yet!).
7988         // Encoding RGBA results in 601-LR for all resolutions.
7989         // This conflicts with the client't defaults which are based on resolution.
7990         //   Eg: 720p will be encoded as 601-LR. Client will say 709.
7991         // Re-enable this code once vp8 encoder generates color-info and hence the
7992         // decoder will be able to override with the correct source color.
7993 #if 0
7994             switch (m_client_color_space.sAspects.mPrimaries) {
7995                 case ColorAspects::PrimariesBT601_6_625:
7996                 case ColorAspects::PrimariesBT601_6_525:
7997                 {
7998                     color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
7999                             ITU_R_601_FR : ITU_R_601;
8000                     break;
8001                 }
8002                 case ColorAspects::PrimariesBT709_5:
8003                 {
8004                     color_space = ITU_R_709;
8005                     break;
8006                 }
8007                 default:
8008                 {
8009                     break;
8010                 }
8011             }
8012 #endif
8013             DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
8014                     color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
8015             set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr);
8016         }
8017         DEBUG_PRINT_LOW("Processing extradata");
8018         handle_extradata(buffer);
8019     }
8020 
8021 #ifdef OUTPUT_EXTRADATA_LOG
8022     if (outputExtradataFile) {
8023         int buf_index = buffer - m_out_mem_ptr;
8024         OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8025 
8026         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8027         p_extra = (OMX_OTHER_EXTRADATATYPE *)
8028             ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8029 
8030         while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8031             DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8032                                     p_extra->nSize, p_extra->eType);
8033             fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8034 
8035             if (p_extra->eType == OMX_ExtraDataNone) {
8036                 break;
8037             }
8038             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8039         }
8040     }
8041 #endif
8042 
8043     /* For use buffer we need to copy the data */
8044     if (!output_flush_progress) {
8045         /* This is the error check for non-recoverable errros */
8046         bool is_duplicate_ts_valid = true;
8047         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8048 
8049         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8050                 output_capability == V4L2_PIX_FMT_MPEG2 ||
8051                 output_capability == V4L2_PIX_FMT_DIVX ||
8052                 output_capability == V4L2_PIX_FMT_DIVX_311)
8053             is_duplicate_ts_valid = false;
8054 
8055         if ((output_capability == V4L2_PIX_FMT_H264 ||
8056                 output_capability == V4L2_PIX_FMT_H264_MVC) &&
8057                 is_interlaced) {
8058             if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8059                 is_interlaced = false;
8060             }
8061         }
8062 
8063         if (buffer->nFilledLen > 0) {
8064             time_stamp_dts.get_next_timestamp(buffer,
8065                     is_interlaced && is_duplicate_ts_valid);
8066             if (m_debug_timestamp) {
8067                 {
8068                     OMX_TICKS expected_ts = 0;
8069                     m_timestamp_list.pop_min_ts(expected_ts);
8070                     if (is_interlaced && is_duplicate_ts_valid) {
8071                         m_timestamp_list.pop_min_ts(expected_ts);
8072                     }
8073                     DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8074                             buffer->nTimeStamp, expected_ts);
8075 
8076                     if (buffer->nTimeStamp != expected_ts) {
8077                         DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8078                     }
8079                 }
8080             }
8081         }
8082     }
8083 
8084     if (m_cb.FillBufferDone) {
8085         if (buffer->nFilledLen > 0) {
8086             if (arbitrary_bytes)
8087                 adjust_timestamp(buffer->nTimeStamp);
8088             else
8089                 set_frame_rate(buffer->nTimeStamp);
8090 
8091             if (perf_flag) {
8092                 if (!proc_frms) {
8093                     dec_time.stop();
8094                     latency = dec_time.processing_time_us() - latency;
8095                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8096                     dec_time.start();
8097                     fps_metrics.start();
8098                 }
8099                 proc_frms++;
8100                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8101                     OMX_U64 proc_time = 0;
8102                     fps_metrics.stop();
8103                     proc_time = fps_metrics.processing_time_us();
8104                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8105                             (unsigned int)proc_frms, (float)proc_time / 1e6,
8106                             (float)(1e6 * proc_frms) / proc_time);
8107                     proc_frms = 0;
8108                 }
8109             }
8110         }
8111         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8112             prev_ts = LLONG_MAX;
8113             rst_prev_ts = true;
8114         }
8115 
8116         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8117             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8118              buffer->pPlatformPrivate)->entryList->entry;
8119         DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8120         OMX_BUFFERHEADERTYPE *il_buffer;
8121         il_buffer = client_buffers.get_il_buf_hdr(buffer);
8122         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8123 
8124         if (il_buffer && m_last_rendered_TS >= 0) {
8125             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8126 
8127             // Current frame can be send for rendering if
8128             // (a) current FPS is <=  60
8129             // (b) is the next frame after the frame with TS 0
8130             // (c) is the first frame after seek
8131             // (d) the delta TS b\w two consecutive frames is > 16 ms
8132             // (e) its TS is equal to previous frame TS
8133             // (f) if marked EOS
8134 
8135             if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8136                il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8137                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8138                m_last_rendered_TS = il_buffer->nTimeStamp;
8139             } else {
8140                //mark for droping
8141                buffer->nFilledLen = 0;
8142             }
8143 
8144             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8145                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8146                               il_buffer->nTimeStamp,ts_delta);
8147 
8148             //above code makes sure that delta b\w two consecutive frames is not
8149             //greater than 16ms, slow-mo feature, so cap fps to max 60
8150             if (current_framerate > 60 ) {
8151                 current_framerate = 60;
8152             }
8153         }
8154 
8155         // add current framerate to gralloc meta data
8156         if (m_enable_android_native_buffers && m_out_mem_ptr) {
8157             OMX_U32 buf_index = buffer - m_out_mem_ptr;
8158             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8159                          UPDATE_REFRESH_RATE, (void*)&current_framerate);
8160         }
8161 
8162         if (il_buffer) {
8163             log_output_buffers(il_buffer);
8164             if (dynamic_buf_mode) {
8165                 unsigned int nPortIndex = 0;
8166                 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8167 
8168                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8169                 // to size of the handle. Do it _after_ log_output_buffers which
8170                 // requires the respective sizes to be accurate.
8171 
8172                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8173                 buffer->nFilledLen = buffer->nFilledLen ?
8174                         sizeof(struct VideoDecoderOutputMetaData) : 0;
8175 
8176                 //Clear graphic buffer handles in dynamic mode
8177                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8178                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8179                     native_buffer[nPortIndex].privatehandle = NULL;
8180                     native_buffer[nPortIndex].nativehandle = NULL;
8181                 } else {
8182                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8183                     return OMX_ErrorBadParameter;
8184                 }
8185             }
8186             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8187         } else {
8188             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8189             return OMX_ErrorBadParameter;
8190         }
8191         DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
8192     } else {
8193         return OMX_ErrorBadParameter;
8194     }
8195 
8196 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8197     if (m_smoothstreaming_mode && m_out_mem_ptr) {
8198         OMX_U32 buf_index = buffer - m_out_mem_ptr;
8199         BufferDim_t dim;
8200         private_handle_t *private_handle = NULL;
8201         dim.sliceWidth = framesize.nWidth;
8202         dim.sliceHeight = framesize.nHeight;
8203         if (buf_index < drv_ctx.op_buf.actualcount &&
8204             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8205             native_buffer[buf_index].privatehandle)
8206             private_handle = native_buffer[buf_index].privatehandle;
8207         if (private_handle) {
8208             DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8209                 dim.sliceWidth, dim.sliceHeight);
8210             setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8211         }
8212     }
8213 #endif
8214 
8215     return OMX_ErrorNone;
8216 }
8217 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8218 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
8219         OMX_BUFFERHEADERTYPE* buffer)
8220 {
8221 
8222     int nBufferIndex = buffer - m_inp_mem_ptr;
8223 
8224     if (buffer == NULL || (nBufferIndex > (int)drv_ctx.ip_buf.actualcount)) {
8225         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8226         return OMX_ErrorBadParameter;
8227     }
8228 
8229     DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
8230             buffer, buffer->pBuffer, buffer->nFlags);
8231     pending_input_buffers--;
8232 
8233     if (arbitrary_bytes) {
8234         if (pdest_frame == NULL && input_flush_progress == false) {
8235             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8236             pdest_frame = buffer;
8237             buffer->nFilledLen = 0;
8238             buffer->nTimeStamp = LLONG_MAX;
8239             push_input_buffer (hComp);
8240         } else {
8241             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8242             buffer->nFilledLen = 0;
8243             if (!m_input_free_q.insert_entry((unsigned long)buffer,
8244                         (unsigned)NULL, (unsigned)NULL)) {
8245                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8246             }
8247         }
8248     } else if (m_cb.EmptyBufferDone) {
8249         buffer->nFilledLen = 0;
8250         if (input_use_buffer == true) {
8251             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8252         }
8253 
8254         /* Restore the FD that we over-wrote in ETB */
8255         if (m_input_pass_buffer_fd) {
8256             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8257         }
8258 
8259         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8260     }
8261     return OMX_ErrorNone;
8262 }
8263 
async_message_process(void * context,void * message)8264 int omx_vdec::async_message_process (void *context, void* message)
8265 {
8266     omx_vdec* omx = NULL;
8267     struct vdec_msginfo *vdec_msg = NULL;
8268     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8269     struct v4l2_buffer *v4l2_buf_ptr = NULL;
8270     struct vdec_output_frameinfo *output_respbuf = NULL;
8271     int rc=1;
8272     if (context == NULL || message == NULL) {
8273         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8274         return -1;
8275     }
8276     vdec_msg = (struct vdec_msginfo *)message;
8277 
8278     omx = reinterpret_cast<omx_vdec*>(context);
8279 
8280     switch (vdec_msg->msgcode) {
8281 
8282         case VDEC_MSG_EVT_HW_ERROR:
8283             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8284                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8285             break;
8286 
8287         case VDEC_MSG_EVT_HW_OVERLOAD:
8288             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8289                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8290             break;
8291 
8292         case VDEC_MSG_EVT_HW_UNSUPPORTED:
8293             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8294                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8295             break;
8296 
8297         case VDEC_MSG_RESP_START_DONE:
8298             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8299                     OMX_COMPONENT_GENERATE_START_DONE);
8300             break;
8301 
8302         case VDEC_MSG_RESP_STOP_DONE:
8303             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8304                     OMX_COMPONENT_GENERATE_STOP_DONE);
8305             break;
8306 
8307         case VDEC_MSG_RESP_RESUME_DONE:
8308             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8309                     OMX_COMPONENT_GENERATE_RESUME_DONE);
8310             break;
8311 
8312         case VDEC_MSG_RESP_PAUSE_DONE:
8313             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8314                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
8315             break;
8316 
8317         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8318             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8319                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8320             break;
8321         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8322             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8323                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8324             break;
8325         case VDEC_MSG_RESP_INPUT_FLUSHED:
8326         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8327 
8328             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8329                vdec_msg->msgdata.input_frame_clientdata; */
8330 
8331             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8332             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8333                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8334                 omxhdr = NULL;
8335                 vdec_msg->status_code = VDEC_S_EFATAL;
8336                 break;
8337 
8338             }
8339             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8340 
8341             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8342                 DEBUG_PRINT_HIGH("Unsupported input");
8343                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8344                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8345             }
8346             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8347                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8348                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8349             }
8350             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8351 
8352                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8353                 android_atomic_dec(&omx->m_queued_codec_config_count);
8354                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8355                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8356                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8357                     sem_post(&omx->m_safe_flush);
8358                 }
8359             }
8360             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8361                 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8362                 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8363             }
8364             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8365                     OMX_COMPONENT_GENERATE_EBD);
8366             break;
8367         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8368             int64_t *timestamp;
8369             timestamp = (int64_t *) malloc(sizeof(int64_t));
8370             if (timestamp) {
8371                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8372                 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8373                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8374                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8375                         (long long)vdec_msg->msgdata.output_frame.time_stamp);
8376             }
8377             break;
8378         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8379         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8380 
8381            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8382 
8383            if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8384                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8385                omxhdr = NULL;
8386                vdec_msg->status_code = VDEC_S_EFATAL;
8387                break;
8388            }
8389 
8390            omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8391 
8392             DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8393                     omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8394                     vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8395                     (unsigned int)vdec_msg->msgdata.output_frame.len,
8396                     vdec_msg->msgdata.output_frame.framesize.left,
8397                     vdec_msg->msgdata.output_frame.framesize.top,
8398                     vdec_msg->msgdata.output_frame.framesize.right,
8399                     vdec_msg->msgdata.output_frame.framesize.bottom);
8400 
8401             if (omxhdr && omxhdr->pOutputPortPrivate &&
8402                     ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8403                     (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8404                       - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8405 
8406                 if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
8407                     omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8408                     omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8409                     omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8410                     omxhdr->nFlags = 0;
8411 
8412                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8413                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8414                         //rc = -1;
8415                     }
8416                     if (omxhdr->nFilledLen) {
8417                         omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8418                     }
8419                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8420                         omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8421                     } else {
8422                         omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8423                     }
8424                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
8425                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8426                     }
8427                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8428                         omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8429                     }
8430 
8431                     if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
8432                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
8433                     }
8434 
8435                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8436                          omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8437                          DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8438                                     omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8439                     }
8440 
8441                     if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
8442                             !omx->output_flush_progress &&
8443                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
8444                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
8445                         unsigned int index = v4l2_buf_ptr->index;
8446                         unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
8447                         struct v4l2_plane *plane = v4l2_buf_ptr->m.planes;
8448                         omx->time_stamp_dts.remove_time_stamp(
8449                                 omxhdr->nTimeStamp,
8450                                 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
8451                                 ?true:false);
8452                         plane[0].bytesused = 0;
8453                         plane[0].m.userptr =
8454                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
8455                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
8456                         plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
8457                         plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
8458                         plane[0].data_offset = 0;
8459                         v4l2_buf_ptr->flags = 0x0;
8460                         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8461                             plane[extra_idx].bytesused = 0;
8462                             plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
8463                             plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
8464 #ifdef USE_ION
8465                             plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
8466 #endif
8467                             plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
8468                             plane[extra_idx].data_offset = 0;
8469                         } else if (extra_idx >= VIDEO_MAX_PLANES) {
8470                             DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8471                             return -1;
8472                         }
8473 
8474                          DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8475                                plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
8476                         if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
8477                             DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]);
8478                             return -1;
8479                         }
8480                         break;
8481                     }
8482                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8483                         omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8484                     }
8485                     vdec_msg->msgdata.output_frame.bufferaddr =
8486                         omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8487 
8488                     /* Post event if resolution OR crop changed */
8489                     /* filled length will be changed if resolution changed */
8490                     /* Crop parameters can be changed even without resolution change */
8491                     if (omxhdr->nFilledLen
8492                         && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8493                         || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8494                         || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8495                         || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8496                         || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
8497                         || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
8498                         || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
8499 
8500                         DEBUG_PRINT_HIGH("Paramters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
8501                                 omx->prev_n_filled_len,
8502                                 omx->drv_ctx.video_resolution.frame_width,
8503                                 omx->drv_ctx.video_resolution.frame_height,
8504                                 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
8505                                 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
8506                                 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
8507                                 vdec_msg->msgdata.output_frame.picsize.frame_height,
8508                                 vdec_msg->msgdata.output_frame.framesize.left,
8509                                 vdec_msg->msgdata.output_frame.framesize.top,
8510                                 vdec_msg->msgdata.output_frame.framesize.right,
8511                                 vdec_msg->msgdata.output_frame.framesize.bottom);
8512 
8513                         omx->drv_ctx.video_resolution.frame_width =
8514                                 vdec_msg->msgdata.output_frame.picsize.frame_width;
8515                         omx->drv_ctx.video_resolution.frame_height =
8516                                 vdec_msg->msgdata.output_frame.picsize.frame_height;
8517                         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
8518                             omx->drv_ctx.video_resolution.stride =
8519                                 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
8520                             omx->drv_ctx.video_resolution.scan_lines =
8521                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
8522                         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
8523                             omx->drv_ctx.video_resolution.stride =
8524                                 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
8525                             omx->drv_ctx.video_resolution.scan_lines =
8526                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
8527                         }
8528 
8529                         memcpy(&omx->drv_ctx.frame_size,
8530                                 &vdec_msg->msgdata.output_frame.framesize,
8531                                 sizeof(struct vdec_framesize));
8532 
8533                         omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8534                                 OMX_IndexConfigCommonOutputCrop,
8535                                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8536                     }
8537 
8538                     if (omxhdr->nFilledLen)
8539                         omx->prev_n_filled_len = omxhdr->nFilledLen;
8540 
8541                     output_respbuf = (struct vdec_output_frameinfo *)\
8542                              omxhdr->pOutputPortPrivate;
8543                     if (!output_respbuf) {
8544                       DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8545                       return -1;
8546                     }
8547                     output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8548                     output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8549 
8550                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8551                         output_respbuf->pic_type = PICTURE_TYPE_I;
8552                     }
8553                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8554                         output_respbuf->pic_type = PICTURE_TYPE_P;
8555                     }
8556                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8557                         output_respbuf->pic_type = PICTURE_TYPE_B;
8558                     }
8559                     if (omxhdr && omxhdr->nFilledLen) {
8560                         omx->request_perf_level(VIDC_NOMINAL);
8561                     }
8562                     if (omx->output_use_buffer && omxhdr->pBuffer &&
8563                         vdec_msg->msgdata.output_frame.bufferaddr)
8564                         memcpy ( omxhdr->pBuffer, (void *)
8565                                 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
8566                                  (unsigned long)vdec_msg->msgdata.output_frame.offset),
8567                                 vdec_msg->msgdata.output_frame.len);
8568                 } else {
8569                     DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
8570                             (unsigned int)vdec_msg->msgdata.output_frame.len,
8571                             omxhdr->nAllocLen, omx->prev_n_filled_len);
8572                     omxhdr->nFilledLen = 0;
8573                 }
8574 
8575                 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
8576                         OMX_COMPONENT_GENERATE_FBD);
8577 
8578             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
8579                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
8580                         OMX_COMPONENT_GENERATE_EOS_DONE);
8581             } else {
8582                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
8583                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8584             }
8585             break;
8586         case VDEC_MSG_EVT_CONFIG_CHANGED:
8587             DEBUG_PRINT_HIGH("Port settings changed");
8588             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8589             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8590             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
8591                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8592             omx->request_perf_level(VIDC_NOMINAL);
8593             break;
8594         default:
8595             break;
8596     }
8597     return rc;
8598 }
8599 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8600 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
8601         OMX_HANDLETYPE hComp,
8602         OMX_BUFFERHEADERTYPE *buffer
8603         )
8604 {
8605     unsigned address,p2,id;
8606     DEBUG_PRINT_LOW("Empty this arbitrary");
8607 
8608     if (buffer == NULL) {
8609         return OMX_ErrorBadParameter;
8610     }
8611     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8612     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
8613             (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
8614 
8615     /* return zero length and not an EOS buffer */
8616     /* return buffer if input flush in progress */
8617     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
8618                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
8619         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
8620         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
8621         return OMX_ErrorNone;
8622     }
8623 
8624     if (psource_frame == NULL) {
8625         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
8626         psource_frame = buffer;
8627         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
8628         push_input_buffer (hComp);
8629     } else {
8630         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
8631         if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
8632                     (unsigned)NULL)) {
8633             return OMX_ErrorBadParameter;
8634         }
8635     }
8636 
8637     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
8638         codec_config_flag = false;
8639     }
8640     return OMX_ErrorNone;
8641 }
8642 
push_input_buffer(OMX_HANDLETYPE hComp)8643 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
8644 {
8645     unsigned long address,p2,id;
8646     OMX_ERRORTYPE ret = OMX_ErrorNone;
8647 
8648     if (pdest_frame == NULL || psource_frame == NULL) {
8649         /*Check if we have a destination buffer*/
8650         if (pdest_frame == NULL) {
8651             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
8652             if (m_input_free_q.m_size) {
8653                 m_input_free_q.pop_entry(&address,&p2,&id);
8654                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
8655                 pdest_frame->nFilledLen = 0;
8656                 pdest_frame->nTimeStamp = LLONG_MAX;
8657                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
8658             }
8659         }
8660 
8661         /*Check if we have a destination buffer*/
8662         if (psource_frame == NULL) {
8663             DEBUG_PRINT_LOW("Get a source buffer from the queue");
8664             if (m_input_pending_q.m_size) {
8665                 m_input_pending_q.pop_entry(&address,&p2,&id);
8666                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
8667                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8668                         psource_frame->nTimeStamp);
8669                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8670                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8671 
8672             }
8673         }
8674 
8675     }
8676 
8677     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
8678         switch (codec_type_parse) {
8679             case CODEC_TYPE_MPEG4:
8680             case CODEC_TYPE_H263:
8681             case CODEC_TYPE_MPEG2:
8682                 ret =  push_input_sc_codec(hComp);
8683                 break;
8684             case CODEC_TYPE_H264:
8685                 ret = push_input_h264(hComp);
8686                 break;
8687             case CODEC_TYPE_HEVC:
8688                 ret = push_input_hevc(hComp);
8689                 break;
8690             case CODEC_TYPE_VC1:
8691                 ret = push_input_vc1(hComp);
8692                 break;
8693             default:
8694                 break;
8695         }
8696         if (ret != OMX_ErrorNone) {
8697             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
8698             omx_report_error ();
8699             break;
8700         }
8701     }
8702 
8703     return ret;
8704 }
8705 
push_input_sc_codec(OMX_HANDLETYPE hComp)8706 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
8707 {
8708     OMX_U32 partial_frame = 1;
8709     OMX_BOOL generate_ebd = OMX_TRUE;
8710     unsigned long address = 0, p2 = 0, id = 0;
8711 
8712     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
8713             psource_frame,psource_frame->nTimeStamp);
8714     if (m_frame_parser.parse_sc_frame(psource_frame,
8715                 pdest_frame,&partial_frame) == -1) {
8716         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8717         return OMX_ErrorBadParameter;
8718     }
8719 
8720     if (partial_frame == 0) {
8721         DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
8722                 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
8723 
8724 
8725         DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
8726         /*First Parsed buffer will have only header Hence skip*/
8727         if (frame_count == 0) {
8728             DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
8729 
8730             if (codec_type_parse == CODEC_TYPE_MPEG4 ||
8731                     codec_type_parse == CODEC_TYPE_DIVX) {
8732                 mp4StreamType psBits;
8733                 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
8734                 psBits.numBytes = pdest_frame->nFilledLen;
8735                 mp4_headerparser.parseHeader(&psBits);
8736             }
8737 
8738             frame_count++;
8739         } else {
8740             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8741             if (pdest_frame->nFilledLen) {
8742                 /*Push the frame to the Decoder*/
8743                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8744                     return OMX_ErrorBadParameter;
8745                 }
8746                 frame_count++;
8747                 pdest_frame = NULL;
8748 
8749                 if (m_input_free_q.m_size) {
8750                     m_input_free_q.pop_entry(&address,&p2,&id);
8751                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8752                     pdest_frame->nFilledLen = 0;
8753                 }
8754             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
8755                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
8756                 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
8757                         (unsigned)NULL);
8758                 pdest_frame = NULL;
8759             }
8760         }
8761     } else {
8762         DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
8763         /*Check if Destination Buffer is full*/
8764         if (pdest_frame->nAllocLen ==
8765                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
8766             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
8767             return OMX_ErrorStreamCorrupt;
8768         }
8769     }
8770 
8771     if (psource_frame->nFilledLen == 0) {
8772         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8773             if (pdest_frame) {
8774                 pdest_frame->nFlags |= psource_frame->nFlags;
8775                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
8776                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8777                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8778                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
8779                 /*Push the frame to the Decoder*/
8780                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8781                     return OMX_ErrorBadParameter;
8782                 }
8783                 frame_count++;
8784                 pdest_frame = NULL;
8785             } else {
8786                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
8787                 generate_ebd = OMX_FALSE;
8788             }
8789         }
8790         if (generate_ebd) {
8791             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
8792             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8793             psource_frame = NULL;
8794 
8795             if (m_input_pending_q.m_size) {
8796                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8797                 m_input_pending_q.pop_entry(&address,&p2,&id);
8798                 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8799                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8800                         psource_frame->nTimeStamp);
8801                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8802                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8803             }
8804         }
8805     }
8806     return OMX_ErrorNone;
8807 }
8808 
push_input_h264(OMX_HANDLETYPE hComp)8809 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
8810 {
8811     OMX_U32 partial_frame = 1;
8812     unsigned long address = 0, p2 = 0, id = 0;
8813     OMX_BOOL isNewFrame = OMX_FALSE;
8814     OMX_BOOL generate_ebd = OMX_TRUE;
8815 
8816     if (h264_scratch.pBuffer == NULL) {
8817         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
8818         return OMX_ErrorBadParameter;
8819     }
8820     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
8821             "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
8822     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
8823     if (h264_scratch.nFilledLen && look_ahead_nal) {
8824         look_ahead_nal = false;
8825         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8826                 h264_scratch.nFilledLen) {
8827             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8828                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
8829             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8830             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
8831             h264_scratch.nFilledLen = 0;
8832         } else {
8833             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
8834             return OMX_ErrorBadParameter;
8835         }
8836     }
8837 
8838     /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
8839        in EOS flag getting associated with the destination
8840     */
8841     if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
8842             pdest_frame->nFilledLen) {
8843         DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
8844         generate_ebd = OMX_FALSE;
8845     }
8846 
8847     if (nal_length == 0) {
8848         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
8849         if (m_frame_parser.parse_sc_frame(psource_frame,
8850                     &h264_scratch,&partial_frame) == -1) {
8851             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8852             return OMX_ErrorBadParameter;
8853         }
8854     } else {
8855         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
8856         if (m_frame_parser.parse_h264_nallength(psource_frame,
8857                     &h264_scratch,&partial_frame) == -1) {
8858             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
8859             return OMX_ErrorBadParameter;
8860         }
8861     }
8862 
8863     if (partial_frame == 0) {
8864         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
8865             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
8866             nal_count++;
8867             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
8868             h264_scratch.nFlags = psource_frame->nFlags;
8869         } else {
8870             DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
8871             if (h264_scratch.nFilledLen) {
8872                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
8873                         NALU_TYPE_SPS);
8874 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8875                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
8876                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8877                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
8878                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8879                     // If timeinfo is present frame info from SEI is already processed
8880                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8881                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
8882 #endif
8883                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8884                 nal_count++;
8885                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
8886                     pdest_frame->nTimeStamp = h264_last_au_ts;
8887                     pdest_frame->nFlags = h264_last_au_flags;
8888 #ifdef PANSCAN_HDLR
8889                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8890                         h264_parser->update_panscan_data(h264_last_au_ts);
8891 #endif
8892                 }
8893                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
8894                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
8895                     h264_last_au_ts = h264_scratch.nTimeStamp;
8896                     h264_last_au_flags = h264_scratch.nFlags;
8897 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8898                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
8899                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
8900                         if (!VALID_TS(h264_last_au_ts))
8901                             h264_last_au_ts = ts_in_sei;
8902                     }
8903 #endif
8904                 } else
8905                     h264_last_au_ts = LLONG_MAX;
8906             }
8907 
8908             if (!isNewFrame) {
8909                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8910                         h264_scratch.nFilledLen) {
8911                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
8912                             (unsigned int)h264_scratch.nFilledLen);
8913                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8914                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
8915                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8916                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
8917                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8918                     h264_scratch.nFilledLen = 0;
8919                 } else {
8920                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
8921                     return OMX_ErrorBadParameter;
8922                 }
8923             } else if(h264_scratch.nFilledLen) {
8924                 look_ahead_nal = true;
8925                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
8926                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8927                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8928                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
8929 
8930                 if (pdest_frame->nFilledLen == 0) {
8931                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
8932                     look_ahead_nal = false;
8933                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8934                             h264_scratch.nFilledLen) {
8935                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8936                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8937                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8938                         h264_scratch.nFilledLen = 0;
8939                     } else {
8940                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
8941                         return OMX_ErrorBadParameter;
8942                     }
8943                 } else {
8944                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
8945                         DEBUG_PRINT_LOW("Reset the EOS Flag");
8946                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8947                     }
8948                     /*Push the frame to the Decoder*/
8949                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8950                         return OMX_ErrorBadParameter;
8951                     }
8952                     //frame_count++;
8953                     pdest_frame = NULL;
8954                     if (m_input_free_q.m_size) {
8955                         m_input_free_q.pop_entry(&address,&p2,&id);
8956                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8957                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
8958                         pdest_frame->nFilledLen = 0;
8959                         pdest_frame->nFlags = 0;
8960                         pdest_frame->nTimeStamp = LLONG_MAX;
8961                     }
8962                 }
8963             }
8964         }
8965     } else {
8966         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
8967         /*Check if Destination Buffer is full*/
8968         if (h264_scratch.nAllocLen ==
8969                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
8970             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
8971             return OMX_ErrorStreamCorrupt;
8972         }
8973     }
8974 
8975     if (!psource_frame->nFilledLen) {
8976         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
8977 
8978         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8979             if (pdest_frame) {
8980                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
8981                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8982                         h264_scratch.nFilledLen) {
8983                     if(pdest_frame->nFilledLen == 0) {
8984                         /* No residual frame from before, send whatever
8985                          * we have left */
8986                         memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8987                                 h264_scratch.pBuffer, h264_scratch.nFilledLen);
8988                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8989                         h264_scratch.nFilledLen = 0;
8990                         pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
8991                     } else {
8992                         m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8993                         if(!isNewFrame) {
8994                             /* Have a residual frame, but we know that the
8995                              * AU in this frame is belonging to whatever
8996                              * frame we had left over.  So append it */
8997                              memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8998                                      h264_scratch.pBuffer,h264_scratch.nFilledLen);
8999                              pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9000                              h264_scratch.nFilledLen = 0;
9001                              if (h264_last_au_ts != LLONG_MAX)
9002                                  pdest_frame->nTimeStamp = h264_last_au_ts;
9003                         } else {
9004                             /* Completely new frame, let's just push what
9005                              * we have now.  The resulting EBD would trigger
9006                              * another push */
9007                             generate_ebd = OMX_FALSE;
9008                             pdest_frame->nTimeStamp = h264_last_au_ts;
9009                             h264_last_au_ts = h264_scratch.nTimeStamp;
9010                         }
9011                     }
9012                 } else {
9013                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9014                     return OMX_ErrorBadParameter;
9015                 }
9016 
9017                 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9018                 if(generate_ebd == OMX_TRUE) {
9019                      pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9020                 }
9021 
9022                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9023                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9024                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9025 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9026                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9027                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9028                     if (!VALID_TS(pdest_frame->nTimeStamp))
9029                         pdest_frame->nTimeStamp = ts_in_sei;
9030                 }
9031 #endif
9032                 /*Push the frame to the Decoder*/
9033                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9034                     return OMX_ErrorBadParameter;
9035                 }
9036                 frame_count++;
9037                 pdest_frame = NULL;
9038             } else {
9039                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9040                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9041                 generate_ebd = OMX_FALSE;
9042             }
9043         }
9044     }
9045     if (generate_ebd && !psource_frame->nFilledLen) {
9046         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9047         psource_frame = NULL;
9048         if (m_input_pending_q.m_size) {
9049             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9050             m_input_pending_q.pop_entry(&address,&p2,&id);
9051             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9052             DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9053                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9054         }
9055     }
9056     return OMX_ErrorNone;
9057 }
9058 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9059 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9060 {
9061     OMX_ERRORTYPE rc = OMX_ErrorNone;
9062     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9063         memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9064         if (pDst->nTimeStamp == LLONG_MAX) {
9065             pDst->nTimeStamp = pSrc->nTimeStamp;
9066             DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9067         }
9068         pDst->nFilledLen += pSrc->nFilledLen;
9069         pSrc->nFilledLen = 0;
9070     } else {
9071         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9072         rc = OMX_ErrorBadParameter;
9073     }
9074     return rc;
9075 }
9076 
push_input_hevc(OMX_HANDLETYPE hComp)9077 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9078 {
9079     OMX_U32 partial_frame = 1;
9080     unsigned long address,p2,id;
9081     OMX_BOOL isNewFrame = OMX_FALSE;
9082     OMX_BOOL generate_ebd = OMX_TRUE;
9083     OMX_ERRORTYPE rc = OMX_ErrorNone;
9084     if (h264_scratch.pBuffer == NULL) {
9085         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9086         return OMX_ErrorBadParameter;
9087     }
9088 
9089     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9090             pdest_frame nFilledLen %u nTimeStamp %lld",
9091             (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9092 
9093     if (h264_scratch.nFilledLen && look_ahead_nal) {
9094         look_ahead_nal = false;
9095         rc = copy_buffer(pdest_frame, &h264_scratch);
9096         if (rc != OMX_ErrorNone) {
9097             return rc;
9098         }
9099     }
9100 
9101     if (nal_length == 0) {
9102         if (m_frame_parser.parse_sc_frame(psource_frame,
9103                     &h264_scratch,&partial_frame) == -1) {
9104             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9105             return OMX_ErrorBadParameter;
9106         }
9107     } else {
9108         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9109         if (m_frame_parser.parse_h264_nallength(psource_frame,
9110                     &h264_scratch,&partial_frame) == -1) {
9111             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9112             return OMX_ErrorBadParameter;
9113         }
9114     }
9115 
9116     if (partial_frame == 0) {
9117         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9118             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9119             nal_count++;
9120             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9121             h264_scratch.nFlags = psource_frame->nFlags;
9122         } else {
9123             DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9124             if (h264_scratch.nFilledLen) {
9125                 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9126                 nal_count++;
9127             }
9128 
9129             if (!isNewFrame) {
9130                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9131                         nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9132                         (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9133                         (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9134                 rc = copy_buffer(pdest_frame, &h264_scratch);
9135                 if (rc != OMX_ErrorNone) {
9136                     return rc;
9137                 }
9138             } else {
9139                 look_ahead_nal = true;
9140                 if (pdest_frame->nFilledLen == 0) {
9141                     look_ahead_nal = false;
9142                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9143                     rc = copy_buffer(pdest_frame, &h264_scratch);
9144                     if (rc != OMX_ErrorNone) {
9145                         return OMX_ErrorBadParameter;
9146                     }
9147                 } else {
9148                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9149                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9150                     }
9151                     DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9152                             nTimeStamp %lld, look_ahead_nal in h264_scratch \
9153                             nFilledLen %u nTimeStamp %lld",
9154                             frame_count++, (unsigned int)pdest_frame->nFilledLen,
9155                             pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9156                             h264_scratch.nTimeStamp);
9157                     if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9158                         return OMX_ErrorBadParameter;
9159                     }
9160                     pdest_frame = NULL;
9161                     if (m_input_free_q.m_size) {
9162                         m_input_free_q.pop_entry(&address, &p2, &id);
9163                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9164                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9165                         pdest_frame->nFilledLen = 0;
9166                         pdest_frame->nFlags = 0;
9167                         pdest_frame->nTimeStamp = LLONG_MAX;
9168                     }
9169                 }
9170             }
9171         }
9172     } else {
9173         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9174                 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9175                 nFilledLen %u nTimeStamp %lld",
9176                 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9177                 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9178                 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9179 
9180         if (h264_scratch.nAllocLen ==
9181                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9182             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9183             return OMX_ErrorStreamCorrupt;
9184         }
9185     }
9186 
9187     if (!psource_frame->nFilledLen) {
9188         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9189         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9190             if (pdest_frame) {
9191                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9192                 rc = copy_buffer(pdest_frame, &h264_scratch);
9193                 if ( rc != OMX_ErrorNone ) {
9194                     return rc;
9195                 }
9196                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9197                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9198                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9199                         frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9200                 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9201                     return OMX_ErrorBadParameter;
9202                 }
9203                 frame_count++;
9204                 pdest_frame = NULL;
9205             } else {
9206                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9207                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9208                 generate_ebd = OMX_FALSE;
9209             }
9210         }
9211     }
9212 
9213     if (generate_ebd && !psource_frame->nFilledLen) {
9214         m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9215         psource_frame = NULL;
9216         if (m_input_pending_q.m_size) {
9217             m_input_pending_q.pop_entry(&address, &p2, &id);
9218             psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9219             DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9220                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9221         }
9222     }
9223     return OMX_ErrorNone;
9224 }
9225 
push_input_vc1(OMX_HANDLETYPE hComp)9226 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
9227 {
9228     OMX_U8 *buf, *pdest;
9229     OMX_U32 partial_frame = 1;
9230     OMX_U32 buf_len, dest_len;
9231 
9232     if (first_frame == 0) {
9233         first_frame = 1;
9234         DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
9235         if (!m_vendor_config.pData) {
9236             DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
9237             buf = psource_frame->pBuffer;
9238             buf_len = psource_frame->nFilledLen;
9239 
9240             if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
9241                     VC1_SP_MP_START_CODE) {
9242                 m_vc1_profile = VC1_SP_MP_RCV;
9243             } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
9244                 m_vc1_profile = VC1_AP;
9245             } else {
9246                 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
9247                 return OMX_ErrorStreamCorrupt;
9248             }
9249         } else {
9250             pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
9251                 pdest_frame->nOffset;
9252             dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
9253                     pdest_frame->nOffset);
9254 
9255             if (dest_len < m_vendor_config.nDataSize) {
9256                 DEBUG_PRINT_ERROR("Destination buffer full");
9257                 return OMX_ErrorBadParameter;
9258             } else {
9259                 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
9260                 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
9261             }
9262         }
9263     }
9264 
9265     switch (m_vc1_profile) {
9266         case VC1_AP:
9267             DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
9268             if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
9269                 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
9270                 return OMX_ErrorBadParameter;
9271             }
9272             break;
9273 
9274         case VC1_SP_MP_RCV:
9275         default:
9276             DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
9277             return OMX_ErrorBadParameter;
9278     }
9279     return OMX_ErrorNone;
9280 }
9281 
9282 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9283 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9284         OMX_U32 alignment)
9285 {
9286     struct pmem_allocation allocation;
9287     allocation.size = buffer_size;
9288     allocation.align = clip2(alignment);
9289     if (allocation.align < 4096) {
9290         allocation.align = 4096;
9291     }
9292     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9293         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9294                 allocation.align, allocation.size);
9295         return false;
9296     }
9297     return true;
9298 }
9299 #endif
9300 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,OMX_U32 alignment,struct ion_allocation_data * alloc_data,struct ion_fd_data * fd_data,int flag)9301 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
9302         OMX_U32 alignment, struct ion_allocation_data *alloc_data,
9303         struct ion_fd_data *fd_data, int flag)
9304 {
9305     int fd = -EINVAL;
9306     int rc = -EINVAL;
9307     int ion_dev_flag;
9308     struct vdec_ion ion_buf_info;
9309     if (!alloc_data || buffer_size <= 0 || !fd_data) {
9310         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9311         return -EINVAL;
9312     }
9313     ion_dev_flag = O_RDONLY;
9314     fd = open (MEM_DEVICE, ion_dev_flag);
9315     if (fd < 0) {
9316         DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
9317         return fd;
9318     }
9319 
9320     alloc_data->flags = flag;
9321     alloc_data->len = buffer_size;
9322     alloc_data->align = clip2(alignment);
9323     if (alloc_data->align < 4096) {
9324         alloc_data->align = 4096;
9325     }
9326 
9327     alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
9328     if (secure_mode && (alloc_data->flags & ION_SECURE)) {
9329         alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9330     }
9331 
9332     /* Use secure display cma heap for obvious reasons. */
9333     if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
9334         alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9335     }
9336 
9337     rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
9338     if (rc || !alloc_data->handle) {
9339         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9340         alloc_data->handle = 0;
9341         close(fd);
9342         fd = -ENOMEM;
9343         return fd;
9344     }
9345     fd_data->handle = alloc_data->handle;
9346     rc = ioctl(fd,ION_IOC_MAP,fd_data);
9347     if (rc) {
9348         DEBUG_PRINT_ERROR("ION MAP failed ");
9349         ion_buf_info.ion_alloc_data = *alloc_data;
9350         ion_buf_info.ion_device_fd = fd;
9351         ion_buf_info.fd_ion_data = *fd_data;
9352         free_ion_memory(&ion_buf_info);
9353         fd_data->fd =-1;
9354         fd = -ENOMEM;
9355     }
9356 
9357     return fd;
9358 }
9359 
free_ion_memory(struct vdec_ion * buf_ion_info)9360 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9361 {
9362 
9363     if (!buf_ion_info) {
9364         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9365         return;
9366     }
9367     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
9368                 &buf_ion_info->ion_alloc_data.handle)) {
9369         DEBUG_PRINT_ERROR("ION: free failed" );
9370     }
9371     close(buf_ion_info->ion_device_fd);
9372     buf_ion_info->ion_device_fd = -1;
9373     buf_ion_info->ion_alloc_data.handle = 0;
9374     buf_ion_info->fd_ion_data.fd = -1;
9375 }
9376 #endif
free_output_buffer_header()9377 void omx_vdec::free_output_buffer_header()
9378 {
9379     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
9380     output_use_buffer = false;
9381     ouput_egl_buffers = false;
9382 
9383     if (m_out_mem_ptr) {
9384         free (m_out_mem_ptr);
9385         m_out_mem_ptr = NULL;
9386     }
9387 
9388     if (m_platform_list) {
9389         free(m_platform_list);
9390         m_platform_list = NULL;
9391     }
9392 
9393     if (drv_ctx.ptr_respbuffer) {
9394         free (drv_ctx.ptr_respbuffer);
9395         drv_ctx.ptr_respbuffer = NULL;
9396     }
9397     if (drv_ctx.ptr_outputbuffer) {
9398         free (drv_ctx.ptr_outputbuffer);
9399         drv_ctx.ptr_outputbuffer = NULL;
9400     }
9401 #ifdef USE_ION
9402     if (drv_ctx.op_buf_ion_info) {
9403         DEBUG_PRINT_LOW("Free o/p ion context");
9404         free(drv_ctx.op_buf_ion_info);
9405         drv_ctx.op_buf_ion_info = NULL;
9406     }
9407 #endif
9408     buf_ref_remove();
9409 }
9410 
free_input_buffer_header()9411 void omx_vdec::free_input_buffer_header()
9412 {
9413     input_use_buffer = false;
9414     if (arbitrary_bytes) {
9415         if (m_inp_heap_ptr) {
9416             DEBUG_PRINT_LOW("Free input Heap Pointer");
9417             free (m_inp_heap_ptr);
9418             m_inp_heap_ptr = NULL;
9419         }
9420 
9421         if (m_phdr_pmem_ptr) {
9422             DEBUG_PRINT_LOW("Free input pmem header Pointer");
9423             free (m_phdr_pmem_ptr);
9424             m_phdr_pmem_ptr = NULL;
9425         }
9426     }
9427     if (m_inp_mem_ptr) {
9428         DEBUG_PRINT_LOW("Free input pmem Pointer area");
9429         free (m_inp_mem_ptr);
9430         m_inp_mem_ptr = NULL;
9431     }
9432     /* We just freed all the buffer headers, every thing in m_input_free_q,
9433      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
9434     while (m_input_free_q.m_size) {
9435         unsigned long address, p2, id;
9436         m_input_free_q.pop_entry(&address, &p2, &id);
9437     }
9438     while (m_input_pending_q.m_size) {
9439         unsigned long address, p2, id;
9440         m_input_pending_q.pop_entry(&address, &p2, &id);
9441     }
9442     pdest_frame = NULL;
9443     psource_frame = NULL;
9444     if (drv_ctx.ptr_inputbuffer) {
9445         DEBUG_PRINT_LOW("Free Driver Context pointer");
9446         free (drv_ctx.ptr_inputbuffer);
9447         drv_ctx.ptr_inputbuffer = NULL;
9448     }
9449 #ifdef USE_ION
9450     if (drv_ctx.ip_buf_ion_info) {
9451         DEBUG_PRINT_LOW("Free ion context");
9452         free(drv_ctx.ip_buf_ion_info);
9453         drv_ctx.ip_buf_ion_info = NULL;
9454     }
9455 #endif
9456 }
9457 
stream_off(OMX_U32 port)9458 int omx_vdec::stream_off(OMX_U32 port)
9459 {
9460     enum v4l2_buf_type btype;
9461     int rc = 0;
9462     enum v4l2_ports v4l2_port = OUTPUT_PORT;
9463 
9464     if (port == OMX_CORE_INPUT_PORT_INDEX) {
9465         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9466         v4l2_port = OUTPUT_PORT;
9467     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
9468         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9469         v4l2_port = CAPTURE_PORT;
9470     } else if (port == OMX_ALL) {
9471         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
9472         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
9473 
9474         if (!rc_input)
9475             return rc_input;
9476         else
9477             return rc_output;
9478     }
9479 
9480     if (!streaming[v4l2_port]) {
9481         // already streamed off, warn and move on
9482         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
9483                 " which is already streamed off", v4l2_port);
9484         return 0;
9485     }
9486 
9487     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
9488 
9489     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
9490     if (rc) {
9491         /*TODO: How to handle this case */
9492         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
9493     } else {
9494         streaming[v4l2_port] = false;
9495     }
9496 
9497     return rc;
9498 }
9499 
get_buffer_req(vdec_allocatorproperty * buffer_prop)9500 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
9501 {
9502     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9503     struct v4l2_requestbuffers bufreq;
9504     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
9505     unsigned int final_extra_data_size = 0;
9506     struct v4l2_format fmt;
9507     int ret = 0;
9508     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9509             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9510     bufreq.memory = V4L2_MEMORY_USERPTR;
9511     bufreq.count = 1;
9512     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9513         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9514         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9515         fmt.fmt.pix_mp.pixelformat = output_capability;
9516     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9517         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9518         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9519         fmt.fmt.pix_mp.pixelformat = capture_capability;
9520     } else {
9521         eRet = OMX_ErrorBadParameter;
9522     }
9523     if (eRet==OMX_ErrorNone) {
9524         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9525     }
9526     if (ret) {
9527         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9528         /*TODO: How to handle this case */
9529         eRet = OMX_ErrorInsufficientResources;
9530         return eRet;
9531     } else {
9532         buffer_prop->actualcount = bufreq.count;
9533         buffer_prop->mincount = bufreq.count;
9534         DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
9535     }
9536     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9537             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9538 
9539     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9540     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9541 
9542     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9543 
9544     update_resolution(fmt.fmt.pix_mp.width,
9545             fmt.fmt.pix_mp.height,
9546             fmt.fmt.pix_mp.plane_fmt[0].bytesperline,
9547             fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
9548     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
9549         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
9550     DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
9551 
9552     if (ret) {
9553         /*TODO: How to handle this case */
9554         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9555         eRet = OMX_ErrorInsufficientResources;
9556     } else {
9557         int extra_idx = 0;
9558 
9559         eRet = is_video_session_supported();
9560         if (eRet)
9561             return eRet;
9562 
9563         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
9564         buf_size = buffer_prop->buffer_size;
9565         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
9566         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
9567             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
9568         } else if (extra_idx >= VIDEO_MAX_PLANES) {
9569             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
9570             return OMX_ErrorBadParameter;
9571         }
9572 
9573         default_extra_data_size = VENUS_EXTRADATA_SIZE(
9574                 drv_ctx.video_resolution.frame_height,
9575                 drv_ctx.video_resolution.frame_width);
9576         final_extra_data_size = extra_data_size > default_extra_data_size ?
9577             extra_data_size : default_extra_data_size;
9578 
9579         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
9580             (~(buffer_prop->alignment - 1));
9581 
9582         drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
9583         drv_ctx.extradata_info.count = buffer_prop->actualcount;
9584         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
9585         if (!secure_mode)
9586             buf_size += final_extra_data_size;
9587         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9588         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
9589                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
9590         if (extra_data_size)
9591             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
9592                 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
9593 
9594         if (in_reconfig) // BufReq will be set to driver when port is disabled
9595             buffer_prop->buffer_size = buf_size;
9596         else if (buf_size != buffer_prop->buffer_size) {
9597             buffer_prop->buffer_size = buf_size;
9598             eRet = set_buffer_req(buffer_prop);
9599         }
9600     }
9601     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
9602             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9603     return eRet;
9604 }
9605 
set_buffer_req(vdec_allocatorproperty * buffer_prop)9606 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
9607 {
9608     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9609     unsigned buf_size = 0;
9610     struct v4l2_format fmt;
9611     struct v4l2_requestbuffers bufreq;
9612     int ret;
9613     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
9614             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9615     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9616     if (buf_size != buffer_prop->buffer_size) {
9617         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
9618                 (unsigned int)buffer_prop->buffer_size, buf_size);
9619         eRet = OMX_ErrorBadParameter;
9620     } else {
9621         memset(&fmt, 0x0, sizeof(struct v4l2_format));
9622         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9623         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9624         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
9625 
9626         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9627             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9628             fmt.fmt.pix_mp.pixelformat = output_capability;
9629         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9630             fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9631             fmt.fmt.pix_mp.pixelformat = capture_capability;
9632         } else {
9633             eRet = OMX_ErrorBadParameter;
9634         }
9635 
9636         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
9637         if (ret) {
9638             /*TODO: How to handle this case */
9639             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
9640             eRet = OMX_ErrorInsufficientResources;
9641         }
9642 
9643         bufreq.memory = V4L2_MEMORY_USERPTR;
9644         bufreq.count = buffer_prop->actualcount;
9645         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9646             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9647         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9648             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9649         } else {
9650             eRet = OMX_ErrorBadParameter;
9651         }
9652 
9653         if (eRet==OMX_ErrorNone) {
9654             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9655         }
9656 
9657         if (ret) {
9658             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
9659             /*TODO: How to handle this case */
9660             eRet = OMX_ErrorInsufficientResources;
9661         } else if (bufreq.count < buffer_prop->actualcount) {
9662             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
9663                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
9664                     buffer_prop->actualcount, bufreq.count);
9665             eRet = OMX_ErrorInsufficientResources;
9666         } else {
9667             if (!client_buffers.update_buffer_req()) {
9668                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
9669                 eRet = OMX_ErrorInsufficientResources;
9670             }
9671         }
9672     }
9673     return eRet;
9674 }
9675 
update_picture_resolution()9676 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
9677 {
9678     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9679     return eRet;
9680 }
9681 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)9682 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
9683 {
9684     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9685     struct v4l2_format fmt;
9686     if (!portDefn) {
9687         return OMX_ErrorBadParameter;
9688     }
9689     DEBUG_PRINT_LOW("omx_vdec::update_portdef");
9690     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
9691     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9692     portDefn->eDomain    = OMX_PortDomainVideo;
9693     if (drv_ctx.frame_rate.fps_denominator > 0)
9694         portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
9695             drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
9696     else {
9697         DEBUG_PRINT_ERROR("Error: Divide by zero");
9698         return OMX_ErrorBadParameter;
9699     }
9700     memset(&fmt, 0x0, sizeof(struct v4l2_format));
9701     if (0 == portDefn->nPortIndex) {
9702         portDefn->eDir =  OMX_DirInput;
9703         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
9704         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
9705         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
9706         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9707         portDefn->format.video.eCompressionFormat = eCompressionFormat;
9708         portDefn->bEnabled   = m_inp_bEnabled;
9709         portDefn->bPopulated = m_inp_bPopulated;
9710 
9711         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9712         fmt.fmt.pix_mp.pixelformat = output_capability;
9713     } else if (1 == portDefn->nPortIndex) {
9714         unsigned int buf_size = 0;
9715         if (!client_buffers.update_buffer_req()) {
9716             DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
9717             return OMX_ErrorHardware;
9718         }
9719         if (!client_buffers.get_buffer_req(buf_size)) {
9720             DEBUG_PRINT_ERROR("update buffer requirements");
9721             return OMX_ErrorHardware;
9722         }
9723         portDefn->nBufferSize = buf_size;
9724         portDefn->eDir =  OMX_DirOutput;
9725         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
9726         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
9727         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9728         portDefn->bEnabled   = m_out_bEnabled;
9729         portDefn->bPopulated = m_out_bPopulated;
9730         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
9731             DEBUG_PRINT_ERROR("Error in getting color format");
9732             return OMX_ErrorHardware;
9733         }
9734         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9735         fmt.fmt.pix_mp.pixelformat = capture_capability;
9736     } else {
9737         portDefn->eDir = OMX_DirMax;
9738         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
9739                 (int)portDefn->nPortIndex);
9740         eRet = OMX_ErrorBadPortIndex;
9741     }
9742     if (is_down_scalar_enabled) {
9743         int ret = 0;
9744         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9745         if (ret) {
9746             DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution");
9747             return OMX_ErrorHardware;
9748         } else {
9749             portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width;
9750             portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height;
9751             portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
9752             portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
9753         }
9754     } else {
9755         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
9756         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
9757         portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9758         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9759     }
9760 
9761     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
9762        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
9763            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
9764            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
9765     }
9766     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
9767             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
9768             (unsigned int)portDefn->nPortIndex,
9769             (unsigned int)portDefn->format.video.nFrameWidth,
9770             (unsigned int)portDefn->format.video.nFrameHeight,
9771             (int)portDefn->format.video.nStride,
9772             (unsigned int)portDefn->format.video.nSliceHeight,
9773             (unsigned int)portDefn->format.video.eColorFormat,
9774             (unsigned int)portDefn->nBufferSize,
9775             (unsigned int)portDefn->nBufferCountActual);
9776 
9777     return eRet;
9778 }
9779 
allocate_output_headers()9780 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
9781 {
9782     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9783     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
9784     unsigned i= 0;
9785 
9786     if (!m_out_mem_ptr) {
9787         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
9788         int nBufHdrSize        = 0;
9789         int nPlatformEntrySize = 0;
9790         int nPlatformListSize  = 0;
9791         int nPMEMInfoSize = 0;
9792         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
9793         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
9794         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
9795 
9796         DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
9797                 drv_ctx.op_buf.actualcount);
9798         nBufHdrSize        = drv_ctx.op_buf.actualcount *
9799             sizeof(OMX_BUFFERHEADERTYPE);
9800 
9801         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
9802             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9803         nPlatformListSize  = drv_ctx.op_buf.actualcount *
9804             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9805         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9806             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9807 
9808         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
9809                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
9810                 nPMEMInfoSize,
9811                 nPlatformListSize);
9812         DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
9813                 m_out_bm_count);
9814         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
9815         // Alloc mem for platform specific info
9816         char *pPtr=NULL;
9817         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9818                 nPMEMInfoSize,1);
9819         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9820                        calloc (sizeof(struct vdec_bufferpayload),
9821                                drv_ctx.op_buf.actualcount);
9822         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
9823                      calloc (sizeof (struct vdec_output_frameinfo),
9824                              drv_ctx.op_buf.actualcount);
9825         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9826             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
9827             return OMX_ErrorInsufficientResources;
9828         }
9829 
9830 #ifdef USE_ION
9831         drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9832                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9833         if (!drv_ctx.op_buf_ion_info) {
9834             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9835             return OMX_ErrorInsufficientResources;
9836         }
9837 #endif
9838         if (dynamic_buf_mode) {
9839             out_dynamic_list = (struct dynamic_buf_list *) \
9840                 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
9841             if (out_dynamic_list) {
9842                for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
9843                   out_dynamic_list[i].dup_fd = -1;
9844             }
9845         }
9846 
9847         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9848                 && drv_ctx.ptr_respbuffer) {
9849             bufHdr          =  m_out_mem_ptr;
9850             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9851             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9852                 (((char *) m_platform_list)  + nPlatformListSize);
9853             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
9854                 (((char *) m_platform_entry) + nPlatformEntrySize);
9855             pPlatformList   = m_platform_list;
9856             pPlatformEntry  = m_platform_entry;
9857             pPMEMInfo       = m_pmem_info;
9858 
9859             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
9860 
9861             // Settting the entire storage nicely
9862             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
9863                     m_out_mem_ptr,pPlatformEntry);
9864             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
9865             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
9866                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
9867                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
9868                 // Set the values when we determine the right HxW param
9869                 bufHdr->nAllocLen          = 0;
9870                 bufHdr->nFilledLen         = 0;
9871                 bufHdr->pAppPrivate        = NULL;
9872                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
9873                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
9874                 pPlatformEntry->entry      = pPMEMInfo;
9875                 // Initialize the Platform List
9876                 pPlatformList->nEntries    = 1;
9877                 pPlatformList->entryList   = pPlatformEntry;
9878                 // Keep pBuffer NULL till vdec is opened
9879                 bufHdr->pBuffer            = NULL;
9880                 pPMEMInfo->offset          =  0;
9881                 pPMEMInfo->pmem_fd = -1;
9882                 bufHdr->pPlatformPrivate = pPlatformList;
9883                 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
9884 #ifdef USE_ION
9885                 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
9886 #endif
9887                 /*Create a mapping between buffers*/
9888                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
9889                 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
9890                                     &drv_ctx.ptr_outputbuffer[i];
9891                 // Move the buffer and buffer header pointers
9892                 bufHdr++;
9893                 pPMEMInfo++;
9894                 pPlatformEntry++;
9895                 pPlatformList++;
9896             }
9897         } else {
9898             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
9899                     m_out_mem_ptr, pPtr);
9900             if (m_out_mem_ptr) {
9901                 free(m_out_mem_ptr);
9902                 m_out_mem_ptr = NULL;
9903             }
9904             if (pPtr) {
9905                 free(pPtr);
9906                 pPtr = NULL;
9907             }
9908             if (drv_ctx.ptr_outputbuffer) {
9909                 free(drv_ctx.ptr_outputbuffer);
9910                 drv_ctx.ptr_outputbuffer = NULL;
9911             }
9912             if (drv_ctx.ptr_respbuffer) {
9913                 free(drv_ctx.ptr_respbuffer);
9914                 drv_ctx.ptr_respbuffer = NULL;
9915             }
9916 #ifdef USE_ION
9917             if (drv_ctx.op_buf_ion_info) {
9918                 DEBUG_PRINT_LOW("Free o/p ion context");
9919                 free(drv_ctx.op_buf_ion_info);
9920                 drv_ctx.op_buf_ion_info = NULL;
9921             }
9922 #endif
9923             eRet =  OMX_ErrorInsufficientResources;
9924         }
9925     } else {
9926         eRet =  OMX_ErrorInsufficientResources;
9927     }
9928     return eRet;
9929 }
9930 
complete_pending_buffer_done_cbs()9931 void omx_vdec::complete_pending_buffer_done_cbs()
9932 {
9933     unsigned long p1, p2, ident;
9934     omx_cmd_queue tmp_q, pending_bd_q;
9935     pthread_mutex_lock(&m_lock);
9936     // pop all pending GENERATE FDB from ftb queue
9937     while (m_ftb_q.m_size) {
9938         m_ftb_q.pop_entry(&p1,&p2,&ident);
9939         if (ident == OMX_COMPONENT_GENERATE_FBD) {
9940             pending_bd_q.insert_entry(p1,p2,ident);
9941         } else {
9942             tmp_q.insert_entry(p1,p2,ident);
9943         }
9944     }
9945     //return all non GENERATE FDB to ftb queue
9946     while (tmp_q.m_size) {
9947         tmp_q.pop_entry(&p1,&p2,&ident);
9948         m_ftb_q.insert_entry(p1,p2,ident);
9949     }
9950     // pop all pending GENERATE EDB from etb queue
9951     while (m_etb_q.m_size) {
9952         m_etb_q.pop_entry(&p1,&p2,&ident);
9953         if (ident == OMX_COMPONENT_GENERATE_EBD) {
9954             pending_bd_q.insert_entry(p1,p2,ident);
9955         } else {
9956             tmp_q.insert_entry(p1,p2,ident);
9957         }
9958     }
9959     //return all non GENERATE FDB to etb queue
9960     while (tmp_q.m_size) {
9961         tmp_q.pop_entry(&p1,&p2,&ident);
9962         m_etb_q.insert_entry(p1,p2,ident);
9963     }
9964     pthread_mutex_unlock(&m_lock);
9965     // process all pending buffer dones
9966     while (pending_bd_q.m_size) {
9967         pending_bd_q.pop_entry(&p1,&p2,&ident);
9968         switch (ident) {
9969             case OMX_COMPONENT_GENERATE_EBD:
9970                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
9971                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
9972                     omx_report_error ();
9973                 }
9974                 break;
9975 
9976             case OMX_COMPONENT_GENERATE_FBD:
9977                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
9978                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
9979                     omx_report_error ();
9980                 }
9981                 break;
9982         }
9983     }
9984 }
9985 
set_frame_rate(OMX_S64 act_timestamp)9986 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
9987 {
9988     OMX_U32 new_frame_interval = 0;
9989     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
9990             && llabs(act_timestamp - prev_ts) > 2000) {
9991         new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
9992             llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
9993         if (new_frame_interval != frm_int || frm_int == 0) {
9994             frm_int = new_frame_interval;
9995             if (frm_int) {
9996                 drv_ctx.frame_rate.fps_numerator = 1e6;
9997                 drv_ctx.frame_rate.fps_denominator = frm_int;
9998                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
9999                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10000                         (float)drv_ctx.frame_rate.fps_denominator);
10001                 m_perf_control.request_cores(frm_int);
10002                 /* We need to report the difference between this FBD and the previous FBD
10003                  * back to the driver for clock scaling purposes. */
10004                 struct v4l2_outputparm oparm;
10005                 /*XXX: we're providing timing info as seconds per frame rather than frames
10006                  * per second.*/
10007                 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10008                 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10009 
10010                 struct v4l2_streamparm sparm;
10011                 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10012                 sparm.parm.output = oparm;
10013                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10014                     DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10015                             performance might be affected");
10016                 }
10017 
10018             }
10019         }
10020     }
10021     prev_ts = act_timestamp;
10022 }
10023 
adjust_timestamp(OMX_S64 & act_timestamp)10024 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10025 {
10026     if (rst_prev_ts && VALID_TS(act_timestamp)) {
10027         prev_ts = act_timestamp;
10028         prev_ts_actual = act_timestamp;
10029         rst_prev_ts = false;
10030     } else if (VALID_TS(prev_ts)) {
10031         bool codec_cond = (drv_ctx.timestamp_adjust)?
10032             (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10033             (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10034              prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10035         if (frm_int > 0 && codec_cond) {
10036             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10037             act_timestamp = prev_ts + frm_int;
10038             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10039             prev_ts = act_timestamp;
10040         } else {
10041             if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10042                 // ensure that timestamps can never step backwards when in display order
10043                 act_timestamp = prev_ts;
10044             }
10045             set_frame_rate(act_timestamp);
10046         }
10047     } else if (frm_int > 0)          // In this case the frame rate was set along
10048     {                               // with the port definition, start ts with 0
10049         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
10050         rst_prev_ts = true;
10051     }
10052 }
10053 
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorSpace_t * color_space,ColorAspects * aspects)10054 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10055     OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
10056 {
10057     switch (primaries) {
10058         case MSM_VIDC_BT709_5:
10059             *color_space = ITU_R_709;
10060             aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10061             break;
10062         case MSM_VIDC_BT470_6_M:
10063             aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10064             break;
10065         case MSM_VIDC_BT601_6_625:
10066             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10067             break;
10068         case MSM_VIDC_BT601_6_525:
10069             *color_space = range ? ITU_R_601_FR : ITU_R_601;
10070             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10071             break;
10072         case MSM_VIDC_GENERIC_FILM:
10073             aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10074             break;
10075         case MSM_VIDC_BT2020:
10076             aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10077             break;
10078         case MSM_VIDC_UNSPECIFIED:
10079             //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10080         default:
10081             //aspects->mPrimaries = ColorAspects::PrimariesOther;
10082             aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10083             break;
10084     }
10085 
10086     aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10087 
10088     switch (transfer) {
10089         case MSM_VIDC_TRANSFER_BT709_5:
10090         case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10091             aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10092             break;
10093         case MSM_VIDC_TRANSFER_BT_470_6_M:
10094             aspects->mTransfer = ColorAspects::TransferGamma22;
10095             break;
10096         case MSM_VIDC_TRANSFER_BT_470_6_BG:
10097             aspects->mTransfer = ColorAspects::TransferGamma28;
10098             break;
10099         case MSM_VIDC_TRANSFER_SMPTE_240M:
10100             aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10101             break;
10102         case MSM_VIDC_TRANSFER_LINEAR:
10103             aspects->mTransfer = ColorAspects::TransferLinear;
10104             break;
10105         case MSM_VIDC_TRANSFER_IEC_61966:
10106             aspects->mTransfer = ColorAspects::TransferXvYCC;
10107             break;
10108         case MSM_VIDC_TRANSFER_BT_1361:
10109             aspects->mTransfer = ColorAspects::TransferBT1361;
10110             break;
10111         case MSM_VIDC_TRANSFER_SRGB:
10112             aspects->mTransfer = ColorAspects::TransferSRGB;
10113             break;
10114         default:
10115             //aspects->mTransfer = ColorAspects::TransferOther;
10116             aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10117             break;
10118     }
10119 
10120     switch (matrix) {
10121         case MSM_VIDC_MATRIX_BT_709_5:
10122             aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10123             break;
10124         case MSM_VIDC_MATRIX_FCC_47:
10125             aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10126             break;
10127         case MSM_VIDC_MATRIX_601_6_625:
10128         case MSM_VIDC_MATRIX_601_6_525:
10129             aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10130             break;
10131         case MSM_VIDC_MATRIX_SMPTE_240M:
10132             aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10133             break;
10134         case MSM_VIDC_MATRIX_BT_2020:
10135             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10136             break;
10137         case MSM_VIDC_MATRIX_BT_2020_CONST:
10138             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10139             break;
10140         default:
10141             //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10142             aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10143             break;
10144     }
10145 }
10146 
print_debug_color_aspects(ColorAspects * aspects,const char * prefix)10147 void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
10148         DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
10149                 prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
10150 }
10151 
handle_color_space_info(void * data,unsigned int buf_index)10152 void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
10153 {
10154     ColorSpace_t color_space = ITU_R_601;
10155     ColorAspects tempAspects;
10156     memset(&tempAspects, 0x0, sizeof(ColorAspects));
10157     ColorAspects *aspects = &tempAspects;
10158 
10159     switch(output_capability) {
10160         case V4L2_PIX_FMT_MPEG2:
10161             {
10162                 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10163                 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10164 
10165                 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10166                  * understand this code */
10167 
10168                 if (seqdisp_payload && seqdisp_payload->color_descp) {
10169 
10170                     convert_color_space_info(seqdisp_payload->color_primaries, 1,
10171                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10172                             &color_space,aspects);
10173                     m_disp_hor_size = seqdisp_payload->disp_width;
10174                     m_disp_vert_size = seqdisp_payload->disp_height;
10175                 }
10176             }
10177             break;
10178         case V4L2_PIX_FMT_H264:
10179         case V4L2_PIX_FMT_HEVC:
10180             {
10181                 struct msm_vidc_vui_display_info_payload *display_info_payload;
10182                 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10183 
10184                 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10185 
10186                 if (display_info_payload->video_signal_present_flag &&
10187                         display_info_payload->color_description_present_flag) {
10188                     convert_color_space_info(display_info_payload->color_primaries,
10189                             display_info_payload->video_full_range_flag,
10190                             display_info_payload->transfer_characteristics,
10191                             display_info_payload->matrix_coefficients,
10192                             &color_space,aspects);
10193                 }
10194             }
10195             break;
10196         case V4L2_PIX_FMT_VC1_ANNEX_G:
10197         case V4L2_PIX_FMT_VC1_ANNEX_L:
10198             {
10199                 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
10200                 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
10201 
10202                 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
10203                  * SMPTE 421M to understand this code */
10204 
10205                 if (m_enable_android_native_buffers &&
10206                         vc1_seq_disp_payload->color_primaries) {
10207 
10208                     convert_color_space_info(vc1_seq_disp_payload->color_primaries,
10209                             1,
10210                             vc1_seq_disp_payload->transfer_char,
10211                             vc1_seq_disp_payload->matrix_coeffs,
10212                             &color_space,aspects);
10213                 }
10214             }
10215             break;
10216         case V4L2_PIX_FMT_VP8:
10217             {
10218                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10219                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10220 
10221                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10222                  * to understand this code */
10223 
10224                 if (vpx_color_space_payload->color_space == 0) {
10225                     color_space = ITU_R_601;
10226                 } else {
10227                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10228                     break;
10229                 }
10230             }
10231             break;
10232         case V4L2_PIX_FMT_VP9:
10233             {
10234                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10235                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10236 
10237                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10238                  * to understand this code */
10239 
10240                 switch(vpx_color_space_payload->color_space) {
10241                     case MSM_VIDC_CS_BT_601:
10242                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10243                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10244                         aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10245                         aspects->mRange = m_client_color_space.sAspects.mRange;
10246                         break;
10247                     case MSM_VIDC_CS_BT_709:
10248                         color_space = ITU_R_709;
10249                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10250                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10251                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
10252                         aspects->mRange = m_client_color_space.sAspects.mRange;
10253                         break;
10254                     case MSM_VIDC_CS_SMPTE_170:
10255                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10256                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10257                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10258                         aspects->mRange = m_client_color_space.sAspects.mRange;
10259                         break;
10260                     case MSM_VIDC_CS_SMPTE_240:
10261                         aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10262                         aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10263                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10264                         aspects->mRange = m_client_color_space.sAspects.mRange;
10265                         break;
10266                     case MSM_VIDC_CS_BT_2020:
10267                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10268                         aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
10269                         aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10270                         aspects->mRange = m_client_color_space.sAspects.mRange;
10271                         break;
10272                     case MSM_VIDC_CS_RESERVED:
10273                         aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10274                         aspects->mTransfer = ColorAspects::TransferOther;
10275                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10276                         aspects->mRange = m_client_color_space.sAspects.mRange;
10277                         break;
10278                     case MSM_VIDC_CS_RGB:
10279                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10280                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10281                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10282                         aspects->mRange = m_client_color_space.sAspects.mRange;
10283                         break;
10284                     default:
10285                         break;
10286                 }
10287             }
10288             break;
10289         default:
10290             break;
10291     }
10292     if (m_enable_android_native_buffers) {
10293         DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
10294         set_colorspace_in_handle(color_space, buf_index);
10295     }
10296     print_debug_color_aspects(aspects, "Bitstream");
10297 
10298     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
10299             m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
10300             m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
10301             m_internal_color_space.sAspects.mRange != aspects->mRange) {
10302         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
10303         m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
10304 
10305         DEBUG_PRINT_HIGH("Initiating PORT Reconfig");
10306         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
10307         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
10308 
10309         post_event(OMX_CORE_OUTPUT_PORT_INDEX,
10310                 OMX_QTIIndexConfigDescribeColorAspects,
10311                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
10312     }
10313 }
10314 
set_colorspace_in_handle(ColorSpace_t color_space,unsigned int buf_index)10315 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
10316     private_handle_t *private_handle = NULL;
10317     if (buf_index < drv_ctx.op_buf.actualcount &&
10318             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
10319             native_buffer[buf_index].privatehandle) {
10320         private_handle = native_buffer[buf_index].privatehandle;
10321     }
10322     if (private_handle) {
10323         setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
10324     }
10325 }
10326 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)10327 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
10328 {
10329     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
10330     OMX_U32 num_conceal_MB = 0;
10331     OMX_TICKS time_stamp = 0;
10332     OMX_U32 frame_rate = 0;
10333     unsigned long consumed_len = 0;
10334     OMX_U32 num_MB_in_frame;
10335     OMX_U32 recovery_sei_flags = 1;
10336     int enable = 0;
10337 
10338     int buf_index = p_buf_hdr - m_out_mem_ptr;
10339     if (buf_index >= drv_ctx.extradata_info.count) {
10340         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
10341                 buf_index, drv_ctx.extradata_info.count);
10342         return;
10343     }
10344     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
10345 
10346     if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
10347         DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
10348         return;
10349     }
10350 
10351     OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
10352         p_buf_hdr->nOffset;
10353 
10354     if (!drv_ctx.extradata_info.uaddr) {
10355         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
10356         return;
10357     }
10358     if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
10359         DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
10360         p_extra = NULL;
10361         return;
10362     }
10363     if (!secure_mode)
10364         p_extra = (OMX_OTHER_EXTRADATATYPE *)
10365             ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
10366     else
10367         p_extra = m_other_extradata;
10368     char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
10369 
10370     if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10371         p_extra = NULL;
10372         DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10373         return;
10374     }
10375     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
10376     if (data && p_extra) {
10377         while ((consumed_len < drv_ctx.extradata_info.buffer_size)
10378                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
10379             if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
10380                 DEBUG_PRINT_LOW("Invalid extra data size");
10381                 break;
10382             }
10383 
10384             if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10385                 p_extra = NULL;
10386                 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10387                 return;
10388             }
10389 
10390             DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
10391             switch ((unsigned long)data->eType) {
10392                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
10393                     struct msm_vidc_interlace_payload *payload;
10394                     OMX_U32 interlace_color_format;
10395                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
10396                     if (payload) {
10397                         enable = 1;
10398                         switch (payload->format) {
10399                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
10400                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10401                                 enable = 0;
10402                                 break;
10403                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
10404                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10405                                 break;
10406                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
10407                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
10408                                 break;
10409                             default:
10410                                 DEBUG_PRINT_LOW("default case - set interlace to topfield");
10411                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10412                         }
10413                         switch (payload->color_format) {
10414                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
10415                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10416                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
10417                                break;
10418                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
10419                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
10420                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
10421                                break;
10422                            default:
10423                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10424                                DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
10425                         }
10426                     }
10427 
10428                     if (m_enable_android_native_buffers) {
10429                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
10430                                          payload->format, interlace_color_format ,enable,
10431                                         (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
10432 
10433                         setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10434                                PP_PARAM_INTERLACED, (void*)&enable);
10435 
10436                         if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
10437                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10438                                LINEAR_FORMAT, (void*)&interlace_color_format);
10439                         }
10440                     }
10441                     if (client_extradata & OMX_INTERLACE_EXTRADATA) {
10442                         append_interlace_extradata(p_extra, payload->format,
10443                                       p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF);
10444                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10445                     }
10446                     break;
10447                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
10448                     struct msm_vidc_framerate_payload *frame_rate_payload;
10449                     frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
10450                     frame_rate = frame_rate_payload->frame_rate;
10451                     break;
10452                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
10453                     struct msm_vidc_ts_payload *time_stamp_payload;
10454                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
10455                     time_stamp = time_stamp_payload->timestamp_lo;
10456                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
10457                     p_buf_hdr->nTimeStamp = time_stamp;
10458                     break;
10459                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
10460                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
10461                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
10462                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10463                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10464                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
10465                     break;
10466                 case MSM_VIDC_EXTRADATA_INDEX:
10467                     int *etype;
10468                     etype  = (int *)(void *)data->data;
10469                     if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
10470                         struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
10471                         aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
10472                         if (aspect_ratio_payload) {
10473                             ((struct vdec_output_frameinfo *)
10474                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
10475                             ((struct vdec_output_frameinfo *)
10476                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
10477                         }
10478                     }
10479                     break;
10480                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
10481                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
10482                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
10483                     recovery_sei_flags = recovery_sei_payload->flags;
10484                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
10485                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
10486                         DEBUG_PRINT_HIGH("***************************************************");
10487                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
10488                         DEBUG_PRINT_HIGH("***************************************************");
10489                     }
10490                     break;
10491                case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
10492                     panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
10493                     if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
10494                         DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
10495                         DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
10496                             MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
10497                         return;
10498                     }
10499                     break;
10500                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
10501                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
10502                 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
10503                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
10504                         handle_color_space_info((void *)data->data, buf_index);
10505                     break;
10506                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
10507                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
10508                     s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
10509                     if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
10510                         append_framepack_extradata(p_extra, s3d_frame_packing_payload);
10511                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10512                     }
10513                     break;
10514                 case MSM_VIDC_EXTRADATA_FRAME_QP:
10515                     struct msm_vidc_frame_qp_payload *qp_payload;
10516                     qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
10517                     if (client_extradata & OMX_QP_EXTRADATA) {
10518                         append_qp_extradata(p_extra, qp_payload);
10519                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10520                     }
10521                     break;
10522                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
10523                     struct msm_vidc_frame_bits_info_payload *bits_info_payload;
10524                     bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
10525                     if (client_extradata & OMX_BITSINFO_EXTRADATA) {
10526                         append_bitsinfo_extradata(p_extra, bits_info_payload);
10527                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10528                     }
10529                     break;
10530                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
10531                     if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
10532                         append_user_extradata(p_extra, data);
10533                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10534                     }
10535                     break;
10536                 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
10537                     struct msm_vidc_vqzip_sei_payload *vqzip_payload;
10538                     vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
10539                     if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
10540                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10541                         append_vqzip_extradata(p_extra, vqzip_payload);
10542                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10543                     }
10544                     break;
10545                 default:
10546                     DEBUG_PRINT_LOW("Unrecognized extradata");
10547                     goto unrecognized_extradata;
10548             }
10549             consumed_len += data->nSize;
10550             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
10551         }
10552         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
10553             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10554             append_frame_info_extradata(p_extra,
10555                     num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10556                     time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10557                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10558             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10559         }
10560         if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
10561             append_frame_dimension_extradata(p_extra);
10562             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10563         }
10564     }
10565 unrecognized_extradata:
10566     if (client_extradata && p_extra) {
10567         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10568         append_terminator_extradata(p_extra);
10569     }
10570     if (secure_mode && p_extradata && m_other_extradata) {
10571         struct vdec_output_frameinfo  *ptr_extradatabuff = NULL;
10572         memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
10573         ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
10574         ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
10575         ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
10576     }
10577     return;
10578 }
10579 
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)10580 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
10581         bool is_internal, bool enable)
10582 {
10583     OMX_ERRORTYPE ret = OMX_ErrorNone;
10584     struct v4l2_control control;
10585     if (m_state != OMX_StateLoaded) {
10586         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
10587         return OMX_ErrorIncorrectStateOperation;
10588     }
10589     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
10590             (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
10591 
10592     if (!is_internal) {
10593         if (enable)
10594             client_extradata |= requested_extradata;
10595         else
10596             client_extradata = client_extradata & ~requested_extradata;
10597     }
10598 
10599     if (enable) {
10600         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
10601             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10602             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
10603             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10604                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
10605                         " Quality of interlaced clips might be impacted.");
10606             }
10607         }
10608         if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
10609             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10610             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
10611             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10612                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
10613             }
10614             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10615             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
10616             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10617                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
10618             }
10619             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10620             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
10621             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10622                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
10623             }
10624             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10625             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
10626             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10627                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10628             }
10629             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10630             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
10631             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10632                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10633             }
10634             if (output_capability == V4L2_PIX_FMT_MPEG2) {
10635                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10636                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10637                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10638                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10639                 }
10640             }
10641         }
10642         if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
10643             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10644             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
10645             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10646                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
10647             }
10648         }
10649         if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
10650             if (output_capability == V4L2_PIX_FMT_H264) {
10651                 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
10652                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10653                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
10654                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10655                     DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
10656                 }
10657             } else {
10658                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
10659             }
10660         }
10661         if (requested_extradata & OMX_QP_EXTRADATA) {
10662             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10663             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10664             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10665                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10666             }
10667         }
10668         if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
10669             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10670             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
10671             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10672                 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
10673             }
10674         }
10675         if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
10676             if (secure_mode) {
10677                 DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions");
10678                 return OMX_ErrorUnsupportedSetting;
10679             }
10680             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10681             control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
10682             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10683                 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
10684             }
10685         }
10686         if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
10687             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10688             control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
10689             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10690                 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
10691             }
10692             client_extradata |= OMX_VQZIPSEI_EXTRADATA;
10693 
10694             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10695             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10696             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10697                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10698             }
10699             client_extradata |= OMX_QP_EXTRADATA;
10700         }
10701         if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
10702             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10703             switch(output_capability) {
10704                 case V4L2_PIX_FMT_H264:
10705                 case V4L2_PIX_FMT_HEVC:
10706                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
10707                     break;
10708                 case CODEC_TYPE_MPEG2:
10709                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10710                     break;
10711                 case V4L2_PIX_FMT_VP8:
10712                 case V4L2_PIX_FMT_VP9:
10713                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
10714                     break;
10715                 case V4L2_PIX_FMT_VC1_ANNEX_G:
10716                 case V4L2_PIX_FMT_VC1_ANNEX_L:
10717                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
10718                     break;
10719                 default:
10720                     DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
10721                     return ret;
10722             }
10723 
10724             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10725                 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
10726             }
10727         }
10728     }
10729     ret = get_buffer_req(&drv_ctx.op_buf);
10730     return ret;
10731 }
10732 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)10733 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10734 {
10735     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
10736     OMX_U8 *data_ptr = extra->data, data = 0;
10737     while (byte_count < extra->nDataSize) {
10738         data = *data_ptr;
10739         while (data) {
10740             num_MB += (data&0x01);
10741             data >>= 1;
10742         }
10743         data_ptr++;
10744         byte_count++;
10745     }
10746     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10747             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10748     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
10749 }
10750 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)10751 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10752 {
10753     if (!m_debug_extradata || !extra)
10754         return;
10755 
10756 
10757     DEBUG_PRINT_HIGH(
10758             "============== Extra Data ==============\n"
10759             "           Size: %u\n"
10760             "        Version: %u\n"
10761             "      PortIndex: %u\n"
10762             "           Type: %x\n"
10763             "       DataSize: %u",
10764             (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
10765             (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
10766 
10767     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
10768         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10769         DEBUG_PRINT_HIGH(
10770                 "------ Interlace Format ------\n"
10771                 "                Size: %u\n"
10772                 "             Version: %u\n"
10773                 "           PortIndex: %u\n"
10774                 " Is Interlace Format: %d\n"
10775                 "   Interlace Formats: %u\n"
10776                 "=========== End of Interlace ===========",
10777                 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
10778                 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
10779     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
10780         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10781 
10782         DEBUG_PRINT_HIGH(
10783                 "-------- Frame Format --------\n"
10784                 "             Picture Type: %d\n"
10785                 "           Interlace Type: %d\n"
10786                 " Pan Scan Total Frame Num: %u\n"
10787                 "   Concealed Macro Blocks: %u\n"
10788                 "               frame rate: %u\n"
10789                 "               Time Stamp: %llu\n"
10790                 "           Aspect Ratio X: %u\n"
10791                 "           Aspect Ratio Y: %u",
10792                 fminfo->ePicType,
10793                 fminfo->interlaceType,
10794                 (unsigned int)fminfo->panScan.numWindows,
10795                 (unsigned int)fminfo->nConcealedMacroblocks,
10796                 (unsigned int)fminfo->nFrameRate,
10797                 fminfo->nTimeStamp,
10798                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
10799                 (unsigned int)fminfo->aspectRatio.aspectRatioY);
10800 
10801         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
10802             DEBUG_PRINT_HIGH(
10803                     "------------------------------"
10804                     "     Pan Scan Frame Num: %u\n"
10805                     "            Rectangle x: %d\n"
10806                     "            Rectangle y: %d\n"
10807                     "           Rectangle dx: %d\n"
10808                     "           Rectangle dy: %d",
10809                     (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
10810                     (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
10811         }
10812 
10813         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
10814     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
10815         OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10816         DEBUG_PRINT_HIGH(
10817                 "------------------ Framepack Format ----------\n"
10818                 "                           id: %u \n"
10819                 "                  cancel_flag: %u \n"
10820                 "                         type: %u \n"
10821                 " quincunx_sampling_flagFormat: %u \n"
10822                 "  content_interpretation_type: %u \n"
10823                 "        spatial_flipping_flag: %u \n"
10824                 "          frame0_flipped_flag: %u \n"
10825                 "             field_views_flag: %u \n"
10826                 " current_frame_is_frame0_flag: %u \n"
10827                 "   frame0_self_contained_flag: %u \n"
10828                 "   frame1_self_contained_flag: %u \n"
10829                 "       frame0_grid_position_x: %u \n"
10830                 "       frame0_grid_position_y: %u \n"
10831                 "       frame1_grid_position_x: %u \n"
10832                 "       frame1_grid_position_y: %u \n"
10833                 "                reserved_byte: %u \n"
10834                 "            repetition_period: %u \n"
10835                 "               extension_flag: %u \n"
10836                 "================== End of Framepack ===========",
10837                 (unsigned int)framepack->id,
10838                 (unsigned int)framepack->cancel_flag,
10839                 (unsigned int)framepack->type,
10840                 (unsigned int)framepack->quincunx_sampling_flag,
10841                 (unsigned int)framepack->content_interpretation_type,
10842                 (unsigned int)framepack->spatial_flipping_flag,
10843                 (unsigned int)framepack->frame0_flipped_flag,
10844                 (unsigned int)framepack->field_views_flag,
10845                 (unsigned int)framepack->current_frame_is_frame0_flag,
10846                 (unsigned int)framepack->frame0_self_contained_flag,
10847                 (unsigned int)framepack->frame1_self_contained_flag,
10848                 (unsigned int)framepack->frame0_grid_position_x,
10849                 (unsigned int)framepack->frame0_grid_position_y,
10850                 (unsigned int)framepack->frame1_grid_position_x,
10851                 (unsigned int)framepack->frame1_grid_position_y,
10852                 (unsigned int)framepack->reserved_byte,
10853                 (unsigned int)framepack->repetition_period,
10854                 (unsigned int)framepack->extension_flag);
10855     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
10856         OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
10857         DEBUG_PRINT_HIGH(
10858                 "---- QP (Frame quantization parameter) ----\n"
10859                 "    Frame QP: %u \n"
10860                 "================ End of QP ================\n",
10861                 (unsigned int)qp->nQP);
10862     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
10863         OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
10864         DEBUG_PRINT_HIGH(
10865                 "--------- Input bits information --------\n"
10866                 "    Header bits: %u \n"
10867                 "     Frame bits: %u \n"
10868                 "===== End of Input bits information =====\n",
10869                 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
10870     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
10871         OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
10872         OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
10873         OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
10874         OMX_U32 i = 0;
10875         DEBUG_PRINT_HIGH(
10876                 "--------------  Userdata  -------------\n"
10877                 "    Stream userdata type: %u\n"
10878                 "          userdata size: %u\n"
10879                 "    STREAM_USERDATA:",
10880                 (unsigned int)userdata->type, (unsigned int)userdata_size);
10881                 for (i = 0; i < userdata_size; i+=4) {
10882                     DEBUG_PRINT_HIGH("        %x %x %x %x",
10883                         data_ptr[i], data_ptr[i+1],
10884                         data_ptr[i+2], data_ptr[i+3]);
10885                 }
10886         DEBUG_PRINT_HIGH(
10887                 "=========== End of Userdata ===========");
10888     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
10889         OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
10890         DEBUG_PRINT_HIGH(
10891                 "--------------  VQZip  -------------\n"
10892                 "    Size: %u\n",
10893                 (unsigned int)vq->nSize);
10894         DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
10895     } else if (extra->eType == OMX_ExtraDataNone) {
10896         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
10897     } else {
10898         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
10899     }
10900 }
10901 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type,bool is_mbaff)10902 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10903         OMX_U32 interlaced_format_type, bool is_mbaff)
10904 {
10905     OMX_STREAMINTERLACEFORMAT *interlace_format;
10906 
10907     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
10908         return;
10909     }
10910     if (!extra) {
10911        DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
10912        return;
10913     }
10914     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
10915     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10916     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10917     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
10918     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10919     interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10920     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10921     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
10922     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10923 
10924     if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) {
10925         interlace_format->bInterlaceFormat = OMX_FALSE;
10926         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
10927         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10928     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) {
10929         interlace_format->bInterlaceFormat = OMX_TRUE;
10930         interlace_format->nInterlaceFormats =  OMX_InterlaceInterleaveFrameTopFieldFirst;
10931         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10932     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) {
10933         interlace_format->bInterlaceFormat = OMX_TRUE;
10934         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
10935         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10936     } else {
10937         interlace_format->bInterlaceFormat = OMX_TRUE;
10938         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
10939         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10940     }
10941     print_debug_extradata(extra);
10942 }
10943 
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)10944 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10945 {
10946     OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
10947     if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
10948         return;
10949     }
10950     extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
10951     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10952     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10953     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
10954     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
10955     frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
10956     frame_dimension->nDecWidth = rectangle.nLeft;
10957     frame_dimension->nDecHeight = rectangle.nTop;
10958     frame_dimension->nActualWidth = rectangle.nWidth;
10959     frame_dimension->nActualHeight = rectangle.nHeight;
10960 }
10961 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)10962 void omx_vdec::fill_aspect_ratio_info(
10963         struct vdec_aspectratioinfo *aspect_ratio_info,
10964         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
10965 {
10966     m_extradata = frame_info;
10967     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
10968     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
10969     DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
10970             (unsigned int)m_extradata->aspectRatio.aspectRatioY);
10971 }
10972 
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 picture_type,OMX_U32 frame_rate,OMX_TICKS time_stamp,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)10973 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10974         OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
10975         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
10976         struct vdec_aspectratioinfo *aspect_ratio_info)
10977 {
10978     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
10979     struct msm_vidc_panscan_window *panscan_window;
10980     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
10981         return;
10982     }
10983     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
10984     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10985     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10986     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
10987     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
10988     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10989     switch (picture_type) {
10990         case PICTURE_TYPE_I:
10991             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
10992             break;
10993         case PICTURE_TYPE_P:
10994             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
10995             break;
10996         case PICTURE_TYPE_B:
10997             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
10998             break;
10999         default:
11000             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
11001     }
11002     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
11003         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
11004     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
11005         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
11006     else
11007         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
11008     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
11009     frame_info->nConcealedMacroblocks = num_conceal_mb;
11010     frame_info->nFrameRate = frame_rate;
11011     frame_info->nTimeStamp = time_stamp;
11012     frame_info->panScan.numWindows = 0;
11013     if (output_capability == V4L2_PIX_FMT_MPEG2) {
11014         if (m_disp_hor_size && m_disp_vert_size) {
11015             frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
11016             frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
11017         } else {
11018             frame_info->displayAspectRatio.displayHorizontalSize = 0;
11019             frame_info->displayAspectRatio.displayVerticalSize = 0;
11020         }
11021     }
11022 
11023     if (panscan_payload) {
11024         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
11025         panscan_window = &panscan_payload->wnd[0];
11026         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
11027             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
11028             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
11029             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
11030             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
11031             panscan_window++;
11032         }
11033     }
11034     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
11035     print_debug_extradata(extra);
11036 }
11037 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)11038 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11039 {
11040     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
11041     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
11042     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11043     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11044     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
11045     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
11046     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
11047     *portDefn = m_port_def;
11048     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
11049             "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
11050             (unsigned int)portDefn->format.video.nFrameWidth,
11051             (unsigned int)portDefn->format.video.nStride,
11052             (unsigned int)portDefn->format.video.nSliceHeight);
11053 }
11054 
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)11055 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11056         struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
11057 {
11058     OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
11059     if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
11060         DEBUG_PRINT_ERROR("frame packing size mismatch");
11061         return;
11062     }
11063     extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
11064     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11065     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11066     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
11067     extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11068     framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11069     framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11070     framepack->nVersion.nVersion = OMX_SPEC_VERSION;
11071     framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11072     memcpy(&framepack->id, s3d_frame_packing_payload,
11073         sizeof(struct msm_vidc_s3d_frame_packing_payload));
11074     memcpy(&m_frame_pack_arrangement, framepack,
11075         sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
11076     print_debug_extradata(extra);
11077 }
11078 
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)11079 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11080             struct msm_vidc_frame_qp_payload *qp_payload)
11081 {
11082     OMX_QCOM_EXTRADATA_QP * qp = NULL;
11083     if (!qp_payload) {
11084         DEBUG_PRINT_ERROR("QP payload is NULL");
11085         return;
11086     }
11087     extra->nSize = OMX_QP_EXTRADATA_SIZE;
11088     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11089     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11090     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
11091     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
11092     qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11093     qp->nQP = qp_payload->frame_qp;
11094     print_debug_extradata(extra);
11095 }
11096 
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)11097 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11098             struct msm_vidc_frame_bits_info_payload *bits_payload)
11099 {
11100     OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
11101     if (!bits_payload) {
11102         DEBUG_PRINT_ERROR("bits info payload is NULL");
11103         return;
11104     }
11105     extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
11106     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11107     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11108     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
11109     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
11110     bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
11111     bits->frame_bits = bits_payload->frame_bits;
11112     bits->header_bits = bits_payload->header_bits;
11113     print_debug_extradata(extra);
11114 }
11115 
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)11116 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11117             OMX_OTHER_EXTRADATATYPE *p_user)
11118 {
11119     int userdata_size = 0;
11120     struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
11121     userdata_payload =
11122         (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
11123     userdata_size = p_user->nDataSize;
11124     extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
11125     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11126     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11127     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
11128     extra->nDataSize = userdata_size;
11129     if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
11130         memcpy(extra->data, p_user->data, extra->nDataSize);
11131     print_debug_extradata(extra);
11132 }
11133 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)11134 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11135 {
11136     if (!client_extradata) {
11137         return;
11138     }
11139     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
11140     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11141     extra->eType = OMX_ExtraDataNone;
11142     extra->nDataSize = 0;
11143     extra->data[0] = 0;
11144 
11145     print_debug_extradata(extra);
11146 }
11147 
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)11148 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11149         struct msm_vidc_vqzip_sei_payload *vqzip_payload)
11150 {
11151     OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
11152 
11153     extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
11154     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11155     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11156     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
11157     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
11158 
11159     vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11160     vq->nSize = vqzip_payload->size;
11161     memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
11162 
11163     print_debug_extradata(extra);
11164 }
11165 
allocate_desc_buffer(OMX_U32 index)11166 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
11167 {
11168     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11169     if (index >= drv_ctx.ip_buf.actualcount) {
11170         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
11171         return OMX_ErrorInsufficientResources;
11172     }
11173     if (m_desc_buffer_ptr == NULL) {
11174         m_desc_buffer_ptr = (desc_buffer_hdr*) \
11175                     calloc( (sizeof(desc_buffer_hdr)),
11176                             drv_ctx.ip_buf.actualcount);
11177         if (m_desc_buffer_ptr == NULL) {
11178             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
11179             return OMX_ErrorInsufficientResources;
11180         }
11181     }
11182 
11183     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
11184     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
11185         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
11186         return OMX_ErrorInsufficientResources;
11187     }
11188 
11189     return eRet;
11190 }
11191 
insert_demux_addr_offset(OMX_U32 address_offset)11192 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
11193 {
11194     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
11195     if (m_demux_entries < 8192) {
11196         m_demux_offsets[m_demux_entries++] = address_offset;
11197     }
11198     return;
11199 }
11200 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)11201 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
11202 {
11203     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
11204     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
11205     OMX_U32 index = 0;
11206 
11207     m_demux_entries = 0;
11208 
11209     while (index < bytes_to_parse) {
11210         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11211                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
11212                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11213                  (buf[index+2] == 0x01)) ) {
11214             //Found start code, insert address offset
11215             insert_demux_addr_offset(index);
11216             if (buf[index+2] == 0x01) // 3 byte start code
11217                 index += 3;
11218             else                      //4 byte start code
11219                 index += 4;
11220         } else
11221             index++;
11222     }
11223     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
11224     return;
11225 }
11226 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)11227 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11228 {
11229     //fix this, handle 3 byte start code, vc1 terminator entry
11230     OMX_U8 *p_demux_data = NULL;
11231     OMX_U32 desc_data = 0;
11232     OMX_U32 start_addr = 0;
11233     OMX_U32 nal_size = 0;
11234     OMX_U32 suffix_byte = 0;
11235     OMX_U32 demux_index = 0;
11236     OMX_U32 buffer_index = 0;
11237 
11238     if (m_desc_buffer_ptr == NULL) {
11239         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
11240         return OMX_ErrorBadParameter;
11241     }
11242 
11243     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
11244     if (buffer_index > drv_ctx.ip_buf.actualcount) {
11245         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
11246         return OMX_ErrorBadParameter;
11247     }
11248 
11249     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
11250 
11251     if ( ((OMX_U8*)p_demux_data == NULL) ||
11252             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
11253         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
11254         return OMX_ErrorBadParameter;
11255     } else {
11256         for (; demux_index < m_demux_entries; demux_index++) {
11257             desc_data = 0;
11258             start_addr = m_demux_offsets[demux_index];
11259             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
11260                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
11261             } else {
11262                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
11263             }
11264             if (demux_index < (m_demux_entries - 1)) {
11265                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
11266             } else {
11267                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
11268             }
11269             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
11270                     (unsigned int)start_addr,
11271                     (unsigned int)suffix_byte,
11272                     (unsigned int)nal_size,
11273                     (unsigned int)demux_index);
11274             desc_data = (start_addr >> 3) << 1;
11275             desc_data |= (start_addr & 7) << 21;
11276             desc_data |= suffix_byte << 24;
11277 
11278             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11279             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
11280             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11281             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11282 
11283             p_demux_data += 16;
11284         }
11285         if (codec_type_parse == CODEC_TYPE_VC1) {
11286             DEBUG_PRINT_LOW("VC1 terminator entry");
11287             desc_data = 0;
11288             desc_data = 0x82 << 24;
11289             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11290             memset(p_demux_data + 4, 0, sizeof(OMX_U32));
11291             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11292             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11293             p_demux_data += 16;
11294             m_demux_entries++;
11295         }
11296         //Add zero word to indicate end of descriptors
11297         memset(p_demux_data, 0, sizeof(OMX_U32));
11298 
11299         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
11300         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
11301     }
11302     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
11303     m_demux_entries = 0;
11304     DEBUG_PRINT_LOW("Demux table complete!");
11305     return OMX_ErrorNone;
11306 }
11307 
request_perf_level(enum vidc_perf_level perf_level)11308 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
11309 {
11310     struct v4l2_control control;
11311     char property_value[PROPERTY_VALUE_MAX] = {0};
11312 
11313     property_get("vidc.debug.turbo", property_value, "0");
11314     memset(&control, 0, sizeof(v4l2_control));
11315     control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
11316     switch (perf_level) {
11317     case VIDC_NOMINAL:
11318         if (atoi(property_value))
11319             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11320         else
11321             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
11322         break;
11323     case VIDC_TURBO:
11324         control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11325         break;
11326      default:
11327         DEBUG_PRINT_ERROR("Requested PERF level not supported");
11328         break;
11329     }
11330     if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
11331         return;
11332 
11333     DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
11334     if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11335         current_perf_level = control.value;
11336     } else {
11337         DEBUG_PRINT_ERROR("Failed to set PERF level");
11338     }
11339 }
11340 
allocate_color_convert_buf()11341 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
11342 {
11343     enabled = false;
11344     omx = NULL;
11345     init_members();
11346     ColorFormat = OMX_COLOR_FormatMax;
11347     dest_format = YCbCr420P;
11348 }
11349 
set_vdec_client(void * client)11350 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
11351 {
11352     omx = reinterpret_cast<omx_vdec*>(client);
11353 }
11354 
init_members()11355 void omx_vdec::allocate_color_convert_buf::init_members()
11356 {
11357     allocated_count = 0;
11358     buffer_size_req = 0;
11359     buffer_alignment_req = 0;
11360     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
11361     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
11362     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
11363     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
11364 #ifdef USE_ION
11365     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
11366 #endif
11367     for (int i = 0; i < MAX_COUNT; i++)
11368         pmem_fd[i] = -1;
11369 }
11370 
~allocate_color_convert_buf()11371 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
11372 {
11373     c2d.destroy();
11374 }
11375 
update_buffer_req()11376 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
11377 {
11378     bool status = true;
11379     unsigned int src_size = 0, destination_size = 0;
11380     OMX_COLOR_FORMATTYPE drv_color_format;
11381     if (!omx) {
11382         DEBUG_PRINT_ERROR("Invalid client in color convert");
11383         return false;
11384     }
11385     if (!enabled) {
11386         DEBUG_PRINT_HIGH("No color conversion required");
11387         return status;
11388     }
11389     pthread_mutex_lock(&omx->c_lock);
11390     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
11391             ColorFormat != OMX_COLOR_FormatYUV420Planar) {
11392         DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
11393         status = false;
11394         goto fail_update_buf_req;
11395     }
11396     c2d.close();
11397     status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
11398             omx->drv_ctx.video_resolution.frame_width,
11399             NV12_128m,dest_format);
11400     if (status) {
11401         status = c2d.get_buffer_size(C2D_INPUT,src_size);
11402         if (status)
11403             status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
11404     }
11405     if (status) {
11406         if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
11407                 !destination_size) {
11408             DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
11409                     "driver size %u destination size %d",
11410                     src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
11411                     destination_size);
11412             status = false;
11413             c2d.close();
11414             buffer_size_req = 0;
11415         } else {
11416             buffer_size_req = destination_size;
11417             if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
11418                 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
11419             if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11420                 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11421         }
11422     }
11423 fail_update_buf_req:
11424     pthread_mutex_unlock(&omx->c_lock);
11425     return status;
11426 }
11427 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)11428 bool omx_vdec::allocate_color_convert_buf::set_color_format(
11429         OMX_COLOR_FORMATTYPE dest_color_format)
11430 {
11431     bool status = true;
11432     OMX_COLOR_FORMATTYPE drv_color_format;
11433     if (!omx) {
11434         DEBUG_PRINT_ERROR("Invalid client in color convert");
11435         return false;
11436     }
11437     pthread_mutex_lock(&omx->c_lock);
11438     if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
11439         if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11440             drv_color_format = (OMX_COLOR_FORMATTYPE)
11441                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11442         else
11443             drv_color_format = (OMX_COLOR_FORMATTYPE)
11444                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11445      else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
11446          drv_color_format = (OMX_COLOR_FORMATTYPE)
11447                   QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11448      } else {
11449         DEBUG_PRINT_ERROR("Incorrect color format");
11450         status = false;
11451     }
11452     if (status &&
11453         drv_color_format != dest_color_format &&
11454         drv_color_format != (OMX_COLOR_FORMATTYPE)
11455                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView &&
11456         drv_color_format != (OMX_COLOR_FORMATTYPE)
11457                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed &&
11458         dest_color_format != (OMX_COLOR_FORMATTYPE)
11459                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11460         DEBUG_PRINT_LOW("Enabling C2D");
11461         if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
11462            (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
11463             DEBUG_PRINT_ERROR("Unsupported color format for c2d");
11464             status = false;
11465         } else {
11466             ColorFormat = dest_color_format;
11467             dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
11468                     YCbCr420P : YCbCr420SP;
11469             if (enabled)
11470                 c2d.destroy();
11471             enabled = false;
11472             if (!c2d.init()) {
11473                 DEBUG_PRINT_ERROR("open failed for c2d");
11474                 status = false;
11475             } else
11476                 enabled = true;
11477         }
11478     } else {
11479         if (enabled)
11480             c2d.destroy();
11481         enabled = false;
11482     }
11483     pthread_mutex_unlock(&omx->c_lock);
11484     return status;
11485 }
11486 
get_il_buf_hdr()11487 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
11488 {
11489     if (!omx) {
11490         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11491         return NULL;
11492     }
11493     if (!enabled)
11494         return omx->m_out_mem_ptr;
11495     return m_out_mem_ptr_client;
11496 }
11497 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11498     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
11499 (OMX_BUFFERHEADERTYPE *bufadd)
11500 {
11501     if (!omx) {
11502         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11503         return NULL;
11504     }
11505     if (!enabled)
11506         return bufadd;
11507 
11508     unsigned index = 0;
11509     index = bufadd - omx->m_out_mem_ptr;
11510     if (index < omx->drv_ctx.op_buf.actualcount) {
11511         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
11512         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
11513         bool status;
11514         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
11515             pthread_mutex_lock(&omx->c_lock);
11516             cache_clean_buffer(index);
11517             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
11518                     omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
11519                     pmem_baseaddress[index], pmem_baseaddress[index]);
11520             if (!status) {
11521                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
11522                 m_out_mem_ptr_client[index].nFilledLen = 0;
11523                 pthread_mutex_unlock(&omx->c_lock);
11524                 return &m_out_mem_ptr_client[index];
11525             } else {
11526                 unsigned int filledLen = 0;
11527                 c2d.get_output_filled_length(filledLen);
11528                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
11529                 cache_clean_invalidate_buffer(index);
11530             }
11531             pthread_mutex_unlock(&omx->c_lock);
11532         } else
11533             m_out_mem_ptr_client[index].nFilledLen = 0;
11534         return &m_out_mem_ptr_client[index];
11535     }
11536     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
11537     return NULL;
11538 }
11539 
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11540     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
11541 (OMX_BUFFERHEADERTYPE *bufadd)
11542 {
11543     if (!omx) {
11544         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11545         return NULL;
11546     }
11547     if (!enabled)
11548         return bufadd;
11549     unsigned index = 0;
11550     index = bufadd - m_out_mem_ptr_client;
11551     if (index < omx->drv_ctx.op_buf.actualcount) {
11552         return &omx->m_out_mem_ptr[index];
11553     }
11554     DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
11555     return NULL;
11556 }
get_buffer_req(unsigned int & buffer_size)11557     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
11558 (unsigned int &buffer_size)
11559 {
11560     bool status = true;
11561     pthread_mutex_lock(&omx->c_lock);
11562     if (!enabled)
11563         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11564     else {
11565         if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
11566             DEBUG_PRINT_ERROR("Get buffer size failed");
11567             status = false;
11568             goto fail_get_buffer_size;
11569         }
11570     }
11571     if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
11572         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11573     if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11574         buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11575 fail_get_buffer_size:
11576     pthread_mutex_unlock(&omx->c_lock);
11577     return status;
11578 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)11579 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
11580         OMX_BUFFERHEADERTYPE *bufhdr)
11581 {
11582     unsigned int index = 0;
11583 
11584     if (!enabled)
11585         return omx->free_output_buffer(bufhdr);
11586     if (enabled && omx->is_component_secure())
11587         return OMX_ErrorNone;
11588     if (!allocated_count || !bufhdr) {
11589         DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
11590         return OMX_ErrorBadParameter;
11591     }
11592     index = bufhdr - m_out_mem_ptr_client;
11593     if (index >= omx->drv_ctx.op_buf.actualcount) {
11594         DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
11595         return OMX_ErrorBadParameter;
11596     }
11597     if (pmem_fd[index] >= 0) {
11598         munmap(pmem_baseaddress[index], buffer_size_req);
11599         close(pmem_fd[index]);
11600     }
11601     pmem_fd[index] = -1;
11602 #ifdef USE_ION
11603     omx->free_ion_memory(&op_buf_ion_info[index]);
11604 #endif
11605     m_heap_ptr[index].video_heap_ptr = NULL;
11606     if (allocated_count > 0)
11607         allocated_count--;
11608     else
11609         allocated_count = 0;
11610     if (!allocated_count) {
11611         pthread_mutex_lock(&omx->c_lock);
11612         c2d.close();
11613         init_members();
11614         pthread_mutex_unlock(&omx->c_lock);
11615     }
11616     return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
11617 }
11618 
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)11619 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
11620         OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
11621 {
11622     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11623     if (!enabled) {
11624         eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
11625         return eRet;
11626     }
11627     if (enabled && omx->is_component_secure()) {
11628         DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
11629                 omx->is_component_secure());
11630         return OMX_ErrorUnsupportedSetting;
11631     }
11632     if (!bufferHdr || bytes > buffer_size_req) {
11633         DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
11634         DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
11635                 (unsigned int)buffer_size_req, (unsigned int)bytes);
11636         return OMX_ErrorBadParameter;
11637     }
11638     if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
11639         DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
11640         return OMX_ErrorInsufficientResources;
11641     }
11642     OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
11643     eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
11644             port,appData,omx->drv_ctx.op_buf.buffer_size);
11645     if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
11646         DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
11647         return eRet;
11648     }
11649     if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
11650             (int)omx->drv_ctx.op_buf.actualcount) {
11651         DEBUG_PRINT_ERROR("Invalid header index %ld",
11652                (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
11653         return OMX_ErrorUndefined;
11654     }
11655     unsigned int i = allocated_count;
11656 #ifdef USE_ION
11657     // Allocate color-conversion buffers as cached to improve software-reading
11658     // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
11659     // cache invalidation.
11660     op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
11661             buffer_size_req,buffer_alignment_req,
11662             &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
11663             ION_FLAG_CACHED);
11664     pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
11665     if (op_buf_ion_info[i].ion_device_fd < 0) {
11666         DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
11667         return OMX_ErrorInsufficientResources;
11668     }
11669     pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
11670             PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
11671 
11672     if (pmem_baseaddress[i] == MAP_FAILED) {
11673         DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
11674         close(pmem_fd[i]);
11675         omx->free_ion_memory(&op_buf_ion_info[i]);
11676         return OMX_ErrorInsufficientResources;
11677     }
11678     m_heap_ptr[i].video_heap_ptr = new VideoHeap (
11679             op_buf_ion_info[i].ion_device_fd,buffer_size_req,
11680             pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
11681 #endif
11682     m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
11683     m_pmem_info_client[i].offset = 0;
11684     m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
11685     m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
11686     m_platform_list_client[i].nEntries = 1;
11687     m_platform_list_client[i].entryList = &m_platform_entry_client[i];
11688     m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
11689     m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
11690     m_out_mem_ptr_client[i].nFilledLen = 0;
11691     m_out_mem_ptr_client[i].nFlags = 0;
11692     m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11693     m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
11694     m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
11695     m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
11696     m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
11697     m_out_mem_ptr_client[i].pAppPrivate = appData;
11698     *bufferHdr = &m_out_mem_ptr_client[i];
11699     DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
11700     allocated_count++;
11701     return eRet;
11702 }
11703 
is_component_secure()11704 bool omx_vdec::is_component_secure()
11705 {
11706     return secure_mode;
11707 }
11708 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)11709 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
11710 {
11711     bool status = true;
11712     if (!enabled) {
11713         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
11714             if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11715                     dest_color_format = (OMX_COLOR_FORMATTYPE)
11716                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11717                 else
11718                     dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11719         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
11720              dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11721         } else
11722             status = false;
11723     } else {
11724         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
11725             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
11726             dest_color_format = ColorFormat;
11727         } else
11728             status = false;
11729     }
11730     return status;
11731 }
11732 
cache_ops(unsigned int index,unsigned int cmd)11733 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
11734         unsigned int index, unsigned int cmd)
11735 {
11736     if (!enabled) {
11737         return OMX_ErrorNone;
11738     }
11739 
11740     if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
11741         DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
11742         return OMX_ErrorBadParameter;
11743     }
11744 
11745     struct ion_flush_data flush_data;
11746     struct ion_custom_data custom_data;
11747 
11748     memset(&flush_data, 0x0, sizeof(flush_data));
11749     memset(&custom_data, 0x0, sizeof(custom_data));
11750 
11751     flush_data.vaddr = pmem_baseaddress[index];
11752     flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
11753     flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
11754     flush_data.length = buffer_size_req;
11755     custom_data.cmd = cmd;
11756     custom_data.arg = (unsigned long)&flush_data;
11757 
11758     DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
11759             (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11760             flush_data.fd, flush_data.handle, flush_data.vaddr,
11761             flush_data.length);
11762     int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
11763     if (ret < 0) {
11764         DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
11765                 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11766                 strerror(errno));
11767         return OMX_ErrorUndefined;
11768     }
11769     return OMX_ErrorNone;
11770 }
11771 
buf_ref_add(int nPortIndex)11772 void omx_vdec::buf_ref_add(int nPortIndex)
11773 {
11774     unsigned long i = 0;
11775     bool buf_present = false;
11776     long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
11777     OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
11778 
11779     if (!dynamic_buf_mode || !out_dynamic_list) {
11780         return;
11781     }
11782 
11783     pthread_mutex_lock(&m_lock);
11784     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11785         //check the buffer fd, offset, uv addr with list contents
11786         //If present increment reference.
11787         if ((out_dynamic_list[i].fd == fd) &&
11788             (out_dynamic_list[i].offset == offset)) {
11789                DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
11790                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11791                if (!secure_mode) {
11792                    drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
11793                }
11794                buf_present = true;
11795                break;
11796         }
11797     }
11798     if (!buf_present) {
11799         for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11800             //search for a entry to insert details of the new buffer
11801             if (out_dynamic_list[i].dup_fd < 0) {
11802                 out_dynamic_list[i].fd = fd;
11803                 out_dynamic_list[i].offset = offset;
11804                 out_dynamic_list[i].dup_fd = dup(fd);
11805                 out_dynamic_list[i].ref_count++;
11806                 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
11807                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11808 
11809                 if (!secure_mode) {
11810                     drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
11811                             (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
11812                                           PROT_READ|PROT_WRITE, MAP_SHARED,
11813                                           drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
11814                     //mmap returns (void *)-1 on failure and sets error code in errno.
11815                     if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
11816                         DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
11817                         drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
11818                         break;
11819                     }
11820                     out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
11821                     out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
11822                     DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11823                 }
11824                 break;
11825             }
11826         }
11827     }
11828    pthread_mutex_unlock(&m_lock);
11829 }
11830 
buf_ref_remove()11831 void omx_vdec::buf_ref_remove()
11832 {
11833     unsigned long i = 0;
11834 
11835     if (!dynamic_buf_mode || !out_dynamic_list) {
11836         return;
11837     }
11838 
11839     pthread_mutex_lock(&m_lock);
11840     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11841         if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
11842             DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11843             munmap(out_dynamic_list[i].buffaddr,
11844                         out_dynamic_list[i].mapped_size);
11845         }
11846 
11847          DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
11848                  (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11849          close(out_dynamic_list[i].dup_fd);
11850          out_dynamic_list[i].dup_fd = -1;
11851     }
11852     pthread_mutex_unlock(&m_lock);
11853 
11854     if (out_dynamic_list) {
11855         free(out_dynamic_list);
11856         out_dynamic_list = NULL;
11857     }
11858 }
11859 
11860 #ifdef _MSM8974_
send_codec_config()11861 void omx_vdec::send_codec_config() {
11862     if (codec_config_flag) {
11863         unsigned long p1 = 0; // Parameter - 1
11864         unsigned long p2 = 0; // Parameter - 2
11865         unsigned long ident = 0;
11866         pthread_mutex_lock(&m_lock);
11867         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
11868         while (m_etb_q.m_size) {
11869             m_etb_q.pop_entry(&p1,&p2,&ident);
11870             if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
11871                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
11872                     if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
11873                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
11874                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
11875                         omx_report_error();
11876                     }
11877                 } else {
11878                     DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
11879                     m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
11880                 }
11881             } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
11882                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
11883                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
11884                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
11885                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
11886                         omx_report_error ();
11887                     }
11888                 } else {
11889                     pending_input_buffers++;
11890                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
11891                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
11892                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
11893                 }
11894             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
11895                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
11896                         (OMX_BUFFERHEADERTYPE *)p1);
11897                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
11898             }
11899         }
11900         pthread_mutex_unlock(&m_lock);
11901     }
11902 }
11903 #endif
11904 
perf_control()11905 omx_vdec::perf_control::perf_control()
11906 {
11907     m_perf_lib = NULL;
11908     m_perf_handle = 0;
11909     m_perf_lock_acquire = NULL;
11910     m_perf_lock_release = NULL;
11911 }
11912 
~perf_control()11913 omx_vdec::perf_control::~perf_control()
11914 {
11915     if (m_perf_handle != 0 && m_perf_lock_release) {
11916         DEBUG_PRINT_LOW("NOTE2: release perf lock");
11917         m_perf_lock_release(m_perf_handle);
11918     }
11919     if (m_perf_lib) {
11920         dlclose(m_perf_lib);
11921     }
11922 }
11923 
11924 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
11925 
11926 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
11927 
send_hint_to_mpctl(bool state)11928 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
11929 {
11930     if (load_lib() == false) {
11931        return;
11932     }
11933     m_perf_lock.lock();
11934     /* 0x4401 maps to video decode playback hint
11935      * in perflock, enum number is 44 and state
11936      * being sent on perflock acquire is 01 (true)
11937      */
11938     int arg = 0x4401;
11939 
11940     if (state == true) {
11941         mpctl_obj.vid_inst_count++;
11942     } else if (state == false) {
11943         mpctl_obj.vid_inst_count--;
11944     }
11945 
11946     if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
11947         mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
11948         mpctl_obj.vid_acquired = true;
11949         DEBUG_PRINT_INFO("Video slvp perflock acquired");
11950     } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
11951         m_perf_lock_release(mpctl_obj.vid_disp_handle);
11952         mpctl_obj.vid_acquired = false;
11953         DEBUG_PRINT_INFO("Video slvp perflock released");
11954     }
11955     m_perf_lock.unlock();
11956 }
11957 
request_cores(int frame_duration_us)11958 void omx_vdec::perf_control::request_cores(int frame_duration_us)
11959 {
11960     if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
11961         return;
11962     }
11963     bool retVal = load_lib();
11964     if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
11965         int arg = 0x700 /*base value*/ + 2 /*cores*/;
11966         m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
11967         if (m_perf_handle) {
11968             DEBUG_PRINT_HIGH("perf lock acquired");
11969         }
11970     }
11971 }
11972 
load_lib()11973 bool omx_vdec::perf_control::load_lib()
11974 {
11975     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
11976     if (m_perf_lib)
11977         return true;
11978 
11979     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
11980         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
11981         goto handle_err;
11982     }
11983 
11984     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
11985         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
11986         goto handle_err;
11987     } else {
11988         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
11989         if (m_perf_lock_acquire == NULL) {
11990             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
11991             goto handle_err;
11992         }
11993         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
11994         if (m_perf_lock_release == NULL) {
11995             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
11996             goto handle_err;
11997         }
11998     }
11999     return true;
12000 
12001 handle_err:
12002     if (m_perf_lib) {
12003         dlclose(m_perf_lib);
12004     }
12005     m_perf_lib = NULL;
12006     return false;
12007 }
12008 
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)12009 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
12010                             unsigned long nMaxFrameHeight)
12011 {
12012 
12013     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12014     int ret = 0;
12015     unsigned long min_res_buf_count = 0;
12016 
12017     eRet = enable_smoothstreaming();
12018     if (eRet != OMX_ErrorNone) {
12019          DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
12020          return eRet;
12021      }
12022 
12023      DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
12024              nMaxFrameWidth,
12025              nMaxFrameHeight);
12026      m_smoothstreaming_mode = true;
12027      m_smoothstreaming_width = nMaxFrameWidth;
12028      m_smoothstreaming_height = nMaxFrameHeight;
12029 
12030      //Get upper limit buffer count for min supported resolution
12031      struct v4l2_format fmt;
12032      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12033      fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
12034      fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
12035      fmt.fmt.pix_mp.pixelformat = output_capability;
12036 
12037      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12038      if (ret) {
12039          DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
12040                            m_decoder_capability.min_height,
12041                            m_decoder_capability.min_width);
12042          return OMX_ErrorUnsupportedSetting;
12043      }
12044 
12045      eRet = get_buffer_req(&drv_ctx.op_buf);
12046      if (eRet != OMX_ErrorNone) {
12047          DEBUG_PRINT_ERROR("failed to get_buffer_req");
12048          return eRet;
12049      }
12050 
12051      min_res_buf_count = drv_ctx.op_buf.mincount;
12052      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
12053                      min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
12054 
12055      update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
12056                        m_smoothstreaming_width, m_smoothstreaming_height);
12057      eRet = is_video_session_supported();
12058      if (eRet != OMX_ErrorNone) {
12059          DEBUG_PRINT_ERROR("video session is not supported");
12060          return eRet;
12061      }
12062 
12063      //Get upper limit buffer size for max smooth streaming resolution set
12064      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12065      fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
12066      fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
12067      fmt.fmt.pix_mp.pixelformat = output_capability;
12068      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12069      if (ret) {
12070          DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
12071          return OMX_ErrorUnsupportedSetting;
12072      }
12073 
12074      eRet = get_buffer_req(&drv_ctx.op_buf);
12075      if (eRet != OMX_ErrorNone) {
12076          DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
12077          return eRet;
12078      }
12079      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
12080                      (unsigned int)drv_ctx.op_buf.buffer_size);
12081 
12082      drv_ctx.op_buf.mincount = min_res_buf_count;
12083      drv_ctx.op_buf.actualcount = min_res_buf_count;
12084      drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
12085      eRet = set_buffer_req(&drv_ctx.op_buf);
12086      if (eRet != OMX_ErrorNone) {
12087          DEBUG_PRINT_ERROR("failed to set_buffer_req");
12088          return eRet;
12089      }
12090 
12091      eRet = get_buffer_req(&drv_ctx.op_buf);
12092      if (eRet != OMX_ErrorNone) {
12093          DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
12094          return eRet;
12095      }
12096      DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
12097                       drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
12098      return eRet;
12099 }
12100 
12101 //static
describeColorFormat(OMX_PTR pParam)12102 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
12103 
12104 #ifndef FLEXYUV_SUPPORTED
12105     return OMX_ErrorUndefined;
12106 #else
12107 
12108     if (pParam == NULL) {
12109         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
12110         return OMX_ErrorBadParameter;
12111     }
12112 
12113     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
12114 
12115     MediaImage *img = &(params->sMediaImage);
12116     switch(params->eColorFormat) {
12117         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
12118         {
12119             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
12120             img->mNumPlanes = 3;
12121             // mWidth and mHeight represent the W x H of the largest plane
12122             // In our case, this happens to be the Stride x Scanlines of Y plane
12123             img->mWidth = params->nFrameWidth;
12124             img->mHeight = params->nFrameHeight;
12125             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12126             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
12127             img->mBitDepth = 8;
12128             //Plane 0 (Y)
12129             img->mPlane[MediaImage::Y].mOffset = 0;
12130             img->mPlane[MediaImage::Y].mColInc = 1;
12131             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
12132             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
12133             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
12134             //Plane 1 (U)
12135             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
12136             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
12137             img->mPlane[MediaImage::U].mRowInc =
12138                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12139             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
12140             img->mPlane[MediaImage::U].mVertSubsampling = 2;
12141             //Plane 2 (V)
12142             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
12143             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
12144             img->mPlane[MediaImage::V].mRowInc =
12145                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12146             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
12147             img->mPlane[MediaImage::V].mVertSubsampling = 2;
12148             break;
12149         }
12150 
12151         case OMX_COLOR_FormatYUV420Planar:
12152         case OMX_COLOR_FormatYUV420SemiPlanar:
12153             // We need not describe the standard OMX linear formats as these are
12154             // understood by client. Fail this deliberately to let client fill-in
12155             return OMX_ErrorUnsupportedSetting;
12156 
12157         default:
12158             // Rest all formats which are non-linear cannot be described
12159             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
12160             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
12161             return OMX_ErrorNone;
12162     };
12163 
12164     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
12165     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
12166     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
12167     for (size_t i = 0; i < img->mNumPlanes; ++i) {
12168         DEBUG_PRINT_LOW("    Plane[%zd] : offset=%d / xStep=%d / yStep = %d",
12169                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
12170     }
12171     return OMX_ErrorNone;
12172 #endif //FLEXYUV_SUPPORTED
12173 }
12174 
prefetchNewBuffers()12175 void omx_vdec::prefetchNewBuffers() {
12176 
12177     struct v4l2_decoder_cmd dec;
12178     uint32_t prefetch_count;
12179     uint32_t prefetch_size;
12180     uint32_t want_size;
12181     uint32_t have_size;
12182     int color_fmt, rc;
12183     uint32_t new_calculated_size;
12184     uint32_t new_buffer_size;
12185     uint32_t new_buffer_count;
12186     uint32_t old_buffer_size;
12187     uint32_t old_buffer_count;
12188 
12189     memset((void *)&dec, 0 , sizeof(dec));
12190     DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n",
12191             (int)drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
12192             drv_ctx.video_resolution.frame_width,
12193             drv_ctx.video_resolution.frame_height);
12194     dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
12195     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
12196         DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
12197     } else {
12198         DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
12199                 dec.raw.data[0], dec.raw.data[1]);
12200     }
12201 
12202     switch ((int)drv_ctx.output_format) {
12203     case VDEC_YUV_FORMAT_NV12:
12204         color_fmt = COLOR_FMT_NV12;
12205         break;
12206     case VDEC_YUV_FORMAT_NV12_UBWC:
12207         color_fmt = COLOR_FMT_NV12_UBWC;
12208         break;
12209     default:
12210         color_fmt = -1;
12211     }
12212 
12213     new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
12214     DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
12215             m_reconfig_width, m_reconfig_height, new_calculated_size);
12216     new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
12217     new_buffer_count = dec.raw.data[1];
12218     old_buffer_size = drv_ctx.op_buf.buffer_size;
12219     old_buffer_count = drv_ctx.op_buf.actualcount;
12220 
12221     new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
12222 
12223     prefetch_count = new_buffer_count;
12224     prefetch_size = new_buffer_size - old_buffer_size;
12225     want_size = new_buffer_size * new_buffer_count;
12226     have_size = old_buffer_size * old_buffer_count;
12227 
12228     if (want_size > have_size) {
12229         DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
12230         DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
12231 
12232         int ion_fd = open(MEM_DEVICE, O_RDONLY);
12233         if (ion_fd < 0) {
12234             DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
12235             return;
12236         }
12237 
12238         struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
12239         struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
12240         struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
12241         size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
12242 
12243         if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
12244             DEBUG_PRINT_ERROR("prefetch data allocation failed");
12245             goto prefetch_exit;
12246         }
12247 
12248         for (uint32_t i = 0; i < prefetch_count; i++) {
12249             sizes[i] = prefetch_size;
12250         }
12251 
12252         regions[0].nr_sizes = prefetch_count;
12253         regions[0].sizes = sizes;
12254         regions[0].vmid = ION_FLAG_CP_PIXEL;
12255 
12256         prefetch_data->nr_regions = 1;
12257         prefetch_data->regions = regions;
12258         prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
12259 
12260         custom_data->cmd = ION_IOC_PREFETCH;
12261         custom_data->arg = (unsigned long )prefetch_data;
12262 
12263         rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
12264         if (rc) {
12265             DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
12266         }
12267 
12268 prefetch_exit:
12269         close(ion_fd);
12270         free(sizes);
12271         free(regions);
12272         free(prefetch_data);
12273         free(custom_data);
12274     }
12275 }
12276 
12277