• 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)
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     m_other_extradata(NULL),
643     m_profile(0),
644     client_set_fps(false),
645     m_last_rendered_TS(-1),
646     m_queued_codec_config_count(0),
647     current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
648     secure_scaling_to_non_secure_opb(false),
649     m_force_compressed_for_dpb(false)
650 {
651     m_pipe_in = -1;
652     m_pipe_out = -1;
653     m_poll_efd = -1;
654     drv_ctx.video_driver_fd = -1;
655     drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
656     /* Assumption is that , to begin with , we have all the frames with decoder */
657     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
658     memset(&m_debug,0,sizeof(m_debug));
659 #ifdef _ANDROID_
660     char property_value[PROPERTY_VALUE_MAX] = {0};
661     property_get("vidc.debug.level", property_value, "1");
662     debug_level = atoi(property_value);
663     property_value[0] = '\0';
664 
665     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
666 
667     property_get("vidc.dec.debug.perf", property_value, "0");
668     perf_flag = atoi(property_value);
669     if (perf_flag) {
670         DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
671         dec_time.start();
672         proc_frms = latency = 0;
673     }
674     prev_n_filled_len = 0;
675     property_value[0] = '\0';
676     property_get("vidc.dec.debug.ts", property_value, "0");
677     m_debug_timestamp = atoi(property_value);
678     DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
679     if (m_debug_timestamp) {
680         time_stamp_dts.set_timestamp_reorder_mode(true);
681         time_stamp_dts.enable_debug_print(true);
682     }
683 
684     property_value[0] = '\0';
685     property_get("vidc.dec.debug.concealedmb", property_value, "0");
686     m_debug_concealedmb = atoi(property_value);
687     DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
688 
689     property_value[0] = '\0';
690     property_get("vidc.dec.profile.check", property_value, "0");
691     m_reject_avc_1080p_mp = atoi(property_value);
692     DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
693 
694     property_value[0] = '\0';
695     property_get("vidc.dec.log.in", property_value, "0");
696     m_debug.in_buffer_log = atoi(property_value);
697 
698     property_value[0] = '\0';
699     property_get("vidc.dec.log.out", property_value, "0");
700     m_debug.out_buffer_log = atoi(property_value);
701     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
702 
703     property_value[0] = '\0';
704     property_get("vidc.dec.meta.log.out", property_value, "0");
705     m_debug.out_meta_buffer_log = atoi(property_value);
706     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
707 
708     property_value[0] = '\0';
709     property_get("vidc.log.loc", property_value, "");
710     if (*property_value)
711         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
712 
713     property_value[0] = '\0';
714     property_get("vidc.dec.120fps.enabled", property_value, "0");
715 
716     //if this feature is not enabled then reset this value -ve
717     if(atoi(property_value)) {
718         DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
719         m_last_rendered_TS = 0;
720     }
721 
722     property_value[0] = '\0';
723     property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
724     m_disable_dynamic_buf_mode = atoi(property_value);
725     DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
726 
727 #ifdef _UBWC_
728     property_value[0] = '\0';
729     property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
730     m_disable_ubwc_mode = atoi(property_value);
731     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
732 #else
733     m_disable_ubwc_mode = true;
734 #endif
735 #endif
736     memset(&m_cmp,0,sizeof(m_cmp));
737     memset(&m_cb,0,sizeof(m_cb));
738     memset (&drv_ctx,0,sizeof(drv_ctx));
739     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
740     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
741     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
742     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
743     m_demux_entries = 0;
744     msg_thread_id = 0;
745     async_thread_id = 0;
746     msg_thread_created = false;
747     async_thread_created = false;
748     async_thread_force_stop = false;
749     message_thread_stop = false;
750 #ifdef _ANDROID_ICS_
751     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
752 #endif
753     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
754 
755     /* invalidate m_frame_pack_arrangement */
756     memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
757     m_frame_pack_arrangement.cancel_flag = 1;
758 
759     drv_ctx.timestamp_adjust = false;
760     m_vendor_config.pData = NULL;
761     pthread_mutex_init(&m_lock, NULL);
762     pthread_mutex_init(&c_lock, NULL);
763     pthread_mutex_init(&buf_lock, NULL);
764     sem_init(&m_cmd_lock,0,0);
765     sem_init(&m_safe_flush, 0, 0);
766     streaming[CAPTURE_PORT] =
767         streaming[OUTPUT_PORT] = false;
768 #ifdef _ANDROID_
769     char extradata_value[PROPERTY_VALUE_MAX] = {0};
770     property_get("vidc.dec.debug.extradata", extradata_value, "0");
771     m_debug_extradata = atoi(extradata_value);
772     DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
773 #endif
774     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
775     client_buffers.set_vdec_client(this);
776     dynamic_buf_mode = false;
777     out_dynamic_list = NULL;
778     is_down_scalar_enabled = false;
779     m_downscalar_width = 0;
780     m_downscalar_height = 0;
781     m_force_down_scalar = 0;
782     m_reconfig_height = 0;
783     m_reconfig_width = 0;
784     m_smoothstreaming_mode = false;
785     m_smoothstreaming_width = 0;
786     m_smoothstreaming_height = 0;
787     is_q6_platform = false;
788     m_perf_control.send_hint_to_mpctl(true);
789     m_input_pass_buffer_fd = false;
790 }
791 
792 static const int event_type[] = {
793     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
794     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
795     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
796     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
797     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
798     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
799     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
800     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
801     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
802 };
803 
subscribe_to_events(int fd)804 static OMX_ERRORTYPE subscribe_to_events(int fd)
805 {
806     OMX_ERRORTYPE eRet = OMX_ErrorNone;
807     struct v4l2_event_subscription sub;
808     int array_sz = sizeof(event_type)/sizeof(int);
809     int i,rc;
810     if (fd < 0) {
811         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
812         return OMX_ErrorBadParameter;
813     }
814 
815     for (i = 0; i < array_sz; ++i) {
816         memset(&sub, 0, sizeof(sub));
817         sub.type = event_type[i];
818         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
819         if (rc) {
820             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
821             break;
822         }
823     }
824     if (i < array_sz) {
825         for (--i; i >=0 ; i--) {
826             memset(&sub, 0, sizeof(sub));
827             sub.type = event_type[i];
828             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
829             if (rc)
830                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
831         }
832         eRet = OMX_ErrorNotImplemented;
833     }
834     return eRet;
835 }
836 
837 
unsubscribe_to_events(int fd)838 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
839 {
840     OMX_ERRORTYPE eRet = OMX_ErrorNone;
841     struct v4l2_event_subscription sub;
842     int array_sz = sizeof(event_type)/sizeof(int);
843     int i,rc;
844     if (fd < 0) {
845         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
846         return OMX_ErrorBadParameter;
847     }
848 
849     for (i = 0; i < array_sz; ++i) {
850         memset(&sub, 0, sizeof(sub));
851         sub.type = event_type[i];
852         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
853         if (rc) {
854             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
855             break;
856         }
857     }
858     return eRet;
859 }
860 
861 /* ======================================================================
862    FUNCTION
863    omx_vdec::~omx_vdec
864 
865    DESCRIPTION
866    Destructor
867 
868    PARAMETERS
869    None
870 
871    RETURN VALUE
872    None.
873    ========================================================================== */
~omx_vdec()874 omx_vdec::~omx_vdec()
875 {
876     m_pmem_info = NULL;
877     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
878     if (msg_thread_created) {
879         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
880         message_thread_stop = true;
881         post_message(this, OMX_COMPONENT_CLOSE_MSG);
882         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
883         pthread_join(msg_thread_id,NULL);
884     }
885     close(m_pipe_in);
886     close(m_pipe_out);
887     m_pipe_in = -1;
888     m_pipe_out = -1;
889     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
890     if(eventfd_write(m_poll_efd, 1)) {
891          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
892          async_thread_force_stop = true;
893     }
894 
895     if (async_thread_created)
896         pthread_join(async_thread_id,NULL);
897     unsubscribe_to_events(drv_ctx.video_driver_fd);
898     close(m_poll_efd);
899     close(drv_ctx.video_driver_fd);
900     pthread_mutex_destroy(&m_lock);
901     pthread_mutex_destroy(&c_lock);
902     pthread_mutex_destroy(&buf_lock);
903     sem_destroy(&m_cmd_lock);
904     if (perf_flag) {
905         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
906         dec_time.end();
907     }
908     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
909     m_perf_control.send_hint_to_mpctl(false);
910 }
911 
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)912 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
913 {
914     struct v4l2_requestbuffers bufreq;
915     int rc = 0;
916     if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
917         bufreq.memory = V4L2_MEMORY_USERPTR;
918         bufreq.count = 0;
919         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
920         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
921     } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
922         bufreq.memory = V4L2_MEMORY_USERPTR;
923         bufreq.count = 0;
924         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
925         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
926     }
927     return rc;
928 }
929 
set_dpb(bool is_split_mode,int dpb_color_format)930 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
931 {
932     int rc = 0;
933     struct v4l2_ext_control ctrl[2];
934     struct v4l2_ext_controls controls;
935 
936     DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
937          is_split_mode ? "split" : "combined",
938          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
939          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
940          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
941          "unknown",
942          capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
943          capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
944          "unknown");
945 
946     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
947     if (is_split_mode) {
948         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
949     } else {
950         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
951     }
952 
953     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
954     ctrl[1].value = dpb_color_format;
955 
956     controls.count = 2;
957     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
958     controls.controls = ctrl;
959 
960     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
961     if (rc) {
962         DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
963         return OMX_ErrorUnsupportedSetting;
964     }
965     return OMX_ErrorNone;
966 }
967 
968 
decide_dpb_buffer_mode(bool force_split_mode)969 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
970 {
971     OMX_ERRORTYPE eRet = OMX_ErrorNone;
972 
973     bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC;
974 
975     bool is_res_above_1080p = (drv_ctx.video_resolution.frame_width > 1920 &&
976             drv_ctx.video_resolution.frame_height > 1088) ||
977             (drv_ctx.video_resolution.frame_height > 1088 &&
978              drv_ctx.video_resolution.frame_width > 1920);
979 
980     if (cpu_access) {
981         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
982             if ((m_force_compressed_for_dpb || is_res_above_1080p) &&
983                 !force_split_mode) {
984                 //split DPB-OPB
985                 //DPB -> UBWC , OPB -> Linear
986                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
987             } else if (force_split_mode) {
988                         //DPB -> Linear, OPB -> Linear
989                         eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
990             } else {
991                         //DPB-OPB combined linear
992                         eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
993            }
994         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
995             //split DPB-OPB
996             //DPB -> UBWC, OPB -> Linear
997             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
998         }
999     } else { //no cpu access
1000         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1001             if (force_split_mode) {
1002                 //split DPB-OPB
1003                 //DPB -> UBWC, OPB -> UBWC
1004                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1005             } else {
1006                 //DPB-OPB combined UBWC
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 -> UBWC
1012             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1013         }
1014     }
1015     if (eRet) {
1016         DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1017     }
1018     return eRet;
1019 }
1020 
enable_downscalar()1021 int omx_vdec::enable_downscalar()
1022 {
1023     int rc = 0;
1024     struct v4l2_control control;
1025     struct v4l2_format fmt;
1026 
1027     if (is_down_scalar_enabled) {
1028         DEBUG_PRINT_LOW("%s: already enabled", __func__);
1029         return 0;
1030     }
1031 
1032     DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1033     rc = decide_dpb_buffer_mode(true);
1034     if (rc) {
1035         DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1036         return rc;
1037     }
1038     is_down_scalar_enabled = true;
1039 
1040     memset(&control, 0x0, sizeof(struct v4l2_control));
1041     control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1042     control.value = 1;
1043     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1044     if (rc) {
1045         DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1046         return rc;
1047     }
1048 
1049     return 0;
1050 }
1051 
disable_downscalar()1052 int omx_vdec::disable_downscalar()
1053 {
1054     int rc = 0;
1055     struct v4l2_control control;
1056 
1057     if (!is_down_scalar_enabled) {
1058         DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1059         return 0;
1060     }
1061 
1062     rc = decide_dpb_buffer_mode(false);
1063     if (rc < 0) {
1064         DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1065         return rc;
1066     }
1067     is_down_scalar_enabled = false;
1068 
1069     return rc;
1070 }
1071 
decide_downscalar()1072 int omx_vdec::decide_downscalar()
1073 {
1074     int rc = 0;
1075     struct v4l2_format fmt;
1076     enum color_fmts color_format;
1077 
1078     if  (!m_downscalar_width || !m_downscalar_height) {
1079         DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1080         return 0;
1081     }
1082 
1083     if (m_force_down_scalar) {
1084         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1085         return 0;
1086     }
1087 
1088     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1089     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1090     fmt.fmt.pix_mp.pixelformat = capture_capability;
1091     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1092     if (rc < 0) {
1093        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1094        return rc;
1095     }
1096 
1097     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__,
1098         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height);
1099 
1100     if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) {
1101         rc = enable_downscalar();
1102         if (rc < 0) {
1103             DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1104             return rc;
1105         }
1106 
1107         OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1108                             fmt.fmt.pix_mp.width : m_downscalar_width;
1109         OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1110                             fmt.fmt.pix_mp.height : m_downscalar_height;
1111         switch (capture_capability) {
1112             case V4L2_PIX_FMT_NV12:
1113                 color_format = COLOR_FMT_NV12;
1114                 break;
1115             case V4L2_PIX_FMT_NV12_UBWC:
1116                 color_format = COLOR_FMT_NV12_UBWC;
1117                 break;
1118             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1119                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1120                 break;
1121             default:
1122                 DEBUG_PRINT_ERROR("Color format not recognized\n");
1123                 rc = OMX_ErrorUndefined;
1124                 return rc;
1125         }
1126 
1127         rc = update_resolution(width, height,
1128                 VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height));
1129         if (rc < 0) {
1130             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height);
1131             return rc;
1132         }
1133     } else {
1134 
1135         rc = disable_downscalar();
1136         if (rc < 0) {
1137             DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1138             return rc;
1139         }
1140 
1141         rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1142                 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
1143         if (rc < 0) {
1144             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width,
1145                 fmt.fmt.pix_mp.height);
1146             return rc;
1147         }
1148     }
1149 
1150     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1151     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1152     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1153     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1154     fmt.fmt.pix_mp.pixelformat = capture_capability;
1155     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1156     if (rc) {
1157         DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1158         return rc;
1159     }
1160 
1161     rc = get_buffer_req(&drv_ctx.op_buf);
1162     if (rc) {
1163         DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1164         return rc;
1165     }
1166 
1167     return rc;
1168 }
1169 
1170 /* ======================================================================
1171    FUNCTION
1172    omx_vdec::OMXCntrlProcessMsgCb
1173 
1174    DESCRIPTION
1175    IL Client callbacks are generated through this routine. The decoder
1176    provides the thread context for this routine.
1177 
1178    PARAMETERS
1179    ctxt -- Context information related to the self.
1180    id   -- Event identifier. This could be any of the following:
1181    1. Command completion event
1182    2. Buffer done callback event
1183    3. Frame done callback event
1184 
1185    RETURN VALUE
1186    None.
1187 
1188    ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1189 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1190 {
1191     unsigned long p1; // Parameter - 1
1192     unsigned long p2; // Parameter - 2
1193     unsigned long ident;
1194     unsigned qsize=0; // qsize
1195     omx_vdec *pThis = (omx_vdec *) ctxt;
1196 
1197     if (!pThis) {
1198         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1199                 __func__);
1200         return;
1201     }
1202 
1203     // Protect the shared queue data structure
1204     do {
1205         /*Read the message id's from the queue*/
1206         pthread_mutex_lock(&pThis->m_lock);
1207         qsize = pThis->m_cmd_q.m_size;
1208         if (qsize) {
1209             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1210         }
1211 
1212         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1213             qsize = pThis->m_ftb_q.m_size;
1214             if (qsize) {
1215                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1216             }
1217         }
1218 
1219         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1220             qsize = pThis->m_etb_q.m_size;
1221             if (qsize) {
1222                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1223             }
1224         }
1225         pthread_mutex_unlock(&pThis->m_lock);
1226 
1227         /*process message if we have one*/
1228         if (qsize > 0) {
1229             id = ident;
1230             switch (id) {
1231                 case OMX_COMPONENT_GENERATE_EVENT:
1232                     if (pThis->m_cb.EventHandler) {
1233                         switch (p1) {
1234                             case OMX_CommandStateSet:
1235                                 pThis->m_state = (OMX_STATETYPE) p2;
1236                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1237                                         pThis->m_state);
1238                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1239                                         OMX_EventCmdComplete, p1, p2, NULL);
1240                                 break;
1241 
1242                             case OMX_EventError:
1243                                 if (p2 == OMX_StateInvalid) {
1244                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1245                                     pThis->m_state = (OMX_STATETYPE) p2;
1246                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1247                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1248                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1249                                     pThis->omx_report_error();
1250                                 } else {
1251                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1252                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
1253                                 }
1254                                 break;
1255 
1256                             case OMX_CommandPortDisable:
1257                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1258                                 if (BITMASK_PRESENT(&pThis->m_flags,
1259                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1260                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1261                                     break;
1262                                 }
1263                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1264                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1265                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1266                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1267                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
1268                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1269                                     pThis->in_reconfig = false;
1270                                     if (eRet !=  OMX_ErrorNone) {
1271                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1272                                         pThis->omx_report_error();
1273                                         break;
1274                                     }
1275                                 }
1276                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1277                                         OMX_EventCmdComplete, p1, p2, NULL );
1278                                 break;
1279                             case OMX_CommandPortEnable:
1280                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1281                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1282                                         OMX_EventCmdComplete, p1, p2, NULL );
1283                                 break;
1284 
1285                             default:
1286                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1287                                         OMX_EventCmdComplete, p1, p2, NULL );
1288                                 break;
1289 
1290                         }
1291                     } else {
1292                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1293                     }
1294                     break;
1295                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1296                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1297                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1298                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1299                         pThis->omx_report_error ();
1300                     }
1301                     break;
1302                 case OMX_COMPONENT_GENERATE_ETB: {
1303                         OMX_ERRORTYPE iret;
1304                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1305                         if (iret == OMX_ErrorInsufficientResources) {
1306                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1307                             pThis->omx_report_hw_overload ();
1308                         } else if (iret != OMX_ErrorNone) {
1309                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1310                             pThis->omx_report_error ();
1311                         }
1312                     }
1313                     break;
1314 
1315                 case OMX_COMPONENT_GENERATE_FTB:
1316                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1317                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1318                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1319                         pThis->omx_report_error ();
1320                     }
1321                     break;
1322 
1323                 case OMX_COMPONENT_GENERATE_COMMAND:
1324                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1325                             (OMX_U32)p2,(OMX_PTR)NULL);
1326                     break;
1327 
1328                 case OMX_COMPONENT_GENERATE_EBD:
1329 
1330                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1331                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1332                         pThis->omx_report_error ();
1333                     } else {
1334                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1335                             pThis->time_stamp_dts.remove_time_stamp(
1336                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1337                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1338                                     ?true:false);
1339                         }
1340 
1341                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1342                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1343                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1344                             pThis->omx_report_error ();
1345                         }
1346                     }
1347                     break;
1348                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1349                                             int64_t *timestamp = (int64_t *)(intptr_t)p1;
1350                                             if (p1) {
1351                                                 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1352                                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1353                                                         ?true:false);
1354                                                 free(timestamp);
1355                                             }
1356                                         }
1357                                         break;
1358                 case OMX_COMPONENT_GENERATE_FBD:
1359                                         if (p2 != VDEC_S_SUCCESS) {
1360                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1361                                             pThis->omx_report_error ();
1362                                         } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1363                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1364                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
1365                                             pThis->omx_report_error ();
1366                                         }
1367                                         break;
1368 
1369                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1370                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1371                                         if (!pThis->input_flush_progress) {
1372                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1373                                         } else {
1374                                             pThis->execute_input_flush();
1375                                             if (pThis->m_cb.EventHandler) {
1376                                                 if (p2 != VDEC_S_SUCCESS) {
1377                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1378                                                     pThis->omx_report_error ();
1379                                                 } else {
1380                                                     /*Check if we need generate event for Flush done*/
1381                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1382                                                                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
1383                                                         BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
1384                                                         DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
1385                                                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1386                                                                 OMX_EventCmdComplete,OMX_CommandFlush,
1387                                                                 OMX_CORE_INPUT_PORT_INDEX,NULL );
1388                                                     }
1389                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1390                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1391                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1392                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1393                                                             pThis->omx_report_error ();
1394                                                         } else {
1395                                                             pThis->streaming[OUTPUT_PORT] = false;
1396                                                         }
1397                                                         if (!pThis->output_flush_progress) {
1398                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1399                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1400                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1401                                                         }
1402                                                     }
1403                                                 }
1404                                             } else {
1405                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1406                                             }
1407                                         }
1408                                         break;
1409 
1410                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1411                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1412                                         if (!pThis->output_flush_progress) {
1413                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1414                                         } else {
1415                                             pThis->execute_output_flush();
1416                                             if (pThis->m_cb.EventHandler) {
1417                                                 if (p2 != VDEC_S_SUCCESS) {
1418                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1419                                                     pThis->omx_report_error ();
1420                                                 } else {
1421                                                     /*Check if we need generate event for Flush done*/
1422                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1423                                                                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
1424                                                         DEBUG_PRINT_LOW("Notify Output Flush done");
1425                                                         BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1426                                                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1427                                                                 OMX_EventCmdComplete,OMX_CommandFlush,
1428                                                                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1429                                                     }
1430                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1431                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1432                                                         DEBUG_PRINT_LOW("Internal flush complete");
1433                                                         BITMASK_CLEAR (&pThis->m_flags,
1434                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1435                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1436                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1437                                                             pThis->post_event(OMX_CommandPortDisable,
1438                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1439                                                                     OMX_COMPONENT_GENERATE_EVENT);
1440                                                             BITMASK_CLEAR (&pThis->m_flags,
1441                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1442                                                             BITMASK_CLEAR (&pThis->m_flags,
1443                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1444 
1445                                                         }
1446                                                     }
1447 
1448                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1449                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1450                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1451                                                             pThis->omx_report_error ();
1452                                                             break;
1453                                                         }
1454                                                         pThis->streaming[CAPTURE_PORT] = false;
1455                                                         if (!pThis->input_flush_progress) {
1456                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1457                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1458                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1459                                                         }
1460                                                     }
1461                                                 }
1462                                             } else {
1463                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1464                                             }
1465                                         }
1466                                         break;
1467 
1468                 case OMX_COMPONENT_GENERATE_START_DONE:
1469                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1470 
1471                                         if (pThis->m_cb.EventHandler) {
1472                                             if (p2 != VDEC_S_SUCCESS) {
1473                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1474                                                 pThis->omx_report_error ();
1475                                             } else {
1476                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1477                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1478                                                     DEBUG_PRINT_LOW("Move to executing");
1479                                                     // Send the callback now
1480                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1481                                                     pThis->m_state = OMX_StateExecuting;
1482                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1483                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1484                                                             OMX_StateExecuting, NULL);
1485                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1486                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1487                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1488                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1489                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1490                                                         pThis->omx_report_error ();
1491                                                     }
1492                                                 }
1493                                             }
1494                                         } else {
1495                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1496                                         }
1497                                         break;
1498 
1499                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1500                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1501                                         if (pThis->m_cb.EventHandler) {
1502                                             if (p2 != VDEC_S_SUCCESS) {
1503                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1504                                                 pThis->omx_report_error ();
1505                                             } else {
1506                                                 pThis->complete_pending_buffer_done_cbs();
1507                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1508                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1509                                                     //Send the callback now
1510                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1511                                                     pThis->m_state = OMX_StatePause;
1512                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1513                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1514                                                             OMX_StatePause, NULL);
1515                                                 }
1516                                             }
1517                                         } else {
1518                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1519                                         }
1520 
1521                                         break;
1522 
1523                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1524                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1525                                         if (pThis->m_cb.EventHandler) {
1526                                             if (p2 != VDEC_S_SUCCESS) {
1527                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1528                                                 pThis->omx_report_error ();
1529                                             } else {
1530                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1531                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1532                                                     // Send the callback now
1533                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1534                                                     pThis->m_state = OMX_StateExecuting;
1535                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1536                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1537                                                             OMX_StateExecuting,NULL);
1538                                                 }
1539                                             }
1540                                         } else {
1541                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1542                                         }
1543 
1544                                         break;
1545 
1546                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1547                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1548                                         if (pThis->m_cb.EventHandler) {
1549                                             if (p2 != VDEC_S_SUCCESS) {
1550                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1551                                                 pThis->omx_report_error ();
1552                                             } else {
1553                                                 pThis->complete_pending_buffer_done_cbs();
1554                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1555                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1556                                                     // Send the callback now
1557                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1558                                                     pThis->m_state = OMX_StateIdle;
1559                                                     DEBUG_PRINT_LOW("Move to Idle State");
1560                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1561                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1562                                                             OMX_StateIdle,NULL);
1563                                                 }
1564                                             }
1565                                         } else {
1566                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1567                                         }
1568 
1569                                         break;
1570 
1571                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1572                                         if (p2 == OMX_IndexParamPortDefinition) {
1573                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1574                                             pThis->in_reconfig = true;
1575                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1576                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1577 
1578                                             /* Check if resolution is changed in smooth streaming mode */
1579                                             if (pThis->m_smoothstreaming_mode &&
1580                                                 (pThis->framesize.nWidth !=
1581                                                     pThis->drv_ctx.video_resolution.frame_width) ||
1582                                                 (pThis->framesize.nHeight !=
1583                                                     pThis->drv_ctx.video_resolution.frame_height)) {
1584 
1585                                                 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1586                                                         pThis->framesize.nWidth,
1587                                                         pThis->framesize.nHeight,
1588                                                         pThis->drv_ctx.video_resolution.frame_width,
1589                                                         pThis->drv_ctx.video_resolution.frame_height);
1590 
1591                                                 /* Update new resolution */
1592                                                 pThis->framesize.nWidth =
1593                                                        pThis->drv_ctx.video_resolution.frame_width;
1594                                                 pThis->framesize.nHeight =
1595                                                        pThis->drv_ctx.video_resolution.frame_height;
1596 
1597                                                 /* Update C2D with new resolution */
1598                                                 if (!pThis->client_buffers.update_buffer_req()) {
1599                                                     DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1600                                                 }
1601                                             }
1602 
1603                                             /* Update new crop information */
1604                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1605                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1606                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1607                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1608 
1609                                             /* Validate the new crop information */
1610                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1611                                                 pThis->drv_ctx.video_resolution.frame_width) {
1612 
1613                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1614                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1615                                                         pThis->drv_ctx.video_resolution.frame_width);
1616                                                 pThis->rectangle.nLeft = 0;
1617 
1618                                                 if (pThis->rectangle.nWidth >
1619                                                     pThis->drv_ctx.video_resolution.frame_width) {
1620 
1621                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1622                                                             pThis->rectangle.nWidth,
1623                                                             pThis->drv_ctx.video_resolution.frame_width);
1624                                                     pThis->rectangle.nWidth =
1625                                                         pThis->drv_ctx.video_resolution.frame_width;
1626                                                 }
1627                                             }
1628                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1629                                                 pThis->drv_ctx.video_resolution.frame_height) {
1630 
1631                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1632                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1633                                                     pThis->drv_ctx.video_resolution.frame_height);
1634                                                 pThis->rectangle.nTop = 0;
1635 
1636                                                 if (pThis->rectangle.nHeight >
1637                                                     pThis->drv_ctx.video_resolution.frame_height) {
1638 
1639                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1640                                                         pThis->rectangle.nHeight,
1641                                                         pThis->drv_ctx.video_resolution.frame_height);
1642                                                     pThis->rectangle.nHeight =
1643                                                         pThis->drv_ctx.video_resolution.frame_height;
1644                                                 }
1645                                             }
1646                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1647                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1648                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1649                                         } else {
1650                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1651                                             break;
1652                                         }
1653                                         if (pThis->m_debug.outfile) {
1654                                             fclose(pThis->m_debug.outfile);
1655                                             pThis->m_debug.outfile = NULL;
1656                                         }
1657                                         if (pThis->m_debug.out_ymeta_file) {
1658                                             fclose(pThis->m_debug.out_ymeta_file);
1659                                             pThis->m_debug.out_ymeta_file = NULL;
1660                                         }
1661                                         if (pThis->m_debug.out_uvmeta_file) {
1662                                             fclose(pThis->m_debug.out_uvmeta_file);
1663                                             pThis->m_debug.out_uvmeta_file = NULL;
1664                                         }
1665 
1666                                         if (pThis->m_cb.EventHandler) {
1667                                             uint32_t frame_data[2];
1668                                             frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1669                                                 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1670                                             frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1671                                                 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1672                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1673                                                     OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1674                                         } else {
1675                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1676                                         }
1677                                         break;
1678 
1679                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1680                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1681                                         if (pThis->m_cb.EventHandler) {
1682                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1683                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1684                                         } else {
1685                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1686                                         }
1687                                         pThis->prev_ts = LLONG_MAX;
1688                                         pThis->rst_prev_ts = true;
1689                                         break;
1690 
1691                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1692                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1693                                         pThis->omx_report_error();
1694                                         break;
1695 
1696                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1697                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1698                                         pThis->omx_report_unsupported_setting();
1699                                         break;
1700 
1701                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1702                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1703                                         pThis->omx_report_hw_overload();
1704                                         break;
1705 
1706                 default:
1707                                         break;
1708             }
1709         }
1710         pthread_mutex_lock(&pThis->m_lock);
1711         qsize = pThis->m_cmd_q.m_size;
1712         if (pThis->m_state != OMX_StatePause)
1713             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1714         pthread_mutex_unlock(&pThis->m_lock);
1715     } while (qsize>0);
1716 
1717 }
1718 
update_resolution(int width,int height,int stride,int scan_lines)1719 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1720 {
1721     int format_changed = 0;
1722     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1723             (width != (int)drv_ctx.video_resolution.frame_width)) {
1724         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1725                 width, drv_ctx.video_resolution.frame_width,
1726                 height,drv_ctx.video_resolution.frame_height);
1727         format_changed = 1;
1728     }
1729     drv_ctx.video_resolution.frame_height = height;
1730     drv_ctx.video_resolution.frame_width = width;
1731     drv_ctx.video_resolution.scan_lines = scan_lines;
1732     drv_ctx.video_resolution.stride = stride;
1733     if(!is_down_scalar_enabled) {
1734         rectangle.nLeft = 0;
1735         rectangle.nTop = 0;
1736         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1737         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1738     }
1739     return format_changed;
1740 }
1741 
is_video_session_supported()1742 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1743 {
1744     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1745                 OMX_MAX_STRINGNAME_SIZE) &&
1746             (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1747         m_decoder_capability.max_width = 1280;
1748         m_decoder_capability.max_height = 720;
1749         DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1750     }
1751 
1752     if ((drv_ctx.video_resolution.frame_width *
1753                 drv_ctx.video_resolution.frame_height >
1754                 m_decoder_capability.max_width *
1755                 m_decoder_capability.max_height) ||
1756             (drv_ctx.video_resolution.frame_width*
1757              drv_ctx.video_resolution.frame_height <
1758              m_decoder_capability.min_width *
1759              m_decoder_capability.min_height)) {
1760         DEBUG_PRINT_ERROR(
1761                 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1762                 drv_ctx.video_resolution.frame_width,
1763                 drv_ctx.video_resolution.frame_height,
1764                 m_decoder_capability.min_width,
1765                 m_decoder_capability.min_height,
1766                 m_decoder_capability.max_width,
1767                 m_decoder_capability.max_height);
1768         return OMX_ErrorUnsupportedSetting;
1769     }
1770     DEBUG_PRINT_HIGH("video session supported");
1771     return OMX_ErrorNone;
1772 }
1773 
log_input_buffers(const char * buffer_addr,int buffer_len)1774 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1775 {
1776     if (m_debug.in_buffer_log && !m_debug.infile) {
1777         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1778            snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1779                    m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1780         } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1781                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1782                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1783         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
1784                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
1785                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1786         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1787                     !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1788                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
1789                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1790         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1791                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1792                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1793         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
1794                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1795                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1796         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
1797                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1798                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1799         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1800                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1801                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1802         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1803                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1804                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1805         } else {
1806                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
1807                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1808         }
1809         m_debug.infile = fopen (m_debug.infile_name, "ab");
1810         if (!m_debug.infile) {
1811             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1812             m_debug.infile_name[0] = '\0';
1813             return -1;
1814         }
1815         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1816                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1817             struct ivf_file_header {
1818                 OMX_U8 signature[4]; //='DKIF';
1819                 OMX_U8 version         ; //= 0;
1820                 OMX_U8 headersize      ; //= 32;
1821                 OMX_U32 FourCC;
1822                 OMX_U8 width;
1823                 OMX_U8 height;
1824                 OMX_U32 rate;
1825                 OMX_U32 scale;
1826                 OMX_U32 length;
1827                 OMX_U8 unused[4];
1828             } file_header;
1829 
1830             memset((void *)&file_header,0,sizeof(file_header));
1831             file_header.signature[0] = 'D';
1832             file_header.signature[1] = 'K';
1833             file_header.signature[2] = 'I';
1834             file_header.signature[3] = 'F';
1835             file_header.version = 0;
1836             file_header.headersize = 32;
1837             switch (drv_ctx.decoder_format) {
1838                 case VDEC_CODECTYPE_VP8:
1839                     file_header.FourCC = 0x30385056;
1840                     break;
1841                 case VDEC_CODECTYPE_VP9:
1842                     file_header.FourCC = 0x30395056;
1843                     break;
1844                 default:
1845                     DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
1846                     break;
1847             }
1848             fwrite((const char *)&file_header,
1849                     sizeof(file_header),1,m_debug.infile);
1850          }
1851     }
1852     if (m_debug.infile && buffer_addr && buffer_len) {
1853         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1854                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1855             struct vpx_ivf_frame_header {
1856                 OMX_U32 framesize;
1857                 OMX_U32 timestamp_lo;
1858                 OMX_U32 timestamp_hi;
1859             } vpx_frame_header;
1860             vpx_frame_header.framesize = buffer_len;
1861             /* Currently FW doesn't use timestamp values */
1862             vpx_frame_header.timestamp_lo = 0;
1863             vpx_frame_header.timestamp_hi = 0;
1864             fwrite((const char *)&vpx_frame_header,
1865                     sizeof(vpx_frame_header),1,m_debug.infile);
1866         }
1867         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1868     }
1869     return 0;
1870 }
1871 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1872 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
1873     int buf_index = 0;
1874     char *temp = NULL;
1875 
1876     if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
1877         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
1878                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1879         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1880         if (!m_debug.outfile) {
1881             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1882             m_debug.outfile_name[0] = '\0';
1883             return -1;
1884         }
1885     }
1886 
1887     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
1888         && buffer->nFilledLen) {
1889         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
1890                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1891         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
1892                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1893         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
1894         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
1895         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
1896             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
1897             m_debug.out_ymetafile_name[0] = '\0';
1898             m_debug.out_uvmetafile_name[0] = '\0';
1899             return -1;
1900         }
1901     }
1902 
1903     if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
1904         return 0;
1905 
1906     buf_index = buffer - m_out_mem_ptr;
1907     temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1908 
1909     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
1910         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
1911             drv_ctx.video_resolution.frame_width,
1912             drv_ctx.video_resolution.frame_height);
1913 
1914         if (m_debug.outfile)
1915             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
1916 
1917         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
1918             unsigned int width = 0, height = 0;
1919             unsigned int y_plane, y_meta_plane;
1920             int y_stride = 0, y_sclines = 0;
1921             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
1922             int color_fmt = COLOR_FMT_NV12_UBWC;
1923             int i;
1924             int bytes_written = 0;
1925 
1926             width = drv_ctx.video_resolution.frame_width;
1927             height = drv_ctx.video_resolution.frame_height;
1928             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
1929             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
1930             y_stride = VENUS_Y_STRIDE(color_fmt, width);
1931             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
1932             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
1933             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
1934 
1935             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
1936             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
1937 
1938             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1939             for (i = 0; i < y_meta_scanlines; i++) {
1940                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
1941                  temp += y_meta_stride;
1942             }
1943 
1944             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
1945             for(i = 0; i < uv_meta_scanlines; i++) {
1946                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
1947                 temp += uv_meta_stride;
1948             }
1949         }
1950     } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) {
1951         int stride = drv_ctx.video_resolution.stride;
1952         int scanlines = drv_ctx.video_resolution.scan_lines;
1953         if (m_smoothstreaming_mode) {
1954             stride = drv_ctx.video_resolution.frame_width;
1955             scanlines = drv_ctx.video_resolution.frame_height;
1956             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
1957             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
1958         }
1959         unsigned i;
1960         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1961             drv_ctx.video_resolution.frame_width,
1962             drv_ctx.video_resolution.frame_height, stride, scanlines);
1963         int bytes_written = 0;
1964         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1965              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1966              temp += stride;
1967         }
1968         temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
1969         int stride_c = stride;
1970         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1971             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1972             temp += stride_c;
1973         }
1974     }
1975     return 0;
1976 }
1977 
1978 /* ======================================================================
1979    FUNCTION
1980    omx_vdec::ComponentInit
1981 
1982    DESCRIPTION
1983    Initialize the component.
1984 
1985    PARAMETERS
1986    ctxt -- Context information related to the self.
1987    id   -- Event identifier. This could be any of the following:
1988    1. Command completion event
1989    2. Buffer done callback event
1990    3. Frame done callback event
1991 
1992    RETURN VALUE
1993    None.
1994 
1995    ========================================================================== */
component_init(OMX_STRING role)1996 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1997 {
1998 
1999     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2000     struct v4l2_fmtdesc fdesc;
2001     struct v4l2_format fmt;
2002     struct v4l2_requestbuffers bufreq;
2003     struct v4l2_control control;
2004     struct v4l2_frmsizeenum frmsize;
2005     unsigned int   alignment = 0,buffer_size = 0;
2006     int fds[2];
2007     int r,ret=0;
2008     bool codec_ambiguous = false;
2009     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2010     char property_value[PROPERTY_VALUE_MAX] = {0};
2011     FILE *soc_file = NULL;
2012     char buffer[10];
2013 
2014 #ifdef _ANDROID_
2015     char platform_name[PROPERTY_VALUE_MAX];
2016     property_get("ro.board.platform", platform_name, "0");
2017     if (!strncmp(platform_name, "msm8610", 7)) {
2018         device_name = (OMX_STRING)"/dev/video/q6_dec";
2019         is_q6_platform = true;
2020         maxSmoothStreamingWidth = 1280;
2021         maxSmoothStreamingHeight = 720;
2022     }
2023 #endif
2024 
2025     is_thulium_v1 = false;
2026     soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2027     if (soc_file) {
2028         fread(buffer, 1, 4, soc_file);
2029         fclose(soc_file);
2030         if (atoi(buffer) == 246) {
2031             soc_file = fopen("/sys/devices/soc0/revision", "r");
2032             if (soc_file) {
2033                 fread(buffer, 1, 4, soc_file);
2034                 fclose(soc_file);
2035                 if (atoi(buffer) == 1) {
2036                     is_thulium_v1 = true;
2037                     DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2038                 }
2039             }
2040         }
2041     }
2042 
2043 #ifdef _ANDROID_
2044     /*
2045      * turn off frame parsing for Android by default.
2046      * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2047      */
2048     arbitrary_bytes = false;
2049     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2050     if (atoi(property_value)) {
2051         DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2052         arbitrary_bytes = true;
2053     }
2054 #endif
2055 
2056     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2057                 OMX_MAX_STRINGNAME_SIZE)) {
2058         secure_mode = true;
2059         arbitrary_bytes = false;
2060         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2061     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2062                 OMX_MAX_STRINGNAME_SIZE)) {
2063         secure_mode = true;
2064         arbitrary_bytes = false;
2065         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2066     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2067                 OMX_MAX_STRINGNAME_SIZE)) {
2068         secure_mode = true;
2069         arbitrary_bytes = false;
2070         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2071     } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2072                 OMX_MAX_STRINGNAME_SIZE)) {
2073         secure_mode = true;
2074         arbitrary_bytes = false;
2075         role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2076     } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2077                 OMX_MAX_STRINGNAME_SIZE)) {
2078         secure_mode = true;
2079         arbitrary_bytes = false;
2080         role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2081     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2082                 OMX_MAX_STRINGNAME_SIZE)) {
2083         secure_mode = true;
2084         arbitrary_bytes = false;
2085         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2086     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2087                 OMX_MAX_STRINGNAME_SIZE)) {
2088         secure_mode = true;
2089         arbitrary_bytes = false;
2090         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2091     }
2092 
2093     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2094 
2095     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2096 
2097     if (drv_ctx.video_driver_fd < 0) {
2098         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2099         return OMX_ErrorInsufficientResources;
2100     }
2101     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2102     drv_ctx.frame_rate.fps_denominator = 1;
2103     m_poll_efd = eventfd(0, 0);
2104     if (m_poll_efd < 0) {
2105         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2106         return OMX_ErrorInsufficientResources;
2107     }
2108     ret = subscribe_to_events(drv_ctx.video_driver_fd);
2109     if (!ret) {
2110         async_thread_created = true;
2111         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2112     }
2113     if (ret) {
2114         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2115         async_thread_created = false;
2116         return OMX_ErrorInsufficientResources;
2117     }
2118 
2119 #ifdef OUTPUT_EXTRADATA_LOG
2120     outputExtradataFile = fopen (output_extradata_filename, "ab");
2121 #endif
2122 
2123     // Copy the role information which provides the decoder kind
2124     strlcpy(drv_ctx.kind,role,128);
2125 
2126     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2127                 OMX_MAX_STRINGNAME_SIZE)) {
2128         strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2129                 OMX_MAX_STRINGNAME_SIZE);
2130         drv_ctx.timestamp_adjust = true;
2131         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2132         eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2133         output_capability=V4L2_PIX_FMT_MPEG4;
2134         /*Initialize Start Code for MPEG4*/
2135         codec_type_parse = CODEC_TYPE_MPEG4;
2136         m_frame_parser.init_start_codes(codec_type_parse);
2137     } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2138                 OMX_MAX_STRINGNAME_SIZE)) {
2139         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2140                 OMX_MAX_STRINGNAME_SIZE);
2141         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2142         output_capability = V4L2_PIX_FMT_MPEG2;
2143         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2144         /*Initialize Start Code for MPEG2*/
2145         codec_type_parse = CODEC_TYPE_MPEG2;
2146         m_frame_parser.init_start_codes(codec_type_parse);
2147     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2148                 OMX_MAX_STRINGNAME_SIZE)) {
2149         strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2150         DEBUG_PRINT_LOW("H263 Decoder selected");
2151         drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2152         eCompressionFormat = OMX_VIDEO_CodingH263;
2153         output_capability = V4L2_PIX_FMT_H263;
2154         codec_type_parse = CODEC_TYPE_H263;
2155         m_frame_parser.init_start_codes(codec_type_parse);
2156     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2157                 OMX_MAX_STRINGNAME_SIZE)) {
2158         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2159         DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2160         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2161         output_capability = V4L2_PIX_FMT_DIVX_311;
2162         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2163         codec_type_parse = CODEC_TYPE_DIVX;
2164         m_frame_parser.init_start_codes(codec_type_parse);
2165 
2166     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2167                 OMX_MAX_STRINGNAME_SIZE)) {
2168         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2169         DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2170         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2171         output_capability = V4L2_PIX_FMT_DIVX;
2172         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2173         codec_type_parse = CODEC_TYPE_DIVX;
2174         codec_ambiguous = true;
2175         m_frame_parser.init_start_codes(codec_type_parse);
2176 
2177     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2178                 OMX_MAX_STRINGNAME_SIZE)) {
2179         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2180         DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2181         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2182         output_capability = V4L2_PIX_FMT_DIVX;
2183         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2184         codec_type_parse = CODEC_TYPE_DIVX;
2185         codec_ambiguous = true;
2186         m_frame_parser.init_start_codes(codec_type_parse);
2187 
2188     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2189                 OMX_MAX_STRINGNAME_SIZE)) {
2190         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2191         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2192         output_capability=V4L2_PIX_FMT_H264;
2193         eCompressionFormat = OMX_VIDEO_CodingAVC;
2194         codec_type_parse = CODEC_TYPE_H264;
2195         m_frame_parser.init_start_codes(codec_type_parse);
2196         m_frame_parser.init_nal_length(nal_length);
2197         if (is_thulium_v1) {
2198             arbitrary_bytes = true;
2199             DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2200         }
2201     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2202                 OMX_MAX_STRINGNAME_SIZE)) {
2203         strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2204         drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2205         output_capability = V4L2_PIX_FMT_H264_MVC;
2206         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2207         codec_type_parse = CODEC_TYPE_H264;
2208         m_frame_parser.init_start_codes(codec_type_parse);
2209         m_frame_parser.init_nal_length(nal_length);
2210     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2211                 OMX_MAX_STRINGNAME_SIZE)) {
2212         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2213         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2214         output_capability = V4L2_PIX_FMT_HEVC;
2215         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2216         codec_type_parse = CODEC_TYPE_HEVC;
2217         m_frame_parser.init_start_codes(codec_type_parse);
2218         m_frame_parser.init_nal_length(nal_length);
2219     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2220                 OMX_MAX_STRINGNAME_SIZE)) {
2221         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2222         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2223         eCompressionFormat = OMX_VIDEO_CodingWMV;
2224         codec_type_parse = CODEC_TYPE_VC1;
2225         output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2226         m_frame_parser.init_start_codes(codec_type_parse);
2227     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2228                 OMX_MAX_STRINGNAME_SIZE)) {
2229         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2230         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2231         eCompressionFormat = OMX_VIDEO_CodingWMV;
2232         codec_type_parse = CODEC_TYPE_VC1;
2233         output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2234         m_frame_parser.init_start_codes(codec_type_parse);
2235     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2236                 OMX_MAX_STRINGNAME_SIZE)) {
2237         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2238         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2239         output_capability = V4L2_PIX_FMT_VP8;
2240         eCompressionFormat = OMX_VIDEO_CodingVP8;
2241         codec_type_parse = CODEC_TYPE_VP8;
2242         arbitrary_bytes = false;
2243     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2244                 OMX_MAX_STRINGNAME_SIZE)) {
2245         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2246         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2247         output_capability = V4L2_PIX_FMT_VP9;
2248         eCompressionFormat = OMX_VIDEO_CodingVP9;
2249         codec_type_parse = CODEC_TYPE_VP9;
2250         arbitrary_bytes = false;
2251     } else {
2252         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2253         eRet = OMX_ErrorInvalidComponentName;
2254     }
2255 
2256     if (eRet == OMX_ErrorNone) {
2257         OMX_COLOR_FORMATTYPE dest_color_format;
2258         if (m_disable_ubwc_mode) {
2259             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2260         } else {
2261             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2262         }
2263         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2264             dest_color_format = (OMX_COLOR_FORMATTYPE)
2265                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2266         else
2267             dest_color_format = (OMX_COLOR_FORMATTYPE)
2268                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2269         if (!client_buffers.set_color_format(dest_color_format)) {
2270             DEBUG_PRINT_ERROR("Setting color format failed");
2271             eRet = OMX_ErrorInsufficientResources;
2272         }
2273 
2274         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2275 
2276         if (m_disable_ubwc_mode) {
2277             capture_capability = V4L2_PIX_FMT_NV12;
2278         } else {
2279             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2280         }
2281 
2282         struct v4l2_capability cap;
2283         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2284         if (ret) {
2285             DEBUG_PRINT_ERROR("Failed to query capabilities");
2286             /*TODO: How to handle this case */
2287         } else {
2288             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2289                 " version = %d, capabilities = %x", cap.driver, cap.card,
2290                 cap.bus_info, cap.version, cap.capabilities);
2291         }
2292         ret=0;
2293         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2294         fdesc.index=0;
2295         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2296             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2297                     fdesc.pixelformat, fdesc.flags);
2298             fdesc.index++;
2299         }
2300         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2301         fdesc.index=0;
2302         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2303 
2304             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2305                     fdesc.pixelformat, fdesc.flags);
2306             fdesc.index++;
2307         }
2308         update_resolution(320, 240, 320, 240);
2309         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2310         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2311         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2312         fmt.fmt.pix_mp.pixelformat = output_capability;
2313         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2314         if (ret) {
2315             /*TODO: How to handle this case */
2316             DEBUG_PRINT_ERROR("Failed to set format on output port");
2317             return OMX_ErrorInsufficientResources;
2318         }
2319         DEBUG_PRINT_HIGH("Set Format was successful");
2320         if (codec_ambiguous) {
2321             if (output_capability == V4L2_PIX_FMT_DIVX) {
2322                 struct v4l2_control divx_ctrl;
2323 
2324                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2325                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2326                 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2327                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2328                 } else {
2329                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2330                 }
2331 
2332                 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2333                 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2334                 if (ret) {
2335                     DEBUG_PRINT_ERROR("Failed to set divx version");
2336                 }
2337             } else {
2338                 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2339             }
2340         }
2341 
2342         property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2343         m_conceal_color= atoi(property_value);
2344         DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2345         control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2346         control.value = m_conceal_color;
2347         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2348         if (ret) {
2349             DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2350         }
2351 
2352         //Get the hardware capabilities
2353         memset((void *)&frmsize,0,sizeof(frmsize));
2354         frmsize.index = 0;
2355         frmsize.pixel_format = output_capability;
2356         ret = ioctl(drv_ctx.video_driver_fd,
2357                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2358         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2359             DEBUG_PRINT_ERROR("Failed to get framesizes");
2360             return OMX_ErrorHardware;
2361         }
2362 
2363         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2364             m_decoder_capability.min_width = frmsize.stepwise.min_width;
2365             m_decoder_capability.max_width = frmsize.stepwise.max_width;
2366             m_decoder_capability.min_height = frmsize.stepwise.min_height;
2367             m_decoder_capability.max_height = frmsize.stepwise.max_height;
2368         }
2369 
2370         memset(&fmt, 0x0, sizeof(struct v4l2_format));
2371         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2372         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2373         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2374         fmt.fmt.pix_mp.pixelformat = capture_capability;
2375         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2376         if (ret) {
2377             /*TODO: How to handle this case */
2378             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2379         }
2380         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2381         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2382         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2383 
2384         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2385         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2386         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2387 
2388         DEBUG_PRINT_HIGH("Set Format was successful");
2389         if (secure_mode) {
2390             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2391             control.value = 1;
2392             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2393             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2394             if (ret) {
2395                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2396                 return OMX_ErrorInsufficientResources;
2397             }
2398         }
2399         if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2400             control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2401             control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2402             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2403             if (ret) {
2404                 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2405                 return OMX_ErrorInsufficientResources;
2406             }
2407         }
2408 
2409         if (is_thulium_v1) {
2410             eRet = enable_smoothstreaming();
2411             if (eRet != OMX_ErrorNone) {
2412                DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2413                return eRet;
2414             }
2415         }
2416 
2417         /*Get the Buffer requirements for input and output ports*/
2418         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2419         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2420 
2421         if (secure_mode) {
2422             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2423             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2424         } else {
2425             drv_ctx.op_buf.alignment = SZ_4K;
2426             drv_ctx.ip_buf.alignment = SZ_4K;
2427         }
2428 
2429         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2430         drv_ctx.extradata = 0;
2431         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2432         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2433         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2434         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2435         drv_ctx.idr_only_decoding = 0;
2436 
2437 #ifdef _ANDROID_
2438         property_get("vidc.dec.downscalar_width",property_value,"0");
2439         if (atoi(property_value)) {
2440             m_downscalar_width = atoi(property_value);
2441         }
2442         property_get("vidc.dec.downscalar_height",property_value,"0");
2443         if (atoi(property_value)) {
2444             m_downscalar_height = atoi(property_value);
2445         }
2446 
2447         if (m_downscalar_width < m_decoder_capability.min_width ||
2448             m_downscalar_height < m_decoder_capability.min_height) {
2449             m_downscalar_width = 0;
2450             m_downscalar_height = 0;
2451         }
2452 
2453         DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2454             m_downscalar_width, m_downscalar_height);
2455 #endif
2456         m_state = OMX_StateLoaded;
2457 #ifdef DEFAULT_EXTRADATA
2458         if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",
2459                     OMX_MAX_STRINGNAME_SIZE) &&
2460                 strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",
2461                         OMX_MAX_STRINGNAME_SIZE)) &&
2462                 (eRet == OMX_ErrorNone))
2463                 enable_extradata(DEFAULT_EXTRADATA, true, true);
2464 #endif
2465         eRet = get_buffer_req(&drv_ctx.ip_buf);
2466         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2467         get_buffer_req(&drv_ctx.op_buf);
2468         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2469                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2470                 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2471                     h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2472                     h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2473                     h264_scratch.nFilledLen = 0;
2474                     h264_scratch.nOffset = 0;
2475 
2476                     if (h264_scratch.pBuffer == NULL) {
2477                         DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2478                         return OMX_ErrorInsufficientResources;
2479                     }
2480         }
2481         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2482             drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2483             if (m_frame_parser.mutils == NULL) {
2484                 m_frame_parser.mutils = new H264_Utils();
2485                 if (m_frame_parser.mutils == NULL) {
2486                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2487                     eRet = OMX_ErrorInsufficientResources;
2488                 } else {
2489                     m_frame_parser.mutils->initialize_frame_checking_environment();
2490                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2491                 }
2492             }
2493 
2494             h264_parser = new h264_stream_parser();
2495             if (!h264_parser) {
2496                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2497                 eRet = OMX_ErrorInsufficientResources;
2498             }
2499         }
2500 
2501         if (pipe(fds)) {
2502             DEBUG_PRINT_ERROR("pipe creation failed");
2503             eRet = OMX_ErrorInsufficientResources;
2504         } else {
2505             m_pipe_in = fds[0];
2506             m_pipe_out = fds[1];
2507             msg_thread_created = true;
2508             r = pthread_create(&msg_thread_id,0,message_thread,this);
2509 
2510             if (r < 0) {
2511                 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
2512                 msg_thread_created = false;
2513                 eRet = OMX_ErrorInsufficientResources;
2514             }
2515         }
2516     }
2517 
2518     if (eRet != OMX_ErrorNone) {
2519         DEBUG_PRINT_ERROR("Component Init Failed");
2520     } else {
2521         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2522                 drv_ctx.video_driver_fd);
2523     }
2524     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2525     return eRet;
2526 }
2527 
2528 /* ======================================================================
2529    FUNCTION
2530    omx_vdec::GetComponentVersion
2531 
2532    DESCRIPTION
2533    Returns the component version.
2534 
2535    PARAMETERS
2536    TBD.
2537 
2538    RETURN VALUE
2539    OMX_ErrorNone.
2540 
2541    ========================================================================== */
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)2542 OMX_ERRORTYPE  omx_vdec::get_component_version
2543 (
2544  OMX_IN OMX_HANDLETYPE hComp,
2545  OMX_OUT OMX_STRING componentName,
2546  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2547  OMX_OUT OMX_VERSIONTYPE* specVersion,
2548  OMX_OUT OMX_UUIDTYPE* componentUUID
2549  )
2550 {
2551     (void) hComp;
2552     (void) componentName;
2553     (void) componentVersion;
2554     (void) componentUUID;
2555     if (m_state == OMX_StateInvalid) {
2556         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2557         return OMX_ErrorInvalidState;
2558     }
2559     /* TBD -- Return the proper version */
2560     if (specVersion) {
2561         specVersion->nVersion = OMX_SPEC_VERSION;
2562     }
2563     return OMX_ErrorNone;
2564 }
2565 /* ======================================================================
2566    FUNCTION
2567    omx_vdec::SendCommand
2568 
2569    DESCRIPTION
2570    Returns zero if all the buffers released..
2571 
2572    PARAMETERS
2573    None.
2574 
2575    RETURN VALUE
2576    true/false
2577 
2578    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2579 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2580         OMX_IN OMX_COMMANDTYPE cmd,
2581         OMX_IN OMX_U32 param1,
2582         OMX_IN OMX_PTR cmdData
2583         )
2584 {
2585     (void) hComp;
2586     (void) cmdData;
2587     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2588     if (m_state == OMX_StateInvalid) {
2589         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2590         return OMX_ErrorInvalidState;
2591     }
2592     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2593             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2594         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2595                 "to invalid port: %u", (unsigned int)param1);
2596         return OMX_ErrorBadPortIndex;
2597     }
2598 
2599     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2600     sem_wait(&m_cmd_lock);
2601     DEBUG_PRINT_LOW("send_command: Command Processed");
2602     return OMX_ErrorNone;
2603 }
2604 
2605 /* ======================================================================
2606    FUNCTION
2607    omx_vdec::SendCommand
2608 
2609    DESCRIPTION
2610    Returns zero if all the buffers released..
2611 
2612    PARAMETERS
2613    None.
2614 
2615    RETURN VALUE
2616    true/false
2617 
2618    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2619 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2620         OMX_IN OMX_COMMANDTYPE cmd,
2621         OMX_IN OMX_U32 param1,
2622         OMX_IN OMX_PTR cmdData
2623         )
2624 {
2625     (void) hComp;
2626     (void) cmdData;
2627     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2628     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2629     int bFlag = 1,sem_posted = 0,ret=0;
2630 
2631     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2632     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2633             m_state, eState);
2634 
2635     if (cmd == OMX_CommandStateSet) {
2636         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2637         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2638         /***************************/
2639         /* Current State is Loaded */
2640         /***************************/
2641         if (m_state == OMX_StateLoaded) {
2642             if (eState == OMX_StateIdle) {
2643                 //if all buffers are allocated or all ports disabled
2644                 if (allocate_done() ||
2645                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2646                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2647                 } else {
2648                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2649                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2650                     // Skip the event notification
2651                     bFlag = 0;
2652                 }
2653             }
2654             /* Requesting transition from Loaded to Loaded */
2655             else if (eState == OMX_StateLoaded) {
2656                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2657                 post_event(OMX_EventError,OMX_ErrorSameState,\
2658                         OMX_COMPONENT_GENERATE_EVENT);
2659                 eRet = OMX_ErrorSameState;
2660             }
2661             /* Requesting transition from Loaded to WaitForResources */
2662             else if (eState == OMX_StateWaitForResources) {
2663                 /* Since error is None , we will post an event
2664                    at the end of this function definition */
2665                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2666             }
2667             /* Requesting transition from Loaded to Executing */
2668             else if (eState == OMX_StateExecuting) {
2669                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2670                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2671                         OMX_COMPONENT_GENERATE_EVENT);
2672                 eRet = OMX_ErrorIncorrectStateTransition;
2673             }
2674             /* Requesting transition from Loaded to Pause */
2675             else if (eState == OMX_StatePause) {
2676                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2677                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2678                         OMX_COMPONENT_GENERATE_EVENT);
2679                 eRet = OMX_ErrorIncorrectStateTransition;
2680             }
2681             /* Requesting transition from Loaded to Invalid */
2682             else if (eState == OMX_StateInvalid) {
2683                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2684                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2685                 eRet = OMX_ErrorInvalidState;
2686             } else {
2687                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2688                         eState);
2689                 eRet = OMX_ErrorBadParameter;
2690             }
2691         }
2692 
2693         /***************************/
2694         /* Current State is IDLE */
2695         /***************************/
2696         else if (m_state == OMX_StateIdle) {
2697             if (eState == OMX_StateLoaded) {
2698                 if (release_done()) {
2699                     /*
2700                        Since error is None , we will post an event at the end
2701                        of this function definition
2702                      */
2703                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2704                 } else {
2705                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2706                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2707                     // Skip the event notification
2708                     bFlag = 0;
2709                 }
2710             }
2711             /* Requesting transition from Idle to Executing */
2712             else if (eState == OMX_StateExecuting) {
2713                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2714                 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2715                 bFlag = 1;
2716                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2717                 m_state=OMX_StateExecuting;
2718                 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2719             }
2720             /* Requesting transition from Idle to Idle */
2721             else if (eState == OMX_StateIdle) {
2722                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2723                 post_event(OMX_EventError,OMX_ErrorSameState,\
2724                         OMX_COMPONENT_GENERATE_EVENT);
2725                 eRet = OMX_ErrorSameState;
2726             }
2727             /* Requesting transition from Idle to WaitForResources */
2728             else if (eState == OMX_StateWaitForResources) {
2729                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2730                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2731                         OMX_COMPONENT_GENERATE_EVENT);
2732                 eRet = OMX_ErrorIncorrectStateTransition;
2733             }
2734             /* Requesting transition from Idle to Pause */
2735             else if (eState == OMX_StatePause) {
2736                 /*To pause the Video core we need to start the driver*/
2737                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2738                       NULL) < */0) {
2739                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2740                     omx_report_error ();
2741                     eRet = OMX_ErrorHardware;
2742                 } else {
2743                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2744                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2745                     bFlag = 0;
2746                 }
2747             }
2748             /* Requesting transition from Idle to Invalid */
2749             else if (eState == OMX_StateInvalid) {
2750                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2751                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2752                 eRet = OMX_ErrorInvalidState;
2753             } else {
2754                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2755                 eRet = OMX_ErrorBadParameter;
2756             }
2757         }
2758 
2759         /******************************/
2760         /* Current State is Executing */
2761         /******************************/
2762         else if (m_state == OMX_StateExecuting) {
2763             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2764             /* Requesting transition from Executing to Idle */
2765             if (eState == OMX_StateIdle) {
2766                 /* Since error is None , we will post an event
2767                    at the end of this function definition
2768                  */
2769                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2770                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2771                 if (!sem_posted) {
2772                     sem_posted = 1;
2773                     sem_post (&m_cmd_lock);
2774                     execute_omx_flush(OMX_ALL);
2775                 }
2776                 bFlag = 0;
2777             }
2778             /* Requesting transition from Executing to Paused */
2779             else if (eState == OMX_StatePause) {
2780                 DEBUG_PRINT_LOW("PAUSE Command Issued");
2781                 m_state = OMX_StatePause;
2782                 bFlag = 1;
2783             }
2784             /* Requesting transition from Executing to Loaded */
2785             else if (eState == OMX_StateLoaded) {
2786                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2787                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2788                         OMX_COMPONENT_GENERATE_EVENT);
2789                 eRet = OMX_ErrorIncorrectStateTransition;
2790             }
2791             /* Requesting transition from Executing to WaitForResources */
2792             else if (eState == OMX_StateWaitForResources) {
2793                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2794                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2795                         OMX_COMPONENT_GENERATE_EVENT);
2796                 eRet = OMX_ErrorIncorrectStateTransition;
2797             }
2798             /* Requesting transition from Executing to Executing */
2799             else if (eState == OMX_StateExecuting) {
2800                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2801                 post_event(OMX_EventError,OMX_ErrorSameState,\
2802                         OMX_COMPONENT_GENERATE_EVENT);
2803                 eRet = OMX_ErrorSameState;
2804             }
2805             /* Requesting transition from Executing to Invalid */
2806             else if (eState == OMX_StateInvalid) {
2807                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2808                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2809                 eRet = OMX_ErrorInvalidState;
2810             } else {
2811                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2812                 eRet = OMX_ErrorBadParameter;
2813             }
2814         }
2815         /***************************/
2816         /* Current State is Pause  */
2817         /***************************/
2818         else if (m_state == OMX_StatePause) {
2819             /* Requesting transition from Pause to Executing */
2820             if (eState == OMX_StateExecuting) {
2821                 DEBUG_PRINT_LOW("Pause --> Executing");
2822                 m_state = OMX_StateExecuting;
2823                 bFlag = 1;
2824             }
2825             /* Requesting transition from Pause to Idle */
2826             else if (eState == OMX_StateIdle) {
2827                 /* Since error is None , we will post an event
2828                    at the end of this function definition */
2829                 DEBUG_PRINT_LOW("Pause --> Idle");
2830                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2831                 if (!sem_posted) {
2832                     sem_posted = 1;
2833                     sem_post (&m_cmd_lock);
2834                     execute_omx_flush(OMX_ALL);
2835                 }
2836                 bFlag = 0;
2837             }
2838             /* Requesting transition from Pause to loaded */
2839             else if (eState == OMX_StateLoaded) {
2840                 DEBUG_PRINT_ERROR("Pause --> loaded");
2841                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2842                         OMX_COMPONENT_GENERATE_EVENT);
2843                 eRet = OMX_ErrorIncorrectStateTransition;
2844             }
2845             /* Requesting transition from Pause to WaitForResources */
2846             else if (eState == OMX_StateWaitForResources) {
2847                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2848                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2849                         OMX_COMPONENT_GENERATE_EVENT);
2850                 eRet = OMX_ErrorIncorrectStateTransition;
2851             }
2852             /* Requesting transition from Pause to Pause */
2853             else if (eState == OMX_StatePause) {
2854                 DEBUG_PRINT_ERROR("Pause --> Pause");
2855                 post_event(OMX_EventError,OMX_ErrorSameState,\
2856                         OMX_COMPONENT_GENERATE_EVENT);
2857                 eRet = OMX_ErrorSameState;
2858             }
2859             /* Requesting transition from Pause to Invalid */
2860             else if (eState == OMX_StateInvalid) {
2861                 DEBUG_PRINT_ERROR("Pause --> Invalid");
2862                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2863                 eRet = OMX_ErrorInvalidState;
2864             } else {
2865                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2866                 eRet = OMX_ErrorBadParameter;
2867             }
2868         }
2869         /***************************/
2870         /* Current State is WaitForResources  */
2871         /***************************/
2872         else if (m_state == OMX_StateWaitForResources) {
2873             /* Requesting transition from WaitForResources to Loaded */
2874             if (eState == OMX_StateLoaded) {
2875                 /* Since error is None , we will post an event
2876                    at the end of this function definition */
2877                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2878             }
2879             /* Requesting transition from WaitForResources to WaitForResources */
2880             else if (eState == OMX_StateWaitForResources) {
2881                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2882                 post_event(OMX_EventError,OMX_ErrorSameState,
2883                         OMX_COMPONENT_GENERATE_EVENT);
2884                 eRet = OMX_ErrorSameState;
2885             }
2886             /* Requesting transition from WaitForResources to Executing */
2887             else if (eState == OMX_StateExecuting) {
2888                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2889                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2890                         OMX_COMPONENT_GENERATE_EVENT);
2891                 eRet = OMX_ErrorIncorrectStateTransition;
2892             }
2893             /* Requesting transition from WaitForResources to Pause */
2894             else if (eState == OMX_StatePause) {
2895                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2896                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2897                         OMX_COMPONENT_GENERATE_EVENT);
2898                 eRet = OMX_ErrorIncorrectStateTransition;
2899             }
2900             /* Requesting transition from WaitForResources to Invalid */
2901             else if (eState == OMX_StateInvalid) {
2902                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2903                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2904                 eRet = OMX_ErrorInvalidState;
2905             }
2906             /* Requesting transition from WaitForResources to Loaded -
2907                is NOT tested by Khronos TS */
2908 
2909         } else {
2910             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2911             eRet = OMX_ErrorBadParameter;
2912         }
2913     }
2914     /********************************/
2915     /* Current State is Invalid */
2916     /*******************************/
2917     else if (m_state == OMX_StateInvalid) {
2918         /* State Transition from Inavlid to any state */
2919         if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
2920                     || OMX_StateIdle || OMX_StateExecuting
2921                     || OMX_StatePause || OMX_StateInvalid)) {
2922             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2923             post_event(OMX_EventError,OMX_ErrorInvalidState,\
2924                     OMX_COMPONENT_GENERATE_EVENT);
2925             eRet = OMX_ErrorInvalidState;
2926         }
2927     } else if (cmd == OMX_CommandFlush) {
2928         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2929                 "with param1: %u", (unsigned int)param1);
2930 #ifdef _MSM8974_
2931         send_codec_config();
2932 #endif
2933         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2934                     param1 == OMX_ALL)) {
2935             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2936                struct timespec ts;
2937 
2938                clock_gettime(CLOCK_REALTIME, &ts);
2939                ts.tv_sec += 2;
2940                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2941                        m_queued_codec_config_count);
2942                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2943                if (sem_timedwait(&m_safe_flush, &ts)) {
2944                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2945                }
2946                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2947             }
2948         }
2949 
2950         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2951             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2952         }
2953         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2954             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2955         }
2956         if (!sem_posted) {
2957             sem_posted = 1;
2958             DEBUG_PRINT_LOW("Set the Semaphore");
2959             sem_post (&m_cmd_lock);
2960             execute_omx_flush(param1);
2961         }
2962         bFlag = 0;
2963     } else if ( cmd == OMX_CommandPortEnable) {
2964         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2965                 "with param1: %u", (unsigned int)param1);
2966         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2967             m_inp_bEnabled = OMX_TRUE;
2968 
2969             if ( (m_state == OMX_StateLoaded &&
2970                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2971                     || allocate_input_done()) {
2972                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2973                         OMX_COMPONENT_GENERATE_EVENT);
2974             } else {
2975                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2976                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2977                 // Skip the event notification
2978                 bFlag = 0;
2979             }
2980         }
2981         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2982             DEBUG_PRINT_LOW("Enable output Port command recieved");
2983             m_out_bEnabled = OMX_TRUE;
2984 
2985             if ( (m_state == OMX_StateLoaded &&
2986                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2987                     || (allocate_output_done())) {
2988                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2989                         OMX_COMPONENT_GENERATE_EVENT);
2990 
2991             } else {
2992                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2993                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2994                 // Skip the event notification
2995                 bFlag = 0;
2996                 /* enable/disable downscaling if required */
2997                 ret = decide_downscalar();
2998                 if (ret) {
2999                     DEBUG_PRINT_LOW("decide_downscalar failed\n");
3000                 }
3001             }
3002         }
3003     } else if (cmd == OMX_CommandPortDisable) {
3004         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3005                 "with param1: %u", (unsigned int)param1);
3006         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3007             codec_config_flag = false;
3008             m_inp_bEnabled = OMX_FALSE;
3009             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3010                     && release_input_done()) {
3011                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3012                         OMX_COMPONENT_GENERATE_EVENT);
3013             } else {
3014                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3015                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3016                     if (!sem_posted) {
3017                         sem_posted = 1;
3018                         sem_post (&m_cmd_lock);
3019                     }
3020                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3021                 }
3022 
3023                 // Skip the event notification
3024                 bFlag = 0;
3025             }
3026         }
3027         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3028             m_out_bEnabled = OMX_FALSE;
3029             DEBUG_PRINT_LOW("Disable output Port command recieved");
3030             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3031                     && release_output_done()) {
3032                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3033                         OMX_COMPONENT_GENERATE_EVENT);
3034             } else {
3035                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_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                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3042                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3043                 }
3044                 // Skip the event notification
3045                 bFlag = 0;
3046 
3047             }
3048         }
3049     } else {
3050         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3051         eRet = OMX_ErrorNotImplemented;
3052     }
3053     if (eRet == OMX_ErrorNone && bFlag) {
3054         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3055     }
3056     if (!sem_posted) {
3057         sem_post(&m_cmd_lock);
3058     }
3059 
3060     return eRet;
3061 }
3062 
3063 /* ======================================================================
3064    FUNCTION
3065    omx_vdec::ExecuteOmxFlush
3066 
3067    DESCRIPTION
3068    Executes the OMX flush.
3069 
3070    PARAMETERS
3071    flushtype - input flush(1)/output flush(0)/ both.
3072 
3073    RETURN VALUE
3074    true/false
3075 
3076    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3077 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3078 {
3079     bool bRet = false;
3080     struct v4l2_plane plane;
3081     struct v4l2_buffer v4l2_buf;
3082     struct v4l2_decoder_cmd dec;
3083     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3084     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3085     dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3086 
3087     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3088 
3089     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3090         output_flush_progress = true;
3091         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3092     } else {
3093         /* XXX: The driver/hardware does not support flushing of individual ports
3094          * in all states. So we pretty much need to flush both ports internally,
3095          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3096          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3097          * we automatically omit sending the FLUSH done for the "opposite" port. */
3098         input_flush_progress = true;
3099         output_flush_progress = true;
3100         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3101         request_perf_level(VIDC_TURBO);
3102     }
3103 
3104     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3105         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3106         bRet = false;
3107     }
3108 
3109     return bRet;
3110 }
3111 /*=========================================================================
3112 FUNCTION : execute_output_flush
3113 
3114 DESCRIPTION
3115 Executes the OMX flush at OUTPUT PORT.
3116 
3117 PARAMETERS
3118 None.
3119 
3120 RETURN VALUE
3121 true/false
3122 ==========================================================================*/
execute_output_flush()3123 bool omx_vdec::execute_output_flush()
3124 {
3125     unsigned long p1 = 0; // Parameter - 1
3126     unsigned long p2 = 0; // Parameter - 2
3127     unsigned long ident = 0;
3128     bool bRet = true;
3129 
3130     /*Generate FBD for all Buffers in the FTBq*/
3131     pthread_mutex_lock(&m_lock);
3132     DEBUG_PRINT_LOW("Initiate Output Flush");
3133 
3134     //reset last render TS
3135     if(m_last_rendered_TS > 0) {
3136         m_last_rendered_TS = 0;
3137     }
3138 
3139     while (m_ftb_q.m_size) {
3140         DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3141                 m_ftb_q.m_size,pending_output_buffers);
3142         m_ftb_q.pop_entry(&p1,&p2,&ident);
3143         DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3144         if (ident == m_fill_output_msg ) {
3145             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3146         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3147             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3148         }
3149     }
3150     pthread_mutex_unlock(&m_lock);
3151     output_flush_progress = false;
3152 
3153     if (arbitrary_bytes) {
3154         prev_ts = LLONG_MAX;
3155         rst_prev_ts = true;
3156     }
3157     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3158     return bRet;
3159 }
3160 /*=========================================================================
3161 FUNCTION : execute_input_flush
3162 
3163 DESCRIPTION
3164 Executes the OMX flush at INPUT PORT.
3165 
3166 PARAMETERS
3167 None.
3168 
3169 RETURN VALUE
3170 true/false
3171 ==========================================================================*/
execute_input_flush()3172 bool omx_vdec::execute_input_flush()
3173 {
3174     unsigned       i =0;
3175     unsigned long p1 = 0; // Parameter - 1
3176     unsigned long p2 = 0; // Parameter - 2
3177     unsigned long ident = 0;
3178     bool bRet = true;
3179 
3180     /*Generate EBD for all Buffers in the ETBq*/
3181     DEBUG_PRINT_LOW("Initiate Input Flush");
3182 
3183     pthread_mutex_lock(&m_lock);
3184     DEBUG_PRINT_LOW("Check if the Queue is empty");
3185     while (m_etb_q.m_size) {
3186         m_etb_q.pop_entry(&p1,&p2,&ident);
3187 
3188         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3189             DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3190             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3191         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3192             pending_input_buffers++;
3193             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3194                     (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3195             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3196         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3197             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3198                     (OMX_BUFFERHEADERTYPE *)p1);
3199             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3200         }
3201     }
3202     time_stamp_dts.flush_timestamp();
3203     /*Check if Heap Buffers are to be flushed*/
3204     if (arbitrary_bytes && !(codec_config_flag)) {
3205         DEBUG_PRINT_LOW("Reset all the variables before flusing");
3206         h264_scratch.nFilledLen = 0;
3207         nal_count = 0;
3208         look_ahead_nal = false;
3209         frame_count = 0;
3210         h264_last_au_ts = LLONG_MAX;
3211         h264_last_au_flags = 0;
3212         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3213         m_demux_entries = 0;
3214         DEBUG_PRINT_LOW("Initialize parser");
3215         if (m_frame_parser.mutils) {
3216             m_frame_parser.mutils->initialize_frame_checking_environment();
3217         }
3218 
3219         while (m_input_pending_q.m_size) {
3220             m_input_pending_q.pop_entry(&p1,&p2,&ident);
3221             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3222         }
3223 
3224         if (psource_frame) {
3225             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3226             psource_frame = NULL;
3227         }
3228 
3229         if (pdest_frame) {
3230             pdest_frame->nFilledLen = 0;
3231             m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3232                     (unsigned int)NULL);
3233             pdest_frame = NULL;
3234         }
3235         m_frame_parser.flush();
3236     } else if (codec_config_flag) {
3237         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3238                 "is not sent to the driver yet");
3239     }
3240     pthread_mutex_unlock(&m_lock);
3241     input_flush_progress = false;
3242     if (!arbitrary_bytes) {
3243         prev_ts = LLONG_MAX;
3244         rst_prev_ts = true;
3245     }
3246 #ifdef _ANDROID_
3247     if (m_debug_timestamp) {
3248         m_timestamp_list.reset_ts_list();
3249     }
3250 #endif
3251     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3252     return bRet;
3253 }
3254 
3255 
3256 /* ======================================================================
3257    FUNCTION
3258    omx_vdec::SendCommandEvent
3259 
3260    DESCRIPTION
3261    Send the event to decoder pipe.  This is needed to generate the callbacks
3262    in decoder thread context.
3263 
3264    PARAMETERS
3265    None.
3266 
3267    RETURN VALUE
3268    true/false
3269 
3270    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3271 bool omx_vdec::post_event(unsigned long p1,
3272         unsigned long p2,
3273         unsigned long id)
3274 {
3275     bool bRet = false;
3276 
3277     /* Just drop messages typically generated by hardware (w/o client request),
3278      * if we've reported an error to client. */
3279     if (m_error_propogated) {
3280         switch (id) {
3281             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3282             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3283                 DEBUG_PRINT_ERROR("Dropping message %lx "
3284                         "since client expected to be in error state", id);
3285                 return false;
3286             default:
3287                 /* whatever */
3288                 break;
3289         }
3290     }
3291 
3292     pthread_mutex_lock(&m_lock);
3293 
3294     if (id == m_fill_output_msg ||
3295             id == OMX_COMPONENT_GENERATE_FBD ||
3296             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3297             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3298         m_ftb_q.insert_entry(p1,p2,id);
3299     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3300             id == OMX_COMPONENT_GENERATE_EBD ||
3301             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3302             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3303         m_etb_q.insert_entry(p1,p2,id);
3304     } else {
3305         m_cmd_q.insert_entry(p1,p2,id);
3306     }
3307 
3308     bRet = true;
3309     DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3310     post_message(this, id);
3311 
3312     pthread_mutex_unlock(&m_lock);
3313 
3314     return bRet;
3315 }
3316 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3317 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3318 {
3319     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3320     if (!profileLevelType)
3321         return OMX_ErrorBadParameter;
3322 
3323     if (profileLevelType->nPortIndex == 0) {
3324         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3325             if (profileLevelType->nProfileIndex == 0) {
3326                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3327                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3328 
3329             } else if (profileLevelType->nProfileIndex == 1) {
3330                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3331                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3332             } else if (profileLevelType->nProfileIndex == 2) {
3333                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3334                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3335             } else {
3336                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3337                         (unsigned int)profileLevelType->nProfileIndex);
3338                 eRet = OMX_ErrorNoMore;
3339             }
3340         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3341             if (profileLevelType->nProfileIndex == 0) {
3342                 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3343                 profileLevelType->eLevel   = QOMX_VIDEO_MVCLevel51;
3344             } else {
3345                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3346                                 (unsigned int)profileLevelType->nProfileIndex);
3347                 eRet = OMX_ErrorNoMore;
3348             }
3349         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3350             if (profileLevelType->nProfileIndex == 0) {
3351                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3352                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3353             } else {
3354                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3355                         (unsigned int)profileLevelType->nProfileIndex);
3356                 eRet = OMX_ErrorNoMore;
3357             }
3358         } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3359             if (profileLevelType->nProfileIndex == 0) {
3360                 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3361                 profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
3362             } else {
3363                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3364                                 (unsigned int)profileLevelType->nProfileIndex);
3365                 eRet = OMX_ErrorNoMore;
3366             }
3367         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3368             if (profileLevelType->nProfileIndex == 0) {
3369                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3370                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3371             } else if (profileLevelType->nProfileIndex == 1) {
3372                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3373                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3374             } else {
3375                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3376                                 (unsigned int)profileLevelType->nProfileIndex);
3377                 eRet = OMX_ErrorNoMore;
3378             }
3379         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3380                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3381             eRet = OMX_ErrorNoMore;
3382         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3383             if (profileLevelType->nProfileIndex == 0) {
3384                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3385                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3386             } else if (profileLevelType->nProfileIndex == 1) {
3387                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3388                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3389             } else {
3390                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3391                                 (unsigned int)profileLevelType->nProfileIndex);
3392                 eRet = OMX_ErrorNoMore;
3393             }
3394         } else {
3395             DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3396             eRet = OMX_ErrorNoMore;
3397         }
3398     } else {
3399         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3400                           (unsigned int)profileLevelType->nPortIndex);
3401         eRet = OMX_ErrorBadPortIndex;
3402     }
3403     return eRet;
3404 }
3405 
3406 /* ======================================================================
3407    FUNCTION
3408    omx_vdec::GetParameter
3409 
3410    DESCRIPTION
3411    OMX Get Parameter method implementation
3412 
3413    PARAMETERS
3414    <TBD>.
3415 
3416    RETURN VALUE
3417    Error None if successful.
3418 
3419    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3420 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3421         OMX_IN OMX_INDEXTYPE paramIndex,
3422         OMX_INOUT OMX_PTR     paramData)
3423 {
3424     (void) hComp;
3425     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3426 
3427     DEBUG_PRINT_LOW("get_parameter:");
3428     if (m_state == OMX_StateInvalid) {
3429         DEBUG_PRINT_ERROR("Get Param in Invalid State");
3430         return OMX_ErrorInvalidState;
3431     }
3432     if (paramData == NULL) {
3433         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3434         return OMX_ErrorBadParameter;
3435     }
3436     switch ((unsigned long)paramIndex) {
3437         case OMX_IndexParamPortDefinition: {
3438                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3439                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3440                                    (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3441                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3442                                decide_dpb_buffer_mode(is_down_scalar_enabled);
3443                                eRet = update_portdef(portDefn);
3444                                if (eRet == OMX_ErrorNone)
3445                                    m_port_def = *portDefn;
3446                                break;
3447                            }
3448         case OMX_IndexParamVideoInit: {
3449                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3450                               OMX_PORT_PARAM_TYPE *portParamType =
3451                                   (OMX_PORT_PARAM_TYPE *) paramData;
3452                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3453 
3454                               portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3455                               portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3456                               portParamType->nPorts           = 2;
3457                               portParamType->nStartPortNumber = 0;
3458                               break;
3459                           }
3460         case OMX_IndexParamVideoPortFormat: {
3461                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3462                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3463                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3464                                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3465 
3466                                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3467                                 portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3468 
3469                                 if (0 == portFmt->nPortIndex) {
3470                                     if (0 == portFmt->nIndex) {
3471                                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3472                                         portFmt->eCompressionFormat = eCompressionFormat;
3473                                     } else {
3474                                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3475                                                 " NoMore compression formats");
3476                                         eRet =  OMX_ErrorNoMore;
3477                                     }
3478                                 } else if (1 == portFmt->nPortIndex) {
3479                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3480 
3481                                     // Distinguish non-surface mode from normal playback use-case based on
3482                                     // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3483                                     // For non-android, use the default list
3484                                     // Also use default format-list if FLEXIBLE YUV is supported,
3485                                     // as the client negotiates the standard color-format if it needs to
3486                                     bool useNonSurfaceMode = false;
3487 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3488                                     useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3489 #endif
3490                                     if (is_thulium_v1) {
3491                                         portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3492                                     } else {
3493                                         portFmt->eColorFormat = useNonSurfaceMode ?
3494                                             getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3495                                             getPreferredColorFormatDefaultMode(portFmt->nIndex);
3496                                     }
3497 
3498                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3499                                         eRet = OMX_ErrorNoMore;
3500                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3501                                                 " NoMore Color formats");
3502                                     }
3503                                     DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3504                                 } else {
3505                                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3506                                             (int)portFmt->nPortIndex);
3507                                     eRet = OMX_ErrorBadPortIndex;
3508                                 }
3509                                 break;
3510                             }
3511                             /*Component should support this port definition*/
3512         case OMX_IndexParamAudioInit: {
3513                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3514                               OMX_PORT_PARAM_TYPE *audioPortParamType =
3515                                   (OMX_PORT_PARAM_TYPE *) paramData;
3516                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3517                               audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3518                               audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3519                               audioPortParamType->nPorts           = 0;
3520                               audioPortParamType->nStartPortNumber = 0;
3521                               break;
3522                           }
3523                           /*Component should support this port definition*/
3524         case OMX_IndexParamImageInit: {
3525                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3526                               OMX_PORT_PARAM_TYPE *imagePortParamType =
3527                                   (OMX_PORT_PARAM_TYPE *) paramData;
3528                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3529                               imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3530                               imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3531                               imagePortParamType->nPorts           = 0;
3532                               imagePortParamType->nStartPortNumber = 0;
3533                               break;
3534 
3535                           }
3536                           /*Component should support this port definition*/
3537         case OMX_IndexParamOtherInit: {
3538                               DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3539                                       paramIndex);
3540                               eRet =OMX_ErrorUnsupportedIndex;
3541                               break;
3542                           }
3543         case OMX_IndexParamStandardComponentRole: {
3544                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3545                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
3546                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3547                                   comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3548                                   comp_role->nSize = sizeof(*comp_role);
3549 
3550                                   DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3551                                           paramIndex);
3552                                   strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3553                                           OMX_MAX_STRINGNAME_SIZE);
3554                                   break;
3555                               }
3556                               /* Added for parameter test */
3557         case OMX_IndexParamPriorityMgmt: {
3558                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3559                              OMX_PRIORITYMGMTTYPE *priorityMgmType =
3560                                  (OMX_PRIORITYMGMTTYPE *) paramData;
3561                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3562                              priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3563                              priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3564 
3565                              break;
3566                          }
3567                          /* Added for parameter test */
3568         case OMX_IndexParamCompBufferSupplier: {
3569                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3570                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3571                                        (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3572                                    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3573 
3574                                    bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3575                                    bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3576                                    if (0 == bufferSupplierType->nPortIndex)
3577                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3578                                    else if (1 == bufferSupplierType->nPortIndex)
3579                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3580                                    else
3581                                        eRet = OMX_ErrorBadPortIndex;
3582 
3583 
3584                                    break;
3585                                }
3586         case OMX_IndexParamVideoAvc: {
3587                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3588                                      paramIndex);
3589                              break;
3590                          }
3591         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3592                              DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3593                                      paramIndex);
3594                              break;
3595                          }
3596         case OMX_IndexParamVideoH263: {
3597                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3598                                       paramIndex);
3599                               break;
3600                           }
3601         case OMX_IndexParamVideoMpeg4: {
3602                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3603                                        paramIndex);
3604                                break;
3605                            }
3606         case OMX_IndexParamVideoMpeg2: {
3607                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3608                                        paramIndex);
3609                                break;
3610                            }
3611         case OMX_IndexParamVideoProfileLevelQuerySupported: {
3612                                         VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3613                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3614                                         OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3615                                             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3616                                         eRet = get_supported_profile_level(profileLevelType);
3617                                         break;
3618                                     }
3619 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3620         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3621                                         VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3622                                         DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3623                                         GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3624                                         if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3625 
3626                                             if (secure_mode && !secure_scaling_to_non_secure_opb) {
3627                                                 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3628                                                         GRALLOC_USAGE_PRIVATE_UNCACHED);
3629                                             } else {
3630                                                 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3631                                             }
3632                                         } else {
3633                                             DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3634                                             eRet = OMX_ErrorBadParameter;
3635                                         }
3636                                     }
3637                                     break;
3638 #endif
3639 
3640 #ifdef FLEXYUV_SUPPORTED
3641         case OMX_QcomIndexFlexibleYUVDescription: {
3642                 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3643                 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3644                 eRet = describeColorFormat(paramData);
3645                 break;
3646             }
3647 #endif
3648         case OMX_IndexParamVideoProfileLevelCurrent: {
3649              VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3650              OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3651              struct v4l2_control profile_control, level_control;
3652 
3653              switch (drv_ctx.decoder_format) {
3654                  case VDEC_CODECTYPE_H264:
3655                      profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3656                      level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3657                      break;
3658                  default:
3659                      DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3660                      eRet = OMX_ErrorNotImplemented;
3661                      break;
3662              }
3663 
3664              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3665                 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3666                     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3667                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3668                         pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3669                         break;
3670                     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3671                         pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3672                         break;
3673                     case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3674                         pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3675                         break;
3676                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3677                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3678                         break;
3679                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3680                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3681                         break;
3682                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3683                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3684                         break;
3685                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3686                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3687                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3688                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3689                     case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3690                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3691                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3692                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3693                     case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3694                     case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3695                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3696                         eRet = OMX_ErrorUnsupportedIndex;
3697                         break;
3698                 }
3699              } else {
3700                  eRet = OMX_ErrorUnsupportedIndex;
3701              }
3702 
3703 
3704              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3705                 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3706                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3707                         pParam->eLevel = OMX_VIDEO_AVCLevel1;
3708                         break;
3709                     case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3710                         pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3711                         break;
3712                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3713                         pParam->eLevel = OMX_VIDEO_AVCLevel11;
3714                         break;
3715                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3716                         pParam->eLevel = OMX_VIDEO_AVCLevel12;
3717                         break;
3718                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3719                         pParam->eLevel = OMX_VIDEO_AVCLevel13;
3720                         break;
3721                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3722                         pParam->eLevel = OMX_VIDEO_AVCLevel2;
3723                         break;
3724                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3725                         pParam->eLevel = OMX_VIDEO_AVCLevel21;
3726                         break;
3727                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3728                         pParam->eLevel = OMX_VIDEO_AVCLevel22;
3729                         break;
3730                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
3731                         pParam->eLevel = OMX_VIDEO_AVCLevel3;
3732                         break;
3733                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
3734                         pParam->eLevel = OMX_VIDEO_AVCLevel31;
3735                         break;
3736                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
3737                         pParam->eLevel = OMX_VIDEO_AVCLevel32;
3738                         break;
3739                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
3740                         pParam->eLevel = OMX_VIDEO_AVCLevel4;
3741                         break;
3742                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
3743                         pParam->eLevel = OMX_VIDEO_AVCLevel41;
3744                         break;
3745                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
3746                         pParam->eLevel = OMX_VIDEO_AVCLevel42;
3747                         break;
3748                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
3749                         pParam->eLevel = OMX_VIDEO_AVCLevel5;
3750                         break;
3751                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
3752                         pParam->eLevel = OMX_VIDEO_AVCLevel51;
3753                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
3754                         pParam->eLevel = OMX_VIDEO_AVCLevel52;
3755                         break;
3756                 }
3757              } else {
3758                  eRet = OMX_ErrorUnsupportedIndex;
3759              }
3760 
3761              break;
3762 
3763          }
3764         default: {
3765                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3766                  eRet =OMX_ErrorUnsupportedIndex;
3767              }
3768 
3769     }
3770 
3771     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3772             drv_ctx.video_resolution.frame_width,
3773             drv_ctx.video_resolution.frame_height,
3774             drv_ctx.video_resolution.stride,
3775             drv_ctx.video_resolution.scan_lines);
3776 
3777     return eRet;
3778 }
3779 
3780 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3781 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3782 {
3783     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3784     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3785     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3786 
3787     if ((params == NULL) ||
3788             (params->nativeBuffer == NULL) ||
3789             (params->nativeBuffer->handle == NULL) ||
3790             !m_enable_android_native_buffers)
3791         return OMX_ErrorBadParameter;
3792     m_use_android_native_buffers = OMX_TRUE;
3793     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3794     private_handle_t *handle = (private_handle_t *)nBuf->handle;
3795     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3796         OMX_U8 *buffer = NULL;
3797         if (!secure_mode) {
3798             buffer = (OMX_U8*)mmap(0, handle->size,
3799                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3800             if (buffer == MAP_FAILED) {
3801                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3802                 return OMX_ErrorInsufficientResources;
3803             }
3804         }
3805         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3806     } else {
3807         eRet = OMX_ErrorBadParameter;
3808     }
3809     return eRet;
3810 }
3811 #endif
3812 
enable_smoothstreaming()3813 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3814     struct v4l2_control control;
3815     struct v4l2_format fmt;
3816     control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3817     control.value = 1;
3818     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3819     if (rc < 0) {
3820         DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3821         return OMX_ErrorHardware;
3822     }
3823     m_smoothstreaming_mode = true;
3824     return OMX_ErrorNone;
3825 }
3826 
3827 /* ======================================================================
3828    FUNCTION
3829    omx_vdec::Setparameter
3830 
3831    DESCRIPTION
3832    OMX Set Parameter method implementation.
3833 
3834    PARAMETERS
3835    <TBD>.
3836 
3837    RETURN VALUE
3838    OMX Error None if successful.
3839 
3840    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3841 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3842         OMX_IN OMX_INDEXTYPE paramIndex,
3843         OMX_IN OMX_PTR        paramData)
3844 {
3845     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3846     int ret=0;
3847     struct v4l2_format fmt;
3848 #ifdef _ANDROID_
3849     char property_value[PROPERTY_VALUE_MAX] = {0};
3850 #endif
3851     if (m_state == OMX_StateInvalid) {
3852         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3853         return OMX_ErrorInvalidState;
3854     }
3855     if (paramData == NULL) {
3856         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
3857         return OMX_ErrorBadParameter;
3858     }
3859     if ((m_state != OMX_StateLoaded) &&
3860             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
3861             (m_out_bEnabled == OMX_TRUE) &&
3862             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
3863             (m_inp_bEnabled == OMX_TRUE)) {
3864         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3865         return OMX_ErrorIncorrectStateOperation;
3866     }
3867     switch ((unsigned long)paramIndex) {
3868         case OMX_IndexParamPortDefinition: {
3869                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3870                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3871                                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3872                                //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
3873                                //been called.
3874                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
3875                                        (int)portDefn->format.video.nFrameHeight,
3876                                        (int)portDefn->format.video.nFrameWidth);
3877 
3878                                if (portDefn->nBufferCountActual >= MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3879                                    DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
3880                                                           portDefn->nBufferCountActual);
3881                                    eRet = OMX_ErrorBadParameter;
3882                                    break;
3883                                }
3884                                if (OMX_DirOutput == portDefn->eDir) {
3885                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
3886                                    bool port_format_changed = false;
3887                                    m_display_id = portDefn->format.video.pNativeWindow;
3888                                    unsigned int buffer_size;
3889                                    /* update output port resolution with client supplied dimensions
3890                                       in case scaling is enabled, else it follows input resolution set
3891                                    */
3892                                    decide_dpb_buffer_mode(is_down_scalar_enabled);
3893                                    if (is_down_scalar_enabled) {
3894                                        DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
3895                                                (unsigned int)portDefn->format.video.nFrameWidth,
3896                                                (unsigned int)portDefn->format.video.nFrameHeight);
3897                                        if (portDefn->format.video.nFrameHeight != 0x0 &&
3898                                                portDefn->format.video.nFrameWidth != 0x0) {
3899                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3900                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3901                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3902                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
3903                                            if (ret) {
3904                                                DEBUG_PRINT_ERROR("Get Resolution failed");
3905                                                eRet = OMX_ErrorHardware;
3906                                                break;
3907                                            }
3908                                            if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
3909                                                (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
3910                                                    port_format_changed = true;
3911                                            }
3912                                            update_resolution(portDefn->format.video.nFrameWidth,
3913                                                    portDefn->format.video.nFrameHeight,
3914                                                    portDefn->format.video.nFrameWidth,
3915                                                    portDefn->format.video.nFrameHeight);
3916 
3917                                            /* set crop info */
3918                                            rectangle.nLeft = 0;
3919                                            rectangle.nTop = 0;
3920                                            rectangle.nWidth = portDefn->format.video.nFrameWidth;
3921                                            rectangle.nHeight = portDefn->format.video.nFrameHeight;
3922 
3923                                            eRet = is_video_session_supported();
3924                                            if (eRet)
3925                                                break;
3926                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3927                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3928                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3929                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3930                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3931                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
3932                                                fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
3933                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3934                                            if (ret) {
3935                                                DEBUG_PRINT_ERROR("Set Resolution failed");
3936                                                eRet = OMX_ErrorUnsupportedSetting;
3937                                            } else
3938                                                eRet = get_buffer_req(&drv_ctx.op_buf);
3939                                        }
3940 
3941                                        if (eRet) {
3942                                            break;
3943                                        }
3944 
3945                                        if (secure_mode) {
3946                                            struct v4l2_control control;
3947                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
3948                                            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
3949                                                DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
3950                                                eRet = OMX_ErrorHardware;
3951                                            } else {
3952                                                /* This is a workaround for a bug in fw which uses stride
3953                                                 * and slice instead of width and height to check against
3954                                                 * the threshold.
3955                                                 */
3956                                                OMX_U32 stride, slice;
3957                                                if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
3958                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
3959                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
3960                                                } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
3961                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
3962                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
3963                                                } else {
3964                                                    stride = portDefn->format.video.nFrameWidth;
3965                                                    slice = portDefn->format.video.nFrameHeight;
3966                                                }
3967 
3968                                                DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
3969                                                DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
3970 
3971                                                if (stride * slice <= (OMX_U32)control.value) {
3972                                                    secure_scaling_to_non_secure_opb = true;
3973                                                    DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
3974                                                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
3975                                                    control.value = 1;
3976                                                    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
3977                                                        DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
3978                                                        eRet = OMX_ErrorUnsupportedSetting;
3979                                                    }
3980                                                }
3981                                            }
3982                                        }
3983                                    }
3984 
3985                                    if (eRet) {
3986                                        break;
3987                                    }
3988 
3989                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3990                                        DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
3991                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
3992                                        eRet = OMX_ErrorBadParameter;
3993                                    } else if (!client_buffers.get_buffer_req(buffer_size)) {
3994                                        DEBUG_PRINT_ERROR("Error in getting buffer requirements");
3995                                        eRet = OMX_ErrorBadParameter;
3996                                    } else if (!port_format_changed) {
3997 
3998                                        // Buffer count can change only when port is disabled
3999                                        if (!release_output_done()) {
4000                                            DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4001                                            eRet = OMX_ErrorInvalidState;
4002                                            break;
4003                                        }
4004 
4005                                        if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
4006                                                portDefn->nBufferSize >=  drv_ctx.op_buf.buffer_size ) {
4007                                            drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
4008                                            drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
4009                                            drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount;
4010                                            drv_ctx.extradata_info.size = drv_ctx.extradata_info.count *
4011                                                drv_ctx.extradata_info.buffer_size;
4012                                            eRet = set_buffer_req(&drv_ctx.op_buf);
4013                                            if (eRet == OMX_ErrorNone)
4014                                                m_port_def = *portDefn;
4015                                        } else {
4016                                            DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4017                                                    drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size,
4018                                                    (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4019                                            eRet = OMX_ErrorBadParameter;
4020                                        }
4021                                    }
4022                                } else if (OMX_DirInput == portDefn->eDir) {
4023                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4024                                    bool port_format_changed = false;
4025                                    if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4026                                            (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4027                                        // Frame rate only should be set if this is a "known value" or to
4028                                        // activate ts prediction logic (arbitrary mode only) sending input
4029                                        // timestamps with max value (LLONG_MAX).
4030                                        DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4031                                                (unsigned int)portDefn->format.video.xFramerate >> 16);
4032                                        Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4033                                                drv_ctx.frame_rate.fps_denominator);
4034                                        if (!drv_ctx.frame_rate.fps_numerator) {
4035                                            DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4036                                            drv_ctx.frame_rate.fps_numerator = 30;
4037                                        }
4038                                        if (drv_ctx.frame_rate.fps_denominator)
4039                                            drv_ctx.frame_rate.fps_numerator = (int)
4040                                                drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4041                                        drv_ctx.frame_rate.fps_denominator = 1;
4042                                        frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4043                                            drv_ctx.frame_rate.fps_numerator;
4044                                        DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4045                                                (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4046                                                (float)drv_ctx.frame_rate.fps_denominator);
4047 
4048                                        struct v4l2_outputparm oparm;
4049                                        /*XXX: we're providing timing info as seconds per frame rather than frames
4050                                         * per second.*/
4051                                        oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4052                                        oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4053 
4054                                        struct v4l2_streamparm sparm;
4055                                        sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4056                                        sparm.parm.output = oparm;
4057                                        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4058                                            DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4059                                            eRet = OMX_ErrorHardware;
4060                                            break;
4061                                        }
4062                                        m_perf_control.request_cores(frm_int);
4063                                    }
4064 
4065                                    if (drv_ctx.video_resolution.frame_height !=
4066                                            portDefn->format.video.nFrameHeight ||
4067                                            drv_ctx.video_resolution.frame_width  !=
4068                                            portDefn->format.video.nFrameWidth) {
4069                                        DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4070                                                (unsigned int)portDefn->format.video.nFrameWidth,
4071                                                (unsigned int)portDefn->format.video.nFrameHeight);
4072                                        port_format_changed = true;
4073                                        OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4074                                        OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4075                                        if (frameHeight != 0x0 && frameWidth != 0x0) {
4076                                            if (m_smoothstreaming_mode &&
4077                                                    ((frameWidth * frameHeight) <
4078                                                    (m_smoothstreaming_width * m_smoothstreaming_height))) {
4079                                                frameWidth = m_smoothstreaming_width;
4080                                                frameHeight = m_smoothstreaming_height;
4081                                                DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4082                                                        "for adaptive-playback/smooth-streaming",
4083                                                        (unsigned int)frameWidth, (unsigned int)frameHeight);
4084                                            }
4085                                            update_resolution(frameWidth, frameHeight,
4086                                                    frameWidth, frameHeight);
4087                                            eRet = is_video_session_supported();
4088                                            if (eRet)
4089                                                break;
4090                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4091                                            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4092                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4093                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4094                                            fmt.fmt.pix_mp.pixelformat = output_capability;
4095                                            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);
4096                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4097                                            if (ret) {
4098                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4099                                                eRet = OMX_ErrorUnsupportedSetting;
4100                                            } else {
4101                                                if (!is_down_scalar_enabled)
4102                                                    eRet = get_buffer_req(&drv_ctx.op_buf);
4103                                            }
4104                                        }
4105                                    }
4106                                    if (m_custom_buffersize.input_buffersize
4107                                         && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4108                                        DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4109                                                m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4110                                        eRet = OMX_ErrorBadParameter;
4111                                        break;
4112                                    }
4113                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4114                                        DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4115                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4116                                        eRet = OMX_ErrorBadParameter;
4117                                        break;
4118                                    }
4119                                    // Buffer count can change only when port is disabled
4120                                    if (!release_input_done()) {
4121                                        DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4122                                        eRet = OMX_ErrorInvalidState;
4123                                        break;
4124                                    }
4125 
4126                                    if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4127                                            || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4128                                        port_format_changed = true;
4129                                        vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4130                                        drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4131                                        drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4132                                            (~(buffer_prop->alignment - 1));
4133                                        eRet = set_buffer_req(buffer_prop);
4134                                    }
4135                                    if (false == port_format_changed) {
4136                                        DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4137                                                drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4138                                                (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4139                                        eRet = OMX_ErrorBadParameter;
4140                                    }
4141                                } else if (portDefn->eDir ==  OMX_DirMax) {
4142                                    DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4143                                            (int)portDefn->nPortIndex);
4144                                    eRet = OMX_ErrorBadPortIndex;
4145                                }
4146                            }
4147                            break;
4148         case OMX_IndexParamVideoPortFormat: {
4149                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4150                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4151                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4152                                 int ret=0;
4153                                 struct v4l2_format fmt;
4154                                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4155                                         portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4156 
4157                                 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4158                                 if (1 == portFmt->nPortIndex) {
4159                                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4160                                     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4161                                     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4162                                     enum vdec_output_fromat op_format;
4163                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4164                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4165                                             portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4166                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4167                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4168                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4169                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4170                                     } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4171                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4172                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4173                                     } else
4174                                         eRet = OMX_ErrorBadParameter;
4175 
4176                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4177                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4178                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4179                                     } else {
4180                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4181                                     }
4182 
4183                                     if (eRet == OMX_ErrorNone) {
4184                                         drv_ctx.output_format = op_format;
4185                                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4186                                         if (ret) {
4187                                             DEBUG_PRINT_ERROR("Set output format failed");
4188                                             eRet = OMX_ErrorUnsupportedSetting;
4189                                             /*TODO: How to handle this case */
4190                                         } else {
4191                                             eRet = get_buffer_req(&drv_ctx.op_buf);
4192                                         }
4193                                     }
4194                                     if (eRet == OMX_ErrorNone) {
4195                                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4196                                             DEBUG_PRINT_ERROR("Set color format failed");
4197                                             eRet = OMX_ErrorBadParameter;
4198                                         }
4199                                     }
4200                                 }
4201                             }
4202                             break;
4203 
4204         case OMX_QcomIndexPortDefn: {
4205                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4206                             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4207                                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4208                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4209                                     (unsigned int)portFmt->nFramePackingFormat);
4210 
4211                             /* Input port */
4212                             if (portFmt->nPortIndex == 0) {
4213                                 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4214                                     if (secure_mode || m_input_pass_buffer_fd) {
4215                                         arbitrary_bytes = false;
4216                                         DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4217                                         eRet = OMX_ErrorUnsupportedSetting;
4218                                     } else {
4219                                         arbitrary_bytes = true;
4220                                     }
4221                                 } else if (portFmt->nFramePackingFormat ==
4222                                         OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4223                                     arbitrary_bytes = false;
4224 #ifdef _ANDROID_
4225                                     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4226                                     if (atoi(property_value)) {
4227                                         DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4228                                         arbitrary_bytes = true;
4229                                     }
4230 #endif
4231                                 } else {
4232                                     DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4233                                             (unsigned int)portFmt->nFramePackingFormat);
4234                                     eRet = OMX_ErrorUnsupportedSetting;
4235                                 }
4236                             } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4237                                 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4238                                 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4239                                             portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4240                                         portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4241                                     m_out_mem_region_smi = OMX_TRUE;
4242                                     if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4243                                         DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4244                                         m_use_output_pmem = OMX_TRUE;
4245                                     }
4246                                 }
4247                             }
4248                         }
4249                         if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4250                                     OMX_MAX_STRINGNAME_SIZE)) {
4251                             arbitrary_bytes = true;
4252                             DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4253                         }
4254                         break;
4255 
4256         case OMX_IndexParamStandardComponentRole: {
4257                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4258                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
4259                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4260                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4261                                           comp_role->cRole);
4262 
4263                                   if ((m_state == OMX_StateLoaded)&&
4264                                           !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4265                                       DEBUG_PRINT_LOW("Set Parameter called in valid state");
4266                                   } else {
4267                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4268                                       return OMX_ErrorIncorrectStateOperation;
4269                                   }
4270 
4271                                   if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4272                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4273                                           strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4274                                       } else {
4275                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4276                                           eRet =OMX_ErrorUnsupportedSetting;
4277                                       }
4278                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4279                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4280                                           strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4281                                       } else {
4282                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4283                                           eRet = OMX_ErrorUnsupportedSetting;
4284                                       }
4285                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4286                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4287                                           strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4288                                       } else {
4289                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4290                                           eRet = OMX_ErrorUnsupportedSetting;
4291                                       }
4292                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4293                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4294                                           strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4295                                       } else {
4296                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4297                                           eRet =OMX_ErrorUnsupportedSetting;
4298                                       }
4299                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4300                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4301                                           strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4302                                       } else {
4303                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4304                                           eRet = OMX_ErrorUnsupportedSetting;
4305                                       }
4306                                   } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4307                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4308                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4309                                         ) {
4310                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4311                                           strlcpy((char*)m_cRole, "video_decoder.divx", 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.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4317                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4318                                         ) {
4319                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4320                                           strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4321                                       } else {
4322                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4323                                           eRet =OMX_ErrorUnsupportedSetting;
4324                                       }
4325                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4326                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4327                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4328                                           strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4329                                       } else {
4330                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4331                                           eRet = OMX_ErrorUnsupportedSetting;
4332                                       }
4333                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4334                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4335                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4336                                           strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4337                                       } else {
4338                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4339                                           eRet = OMX_ErrorUnsupportedSetting;
4340                                       }
4341                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4342                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4343                                           strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4344                                       } else {
4345                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4346                                           eRet = OMX_ErrorUnsupportedSetting;
4347                                       }
4348                                   } else {
4349                                       DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4350                                       eRet = OMX_ErrorInvalidComponentName;
4351                                   }
4352                                   break;
4353                               }
4354 
4355         case OMX_IndexParamPriorityMgmt: {
4356                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4357                              if (m_state != OMX_StateLoaded) {
4358                                  DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4359                                  return OMX_ErrorIncorrectStateOperation;
4360                              }
4361                              OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4362                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4363                                      (unsigned int)priorityMgmtype->nGroupID);
4364 
4365                              DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4366                                      (unsigned int)priorityMgmtype->nGroupPriority);
4367 
4368                              m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4369                              m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4370 
4371                              break;
4372                          }
4373 
4374         case OMX_IndexParamCompBufferSupplier: {
4375                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4376                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4377                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4378                                            bufferSupplierType->eBufferSupplier);
4379                                    if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4380                                        m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4381 
4382                                    else
4383 
4384                                        eRet = OMX_ErrorBadPortIndex;
4385 
4386                                    break;
4387 
4388                                }
4389         case OMX_IndexParamVideoAvc: {
4390                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4391                                      paramIndex);
4392                              break;
4393                          }
4394         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4395                             DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4396                                      paramIndex);
4397                              break;
4398                         }
4399         case OMX_IndexParamVideoH263: {
4400                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4401                                       paramIndex);
4402                               break;
4403                           }
4404         case OMX_IndexParamVideoMpeg4: {
4405                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4406                                        paramIndex);
4407                                break;
4408                            }
4409         case OMX_IndexParamVideoMpeg2: {
4410                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4411                                        paramIndex);
4412                                break;
4413                            }
4414         case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4415                                      VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4416                                      QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4417                                          (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4418                                      struct v4l2_control control;
4419                                      int pic_order,rc=0;
4420                                      DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4421                                              pictureOrder->eOutputPictureOrder);
4422                                      if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4423                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4424                                      } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4425                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4426                                          time_stamp_dts.set_timestamp_reorder_mode(false);
4427                                      } else
4428                                          eRet = OMX_ErrorBadParameter;
4429                                      if (eRet == OMX_ErrorNone) {
4430                                          control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4431                                          control.value = pic_order;
4432                                          rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4433                                          if (rc) {
4434                                              DEBUG_PRINT_ERROR("Set picture order failed");
4435                                              eRet = OMX_ErrorUnsupportedSetting;
4436                                          }
4437                                      }
4438                                      break;
4439                                  }
4440         case OMX_QcomIndexParamConcealMBMapExtraData:
4441                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4442                                eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4443                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4444                                break;
4445         case OMX_QcomIndexParamFrameInfoExtraData:
4446                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4447                                eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4448                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4449                                break;
4450         case OMX_ExtraDataFrameDimension:
4451                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4452                                eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4453                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4454                                break;
4455         case OMX_QcomIndexParamInterlaceExtraData:
4456                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4457                                eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4458                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4459                                break;
4460         case OMX_QcomIndexParamH264TimeInfo:
4461                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4462                                eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4463                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4464                                break;
4465         case OMX_QcomIndexParamVideoFramePackingExtradata:
4466                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4467                                eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4468                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4469                                break;
4470         case OMX_QcomIndexParamVideoQPExtraData:
4471                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4472                                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4473                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4474                                break;
4475         case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4476                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4477                                eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4478                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4479                                break;
4480         case OMX_QcomIndexEnableExtnUserData:
4481                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4482                                 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4483                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4484                                 break;
4485         case OMX_QTIIndexParamVQZipSEIExtraData:
4486                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4487                                 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4488                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4489                                 break;
4490         case OMX_QcomIndexParamVideoDivx: {
4491                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4492                           }
4493                           break;
4494         case OMX_QcomIndexPlatformPvt: {
4495                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4496                                DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4497                                OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4498                                if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4499                                    DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4500                                    eRet = OMX_ErrorUnsupportedSetting;
4501                                } else {
4502                                    m_out_pvt_entry_pmem = OMX_TRUE;
4503                                    if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4504                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4505                                        m_use_output_pmem = OMX_TRUE;
4506                                    }
4507                                }
4508 
4509                            }
4510                            break;
4511         case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4512                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4513                                        DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4514                                        struct v4l2_control control;
4515                                        int rc;
4516                                        drv_ctx.idr_only_decoding = 1;
4517                                        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4518                                        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4519                                        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4520                                        if (rc) {
4521                                            DEBUG_PRINT_ERROR("Set picture order failed");
4522                                            eRet = OMX_ErrorUnsupportedSetting;
4523                                        } else {
4524                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4525                                            control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4526                                            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4527                                            if (rc) {
4528                                                DEBUG_PRINT_ERROR("Sync frame setting failed");
4529                                                eRet = OMX_ErrorUnsupportedSetting;
4530                                            }
4531                                            /*Setting sync frame decoding on driver might change buffer
4532                                             * requirements so update them here*/
4533                                            if (get_buffer_req(&drv_ctx.ip_buf)) {
4534                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4535                                                eRet = OMX_ErrorUnsupportedSetting;
4536                                            }
4537                                            if (get_buffer_req(&drv_ctx.op_buf)) {
4538                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4539                                                eRet = OMX_ErrorUnsupportedSetting;
4540                                            }
4541                                        }
4542                                    }
4543                                    break;
4544 
4545         case OMX_QcomIndexParamIndexExtraDataType: {
4546                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4547                                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4548                                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4549                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4550                                             (extradataIndexType->nPortIndex == 1)) {
4551                                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4552                                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4553 
4554                                     }
4555                                 }
4556                                 break;
4557         case OMX_QcomIndexParamEnableSmoothStreaming: {
4558 #ifndef SMOOTH_STREAMING_DISABLED
4559                                       eRet = enable_smoothstreaming();
4560 #else
4561                                       eRet = OMX_ErrorUnsupportedSetting;
4562 #endif
4563                                   }
4564                                   break;
4565 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4566                                   /* Need to allow following two set_parameters even in Idle
4567                                    * state. This is ANDROID architecture which is not in sync
4568                                    * with openmax standard. */
4569         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4570                                            VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4571                                            EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4572                                            if (enableNativeBuffers) {
4573                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
4574                                            }
4575 #if !defined(FLEXYUV_SUPPORTED)
4576                                            if (m_enable_android_native_buffers) {
4577                                                // Use the most-preferred-native-color-format as surface-mode is hinted here
4578                                                if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4579                                                    DEBUG_PRINT_ERROR("Failed to set native color format!");
4580                                                    eRet = OMX_ErrorUnsupportedSetting;
4581                                                }
4582                                            }
4583 #endif
4584                                        }
4585                                        break;
4586         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4587                                        VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4588                                        eRet = use_android_native_buffer(hComp, paramData);
4589                                    }
4590                                    break;
4591 #endif
4592         case OMX_QcomIndexParamEnableTimeStampReorder: {
4593                                        VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4594                                        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4595                                        if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4596                                            if (reorder->bEnable == OMX_TRUE) {
4597                                                frm_int =0;
4598                                                time_stamp_dts.set_timestamp_reorder_mode(true);
4599                                            } else
4600                                                time_stamp_dts.set_timestamp_reorder_mode(false);
4601                                        } else {
4602                                            time_stamp_dts.set_timestamp_reorder_mode(false);
4603                                            if (reorder->bEnable == OMX_TRUE) {
4604                                                eRet = OMX_ErrorUnsupportedSetting;
4605                                            }
4606                                        }
4607                                    }
4608                                    break;
4609         case OMX_IndexParamVideoProfileLevelCurrent: {
4610                                      VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4611                                      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4612                                          (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4613                                      if (pParam) {
4614                                          m_profile_lvl.eProfile = pParam->eProfile;
4615                                          m_profile_lvl.eLevel = pParam->eLevel;
4616                                      }
4617                                      break;
4618 
4619                                  }
4620         case OMX_QcomIndexParamVideoMetaBufferMode:
4621         {
4622             VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4623             StoreMetaDataInBuffersParams *metabuffer =
4624                 (StoreMetaDataInBuffersParams *)paramData;
4625             if (!metabuffer) {
4626                 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4627                 eRet = OMX_ErrorBadParameter;
4628                 break;
4629             }
4630             if (m_disable_dynamic_buf_mode) {
4631                 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4632                 eRet = OMX_ErrorUnsupportedSetting;
4633                 break;
4634             }
4635             if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4636                     //set property dynamic buffer mode to driver.
4637                     struct v4l2_control control;
4638                     struct v4l2_format fmt;
4639                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
4640                     if (metabuffer->bStoreMetaData == true) {
4641                         control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
4642                     } else {
4643                         control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
4644                     }
4645                     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4646                     if (!rc) {
4647                         DEBUG_PRINT_HIGH("%s buffer mode",
4648                            (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4649                                dynamic_buf_mode = metabuffer->bStoreMetaData;
4650                     } else {
4651                         DEBUG_PRINT_ERROR("Failed to %s buffer mode",
4652                            (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
4653                         eRet = OMX_ErrorUnsupportedSetting;
4654                     }
4655                 } else {
4656                     DEBUG_PRINT_ERROR(
4657                        "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4658                        (unsigned int)metabuffer->nPortIndex);
4659                     eRet = OMX_ErrorUnsupportedSetting;
4660                 }
4661                 break;
4662         }
4663         case OMX_QcomIndexParamVideoDownScalar:
4664         {
4665             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4666             QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4667             struct v4l2_control control;
4668             int rc;
4669             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
4670 
4671             if (pParam && pParam->bEnable) {
4672                 rc = enable_downscalar();
4673                 if (rc < 0) {
4674                     DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
4675                     return OMX_ErrorUnsupportedSetting;
4676                 }
4677                 m_force_down_scalar = pParam->bEnable;
4678             } else {
4679                 rc = disable_downscalar();
4680                 if (rc < 0) {
4681                     DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
4682                     return OMX_ErrorUnsupportedSetting;
4683                 }
4684                 m_force_down_scalar = pParam->bEnable;
4685             }
4686             break;
4687         }
4688 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4689         case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4690         {
4691             VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4692             DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4693             PrepareForAdaptivePlaybackParams* pParams =
4694                     (PrepareForAdaptivePlaybackParams *) paramData;
4695             if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4696                 if (!pParams->bEnable) {
4697                     return OMX_ErrorNone;
4698                 }
4699                 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4700                         || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4701                     DEBUG_PRINT_ERROR(
4702                             "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4703                              (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4704                              (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4705                     eRet = OMX_ErrorBadParameter;
4706                 } else {
4707                     eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4708                 }
4709             } else {
4710                 DEBUG_PRINT_ERROR(
4711                         "Prepare for adaptive playback supported only on output port");
4712                 eRet = OMX_ErrorBadParameter;
4713             }
4714             break;
4715         }
4716 
4717         case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
4718         {
4719             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4720             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
4721             m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4722             if (m_disable_dynamic_buf_mode) {
4723                 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
4724             }
4725             break;
4726         }
4727 #endif
4728         case OMX_QcomIndexParamVideoCustomBufferSize:
4729         {
4730             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4731             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4732             QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4733             if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4734                 struct v4l2_control control;
4735                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4736                 control.value = pParam->nBufferSize;
4737                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4738                     DEBUG_PRINT_ERROR("Failed to set input buffer size");
4739                     eRet = OMX_ErrorUnsupportedSetting;
4740                 } else {
4741                     eRet = get_buffer_req(&drv_ctx.ip_buf);
4742                     if (eRet == OMX_ErrorNone) {
4743                         m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4744                         DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4745                             m_custom_buffersize.input_buffersize);
4746                     } else {
4747                         DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4748                     }
4749                 }
4750             } else {
4751                 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4752                 eRet = OMX_ErrorBadParameter;
4753             }
4754             break;
4755         }
4756         case OMX_QTIIndexParamVQZIPSEIType:
4757         {
4758             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
4759             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
4760             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
4761                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
4762                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
4763             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4764                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4765             if (eRet != OMX_ErrorNone) {
4766                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
4767                 eRet = OMX_ErrorBadParameter;
4768                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4769             } else {
4770                 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4771                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4772                 if (eRet != OMX_ErrorNone) {
4773                     DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
4774                     eRet = OMX_ErrorBadParameter;
4775                     client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4776                     client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4777                 }
4778             }
4779             break;
4780         }
4781 
4782         case OMX_QTIIndexParamPassInputBufferFd:
4783         {
4784             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4785             if (arbitrary_bytes) {
4786                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
4787                 eRet = OMX_ErrorUnsupportedSetting;
4788                 break;
4789             }
4790 
4791             m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4792             if (m_input_pass_buffer_fd)
4793                 DEBUG_PRINT_LOW("Enable passing input buffer FD");
4794             break;
4795         }
4796         case OMX_QTIIndexParamForceCompressedForDPB:
4797         {
4798             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
4799             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
4800             OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
4801                 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
4802             if (m_disable_ubwc_mode) {
4803                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
4804                 eRet = OMX_ErrorUnsupportedSetting;
4805                 break;
4806             }
4807             if (!paramData) {
4808                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
4809                eRet = OMX_ErrorBadParameter;
4810                break;
4811             }
4812 
4813             m_force_compressed_for_dpb = pParam->bEnable;
4814             break;
4815         }
4816         case OMX_QTIIndexParamForceUnCompressedForOPB:
4817         {
4818             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE);
4819             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
4820             OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
4821                 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
4822             if (!paramData) {
4823                 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
4824                 eRet = OMX_ErrorBadParameter;
4825                 break;
4826             }
4827             m_disable_ubwc_mode = pParam->bEnable;
4828             DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
4829             break;
4830         }
4831 
4832 
4833         default: {
4834                  DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4835                  eRet = OMX_ErrorUnsupportedIndex;
4836              }
4837     }
4838     if (eRet != OMX_ErrorNone)
4839         DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4840     return eRet;
4841 }
4842 
4843 /* ======================================================================
4844    FUNCTION
4845    omx_vdec::GetConfig
4846 
4847    DESCRIPTION
4848    OMX Get Config Method implementation.
4849 
4850    PARAMETERS
4851    <TBD>.
4852 
4853    RETURN VALUE
4854    OMX Error None if successful.
4855 
4856    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4857 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
4858         OMX_IN OMX_INDEXTYPE configIndex,
4859         OMX_INOUT OMX_PTR     configData)
4860 {
4861     (void) hComp;
4862     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4863 
4864     if (m_state == OMX_StateInvalid) {
4865         DEBUG_PRINT_ERROR("Get Config in Invalid State");
4866         return OMX_ErrorInvalidState;
4867     }
4868 
4869     switch ((unsigned long)configIndex) {
4870         case OMX_QcomIndexConfigInterlaced: {
4871                                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
4872                                 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
4873                                     (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
4874                                 if (configFmt->nPortIndex == 1) {
4875                                     if (configFmt->nIndex == 0) {
4876                                         configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
4877                                     } else if (configFmt->nIndex == 1) {
4878                                         configFmt->eInterlaceType =
4879                                             OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
4880                                     } else if (configFmt->nIndex == 2) {
4881                                         configFmt->eInterlaceType =
4882                                             OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
4883                                     } else {
4884                                         DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
4885                                                 " NoMore Interlaced formats");
4886                                         eRet = OMX_ErrorNoMore;
4887                                     }
4888 
4889                                 } else {
4890                                     DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
4891                                             (int)configFmt->nPortIndex);
4892                                     eRet = OMX_ErrorBadPortIndex;
4893                                 }
4894                                 break;
4895                             }
4896         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
4897                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
4898                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
4899                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
4900                                      decoderinstances->nNumOfInstances = 16;
4901                                      /*TODO: How to handle this case */
4902                                      break;
4903                                  }
4904         case OMX_QcomIndexConfigVideoFramePackingArrangement: {
4905                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
4906                                               VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
4907                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
4908                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
4909                                               memcpy(configFmt, &m_frame_pack_arrangement,
4910                                                   sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
4911                                           } else {
4912                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
4913                                           }
4914                                           break;
4915                                       }
4916         case OMX_IndexConfigCommonOutputCrop: {
4917                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
4918                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
4919                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
4920                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
4921                                         rectangle.nLeft, rectangle.nTop,
4922                                         rectangle.nWidth, rectangle.nHeight);
4923                                   break;
4924                               }
4925         case OMX_QcomIndexConfigPerfLevel: {
4926                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
4927                 struct v4l2_control control;
4928                 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
4929                         (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
4930 
4931                 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
4932                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4933                     DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
4934                     eRet = OMX_ErrorHardware;
4935                 }
4936 
4937                 if (eRet == OMX_ErrorNone) {
4938                     switch (control.value) {
4939                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
4940                             perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
4941                             break;
4942                         default:
4943                             DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
4944                             /* Fall through */
4945                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
4946                             perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
4947                             break;
4948                     }
4949                 }
4950 
4951                 break;
4952         }
4953         case OMX_QcomIndexConfigH264EntropyCodingCabac: {
4954             VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
4955             QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
4956             struct v4l2_control control;
4957 
4958             if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
4959                 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
4960                 eRet = OMX_ErrorNotImplemented;
4961                 break;
4962             }
4963 
4964             control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
4965             if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
4966                 coding->bCabac = (OMX_BOOL)
4967                     (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
4968                 /* We can't query driver at the moment for the cabac mode, so
4969                  * just use 0xff...f as a place holder for future improvement */
4970                 coding->nCabacInitIdc = ~0;
4971             } else {
4972                 eRet = OMX_ErrorUnsupportedIndex;
4973             }
4974 
4975             break;
4976         }
4977         default: {
4978                  DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
4979                  eRet = OMX_ErrorBadParameter;
4980              }
4981 
4982     }
4983 
4984     return eRet;
4985 }
4986 
4987 /* ======================================================================
4988    FUNCTION
4989    omx_vdec::SetConfig
4990 
4991    DESCRIPTION
4992    OMX Set Config method implementation
4993 
4994    PARAMETERS
4995    <TBD>.
4996 
4997    RETURN VALUE
4998    OMX Error None if successful.
4999    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5000 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5001         OMX_IN OMX_INDEXTYPE configIndex,
5002         OMX_IN OMX_PTR        configData)
5003 {
5004     (void) hComp;
5005     if (m_state == OMX_StateInvalid) {
5006         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5007         return OMX_ErrorInvalidState;
5008     }
5009 
5010     OMX_ERRORTYPE ret = OMX_ErrorNone;
5011     OMX_VIDEO_CONFIG_NALSIZE *pNal;
5012 
5013     DEBUG_PRINT_LOW("Set Config Called");
5014 
5015     if (configIndex == OMX_IndexConfigVideoNalSize) {
5016         struct v4l2_control temp;
5017         temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5018 
5019         VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5020         pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5021         switch (pNal->nNaluBytes) {
5022             case 0:
5023                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5024                 break;
5025             case 2:
5026                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5027                 break;
5028             case 4:
5029                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5030                 break;
5031             default:
5032                 return OMX_ErrorUnsupportedSetting;
5033         }
5034 
5035         if (!arbitrary_bytes) {
5036             /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5037              * with start code, so only need to notify driver in frame by frame mode */
5038             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5039                 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5040                 return OMX_ErrorHardware;
5041             }
5042         }
5043 
5044         nal_length = pNal->nNaluBytes;
5045         m_frame_parser.init_nal_length(nal_length);
5046 
5047         DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5048         return ret;
5049     } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5050         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5051         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5052 
5053         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5054             if (config->bEnabled) {
5055                 if ((config->nFps >> 16) > 0) {
5056                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5057                             (unsigned int)config->nFps >> 16);
5058                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5059                             drv_ctx.frame_rate.fps_denominator);
5060 
5061                     if (!drv_ctx.frame_rate.fps_numerator) {
5062                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5063                         drv_ctx.frame_rate.fps_numerator = 30;
5064                     }
5065 
5066                     if (drv_ctx.frame_rate.fps_denominator) {
5067                         drv_ctx.frame_rate.fps_numerator = (int)
5068                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5069                     }
5070 
5071                     drv_ctx.frame_rate.fps_denominator = 1;
5072                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5073                         drv_ctx.frame_rate.fps_numerator;
5074 
5075                     struct v4l2_outputparm oparm;
5076                     /*XXX: we're providing timing info as seconds per frame rather than frames
5077                      * per second.*/
5078                     oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5079                     oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5080 
5081                     struct v4l2_streamparm sparm;
5082                     sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5083                     sparm.parm.output = oparm;
5084                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5085                         DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5086                                 performance might be affected");
5087                         ret = OMX_ErrorHardware;
5088                     }
5089                     client_set_fps = true;
5090                 } else {
5091                     DEBUG_PRINT_ERROR("Frame rate not supported.");
5092                     ret = OMX_ErrorUnsupportedSetting;
5093                 }
5094             } else {
5095                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5096                 client_set_fps = false;
5097             }
5098         } else {
5099             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5100                     (int)config->nPortIndex);
5101             ret = OMX_ErrorBadPortIndex;
5102         }
5103 
5104         return ret;
5105     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5106         OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5107             (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5108         struct v4l2_control control;
5109 
5110         DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5111 
5112         control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5113 
5114         switch (perf->ePerfLevel) {
5115             case OMX_QCOM_PerfLevelNominal:
5116                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5117                 break;
5118             case OMX_QCOM_PerfLevelTurbo:
5119                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5120                 break;
5121             default:
5122                 ret = OMX_ErrorUnsupportedSetting;
5123                 break;
5124         }
5125 
5126         if (ret == OMX_ErrorNone) {
5127             ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5128                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5129         }
5130 
5131         return ret;
5132     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5133         OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5134             (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5135         struct v4l2_control control;
5136         DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5137         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5138 
5139         switch (config->eDecodeType) {
5140             case OMX_QCOM_PictypeDecode_I:
5141                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5142                 break;
5143             case OMX_QCOM_PictypeDecode_IPB:
5144             default:
5145                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5146                 break;
5147         }
5148 
5149         ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5150                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5151         if (ret)
5152             DEBUG_PRINT_ERROR("Failed to set picture type decode");
5153 
5154         return ret;
5155     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5156         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5157         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5158 
5159         struct v4l2_control control;
5160 
5161         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5162         if (priority->nU32 == 0)
5163             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5164         else
5165             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5166 
5167         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5168             DEBUG_PRINT_ERROR("Failed to set Priority");
5169             ret = OMX_ErrorUnsupportedSetting;
5170         }
5171         return ret;
5172     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5173         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5174         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5175 
5176         struct v4l2_control control;
5177 
5178         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5179         control.value = rate->nU32;
5180 
5181         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5182             ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5183                     OMX_ErrorUnsupportedSetting;
5184             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5185                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5186         }
5187         return ret;
5188     }
5189 
5190     return OMX_ErrorNotImplemented;
5191 }
5192 
5193 #define extn_equals(param, extn) (!strcmp(param, extn))
5194 
5195 /* ======================================================================
5196    FUNCTION
5197    omx_vdec::GetExtensionIndex
5198 
5199    DESCRIPTION
5200    OMX GetExtensionIndex method implementaion.  <TBD>
5201 
5202    PARAMETERS
5203    <TBD>.
5204 
5205    RETURN VALUE
5206    OMX Error None if everything successful.
5207 
5208    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5209 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5210         OMX_IN OMX_STRING      paramName,
5211         OMX_OUT OMX_INDEXTYPE* indexType)
5212 {
5213     (void) hComp;
5214     if (m_state == OMX_StateInvalid) {
5215         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5216         return OMX_ErrorInvalidState;
5217     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5218         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5219     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5220         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5221     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5222         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5223     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5224         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5225     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5226         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5227     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5228         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5229     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5230         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5231     }
5232 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5233     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5234         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5235     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5236         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5237     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5238         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5239         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5240     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5241         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5242     }
5243 #endif
5244     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5245         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5246     }
5247 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5248     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5249         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5250     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5251         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5252     }
5253 #endif
5254 #ifdef FLEXYUV_SUPPORTED
5255     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5256         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5257     }
5258 #endif
5259     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5260         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5261     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5262         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5263     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5264         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5265     } else {
5266         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5267         return OMX_ErrorNotImplemented;
5268     }
5269     return OMX_ErrorNone;
5270 }
5271 
5272 /* ======================================================================
5273    FUNCTION
5274    omx_vdec::GetState
5275 
5276    DESCRIPTION
5277    Returns the state information back to the caller.<TBD>
5278 
5279    PARAMETERS
5280    <TBD>.
5281 
5282    RETURN VALUE
5283    Error None if everything is successful.
5284    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5285 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5286         OMX_OUT OMX_STATETYPE* state)
5287 {
5288     (void) hComp;
5289     *state = m_state;
5290     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5291     return OMX_ErrorNone;
5292 }
5293 
5294 /* ======================================================================
5295    FUNCTION
5296    omx_vdec::ComponentTunnelRequest
5297 
5298    DESCRIPTION
5299    OMX Component Tunnel Request method implementation. <TBD>
5300 
5301    PARAMETERS
5302    None.
5303 
5304    RETURN VALUE
5305    OMX Error None if everything successful.
5306 
5307    ========================================================================== */
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)5308 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5309         OMX_IN OMX_U32                        port,
5310         OMX_IN OMX_HANDLETYPE        peerComponent,
5311         OMX_IN OMX_U32                    peerPort,
5312         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5313 {
5314     (void) hComp;
5315     (void) port;
5316     (void) peerComponent;
5317     (void) peerPort;
5318     (void) tunnelSetup;
5319     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5320     return OMX_ErrorNotImplemented;
5321 }
5322 
5323 /* ======================================================================
5324    FUNCTION
5325    omx_vdec::UseOutputBuffer
5326 
5327    DESCRIPTION
5328    Helper function for Use buffer in the input pin
5329 
5330    PARAMETERS
5331    None.
5332 
5333    RETURN VALUE
5334    true/false
5335 
5336    ========================================================================== */
allocate_extradata()5337 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5338 {
5339 #ifdef USE_ION
5340     if (drv_ctx.extradata_info.buffer_size) {
5341         if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5342             munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5343             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5344             free_ion_memory(&drv_ctx.extradata_info.ion);
5345         }
5346         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5347         drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5348                 drv_ctx.extradata_info.size, 4096,
5349                 &drv_ctx.extradata_info.ion.ion_alloc_data,
5350                 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5351         if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5352             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5353             return OMX_ErrorInsufficientResources;
5354         }
5355         drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5356                 drv_ctx.extradata_info.size,
5357                 PROT_READ|PROT_WRITE, MAP_SHARED,
5358                 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5359         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5360             DEBUG_PRINT_ERROR("Failed to map extradata memory");
5361             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5362             free_ion_memory(&drv_ctx.extradata_info.ion);
5363             return OMX_ErrorInsufficientResources;
5364         }
5365     }
5366 #endif
5367     if (!m_other_extradata) {
5368         m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5369         if (!m_other_extradata) {
5370             DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5371             return OMX_ErrorInsufficientResources;
5372         }
5373     }
5374     return OMX_ErrorNone;
5375 }
5376 
free_extradata()5377 void omx_vdec::free_extradata()
5378 {
5379 #ifdef USE_ION
5380     if (drv_ctx.extradata_info.uaddr) {
5381         munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5382         close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5383         free_ion_memory(&drv_ctx.extradata_info.ion);
5384     }
5385     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
5386 #endif
5387     if (m_other_extradata) {
5388         free(m_other_extradata);
5389         m_other_extradata = NULL;
5390     }
5391 }
5392 
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)5393 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5394         OMX_IN OMX_HANDLETYPE            hComp,
5395         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5396         OMX_IN OMX_U32                   port,
5397         OMX_IN OMX_PTR                   appData,
5398         OMX_IN OMX_U32                   bytes,
5399         OMX_IN OMX_U8*                   buffer)
5400 {
5401     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5402     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5403     unsigned                         i= 0; // Temporary counter
5404     struct vdec_setbuffer_cmd setbuffers;
5405     OMX_PTR privateAppData = NULL;
5406     private_handle_t *handle = NULL;
5407     OMX_U8 *buff = buffer;
5408     struct v4l2_buffer buf;
5409     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5410     int extra_idx = 0;
5411     (void) hComp;
5412     (void) port;
5413 
5414     if (!m_out_mem_ptr) {
5415         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5416         eRet = allocate_output_headers();
5417         if (eRet == OMX_ErrorNone)
5418             eRet = allocate_extradata();
5419     }
5420 
5421     if (eRet == OMX_ErrorNone) {
5422         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5423             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5424                 break;
5425             }
5426         }
5427     }
5428 
5429     if (i >= drv_ctx.op_buf.actualcount) {
5430         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5431         eRet = OMX_ErrorInsufficientResources;
5432     }
5433 
5434     if (eRet != OMX_ErrorNone)
5435        return eRet;
5436 
5437     if (dynamic_buf_mode) {
5438         *bufferHdr = (m_out_mem_ptr + i );
5439         (*bufferHdr)->pBuffer = NULL;
5440         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5441             enum v4l2_buf_type buf_type;
5442             int rr = 0;
5443             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5444             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5445                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5446                 return OMX_ErrorInsufficientResources;
5447             } else {
5448                 streaming[CAPTURE_PORT] = true;
5449                 DEBUG_PRINT_LOW("STREAMON Successful");
5450             }
5451 
5452             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5453             request_perf_level(VIDC_TURBO);
5454         }
5455         BITMASK_SET(&m_out_bm_count,i);
5456         (*bufferHdr)->pAppPrivate = appData;
5457         (*bufferHdr)->pBuffer = buffer;
5458         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5459         return eRet;
5460     }
5461 
5462     if (eRet == OMX_ErrorNone) {
5463 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5464         if (m_enable_android_native_buffers) {
5465             if (m_use_android_native_buffers) {
5466                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5467                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5468                 handle = (private_handle_t *)nBuf->handle;
5469                 privateAppData = params->pAppPrivate;
5470             } else {
5471                 handle = (private_handle_t *)buff;
5472                 privateAppData = appData;
5473             }
5474             if (!handle) {
5475                 DEBUG_PRINT_ERROR("handle is invalid");
5476                 return OMX_ErrorBadParameter;
5477             }
5478 
5479             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5480                 if (secure_mode && secure_scaling_to_non_secure_opb) {
5481                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5482                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5483                 } else {
5484                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5485                             " expected %u, got %u",
5486                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5487                     return OMX_ErrorBadParameter;
5488                 }
5489             }
5490 
5491             drv_ctx.op_buf.buffer_size = handle->size;
5492 
5493             if (!m_use_android_native_buffers) {
5494                 if (!secure_mode) {
5495                     buff =  (OMX_U8*)mmap(0, handle->size,
5496                             PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
5497                     if (buff == MAP_FAILED) {
5498                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5499                         return OMX_ErrorInsufficientResources;
5500                     }
5501                 }
5502             }
5503 #if defined(_ANDROID_ICS_)
5504             native_buffer[i].nativehandle = handle;
5505             native_buffer[i].privatehandle = handle;
5506 #endif
5507             if (!handle) {
5508                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5509                 return OMX_ErrorBadParameter;
5510             }
5511             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5512             drv_ctx.ptr_outputbuffer[i].offset = 0;
5513             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5514             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5515             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5516         } else
5517 #endif
5518 
5519             if (!ouput_egl_buffers && !m_use_output_pmem) {
5520 #ifdef USE_ION
5521                 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5522                         drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
5523                         &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
5524                         &drv_ctx.op_buf_ion_info[i].fd_ion_data,
5525                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5526                 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
5527                     DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
5528                     return OMX_ErrorInsufficientResources;
5529                 }
5530                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5531                                       drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5532 #else
5533                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5534                                       open (MEM_DEVICE,O_RDWR);
5535 
5536                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5537                     DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5538                     return OMX_ErrorInsufficientResources;
5539                 }
5540 
5541                 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
5542                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
5543                     drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5544                                           open (MEM_DEVICE,O_RDWR);
5545                     if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5546                         DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5547                         return OMX_ErrorInsufficientResources;
5548                     }
5549                 }
5550 
5551                 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5552                             drv_ctx.op_buf.buffer_size,
5553                             drv_ctx.op_buf.alignment)) {
5554                     DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5555                     close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5556                     return OMX_ErrorInsufficientResources;
5557                 }
5558 #endif
5559                 if (!secure_mode) {
5560                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
5561                         (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
5562                                 PROT_READ|PROT_WRITE, MAP_SHARED,
5563                                 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
5564                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5565                         close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5566 #ifdef USE_ION
5567                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5568 #endif
5569                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5570                         return OMX_ErrorInsufficientResources;
5571                     }
5572                 }
5573                 drv_ctx.ptr_outputbuffer[i].offset = 0;
5574                 privateAppData = appData;
5575             } else {
5576 
5577                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5578                 if (!appData || !bytes ) {
5579                     if (!secure_mode && !buffer) {
5580                         DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
5581                         return OMX_ErrorBadParameter;
5582                     }
5583                 }
5584 
5585                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
5586                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
5587                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
5588                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
5589                         !pmem_list->nEntries ||
5590                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
5591                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
5592                     return OMX_ErrorBadParameter;
5593                 }
5594                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5595                     pmem_list->entryList->entry;
5596                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
5597                         pmem_info->pmem_fd);
5598                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
5599                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
5600                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5601                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
5602                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5603                 privateAppData = appData;
5604             }
5605         m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5606         m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5607         m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5608         m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5609         m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5610 
5611         *bufferHdr = (m_out_mem_ptr + i );
5612         if (secure_mode)
5613             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5614         //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5615         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
5616                 sizeof (vdec_bufferpayload));
5617 
5618         DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
5619                 drv_ctx.ptr_outputbuffer[i].bufferaddr,
5620                 drv_ctx.ptr_outputbuffer[i].pmem_fd );
5621 
5622         buf.index = i;
5623         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5624         buf.memory = V4L2_MEMORY_USERPTR;
5625         plane[0].length = drv_ctx.op_buf.buffer_size;
5626         plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
5627             (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
5628         plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5629         plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
5630         plane[0].data_offset = 0;
5631         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5632         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5633             plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5634             plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
5635 #ifdef USE_ION
5636             plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5637 #endif
5638             plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
5639             plane[extra_idx].data_offset = 0;
5640         } else if  (extra_idx >= VIDEO_MAX_PLANES) {
5641             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
5642             return OMX_ErrorBadParameter;
5643         }
5644         buf.m.planes = plane;
5645         buf.length = drv_ctx.num_planes;
5646 
5647         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
5648             DEBUG_PRINT_ERROR("Failed to prepare bufs");
5649             /*TODO: How to handle this case */
5650             return OMX_ErrorInsufficientResources;
5651         }
5652 
5653         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
5654             enum v4l2_buf_type buf_type;
5655             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5656             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
5657                 return OMX_ErrorInsufficientResources;
5658             } else {
5659                 streaming[CAPTURE_PORT] = true;
5660                 DEBUG_PRINT_LOW("STREAMON Successful");
5661             }
5662 
5663             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5664             request_perf_level(VIDC_TURBO);
5665         }
5666 
5667         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
5668         if (m_enable_android_native_buffers) {
5669             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
5670             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
5671         } else {
5672             (*bufferHdr)->pBuffer = buff;
5673         }
5674         (*bufferHdr)->pAppPrivate = privateAppData;
5675         BITMASK_SET(&m_out_bm_count,i);
5676     }
5677     return eRet;
5678 }
5679 
5680 /* ======================================================================
5681    FUNCTION
5682    omx_vdec::use_input_heap_buffers
5683 
5684    DESCRIPTION
5685    OMX Use Buffer Heap allocation method implementation.
5686 
5687    PARAMETERS
5688    <TBD>.
5689 
5690    RETURN VALUE
5691    OMX Error None , if everything successful.
5692 
5693    ========================================================================== */
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)5694 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
5695         OMX_IN OMX_HANDLETYPE            hComp,
5696         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5697         OMX_IN OMX_U32                   port,
5698         OMX_IN OMX_PTR                   appData,
5699         OMX_IN OMX_U32                   bytes,
5700         OMX_IN OMX_U8*                   buffer)
5701 {
5702     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5703     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5704     if (!m_inp_heap_ptr)
5705         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5706             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5707                     drv_ctx.ip_buf.actualcount);
5708     if (!m_phdr_pmem_ptr)
5709         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5710             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5711                     drv_ctx.ip_buf.actualcount);
5712     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5713         DEBUG_PRINT_ERROR("Insufficent memory");
5714         eRet = OMX_ErrorInsufficientResources;
5715     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5716         input_use_buffer = true;
5717         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5718         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5719         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5720         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5721         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5722         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5723         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5724         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5725         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5726         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5727                     (unsigned)NULL, (unsigned)NULL)) {
5728             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5729             return OMX_ErrorInsufficientResources;
5730         }
5731         m_in_alloc_cnt++;
5732     } else {
5733         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5734         eRet = OMX_ErrorInsufficientResources;
5735     }
5736     return eRet;
5737 }
5738 
5739 /* ======================================================================
5740    FUNCTION
5741    omx_vdec::UseBuffer
5742 
5743    DESCRIPTION
5744    OMX Use Buffer method implementation.
5745 
5746    PARAMETERS
5747    <TBD>.
5748 
5749    RETURN VALUE
5750    OMX Error None , if everything successful.
5751 
5752    ========================================================================== */
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)5753 OMX_ERRORTYPE  omx_vdec::use_buffer(
5754         OMX_IN OMX_HANDLETYPE            hComp,
5755         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5756         OMX_IN OMX_U32                   port,
5757         OMX_IN OMX_PTR                   appData,
5758         OMX_IN OMX_U32                   bytes,
5759         OMX_IN OMX_U8*                   buffer)
5760 {
5761     OMX_ERRORTYPE error = OMX_ErrorNone;
5762     struct vdec_setbuffer_cmd setbuffers;
5763 
5764     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5765             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5766             return OMX_ErrorBadParameter;
5767     }
5768     if (m_state == OMX_StateInvalid) {
5769         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5770         return OMX_ErrorInvalidState;
5771     }
5772     if (port == OMX_CORE_INPUT_PORT_INDEX)
5773         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5774     else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
5775         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5776     else {
5777         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5778         error = OMX_ErrorBadPortIndex;
5779     }
5780     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5781     if (error == OMX_ErrorNone) {
5782         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5783             // Send the callback now
5784             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5785             post_event(OMX_CommandStateSet,OMX_StateIdle,
5786                     OMX_COMPONENT_GENERATE_EVENT);
5787         }
5788         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5789                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5790             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5791             post_event(OMX_CommandPortEnable,
5792                     OMX_CORE_INPUT_PORT_INDEX,
5793                     OMX_COMPONENT_GENERATE_EVENT);
5794         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
5795                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5796             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5797             post_event(OMX_CommandPortEnable,
5798                     OMX_CORE_OUTPUT_PORT_INDEX,
5799                     OMX_COMPONENT_GENERATE_EVENT);
5800         }
5801     }
5802     return error;
5803 }
5804 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)5805 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
5806         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
5807 {
5808     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
5809         if (m_inp_heap_ptr[bufferindex].pBuffer)
5810             free(m_inp_heap_ptr[bufferindex].pBuffer);
5811         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
5812     }
5813     if (pmem_bufferHdr)
5814         free_input_buffer(pmem_bufferHdr);
5815     return OMX_ErrorNone;
5816 }
5817 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5818 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5819 {
5820     unsigned int index = 0;
5821     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
5822         return OMX_ErrorBadParameter;
5823     }
5824 
5825     index = bufferHdr - m_inp_mem_ptr;
5826     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5827 
5828     auto_lock l(buf_lock);
5829     bufferHdr->pInputPortPrivate = NULL;
5830 
5831     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
5832         DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5833         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
5834             struct vdec_setbuffer_cmd setbuffers;
5835             setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
5836             memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
5837                     sizeof (vdec_bufferpayload));
5838             if (!secure_mode) {
5839                 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
5840                         drv_ctx.ptr_inputbuffer[index].pmem_fd);
5841                 DEBUG_PRINT_LOW("unmap the input buffer size=%u  address = %p",
5842                         (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
5843                         drv_ctx.ptr_inputbuffer[index].bufferaddr);
5844                 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
5845                         drv_ctx.ptr_inputbuffer[index].mmaped_size);
5846             }
5847             close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
5848             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
5849             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
5850                 free(m_desc_buffer_ptr[index].buf_addr);
5851                 m_desc_buffer_ptr[index].buf_addr = NULL;
5852                 m_desc_buffer_ptr[index].desc_data_size = 0;
5853             }
5854 #ifdef USE_ION
5855             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
5856 #endif
5857         }
5858     }
5859 
5860     return OMX_ErrorNone;
5861 }
5862 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5863 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5864 {
5865     unsigned int index = 0;
5866 
5867     if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
5868         return OMX_ErrorBadParameter;
5869     }
5870 
5871     index = bufferHdr - m_out_mem_ptr;
5872     DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
5873 
5874     if (index < drv_ctx.op_buf.actualcount
5875             && drv_ctx.ptr_outputbuffer) {
5876         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
5877                 drv_ctx.ptr_outputbuffer[index].bufferaddr);
5878 
5879         struct vdec_setbuffer_cmd setbuffers;
5880         setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5881         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
5882                 sizeof (vdec_bufferpayload));
5883 
5884         if (!dynamic_buf_mode) {
5885             if (streaming[CAPTURE_PORT] &&
5886                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
5887                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
5888                     DEBUG_PRINT_ERROR("STREAMOFF Failed");
5889                 } else {
5890                     DEBUG_PRINT_LOW("STREAMOFF Successful");
5891                 }
5892             }
5893 #ifdef _ANDROID_
5894             if (m_enable_android_native_buffers) {
5895                 if (!secure_mode) {
5896                     if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
5897                         munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
5898                                 drv_ctx.ptr_outputbuffer[index].mmaped_size);
5899                     }
5900                 }
5901                 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
5902             } else {
5903 #endif
5904                 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
5905                     if (!secure_mode) {
5906                         DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
5907                                 drv_ctx.ptr_outputbuffer[0].pmem_fd);
5908                         DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
5909                                 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
5910                                 drv_ctx.ptr_outputbuffer[0].bufferaddr);
5911                         munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
5912                                 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
5913                     }
5914                     close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
5915                     drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
5916 #ifdef USE_ION
5917                     free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
5918 #endif
5919                 }
5920 #ifdef _ANDROID_
5921             }
5922 #endif
5923         } //!dynamic_buf_mode
5924         if (release_output_done()) {
5925             free_extradata();
5926         }
5927     }
5928 
5929     return OMX_ErrorNone;
5930 
5931 }
5932 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)5933 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
5934         OMX_BUFFERHEADERTYPE **bufferHdr,
5935         OMX_U32              port,
5936         OMX_PTR              appData,
5937         OMX_U32              bytes)
5938 {
5939     OMX_BUFFERHEADERTYPE *input = NULL;
5940     unsigned char *buf_addr = NULL;
5941     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5942     unsigned   i = 0;
5943 
5944     /* Sanity Check*/
5945     if (bufferHdr == NULL) {
5946         return OMX_ErrorBadParameter;
5947     }
5948 
5949     if (m_inp_heap_ptr == NULL) {
5950         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
5951                  calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5952                          drv_ctx.ip_buf.actualcount);
5953         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
5954                   calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5955                           drv_ctx.ip_buf.actualcount);
5956 
5957         if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
5958             DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
5959             return OMX_ErrorInsufficientResources;
5960         }
5961     }
5962 
5963     /*Find a Free index*/
5964     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
5965         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
5966             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
5967             break;
5968         }
5969     }
5970 
5971     if (i < drv_ctx.ip_buf.actualcount) {
5972         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
5973 
5974         if (buf_addr == NULL) {
5975             return OMX_ErrorInsufficientResources;
5976         }
5977 
5978         *bufferHdr = (m_inp_heap_ptr + i);
5979         input = *bufferHdr;
5980         BITMASK_SET(&m_heap_inp_bm_count,i);
5981 
5982         input->pBuffer           = (OMX_U8 *)buf_addr;
5983         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
5984         input->nVersion.nVersion = OMX_SPEC_VERSION;
5985         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
5986         input->pAppPrivate       = appData;
5987         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
5988         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
5989         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
5990         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
5991         /*Add the Buffers to freeq*/
5992         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
5993                     (unsigned)NULL, (unsigned)NULL)) {
5994             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5995             return OMX_ErrorInsufficientResources;
5996         }
5997     } else {
5998         return OMX_ErrorBadParameter;
5999     }
6000 
6001     return eRet;
6002 
6003 }
6004 
6005 
6006 /* ======================================================================
6007    FUNCTION
6008    omx_vdec::AllocateInputBuffer
6009 
6010    DESCRIPTION
6011    Helper function for allocate buffer in the input pin
6012 
6013    PARAMETERS
6014    None.
6015 
6016    RETURN VALUE
6017    true/false
6018 
6019    ========================================================================== */
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)6020 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6021         OMX_IN OMX_HANDLETYPE            hComp,
6022         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6023         OMX_IN OMX_U32                   port,
6024         OMX_IN OMX_PTR                   appData,
6025         OMX_IN OMX_U32                   bytes)
6026 {
6027     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6028     struct vdec_setbuffer_cmd setbuffers;
6029     OMX_BUFFERHEADERTYPE *input = NULL;
6030     unsigned   i = 0;
6031     unsigned char *buf_addr = NULL;
6032     int pmem_fd = -1;
6033 
6034     (void) hComp;
6035     (void) port;
6036 
6037 
6038     if (bytes != drv_ctx.ip_buf.buffer_size) {
6039         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6040                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6041         return OMX_ErrorBadParameter;
6042     }
6043 
6044     if (!m_inp_mem_ptr) {
6045         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6046                 drv_ctx.ip_buf.actualcount,
6047                 (unsigned int)drv_ctx.ip_buf.buffer_size);
6048 
6049         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6050                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6051 
6052         if (m_inp_mem_ptr == NULL) {
6053             return OMX_ErrorInsufficientResources;
6054         }
6055 
6056         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6057                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6058 
6059         if (drv_ctx.ptr_inputbuffer == NULL) {
6060             return OMX_ErrorInsufficientResources;
6061         }
6062 #ifdef USE_ION
6063         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6064                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6065 
6066         if (drv_ctx.ip_buf_ion_info == NULL) {
6067             return OMX_ErrorInsufficientResources;
6068         }
6069 #endif
6070 
6071         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6072             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6073 #ifdef USE_ION
6074             drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6075 #endif
6076         }
6077     }
6078 
6079     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6080         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6081             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6082             break;
6083         }
6084     }
6085 
6086     if (i < drv_ctx.ip_buf.actualcount) {
6087         struct v4l2_buffer buf;
6088         struct v4l2_plane plane;
6089         int rc;
6090         DEBUG_PRINT_LOW("Allocate input Buffer");
6091 #ifdef USE_ION
6092         drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6093                 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
6094                 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6095                 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6096                 SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6097         if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6098             return OMX_ErrorInsufficientResources;
6099         }
6100         pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6101 #else
6102         pmem_fd = open (MEM_DEVICE,O_RDWR);
6103 
6104         if (pmem_fd < 0) {
6105             DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6106             return OMX_ErrorInsufficientResources;
6107         }
6108 
6109         if (pmem_fd == 0) {
6110             pmem_fd = open (MEM_DEVICE,O_RDWR);
6111 
6112             if (pmem_fd < 0) {
6113                 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6114                 return OMX_ErrorInsufficientResources;
6115             }
6116         }
6117 
6118         if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6119                     drv_ctx.ip_buf.alignment)) {
6120             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6121             close(pmem_fd);
6122             return OMX_ErrorInsufficientResources;
6123         }
6124 #endif
6125         if (!secure_mode) {
6126             buf_addr = (unsigned char *)mmap(NULL,
6127                     drv_ctx.ip_buf.buffer_size,
6128                     PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6129 
6130             if (buf_addr == MAP_FAILED) {
6131                 close(pmem_fd);
6132 #ifdef USE_ION
6133                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6134 #endif
6135                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6136                 return OMX_ErrorInsufficientResources;
6137             }
6138         }
6139         *bufferHdr = (m_inp_mem_ptr + i);
6140         if (secure_mode)
6141             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6142         else
6143             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6144         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6145         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6146         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6147         drv_ctx.ptr_inputbuffer [i].offset = 0;
6148 
6149 
6150         buf.index = i;
6151         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6152         buf.memory = V4L2_MEMORY_USERPTR;
6153         plane.bytesused = 0;
6154         plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6155         plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6156         plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6157         plane.reserved[1] = 0;
6158         plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6159         buf.m.planes = &plane;
6160         buf.length = 1;
6161 
6162         DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6163                 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6164 
6165         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6166 
6167         if (rc) {
6168             DEBUG_PRINT_ERROR("Failed to prepare bufs");
6169             /*TODO: How to handle this case */
6170             return OMX_ErrorInsufficientResources;
6171         }
6172 
6173         input = *bufferHdr;
6174         BITMASK_SET(&m_inp_bm_count,i);
6175         DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6176         if (secure_mode || m_input_pass_buffer_fd)
6177             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6178         else
6179             input->pBuffer = (OMX_U8 *)buf_addr;
6180 
6181         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6182         input->nVersion.nVersion = OMX_SPEC_VERSION;
6183         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6184         input->pAppPrivate       = appData;
6185         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6186         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6187 
6188         if (drv_ctx.disable_dmx) {
6189             eRet = allocate_desc_buffer(i);
6190         }
6191     } else {
6192         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6193         eRet = OMX_ErrorInsufficientResources;
6194     }
6195     return eRet;
6196 }
6197 
6198 
6199 /* ======================================================================
6200    FUNCTION
6201    omx_vdec::AllocateOutputBuffer
6202 
6203    DESCRIPTION
6204    Helper fn for AllocateBuffer in the output pin
6205 
6206    PARAMETERS
6207    <TBD>.
6208 
6209    RETURN VALUE
6210    OMX Error None if everything went well.
6211 
6212    ========================================================================== */
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)6213 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6214         OMX_IN OMX_HANDLETYPE            hComp,
6215         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6216         OMX_IN OMX_U32                   port,
6217         OMX_IN OMX_PTR                   appData,
6218         OMX_IN OMX_U32                   bytes)
6219 {
6220     (void)hComp;
6221     (void)port;
6222     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6223     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6224     unsigned                         i= 0; // Temporary counter
6225     struct vdec_setbuffer_cmd setbuffers;
6226     int extra_idx = 0;
6227 #ifdef USE_ION
6228     int ion_device_fd =-1;
6229     struct ion_allocation_data ion_alloc_data;
6230     struct ion_fd_data fd_ion_data;
6231 #endif
6232     if (!m_out_mem_ptr) {
6233         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6234                 drv_ctx.op_buf.actualcount,
6235                 (unsigned int)drv_ctx.op_buf.buffer_size);
6236         int nBufHdrSize        = 0;
6237         int nPlatformEntrySize = 0;
6238         int nPlatformListSize  = 0;
6239         int nPMEMInfoSize = 0;
6240         int pmem_fd = -1;
6241         unsigned char *pmem_baseaddress = NULL;
6242 
6243         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6244         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6245         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6246 
6247         DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6248                 drv_ctx.op_buf.actualcount);
6249         nBufHdrSize        = drv_ctx.op_buf.actualcount *
6250             sizeof(OMX_BUFFERHEADERTYPE);
6251 
6252         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6253             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6254         nPlatformListSize  = drv_ctx.op_buf.actualcount *
6255             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6256         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6257             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6258 
6259         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6260                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6261                 nPMEMInfoSize,
6262                 nPlatformListSize);
6263         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6264                 drv_ctx.op_buf.actualcount);
6265 #ifdef USE_ION
6266         // Allocate output buffers as cached to improve performance of software-reading
6267         // of the YUVs. Output buffers are cache-invalidated in driver.
6268         // If color-conversion is involved, Only the C2D output buffers are cached, no
6269         // need to cache the decoder's output buffers
6270         int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6271         ion_device_fd = alloc_map_ion_memory(
6272                 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
6273                 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6274                 &ion_alloc_data, &fd_ion_data,
6275                 (secure_mode && !secure_scaling_to_non_secure_opb) ?
6276                 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6277         if (ion_device_fd < 0) {
6278             return OMX_ErrorInsufficientResources;
6279         }
6280         pmem_fd = fd_ion_data.fd;
6281 #else
6282         pmem_fd = open (MEM_DEVICE,O_RDWR);
6283 
6284         if (pmem_fd < 0) {
6285             DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6286                     drv_ctx.op_buf.buffer_size);
6287             return OMX_ErrorInsufficientResources;
6288         }
6289 
6290         if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
6291                     drv_ctx.op_buf.actualcount,
6292                     drv_ctx.op_buf.alignment)) {
6293             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6294             close(pmem_fd);
6295             return OMX_ErrorInsufficientResources;
6296         }
6297 #endif
6298         if (!secure_mode) {
6299             pmem_baseaddress = (unsigned char *)mmap(NULL,
6300                     (drv_ctx.op_buf.buffer_size *
6301                      drv_ctx.op_buf.actualcount),
6302                     PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
6303             if (pmem_baseaddress == MAP_FAILED) {
6304                 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6305                         (unsigned int)drv_ctx.op_buf.buffer_size);
6306                 close(pmem_fd);
6307 #ifdef USE_ION
6308                 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6309 #endif
6310                 return OMX_ErrorInsufficientResources;
6311             }
6312         }
6313         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
6314         // Alloc mem for platform specific info
6315         char *pPtr=NULL;
6316         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6317                 nPMEMInfoSize,1);
6318         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6319                        calloc (sizeof(struct vdec_bufferpayload),
6320                                drv_ctx.op_buf.actualcount);
6321         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
6322                      calloc (sizeof (struct vdec_output_frameinfo),
6323                              drv_ctx.op_buf.actualcount);
6324         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6325             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6326             return OMX_ErrorInsufficientResources;
6327         }
6328 
6329 #ifdef USE_ION
6330         drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6331                       calloc (sizeof(struct vdec_ion),
6332                               drv_ctx.op_buf.actualcount);
6333         if (!drv_ctx.op_buf_ion_info) {
6334             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6335             return OMX_ErrorInsufficientResources;
6336         }
6337 #endif
6338 
6339         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6340                 && drv_ctx.ptr_respbuffer) {
6341             drv_ctx.ptr_outputbuffer[0].mmaped_size =
6342                 (drv_ctx.op_buf.buffer_size *
6343                  drv_ctx.op_buf.actualcount);
6344             bufHdr          =  m_out_mem_ptr;
6345             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6346             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6347                 (((char *) m_platform_list)  + nPlatformListSize);
6348             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6349                 (((char *) m_platform_entry) + nPlatformEntrySize);
6350             pPlatformList   = m_platform_list;
6351             pPlatformEntry  = m_platform_entry;
6352             pPMEMInfo       = m_pmem_info;
6353 
6354             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6355 
6356             // Settting the entire storage nicely
6357             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
6358             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
6359             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6360                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6361                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6362                 // Set the values when we determine the right HxW param
6363                 bufHdr->nAllocLen          = bytes;
6364                 bufHdr->nFilledLen         = 0;
6365                 bufHdr->pAppPrivate        = appData;
6366                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
6367                 // Platform specific PMEM Information
6368                 // Initialize the Platform Entry
6369                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6370                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6371                 pPlatformEntry->entry      = pPMEMInfo;
6372                 // Initialize the Platform List
6373                 pPlatformList->nEntries    = 1;
6374                 pPlatformList->entryList   = pPlatformEntry;
6375                 // Keep pBuffer NULL till vdec is opened
6376                 bufHdr->pBuffer            = NULL;
6377                 bufHdr->nOffset            = 0;
6378 
6379                 pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
6380                 pPMEMInfo->pmem_fd = -1;
6381                 bufHdr->pPlatformPrivate = pPlatformList;
6382 
6383                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
6384                 m_pmem_info[i].pmem_fd = pmem_fd;
6385 #ifdef USE_ION
6386                 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
6387                 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
6388                 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
6389 #endif
6390 
6391                 /*Create a mapping between buffers*/
6392                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
6393                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
6394                                     &drv_ctx.ptr_outputbuffer[i];
6395                 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
6396                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6397                     pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
6398                 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6399                 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6400                 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6401 
6402                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
6403                         pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
6404                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
6405                 // Move the buffer and buffer header pointers
6406                 bufHdr++;
6407                 pPMEMInfo++;
6408                 pPlatformEntry++;
6409                 pPlatformList++;
6410             }
6411         } else {
6412             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6413                     m_out_mem_ptr, pPtr);
6414             if (m_out_mem_ptr) {
6415                 free(m_out_mem_ptr);
6416                 m_out_mem_ptr = NULL;
6417             }
6418             if (pPtr) {
6419                 free(pPtr);
6420                 pPtr = NULL;
6421             }
6422             if (drv_ctx.ptr_outputbuffer) {
6423                 free(drv_ctx.ptr_outputbuffer);
6424                 drv_ctx.ptr_outputbuffer = NULL;
6425             }
6426             if (drv_ctx.ptr_respbuffer) {
6427                 free(drv_ctx.ptr_respbuffer);
6428                 drv_ctx.ptr_respbuffer = NULL;
6429             }
6430 #ifdef USE_ION
6431             if (drv_ctx.op_buf_ion_info) {
6432                 DEBUG_PRINT_LOW("Free o/p ion context");
6433                 free(drv_ctx.op_buf_ion_info);
6434                 drv_ctx.op_buf_ion_info = NULL;
6435             }
6436 #endif
6437             eRet =  OMX_ErrorInsufficientResources;
6438         }
6439         if (eRet == OMX_ErrorNone)
6440             eRet = allocate_extradata();
6441     }
6442 
6443     for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6444         if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6445             DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
6446             break;
6447         }
6448     }
6449 
6450     if (eRet == OMX_ErrorNone) {
6451         if (i < drv_ctx.op_buf.actualcount) {
6452             struct v4l2_buffer buf;
6453             struct v4l2_plane plane[VIDEO_MAX_PLANES];
6454             int rc;
6455             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6456 
6457             drv_ctx.ptr_outputbuffer[i].buffer_len =
6458                 drv_ctx.op_buf.buffer_size;
6459 
6460             *bufferHdr = (m_out_mem_ptr + i );
6461             if (secure_mode) {
6462 #ifdef USE_ION
6463                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6464                     (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6465 #else
6466                 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6467 #endif
6468             }
6469             drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6470 
6471             buf.index = i;
6472             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6473             buf.memory = V4L2_MEMORY_USERPTR;
6474             plane[0].length = drv_ctx.op_buf.buffer_size;
6475             plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6476                 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6477 #ifdef USE_ION
6478             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6479 #endif
6480             plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6481             plane[0].data_offset = 0;
6482             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6483             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6484                 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6485                 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6486 #ifdef USE_ION
6487                 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6488 #endif
6489                 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6490                 plane[extra_idx].data_offset = 0;
6491             } else if (extra_idx >= VIDEO_MAX_PLANES) {
6492                 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
6493                 return OMX_ErrorBadParameter;
6494             }
6495             buf.m.planes = plane;
6496             buf.length = drv_ctx.num_planes;
6497             DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
6498             rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6499             if (rc) {
6500                 /*TODO: How to handle this case */
6501                 return OMX_ErrorInsufficientResources;
6502             }
6503 
6504             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6505                 enum v4l2_buf_type buf_type;
6506                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6507                 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6508                 if (rc) {
6509                     return OMX_ErrorInsufficientResources;
6510                 } else {
6511                     streaming[CAPTURE_PORT] = true;
6512                     DEBUG_PRINT_LOW("STREAMON Successful");
6513                 }
6514 
6515                 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6516                 request_perf_level(VIDC_TURBO);
6517             }
6518 
6519             (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
6520             (*bufferHdr)->pAppPrivate = appData;
6521             BITMASK_SET(&m_out_bm_count,i);
6522         } else {
6523             DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
6524             eRet = OMX_ErrorInsufficientResources;
6525         }
6526     }
6527 
6528     return eRet;
6529 }
6530 
6531 
6532 // AllocateBuffer  -- API Call
6533 /* ======================================================================
6534    FUNCTION
6535    omx_vdec::AllocateBuffer
6536 
6537    DESCRIPTION
6538    Returns zero if all the buffers released..
6539 
6540    PARAMETERS
6541    None.
6542 
6543    RETURN VALUE
6544    true/false
6545 
6546    ========================================================================== */
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)6547 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
6548         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6549         OMX_IN OMX_U32                        port,
6550         OMX_IN OMX_PTR                     appData,
6551         OMX_IN OMX_U32                       bytes)
6552 {
6553     unsigned i = 0;
6554     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
6555 
6556     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
6557     if (m_state == OMX_StateInvalid) {
6558         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
6559         return OMX_ErrorInvalidState;
6560     }
6561 
6562     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6563         if (arbitrary_bytes) {
6564             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
6565         } else {
6566             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
6567         }
6568     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6569         eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
6570                 appData,bytes);
6571     } else {
6572         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6573         eRet = OMX_ErrorBadPortIndex;
6574     }
6575     DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
6576     if (eRet == OMX_ErrorNone) {
6577         if (allocate_done()) {
6578             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6579                 // Send the callback now
6580                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6581                 post_event(OMX_CommandStateSet,OMX_StateIdle,
6582                         OMX_COMPONENT_GENERATE_EVENT);
6583             }
6584         }
6585         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
6586             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6587                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6588                 post_event(OMX_CommandPortEnable,
6589                         OMX_CORE_INPUT_PORT_INDEX,
6590                         OMX_COMPONENT_GENERATE_EVENT);
6591             }
6592         }
6593         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
6594             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6595                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6596                 post_event(OMX_CommandPortEnable,
6597                         OMX_CORE_OUTPUT_PORT_INDEX,
6598                         OMX_COMPONENT_GENERATE_EVENT);
6599             }
6600         }
6601     }
6602     DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
6603     return eRet;
6604 }
6605 
6606 // Free Buffer - API call
6607 /* ======================================================================
6608    FUNCTION
6609    omx_vdec::FreeBuffer
6610 
6611    DESCRIPTION
6612 
6613    PARAMETERS
6614    None.
6615 
6616    RETURN VALUE
6617    true/false
6618 
6619    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6620 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6621         OMX_IN OMX_U32                 port,
6622         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6623 {
6624     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6625     unsigned int nPortIndex;
6626     (void) hComp;
6627     DEBUG_PRINT_LOW("In for decoder free_buffer");
6628 
6629     if (m_state == OMX_StateIdle &&
6630             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6631         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
6632     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
6633             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
6634         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
6635     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
6636                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
6637             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
6638              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
6639         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
6640     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
6641         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
6642         post_event(OMX_EventError,
6643                 OMX_ErrorPortUnpopulated,
6644                 OMX_COMPONENT_GENERATE_EVENT);
6645 
6646         return OMX_ErrorIncorrectStateOperation;
6647     } else if (m_state != OMX_StateInvalid) {
6648         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6649         post_event(OMX_EventError,
6650                 OMX_ErrorPortUnpopulated,
6651                 OMX_COMPONENT_GENERATE_EVENT);
6652     }
6653 
6654     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6655         /*Check if arbitrary bytes*/
6656         if (!arbitrary_bytes && !input_use_buffer)
6657             nPortIndex = buffer - m_inp_mem_ptr;
6658         else
6659             nPortIndex = buffer - m_inp_heap_ptr;
6660 
6661         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6662         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6663                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6664             // Clear the bit associated with it.
6665             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6666             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6667             if (input_use_buffer == true) {
6668 
6669                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6670                 if (m_phdr_pmem_ptr)
6671                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6672             } else {
6673                 if (arbitrary_bytes) {
6674                     if (m_phdr_pmem_ptr)
6675                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
6676                     else
6677                         free_input_buffer(nPortIndex,NULL);
6678                 } else
6679                     free_input_buffer(buffer);
6680             }
6681             m_inp_bPopulated = OMX_FALSE;
6682             if(release_input_done())
6683                 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
6684             /*Free the Buffer Header*/
6685             if (release_input_done()) {
6686                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6687                 free_input_buffer_header();
6688             }
6689         } else {
6690             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6691             eRet = OMX_ErrorBadPortIndex;
6692         }
6693 
6694         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6695                 && release_input_done()) {
6696             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6697             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6698             post_event(OMX_CommandPortDisable,
6699                     OMX_CORE_INPUT_PORT_INDEX,
6700                     OMX_COMPONENT_GENERATE_EVENT);
6701         }
6702     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6703         // check if the buffer is valid
6704         nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6705         if (nPortIndex < drv_ctx.op_buf.actualcount &&
6706                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6707             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6708             // Clear the bit associated with it.
6709             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6710             m_out_bPopulated = OMX_FALSE;
6711             client_buffers.free_output_buffer (buffer);
6712 
6713             if(release_output_done()) {
6714                 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
6715             }
6716             if (release_output_done()) {
6717                 free_output_buffer_header();
6718             }
6719         } else {
6720             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6721             eRet = OMX_ErrorBadPortIndex;
6722         }
6723         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6724                 && release_output_done()) {
6725             DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
6726 
6727             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6728             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6729 #ifdef _ANDROID_ICS_
6730             if (m_enable_android_native_buffers) {
6731                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6732                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6733             }
6734 #endif
6735 
6736             post_event(OMX_CommandPortDisable,
6737                     OMX_CORE_OUTPUT_PORT_INDEX,
6738                     OMX_COMPONENT_GENERATE_EVENT);
6739         }
6740     } else {
6741         eRet = OMX_ErrorBadPortIndex;
6742     }
6743     if ((eRet == OMX_ErrorNone) &&
6744             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6745         if (release_done()) {
6746             // Send the callback now
6747             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6748             post_event(OMX_CommandStateSet, OMX_StateLoaded,
6749                     OMX_COMPONENT_GENERATE_EVENT);
6750         }
6751     }
6752     return eRet;
6753 }
6754 
6755 
6756 /* ======================================================================
6757    FUNCTION
6758    omx_vdec::EmptyThisBuffer
6759 
6760    DESCRIPTION
6761    This routine is used to push the encoded video frames to
6762    the video decoder.
6763 
6764    PARAMETERS
6765    None.
6766 
6767    RETURN VALUE
6768    OMX Error None if everything went successful.
6769 
6770    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6771 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6772         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6773 {
6774     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6775     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6776 
6777     if (m_state != OMX_StateExecuting &&
6778             m_state != OMX_StatePause &&
6779             m_state != OMX_StateIdle) {
6780         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6781         return OMX_ErrorInvalidState;
6782     }
6783 
6784     if (buffer == NULL) {
6785         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6786         return OMX_ErrorBadParameter;
6787     }
6788 
6789     if (!m_inp_bEnabled) {
6790         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
6791         return OMX_ErrorIncorrectStateOperation;
6792     }
6793 
6794     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
6795         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
6796         return OMX_ErrorBadPortIndex;
6797     }
6798 
6799     if (perf_flag) {
6800         if (!latency) {
6801             dec_time.stop();
6802             latency = dec_time.processing_time_us();
6803             dec_time.start();
6804         }
6805     }
6806 
6807     if (arbitrary_bytes) {
6808         nBufferIndex = buffer - m_inp_heap_ptr;
6809     } else {
6810         if (input_use_buffer == true) {
6811             nBufferIndex = buffer - m_inp_heap_ptr;
6812             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
6813             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
6814             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
6815             buffer = &m_inp_mem_ptr[nBufferIndex];
6816             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
6817                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
6818         } else {
6819             nBufferIndex = buffer - m_inp_mem_ptr;
6820         }
6821     }
6822 
6823     if (nBufferIndex > drv_ctx.ip_buf.actualcount ) {
6824         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
6825         return OMX_ErrorBadParameter;
6826     }
6827 
6828     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6829         codec_config_flag = true;
6830         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
6831     }
6832 
6833     /* The client should not set this when codec is in arbitrary bytes mode */
6834     if (m_input_pass_buffer_fd) {
6835         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
6836     }
6837 
6838     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
6839             buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
6840     if (arbitrary_bytes) {
6841         post_event ((unsigned long)hComp,(unsigned long)buffer,
6842                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
6843     } else {
6844         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
6845     }
6846     time_stamp_dts.insert_timestamp(buffer);
6847     return OMX_ErrorNone;
6848 }
6849 
6850 /* ======================================================================
6851    FUNCTION
6852    omx_vdec::empty_this_buffer_proxy
6853 
6854    DESCRIPTION
6855    This routine is used to push the encoded video frames to
6856    the video decoder.
6857 
6858    PARAMETERS
6859    None.
6860 
6861    RETURN VALUE
6862    OMX Error None if everything went successful.
6863 
6864    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6865 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
6866         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6867 {
6868     (void) hComp;
6869     int push_cnt = 0,i=0;
6870     unsigned nPortIndex = 0;
6871     OMX_ERRORTYPE ret = OMX_ErrorNone;
6872     struct vdec_input_frameinfo frameinfo;
6873     struct vdec_bufferpayload *temp_buffer;
6874     struct vdec_seqheader seq_header;
6875     bool port_setting_changed = true;
6876 
6877     /*Should we generate a Aync error event*/
6878     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
6879         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
6880         return OMX_ErrorBadParameter;
6881     }
6882 
6883     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
6884 
6885     if (nPortIndex > drv_ctx.ip_buf.actualcount) {
6886         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
6887                 nPortIndex);
6888         return OMX_ErrorBadParameter;
6889     }
6890 
6891     pending_input_buffers++;
6892 
6893     /* return zero length and not an EOS buffer */
6894     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
6895             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
6896         DEBUG_PRINT_HIGH("return zero legth buffer");
6897         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6898                 OMX_COMPONENT_GENERATE_EBD);
6899         return OMX_ErrorNone;
6900     }
6901 
6902     if (input_flush_progress == true) {
6903         DEBUG_PRINT_LOW("Flush in progress return buffer ");
6904         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6905                 OMX_COMPONENT_GENERATE_EBD);
6906         return OMX_ErrorNone;
6907     }
6908 
6909     auto_lock l(buf_lock);
6910     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
6911 
6912     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
6913         return OMX_ErrorBadParameter;
6914     }
6915     /* If its first frame, H264 codec and reject is true, then parse the nal
6916        and get the profile. Based on this, reject the clip playback */
6917     if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
6918             m_reject_avc_1080p_mp) {
6919         first_frame = 1;
6920         DEBUG_PRINT_ERROR("Parse nal to get the profile");
6921         h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
6922                 NALU_TYPE_SPS);
6923         m_profile = h264_parser->get_profile();
6924         ret = is_video_session_supported();
6925         if (ret) {
6926             post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
6927             post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
6928             /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
6929             m_state = OMX_StateInvalid;
6930             return OMX_ErrorNone;
6931         }
6932     }
6933 
6934     DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6935     /*for use buffer we need to memcpy the data*/
6936     temp_buffer->buffer_len = buffer->nFilledLen;
6937 
6938     if (input_use_buffer && temp_buffer->bufferaddr) {
6939         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
6940             if (arbitrary_bytes) {
6941                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
6942             } else {
6943                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
6944                         buffer->nFilledLen);
6945             }
6946         } else {
6947             return OMX_ErrorBadParameter;
6948         }
6949 
6950     }
6951 
6952     frameinfo.bufferaddr = temp_buffer->bufferaddr;
6953     frameinfo.client_data = (void *) buffer;
6954     frameinfo.datalen = temp_buffer->buffer_len;
6955     frameinfo.flags = 0;
6956     frameinfo.offset = buffer->nOffset;
6957     frameinfo.pmem_fd = temp_buffer->pmem_fd;
6958     frameinfo.pmem_offset = temp_buffer->offset;
6959     frameinfo.timestamp = buffer->nTimeStamp;
6960     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
6961         DEBUG_PRINT_LOW("ETB: dmx enabled");
6962         if (m_demux_entries == 0) {
6963             extract_demux_addr_offsets(buffer);
6964         }
6965 
6966         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
6967         handle_demux_data(buffer);
6968         frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
6969         frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
6970     } else {
6971         frameinfo.desc_addr = NULL;
6972         frameinfo.desc_size = 0;
6973     }
6974     if (!arbitrary_bytes) {
6975         frameinfo.flags |= buffer->nFlags;
6976     }
6977 
6978 #ifdef _ANDROID_
6979     if (m_debug_timestamp) {
6980         if (arbitrary_bytes) {
6981             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
6982             m_timestamp_list.insert_ts(buffer->nTimeStamp);
6983         } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
6984             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
6985             m_timestamp_list.insert_ts(buffer->nTimeStamp);
6986         }
6987     }
6988 #endif
6989 
6990 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
6991 
6992 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
6993         frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6994         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6995     }
6996 
6997     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
6998         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
6999         frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7000         h264_scratch.nFilledLen = 0;
7001         nal_count = 0;
7002         look_ahead_nal = false;
7003         frame_count = 0;
7004         if (m_frame_parser.mutils)
7005             m_frame_parser.mutils->initialize_frame_checking_environment();
7006         m_frame_parser.flush();
7007         h264_last_au_ts = LLONG_MAX;
7008         h264_last_au_flags = 0;
7009         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7010         m_demux_entries = 0;
7011     }
7012     struct v4l2_buffer buf;
7013     struct v4l2_plane plane;
7014     memset( (void *)&buf, 0, sizeof(buf));
7015     memset( (void *)&plane, 0, sizeof(plane));
7016     int rc;
7017     unsigned long  print_count;
7018     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7019         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7020         DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7021     }
7022     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7023     buf.index = nPortIndex;
7024     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7025     buf.memory = V4L2_MEMORY_USERPTR;
7026     plane.bytesused = temp_buffer->buffer_len;
7027     plane.length = drv_ctx.ip_buf.buffer_size;
7028     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7029         (unsigned long)temp_buffer->offset;
7030     plane.reserved[0] = temp_buffer->pmem_fd;
7031     plane.reserved[1] = temp_buffer->offset;
7032     plane.data_offset = 0;
7033     buf.m.planes = &plane;
7034     buf.length = 1;
7035     if (frameinfo.timestamp >= LLONG_MAX) {
7036         buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7037     }
7038     //assumption is that timestamp is in milliseconds
7039     buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7040     buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7041     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7042     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7043 
7044     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7045         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7046         android_atomic_inc(&m_queued_codec_config_count);
7047     }
7048 
7049     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7050     if (rc) {
7051         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
7052         return OMX_ErrorHardware;
7053     }
7054 
7055     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7056         codec_config_flag = false;
7057     }
7058     if (!streaming[OUTPUT_PORT]) {
7059         enum v4l2_buf_type buf_type;
7060         int ret,r;
7061 
7062         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7063         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7064         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7065         if (!ret) {
7066             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7067             streaming[OUTPUT_PORT] = true;
7068         } else if (errno == EBUSY) {
7069             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7070             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7071                     OMX_COMPONENT_GENERATE_EBD);
7072             return OMX_ErrorInsufficientResources;
7073         } else {
7074             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7075             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7076             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7077                     OMX_COMPONENT_GENERATE_EBD);
7078             return OMX_ErrorBadParameter;
7079         }
7080     }
7081     DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7082             frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7083             (unsigned int)frameinfo.datalen);
7084 
7085     return ret;
7086 }
7087 
7088 /* ======================================================================
7089    FUNCTION
7090    omx_vdec::FillThisBuffer
7091 
7092    DESCRIPTION
7093    IL client uses this method to release the frame buffer
7094    after displaying them.
7095 
7096    PARAMETERS
7097    None.
7098 
7099    RETURN VALUE
7100    true/false
7101 
7102    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7103 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7104         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7105 {
7106     if (m_state != OMX_StateExecuting &&
7107             m_state != OMX_StatePause &&
7108             m_state != OMX_StateIdle) {
7109         DEBUG_PRINT_ERROR("FTB in Invalid State");
7110         return OMX_ErrorInvalidState;
7111     }
7112 
7113     if (!m_out_bEnabled) {
7114         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7115         return OMX_ErrorIncorrectStateOperation;
7116     }
7117 
7118     unsigned nPortIndex = 0;
7119     if (dynamic_buf_mode) {
7120         private_handle_t *handle = NULL;
7121         struct VideoDecoderOutputMetaData *meta;
7122         unsigned int nPortIndex = 0;
7123 
7124         if (!buffer || !buffer->pBuffer) {
7125             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7126             return OMX_ErrorBadParameter;
7127         }
7128 
7129         //get the buffer type and fd info
7130         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7131         handle = (private_handle_t *)meta->pHandle;
7132         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7133 
7134         if (!handle) {
7135             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7136             return OMX_ErrorBadParameter;
7137         }
7138         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7139         nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7140         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7141             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7142             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7143             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7144 
7145            //Store private handle from GraphicBuffer
7146             native_buffer[nPortIndex].privatehandle = handle;
7147             native_buffer[nPortIndex].nativehandle = handle;
7148         } else {
7149             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7150             return OMX_ErrorBadParameter;
7151         }
7152 
7153         //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7154         //this with a more sane size so that we don't compensate in rest of code
7155         //We'll restore this size later on, so that it's transparent to client
7156         buffer->nFilledLen = 0;
7157         buffer->nAllocLen = handle->size;
7158     }
7159 
7160     nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7161     if (buffer == NULL ||
7162             (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7163         DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7164             nPortIndex, drv_ctx.op_buf.actualcount);
7165         return OMX_ErrorBadParameter;
7166     }
7167 
7168     if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7169         DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7170         return OMX_ErrorBadPortIndex;
7171     }
7172 
7173     DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7174     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7175     return OMX_ErrorNone;
7176 }
7177 /* ======================================================================
7178    FUNCTION
7179    omx_vdec::fill_this_buffer_proxy
7180 
7181    DESCRIPTION
7182    IL client uses this method to release the frame buffer
7183    after displaying them.
7184 
7185    PARAMETERS
7186    None.
7187 
7188    RETURN VALUE
7189    true/false
7190 
7191    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7192 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
7193         OMX_IN OMX_HANDLETYPE        hComp,
7194         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7195 {
7196     OMX_ERRORTYPE nRet = OMX_ErrorNone;
7197     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7198     unsigned nPortIndex = 0;
7199     struct vdec_fillbuffer_cmd fillbuffer;
7200     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
7201     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
7202 
7203     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7204 
7205     if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) {
7206         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7207             nPortIndex, drv_ctx.op_buf.actualcount);
7208         return OMX_ErrorBadParameter;
7209     }
7210 
7211     DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
7212             bufferAdd, bufferAdd->pBuffer);
7213     /*Return back the output buffer to client*/
7214     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
7215         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7216         buffer->nFilledLen = 0;
7217         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7218         return OMX_ErrorNone;
7219     }
7220 
7221     if (dynamic_buf_mode) {
7222         drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7223         drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7224         buf_ref_add(nPortIndex);
7225         drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7226     }
7227 
7228     pending_output_buffers++;
7229     buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7230     if (!buffer) {
7231        DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7232        return OMX_ErrorBadParameter;
7233     }
7234     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7235     if (ptr_respbuffer) {
7236         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7237     }
7238 
7239     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7240         DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
7241         buffer->nFilledLen = 0;
7242         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7243         pending_output_buffers--;
7244         return OMX_ErrorBadParameter;
7245     }
7246 
7247     int rc = 0;
7248     struct v4l2_buffer buf;
7249     struct v4l2_plane plane[VIDEO_MAX_PLANES];
7250     memset( (void *)&buf, 0, sizeof(buf));
7251     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7252     unsigned int extra_idx = 0;
7253 
7254     buf.index = nPortIndex;
7255     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7256     buf.memory = V4L2_MEMORY_USERPTR;
7257     plane[0].bytesused = buffer->nFilledLen;
7258     plane[0].length = buffer->nAllocLen;
7259     plane[0].m.userptr =
7260         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7261         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7262     plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7263     plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7264     plane[0].data_offset = 0;
7265     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7266     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7267         plane[extra_idx].bytesused = 0;
7268         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7269         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7270 #ifdef USE_ION
7271         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7272 #endif
7273         plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7274         plane[extra_idx].data_offset = 0;
7275     } else if (extra_idx >= VIDEO_MAX_PLANES) {
7276         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7277         return OMX_ErrorBadParameter;
7278     }
7279     buf.m.planes = plane;
7280     buf.length = drv_ctx.num_planes;
7281     DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
7282              plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
7283 
7284     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7285     if (rc) {
7286         /*TODO: How to handle this case */
7287         DEBUG_PRINT_ERROR("Failed to qbuf to driver");
7288     }
7289 return OMX_ErrorNone;
7290 }
7291 
7292 /* ======================================================================
7293    FUNCTION
7294    omx_vdec::SetCallbacks
7295 
7296    DESCRIPTION
7297    Set the callbacks.
7298 
7299    PARAMETERS
7300    None.
7301 
7302    RETURN VALUE
7303    OMX Error None if everything successful.
7304 
7305    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7306 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
7307         OMX_IN OMX_CALLBACKTYPE* callbacks,
7308         OMX_IN OMX_PTR             appData)
7309 {
7310     (void) hComp;
7311     m_cb       = *callbacks;
7312     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7313             m_cb.EventHandler,m_cb.FillBufferDone);
7314     m_app_data =    appData;
7315     return OMX_ErrorNotImplemented;
7316 }
7317 
7318 /* ======================================================================
7319    FUNCTION
7320    omx_vdec::ComponentDeInit
7321 
7322    DESCRIPTION
7323    Destroys the component and release memory allocated to the heap.
7324 
7325    PARAMETERS
7326    <TBD>.
7327 
7328    RETURN VALUE
7329    OMX Error None if everything successful.
7330 
7331    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7332 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7333 {
7334    (void) hComp;
7335 
7336     unsigned i = 0;
7337     if (OMX_StateLoaded != m_state) {
7338         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7339                 m_state);
7340         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7341     } else {
7342         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7343     }
7344 
7345     /*Check if the output buffers have to be cleaned up*/
7346     if (m_out_mem_ptr) {
7347         DEBUG_PRINT_LOW("Freeing the Output Memory");
7348         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7349             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7350                 BITMASK_CLEAR(&m_out_bm_count, i);
7351                 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
7352             }
7353 
7354             if (release_output_done()) {
7355                 break;
7356             }
7357         }
7358 #ifdef _ANDROID_ICS_
7359         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7360 #endif
7361     }
7362 
7363     /*Check if the input buffers have to be cleaned up*/
7364     if (m_inp_mem_ptr || m_inp_heap_ptr) {
7365         DEBUG_PRINT_LOW("Freeing the Input Memory");
7366         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7367 
7368             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7369                 BITMASK_CLEAR(&m_inp_bm_count, i);
7370                 if (m_inp_mem_ptr)
7371                     free_input_buffer (i,&m_inp_mem_ptr[i]);
7372                 else
7373                     free_input_buffer (i,NULL);
7374             }
7375 
7376             if (release_input_done()) {
7377                 break;
7378             }
7379        }
7380     }
7381     free_input_buffer_header();
7382     free_output_buffer_header();
7383     if (h264_scratch.pBuffer) {
7384         free(h264_scratch.pBuffer);
7385         h264_scratch.pBuffer = NULL;
7386     }
7387 
7388     if (h264_parser) {
7389         delete h264_parser;
7390         h264_parser = NULL;
7391     }
7392 
7393     if (m_frame_parser.mutils) {
7394         DEBUG_PRINT_LOW("Free utils parser");
7395         delete (m_frame_parser.mutils);
7396         m_frame_parser.mutils = NULL;
7397     }
7398 
7399     if (m_platform_list) {
7400         free(m_platform_list);
7401         m_platform_list = NULL;
7402     }
7403     if (m_vendor_config.pData) {
7404         free(m_vendor_config.pData);
7405         m_vendor_config.pData = NULL;
7406     }
7407 
7408     // Reset counters in mesg queues
7409     m_ftb_q.m_size=0;
7410     m_cmd_q.m_size=0;
7411     m_etb_q.m_size=0;
7412     m_ftb_q.m_read = m_ftb_q.m_write =0;
7413     m_cmd_q.m_read = m_cmd_q.m_write =0;
7414     m_etb_q.m_read = m_etb_q.m_write =0;
7415 #ifdef _ANDROID_
7416     if (m_debug_timestamp) {
7417         m_timestamp_list.reset_ts_list();
7418     }
7419 #endif
7420 
7421     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7422     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7423     // NULL);
7424     DEBUG_PRINT_HIGH("Close the driver instance");
7425 
7426     if (m_debug.infile) {
7427         fclose(m_debug.infile);
7428         m_debug.infile = NULL;
7429     }
7430     if (m_debug.outfile) {
7431         fclose(m_debug.outfile);
7432         m_debug.outfile = NULL;
7433     }
7434     if (m_debug.out_ymeta_file) {
7435         fclose(m_debug.out_ymeta_file);
7436         m_debug.out_ymeta_file = NULL;
7437     }
7438     if (m_debug.out_uvmeta_file) {
7439         fclose(m_debug.out_uvmeta_file);
7440         m_debug.out_uvmeta_file = NULL;
7441     }
7442 #ifdef OUTPUT_EXTRADATA_LOG
7443     if (outputExtradataFile)
7444         fclose (outputExtradataFile);
7445 #endif
7446     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
7447     return OMX_ErrorNone;
7448 }
7449 
7450 /* ======================================================================
7451    FUNCTION
7452    omx_vdec::UseEGLImage
7453 
7454    DESCRIPTION
7455    OMX Use EGL Image method implementation <TBD>.
7456 
7457    PARAMETERS
7458    <TBD>.
7459 
7460    RETURN VALUE
7461    Not Implemented error.
7462 
7463    ========================================================================== */
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)7464 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
7465         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7466         OMX_IN OMX_U32                        port,
7467         OMX_IN OMX_PTR                     appData,
7468         OMX_IN void*                      eglImage)
7469 {
7470     (void) appData;
7471     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
7472     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
7473     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
7474 
7475 #ifdef USE_EGL_IMAGE_GPU
7476     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
7477     EGLint fd = -1, offset = 0,pmemPtr = 0;
7478 #else
7479     int fd = -1, offset = 0;
7480 #endif
7481     DEBUG_PRINT_HIGH("use EGL image support for decoder");
7482     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
7483         DEBUG_PRINT_ERROR("Invalid EGL image");
7484     }
7485 #ifdef USE_EGL_IMAGE_GPU
7486     if (m_display_id == NULL) {
7487         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
7488         return OMX_ErrorInsufficientResources;
7489     }
7490     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
7491         eglGetProcAddress("eglQueryImageKHR");
7492     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
7493     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
7494     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
7495 #else //with OMX test app
7496     struct temp_egl {
7497         int pmem_fd;
7498         int offset;
7499     };
7500     struct temp_egl *temp_egl_id = NULL;
7501     void * pmemPtr = (void *) eglImage;
7502     temp_egl_id = (struct temp_egl *)eglImage;
7503     if (temp_egl_id != NULL) {
7504         fd = temp_egl_id->pmem_fd;
7505         offset = temp_egl_id->offset;
7506     }
7507 #endif
7508     if (fd < 0) {
7509         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
7510         return OMX_ErrorInsufficientResources;
7511     }
7512     pmem_info.pmem_fd = (OMX_U32) fd;
7513     pmem_info.offset = (OMX_U32) offset;
7514     pmem_entry.entry = (void *) &pmem_info;
7515     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7516     pmem_list.entryList = &pmem_entry;
7517     pmem_list.nEntries = 1;
7518     ouput_egl_buffers = true;
7519     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
7520                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
7521                 (OMX_U8 *)pmemPtr)) {
7522         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
7523         return OMX_ErrorInsufficientResources;
7524     }
7525     return OMX_ErrorNone;
7526 }
7527 
7528 /* ======================================================================
7529    FUNCTION
7530    omx_vdec::ComponentRoleEnum
7531 
7532    DESCRIPTION
7533    OMX Component Role Enum method implementation.
7534 
7535    PARAMETERS
7536    <TBD>.
7537 
7538    RETURN VALUE
7539    OMX Error None if everything is successful.
7540    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)7541 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
7542         OMX_OUT OMX_U8*        role,
7543         OMX_IN OMX_U32        index)
7544 {
7545     (void) hComp;
7546     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7547 
7548     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
7549         if ((0 == index) && role) {
7550             strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
7551             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7552         } else {
7553             eRet = OMX_ErrorNoMore;
7554         }
7555     }
7556     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
7557         if ((0 == index) && role) {
7558             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
7559             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7560         } else {
7561             eRet = OMX_ErrorNoMore;
7562         }
7563     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
7564         if ((0 == index) && role) {
7565             strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
7566             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7567         } else {
7568             DEBUG_PRINT_LOW("No more roles");
7569             eRet = OMX_ErrorNoMore;
7570         }
7571     }
7572 
7573     else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
7574             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
7575         if ((0 == index) && role) {
7576             strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
7577             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7578         } else {
7579             DEBUG_PRINT_LOW("No more roles");
7580             eRet = OMX_ErrorNoMore;
7581         }
7582     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
7583         if ((0 == index) && role) {
7584             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
7585             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7586         } else {
7587             DEBUG_PRINT_LOW("No more roles");
7588             eRet = OMX_ErrorNoMore;
7589         }
7590     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
7591         if ((0 == index) && role) {
7592             strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
7593             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7594         } else {
7595             DEBUG_PRINT_LOW("No more roles");
7596             eRet = OMX_ErrorNoMore;
7597         }
7598     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
7599         if ((0 == index) && role) {
7600             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
7601             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
7602         } else {
7603             DEBUG_PRINT_LOW("No more roles");
7604             eRet = OMX_ErrorNoMore;
7605         }
7606     } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
7607             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
7608           ) {
7609         if ((0 == index) && role) {
7610             strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
7611             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7612         } else {
7613             DEBUG_PRINT_LOW("No more roles");
7614             eRet = OMX_ErrorNoMore;
7615         }
7616     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7617         if ((0 == index) && role) {
7618             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7619             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7620         } else {
7621             DEBUG_PRINT_LOW("No more roles");
7622             eRet = OMX_ErrorNoMore;
7623         }
7624     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
7625         if ((0 == index) && role) {
7626             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
7627             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7628         } else {
7629             DEBUG_PRINT_LOW("No more roles");
7630             eRet = OMX_ErrorNoMore;
7631         }
7632     } else {
7633         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7634         eRet = OMX_ErrorInvalidComponentName;
7635     }
7636     return eRet;
7637 }
7638 
7639 
7640 
7641 
7642 /* ======================================================================
7643    FUNCTION
7644    omx_vdec::AllocateDone
7645 
7646    DESCRIPTION
7647    Checks if entire buffer pool is allocated by IL Client or not.
7648    Need this to move to IDLE state.
7649 
7650    PARAMETERS
7651    None.
7652 
7653    RETURN VALUE
7654    true/false.
7655 
7656    ========================================================================== */
allocate_done(void)7657 bool omx_vdec::allocate_done(void)
7658 {
7659     bool bRet = false;
7660     bool bRet_In = false;
7661     bool bRet_Out = false;
7662 
7663     bRet_In = allocate_input_done();
7664     bRet_Out = allocate_output_done();
7665 
7666     if (bRet_In && bRet_Out) {
7667         bRet = true;
7668     }
7669 
7670     return bRet;
7671 }
7672 /* ======================================================================
7673    FUNCTION
7674    omx_vdec::AllocateInputDone
7675 
7676    DESCRIPTION
7677    Checks if I/P buffer pool is allocated by IL Client or not.
7678 
7679    PARAMETERS
7680    None.
7681 
7682    RETURN VALUE
7683    true/false.
7684 
7685    ========================================================================== */
allocate_input_done(void)7686 bool omx_vdec::allocate_input_done(void)
7687 {
7688     bool bRet = false;
7689     unsigned i=0;
7690 
7691     if (m_inp_mem_ptr == NULL) {
7692         return bRet;
7693     }
7694     if (m_inp_mem_ptr ) {
7695         for (; i<drv_ctx.ip_buf.actualcount; i++) {
7696             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7697                 break;
7698             }
7699         }
7700     }
7701     if (i == drv_ctx.ip_buf.actualcount) {
7702         bRet = true;
7703         DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
7704     }
7705     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7706         m_inp_bPopulated = OMX_TRUE;
7707     }
7708     return bRet;
7709 }
7710 /* ======================================================================
7711    FUNCTION
7712    omx_vdec::AllocateOutputDone
7713 
7714    DESCRIPTION
7715    Checks if entire O/P buffer pool is allocated by IL Client or not.
7716 
7717    PARAMETERS
7718    None.
7719 
7720    RETURN VALUE
7721    true/false.
7722 
7723    ========================================================================== */
allocate_output_done(void)7724 bool omx_vdec::allocate_output_done(void)
7725 {
7726     bool bRet = false;
7727     unsigned j=0;
7728 
7729     if (m_out_mem_ptr == NULL) {
7730         return bRet;
7731     }
7732 
7733     if (m_out_mem_ptr) {
7734         for (; j < drv_ctx.op_buf.actualcount; j++) {
7735             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7736                 break;
7737             }
7738         }
7739     }
7740 
7741     if (j == drv_ctx.op_buf.actualcount) {
7742         bRet = true;
7743         DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
7744         if (m_out_bEnabled)
7745             m_out_bPopulated = OMX_TRUE;
7746     }
7747 
7748     return bRet;
7749 }
7750 
7751 /* ======================================================================
7752    FUNCTION
7753    omx_vdec::ReleaseDone
7754 
7755    DESCRIPTION
7756    Checks if IL client has released all the buffers.
7757 
7758    PARAMETERS
7759    None.
7760 
7761    RETURN VALUE
7762    true/false
7763 
7764    ========================================================================== */
release_done(void)7765 bool omx_vdec::release_done(void)
7766 {
7767     bool bRet = false;
7768 
7769     if (release_input_done()) {
7770         if (release_output_done()) {
7771             bRet = true;
7772         }
7773     }
7774     return bRet;
7775 }
7776 
7777 
7778 /* ======================================================================
7779    FUNCTION
7780    omx_vdec::ReleaseOutputDone
7781 
7782    DESCRIPTION
7783    Checks if IL client has released all the buffers.
7784 
7785    PARAMETERS
7786    None.
7787 
7788    RETURN VALUE
7789    true/false
7790 
7791    ========================================================================== */
release_output_done(void)7792 bool omx_vdec::release_output_done(void)
7793 {
7794     bool bRet = false;
7795     unsigned i=0,j=0;
7796 
7797     DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
7798     if (m_out_mem_ptr) {
7799         for (; j < drv_ctx.op_buf.actualcount ; j++) {
7800             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
7801                 break;
7802             }
7803         }
7804         if (j == drv_ctx.op_buf.actualcount) {
7805             m_out_bm_count = 0;
7806             bRet = true;
7807         }
7808     } else {
7809         m_out_bm_count = 0;
7810         bRet = true;
7811     }
7812     return bRet;
7813 }
7814 /* ======================================================================
7815    FUNCTION
7816    omx_vdec::ReleaseInputDone
7817 
7818    DESCRIPTION
7819    Checks if IL client has released all the buffers.
7820 
7821    PARAMETERS
7822    None.
7823 
7824    RETURN VALUE
7825    true/false
7826 
7827    ========================================================================== */
release_input_done(void)7828 bool omx_vdec::release_input_done(void)
7829 {
7830     bool bRet = false;
7831     unsigned i=0,j=0;
7832 
7833     DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
7834     if (m_inp_mem_ptr) {
7835         for (; j<drv_ctx.ip_buf.actualcount; j++) {
7836             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
7837                 break;
7838             }
7839         }
7840         if (j==drv_ctx.ip_buf.actualcount) {
7841             bRet = true;
7842         }
7843     } else {
7844         bRet = true;
7845     }
7846     return bRet;
7847 }
7848 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7849 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
7850         OMX_BUFFERHEADERTYPE * buffer)
7851 {
7852     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
7853     if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
7854         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
7855         return OMX_ErrorBadParameter;
7856     } else if (output_flush_progress) {
7857         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
7858         buffer->nFilledLen = 0;
7859         buffer->nTimeStamp = 0;
7860         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
7861         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7862         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
7863     }
7864 
7865     if (m_debug_extradata) {
7866         if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7867             DEBUG_PRINT_HIGH("***************************************************");
7868             DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
7869             DEBUG_PRINT_HIGH("***************************************************");
7870         }
7871 
7872         if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
7873             DEBUG_PRINT_HIGH("***************************************************");
7874             DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
7875             DEBUG_PRINT_HIGH("***************************************************");
7876         }
7877     }
7878 
7879 
7880     DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
7881             buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
7882     pending_output_buffers --;
7883 
7884     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7885         DEBUG_PRINT_HIGH("Output EOS has been reached");
7886         if (!output_flush_progress)
7887             post_event((unsigned)NULL, (unsigned)NULL,
7888                     OMX_COMPONENT_GENERATE_EOS_DONE);
7889 
7890         if (psource_frame) {
7891             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
7892             psource_frame = NULL;
7893         }
7894         if (pdest_frame) {
7895             pdest_frame->nFilledLen = 0;
7896             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
7897                     (unsigned)NULL);
7898             pdest_frame = NULL;
7899         }
7900     }
7901 
7902     if (!output_flush_progress && (buffer->nFilledLen > 0)) {
7903         DEBUG_PRINT_LOW("Processing extradata");
7904         handle_extradata(buffer);
7905     }
7906 
7907 #ifdef OUTPUT_EXTRADATA_LOG
7908     if (outputExtradataFile) {
7909         int buf_index = buffer - m_out_mem_ptr;
7910         OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
7911 
7912         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
7913         p_extra = (OMX_OTHER_EXTRADATATYPE *)
7914             ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
7915 
7916         while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
7917             DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
7918                                     p_extra->nSize, p_extra->eType);
7919             fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
7920 
7921             if (p_extra->eType == OMX_ExtraDataNone) {
7922                 break;
7923             }
7924             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7925         }
7926     }
7927 #endif
7928 
7929     /* For use buffer we need to copy the data */
7930     if (!output_flush_progress) {
7931         /* This is the error check for non-recoverable errros */
7932         bool is_duplicate_ts_valid = true;
7933         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
7934 
7935         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
7936                 output_capability == V4L2_PIX_FMT_MPEG2 ||
7937                 output_capability == V4L2_PIX_FMT_DIVX ||
7938                 output_capability == V4L2_PIX_FMT_DIVX_311)
7939             is_duplicate_ts_valid = false;
7940 
7941         if ((output_capability == V4L2_PIX_FMT_H264 ||
7942                 output_capability == V4L2_PIX_FMT_H264_MVC) &&
7943                 is_interlaced) {
7944             if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
7945                 is_interlaced = false;
7946             }
7947         }
7948 
7949         if (buffer->nFilledLen > 0) {
7950             time_stamp_dts.get_next_timestamp(buffer,
7951                     is_interlaced && is_duplicate_ts_valid);
7952             if (m_debug_timestamp) {
7953                 {
7954                     OMX_TICKS expected_ts = 0;
7955                     m_timestamp_list.pop_min_ts(expected_ts);
7956                     if (is_interlaced && is_duplicate_ts_valid) {
7957                         m_timestamp_list.pop_min_ts(expected_ts);
7958                     }
7959                     DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
7960                             buffer->nTimeStamp, expected_ts);
7961 
7962                     if (buffer->nTimeStamp != expected_ts) {
7963                         DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
7964                     }
7965                 }
7966             }
7967         }
7968     }
7969 
7970     if (m_cb.FillBufferDone) {
7971         if (buffer->nFilledLen > 0) {
7972             if (arbitrary_bytes)
7973                 adjust_timestamp(buffer->nTimeStamp);
7974             else
7975                 set_frame_rate(buffer->nTimeStamp);
7976 
7977             if (perf_flag) {
7978                 if (!proc_frms) {
7979                     dec_time.stop();
7980                     latency = dec_time.processing_time_us() - latency;
7981                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
7982                     dec_time.start();
7983                     fps_metrics.start();
7984                 }
7985                 proc_frms++;
7986                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7987                     OMX_U64 proc_time = 0;
7988                     fps_metrics.stop();
7989                     proc_time = fps_metrics.processing_time_us();
7990                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
7991                             (unsigned int)proc_frms, (float)proc_time / 1e6,
7992                             (float)(1e6 * proc_frms) / proc_time);
7993                     proc_frms = 0;
7994                 }
7995             }
7996         }
7997         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7998             prev_ts = LLONG_MAX;
7999             rst_prev_ts = true;
8000         }
8001 
8002         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8003             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8004              buffer->pPlatformPrivate)->entryList->entry;
8005         DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8006         OMX_BUFFERHEADERTYPE *il_buffer;
8007         il_buffer = client_buffers.get_il_buf_hdr(buffer);
8008         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8009 
8010         if (il_buffer && m_last_rendered_TS >= 0) {
8011             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8012 
8013             // Current frame can be send for rendering if
8014             // (a) current FPS is <=  60
8015             // (b) is the next frame after the frame with TS 0
8016             // (c) is the first frame after seek
8017             // (d) the delta TS b\w two consecutive frames is > 16 ms
8018             // (e) its TS is equal to previous frame TS
8019             // (f) if marked EOS
8020 
8021             if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8022                il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8023                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8024                m_last_rendered_TS = il_buffer->nTimeStamp;
8025             } else {
8026                //mark for droping
8027                buffer->nFilledLen = 0;
8028             }
8029 
8030             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8031                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8032                               il_buffer->nTimeStamp,ts_delta);
8033 
8034             //above code makes sure that delta b\w two consecutive frames is not
8035             //greater than 16ms, slow-mo feature, so cap fps to max 60
8036             if (current_framerate > 60 ) {
8037                 current_framerate = 60;
8038             }
8039         }
8040 
8041         // add current framerate to gralloc meta data
8042         if (m_enable_android_native_buffers && m_out_mem_ptr) {
8043             OMX_U32 buf_index = buffer - m_out_mem_ptr;
8044             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8045                          UPDATE_REFRESH_RATE, (void*)&current_framerate);
8046         }
8047 
8048         if (il_buffer) {
8049             log_output_buffers(il_buffer);
8050             if (dynamic_buf_mode) {
8051                 unsigned int nPortIndex = 0;
8052                 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8053 
8054                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8055                 // to size of the handle. Do it _after_ log_output_buffers which
8056                 // requires the respective sizes to be accurate.
8057 
8058                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8059                 buffer->nFilledLen = buffer->nFilledLen ?
8060                         sizeof(struct VideoDecoderOutputMetaData) : 0;
8061 
8062                 //Clear graphic buffer handles in dynamic mode
8063                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8064                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8065                     native_buffer[nPortIndex].privatehandle = NULL;
8066                     native_buffer[nPortIndex].nativehandle = NULL;
8067                 } else {
8068                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8069                     return OMX_ErrorBadParameter;
8070                 }
8071             }
8072             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8073         } else {
8074             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8075             return OMX_ErrorBadParameter;
8076         }
8077         DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
8078     } else {
8079         return OMX_ErrorBadParameter;
8080     }
8081 
8082 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8083     if (m_smoothstreaming_mode && m_out_mem_ptr) {
8084         OMX_U32 buf_index = buffer - m_out_mem_ptr;
8085         BufferDim_t dim;
8086         private_handle_t *private_handle = NULL;
8087         dim.sliceWidth = framesize.nWidth;
8088         dim.sliceHeight = framesize.nHeight;
8089         if (buf_index < drv_ctx.op_buf.actualcount &&
8090             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8091             native_buffer[buf_index].privatehandle)
8092             private_handle = native_buffer[buf_index].privatehandle;
8093         if (private_handle) {
8094             DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8095                 dim.sliceWidth, dim.sliceHeight);
8096             setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8097         }
8098     }
8099 #endif
8100 
8101     return OMX_ErrorNone;
8102 }
8103 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8104 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
8105         OMX_BUFFERHEADERTYPE* buffer)
8106 {
8107 
8108     int nBufferIndex = buffer - m_inp_mem_ptr;
8109 
8110     if (buffer == NULL || (nBufferIndex > (int)drv_ctx.ip_buf.actualcount)) {
8111         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8112         return OMX_ErrorBadParameter;
8113     }
8114 
8115     DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
8116             buffer, buffer->pBuffer, buffer->nFlags);
8117     pending_input_buffers--;
8118 
8119     if (arbitrary_bytes) {
8120         if (pdest_frame == NULL && input_flush_progress == false) {
8121             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8122             pdest_frame = buffer;
8123             buffer->nFilledLen = 0;
8124             buffer->nTimeStamp = LLONG_MAX;
8125             push_input_buffer (hComp);
8126         } else {
8127             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8128             buffer->nFilledLen = 0;
8129             if (!m_input_free_q.insert_entry((unsigned long)buffer,
8130                         (unsigned)NULL, (unsigned)NULL)) {
8131                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8132             }
8133         }
8134     } else if (m_cb.EmptyBufferDone) {
8135         buffer->nFilledLen = 0;
8136         if (input_use_buffer == true) {
8137             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8138         }
8139 
8140         /* Restore the FD that we over-wrote in ETB */
8141         if (m_input_pass_buffer_fd) {
8142             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8143         }
8144 
8145         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8146     }
8147     return OMX_ErrorNone;
8148 }
8149 
async_message_process(void * context,void * message)8150 int omx_vdec::async_message_process (void *context, void* message)
8151 {
8152     omx_vdec* omx = NULL;
8153     struct vdec_msginfo *vdec_msg = NULL;
8154     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8155     struct v4l2_buffer *v4l2_buf_ptr = NULL;
8156     struct vdec_output_frameinfo *output_respbuf = NULL;
8157     int rc=1;
8158     if (context == NULL || message == NULL) {
8159         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8160         return -1;
8161     }
8162     vdec_msg = (struct vdec_msginfo *)message;
8163 
8164     omx = reinterpret_cast<omx_vdec*>(context);
8165 
8166     switch (vdec_msg->msgcode) {
8167 
8168         case VDEC_MSG_EVT_HW_ERROR:
8169             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8170                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8171             break;
8172 
8173         case VDEC_MSG_EVT_HW_OVERLOAD:
8174             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8175                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8176             break;
8177 
8178         case VDEC_MSG_EVT_HW_UNSUPPORTED:
8179             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8180                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8181             break;
8182 
8183         case VDEC_MSG_RESP_START_DONE:
8184             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8185                     OMX_COMPONENT_GENERATE_START_DONE);
8186             break;
8187 
8188         case VDEC_MSG_RESP_STOP_DONE:
8189             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8190                     OMX_COMPONENT_GENERATE_STOP_DONE);
8191             break;
8192 
8193         case VDEC_MSG_RESP_RESUME_DONE:
8194             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8195                     OMX_COMPONENT_GENERATE_RESUME_DONE);
8196             break;
8197 
8198         case VDEC_MSG_RESP_PAUSE_DONE:
8199             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8200                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
8201             break;
8202 
8203         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8204             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8205                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8206             break;
8207         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8208             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8209                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8210             break;
8211         case VDEC_MSG_RESP_INPUT_FLUSHED:
8212         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8213 
8214             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8215                vdec_msg->msgdata.input_frame_clientdata; */
8216 
8217             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8218             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8219                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8220                 omxhdr = NULL;
8221                 vdec_msg->status_code = VDEC_S_EFATAL;
8222                 break;
8223 
8224             }
8225             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8226 
8227             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8228                 DEBUG_PRINT_HIGH("Unsupported input");
8229                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8230                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8231             }
8232             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8233                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8234                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8235             }
8236             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8237 
8238                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8239                 android_atomic_dec(&omx->m_queued_codec_config_count);
8240                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8241                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8242                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8243                     sem_post(&omx->m_safe_flush);
8244                 }
8245             }
8246             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8247                 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8248                 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8249             }
8250             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8251                     OMX_COMPONENT_GENERATE_EBD);
8252             break;
8253         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8254             int64_t *timestamp;
8255             timestamp = (int64_t *) malloc(sizeof(int64_t));
8256             if (timestamp) {
8257                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8258                 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8259                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8260                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8261                         (long long)vdec_msg->msgdata.output_frame.time_stamp);
8262             }
8263             break;
8264         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8265         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8266 
8267            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8268 
8269            if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8270                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8271                omxhdr = NULL;
8272                vdec_msg->status_code = VDEC_S_EFATAL;
8273                break;
8274            }
8275 
8276            omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8277 
8278             DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8279                     omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8280                     vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8281                     (unsigned int)vdec_msg->msgdata.output_frame.len,
8282                     vdec_msg->msgdata.output_frame.framesize.left,
8283                     vdec_msg->msgdata.output_frame.framesize.top,
8284                     vdec_msg->msgdata.output_frame.framesize.right,
8285                     vdec_msg->msgdata.output_frame.framesize.bottom);
8286 
8287             if (omxhdr && omxhdr->pOutputPortPrivate &&
8288                     ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8289                     (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8290                       - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8291 
8292                 if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
8293                     omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8294                     omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8295                     omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8296                     omxhdr->nFlags = 0;
8297 
8298                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8299                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8300                         //rc = -1;
8301                     }
8302                     if (omxhdr->nFilledLen) {
8303                         omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8304                     }
8305                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8306                         omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8307                     } else {
8308                         omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8309                     }
8310                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
8311                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8312                     }
8313                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8314                         omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8315                     }
8316 
8317                     if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
8318                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
8319                     }
8320 
8321                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8322                          omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8323                          DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8324                                     omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8325                     }
8326 
8327                     if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
8328                             !omx->output_flush_progress &&
8329                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
8330                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
8331                         unsigned int index = v4l2_buf_ptr->index;
8332                         unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
8333                         struct v4l2_plane *plane = v4l2_buf_ptr->m.planes;
8334                         omx->time_stamp_dts.remove_time_stamp(
8335                                 omxhdr->nTimeStamp,
8336                                 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
8337                                 ?true:false);
8338                         plane[0].bytesused = 0;
8339                         plane[0].m.userptr =
8340                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
8341                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
8342                         plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
8343                         plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
8344                         plane[0].data_offset = 0;
8345                         v4l2_buf_ptr->flags = 0x0;
8346                         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8347                             plane[extra_idx].bytesused = 0;
8348                             plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
8349                             plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
8350 #ifdef USE_ION
8351                             plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
8352 #endif
8353                             plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
8354                             plane[extra_idx].data_offset = 0;
8355                         } else if (extra_idx >= VIDEO_MAX_PLANES) {
8356                             DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8357                             return -1;
8358                         }
8359 
8360                          DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8361                                plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
8362                         if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
8363                             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]);
8364                             return -1;
8365                         }
8366                         break;
8367                     }
8368                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8369                         omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8370                     }
8371                     vdec_msg->msgdata.output_frame.bufferaddr =
8372                         omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8373 
8374                     /* Post event if resolution OR crop changed */
8375                     /* filled length will be changed if resolution changed */
8376                     /* Crop parameters can be changed even without resolution change */
8377                     if (omxhdr->nFilledLen
8378                         && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8379                         || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8380                         || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8381                         || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8382                         || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
8383                         || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
8384                         || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
8385 
8386                         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",
8387                                 omx->prev_n_filled_len,
8388                                 omx->drv_ctx.video_resolution.frame_width,
8389                                 omx->drv_ctx.video_resolution.frame_height,
8390                                 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
8391                                 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
8392                                 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
8393                                 vdec_msg->msgdata.output_frame.picsize.frame_height,
8394                                 vdec_msg->msgdata.output_frame.framesize.left,
8395                                 vdec_msg->msgdata.output_frame.framesize.top,
8396                                 vdec_msg->msgdata.output_frame.framesize.right,
8397                                 vdec_msg->msgdata.output_frame.framesize.bottom);
8398 
8399                         omx->drv_ctx.video_resolution.frame_width =
8400                                 vdec_msg->msgdata.output_frame.picsize.frame_width;
8401                         omx->drv_ctx.video_resolution.frame_height =
8402                                 vdec_msg->msgdata.output_frame.picsize.frame_height;
8403                         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
8404                             omx->drv_ctx.video_resolution.stride =
8405                                 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
8406                             omx->drv_ctx.video_resolution.scan_lines =
8407                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
8408                         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
8409                             omx->drv_ctx.video_resolution.stride =
8410                                 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
8411                             omx->drv_ctx.video_resolution.scan_lines =
8412                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
8413                         }
8414 
8415                         memcpy(&omx->drv_ctx.frame_size,
8416                                 &vdec_msg->msgdata.output_frame.framesize,
8417                                 sizeof(struct vdec_framesize));
8418 
8419                         omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8420                                 OMX_IndexConfigCommonOutputCrop,
8421                                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8422                     }
8423 
8424                     if (omxhdr->nFilledLen)
8425                         omx->prev_n_filled_len = omxhdr->nFilledLen;
8426 
8427                     output_respbuf = (struct vdec_output_frameinfo *)\
8428                              omxhdr->pOutputPortPrivate;
8429                     if (!output_respbuf) {
8430                       DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8431                       return -1;
8432                     }
8433                     output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8434                     output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8435 
8436                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8437                         output_respbuf->pic_type = PICTURE_TYPE_I;
8438                     }
8439                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8440                         output_respbuf->pic_type = PICTURE_TYPE_P;
8441                     }
8442                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8443                         output_respbuf->pic_type = PICTURE_TYPE_B;
8444                     }
8445                     if (omxhdr && omxhdr->nFilledLen) {
8446                         omx->request_perf_level(VIDC_NOMINAL);
8447                     }
8448                     if (omx->output_use_buffer && omxhdr->pBuffer &&
8449                         vdec_msg->msgdata.output_frame.bufferaddr)
8450                         memcpy ( omxhdr->pBuffer, (void *)
8451                                 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
8452                                  (unsigned long)vdec_msg->msgdata.output_frame.offset),
8453                                 vdec_msg->msgdata.output_frame.len);
8454                 } else {
8455                     DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
8456                             (unsigned int)vdec_msg->msgdata.output_frame.len,
8457                             omxhdr->nAllocLen, omx->prev_n_filled_len);
8458                     omxhdr->nFilledLen = 0;
8459                 }
8460 
8461                 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
8462                         OMX_COMPONENT_GENERATE_FBD);
8463 
8464             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
8465                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
8466                         OMX_COMPONENT_GENERATE_EOS_DONE);
8467             } else {
8468                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
8469                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8470             }
8471             break;
8472         case VDEC_MSG_EVT_CONFIG_CHANGED:
8473             DEBUG_PRINT_HIGH("Port settings changed");
8474             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8475             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8476             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
8477                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8478             omx->request_perf_level(VIDC_NOMINAL);
8479             break;
8480         default:
8481             break;
8482     }
8483     return rc;
8484 }
8485 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8486 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
8487         OMX_HANDLETYPE hComp,
8488         OMX_BUFFERHEADERTYPE *buffer
8489         )
8490 {
8491     unsigned address,p2,id;
8492     DEBUG_PRINT_LOW("Empty this arbitrary");
8493 
8494     if (buffer == NULL) {
8495         return OMX_ErrorBadParameter;
8496     }
8497     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8498     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
8499             (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
8500 
8501     /* return zero length and not an EOS buffer */
8502     /* return buffer if input flush in progress */
8503     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
8504                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
8505         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
8506         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
8507         return OMX_ErrorNone;
8508     }
8509 
8510     if (psource_frame == NULL) {
8511         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
8512         psource_frame = buffer;
8513         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
8514         push_input_buffer (hComp);
8515     } else {
8516         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
8517         if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
8518                     (unsigned)NULL)) {
8519             return OMX_ErrorBadParameter;
8520         }
8521     }
8522 
8523     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
8524         codec_config_flag = false;
8525     }
8526     return OMX_ErrorNone;
8527 }
8528 
push_input_buffer(OMX_HANDLETYPE hComp)8529 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
8530 {
8531     unsigned long address,p2,id;
8532     OMX_ERRORTYPE ret = OMX_ErrorNone;
8533 
8534     if (pdest_frame == NULL || psource_frame == NULL) {
8535         /*Check if we have a destination buffer*/
8536         if (pdest_frame == NULL) {
8537             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
8538             if (m_input_free_q.m_size) {
8539                 m_input_free_q.pop_entry(&address,&p2,&id);
8540                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
8541                 pdest_frame->nFilledLen = 0;
8542                 pdest_frame->nTimeStamp = LLONG_MAX;
8543                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
8544             }
8545         }
8546 
8547         /*Check if we have a destination buffer*/
8548         if (psource_frame == NULL) {
8549             DEBUG_PRINT_LOW("Get a source buffer from the queue");
8550             if (m_input_pending_q.m_size) {
8551                 m_input_pending_q.pop_entry(&address,&p2,&id);
8552                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
8553                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8554                         psource_frame->nTimeStamp);
8555                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8556                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8557 
8558             }
8559         }
8560 
8561     }
8562 
8563     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
8564         switch (codec_type_parse) {
8565             case CODEC_TYPE_MPEG4:
8566             case CODEC_TYPE_H263:
8567             case CODEC_TYPE_MPEG2:
8568                 ret =  push_input_sc_codec(hComp);
8569                 break;
8570             case CODEC_TYPE_H264:
8571                 ret = push_input_h264(hComp);
8572                 break;
8573             case CODEC_TYPE_HEVC:
8574                 ret = push_input_hevc(hComp);
8575                 break;
8576             case CODEC_TYPE_VC1:
8577                 ret = push_input_vc1(hComp);
8578                 break;
8579             default:
8580                 break;
8581         }
8582         if (ret != OMX_ErrorNone) {
8583             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
8584             omx_report_error ();
8585             break;
8586         }
8587     }
8588 
8589     return ret;
8590 }
8591 
push_input_sc_codec(OMX_HANDLETYPE hComp)8592 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
8593 {
8594     OMX_U32 partial_frame = 1;
8595     OMX_BOOL generate_ebd = OMX_TRUE;
8596     unsigned long address = 0, p2 = 0, id = 0;
8597 
8598     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
8599             psource_frame,psource_frame->nTimeStamp);
8600     if (m_frame_parser.parse_sc_frame(psource_frame,
8601                 pdest_frame,&partial_frame) == -1) {
8602         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8603         return OMX_ErrorBadParameter;
8604     }
8605 
8606     if (partial_frame == 0) {
8607         DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
8608                 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
8609 
8610 
8611         DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
8612         /*First Parsed buffer will have only header Hence skip*/
8613         if (frame_count == 0) {
8614             DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
8615 
8616             if (codec_type_parse == CODEC_TYPE_MPEG4 ||
8617                     codec_type_parse == CODEC_TYPE_DIVX) {
8618                 mp4StreamType psBits;
8619                 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
8620                 psBits.numBytes = pdest_frame->nFilledLen;
8621                 mp4_headerparser.parseHeader(&psBits);
8622             }
8623 
8624             frame_count++;
8625         } else {
8626             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8627             if (pdest_frame->nFilledLen) {
8628                 /*Push the frame to the Decoder*/
8629                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8630                     return OMX_ErrorBadParameter;
8631                 }
8632                 frame_count++;
8633                 pdest_frame = NULL;
8634 
8635                 if (m_input_free_q.m_size) {
8636                     m_input_free_q.pop_entry(&address,&p2,&id);
8637                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8638                     pdest_frame->nFilledLen = 0;
8639                 }
8640             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
8641                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
8642                 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
8643                         (unsigned)NULL);
8644                 pdest_frame = NULL;
8645             }
8646         }
8647     } else {
8648         DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
8649         /*Check if Destination Buffer is full*/
8650         if (pdest_frame->nAllocLen ==
8651                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
8652             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
8653             return OMX_ErrorStreamCorrupt;
8654         }
8655     }
8656 
8657     if (psource_frame->nFilledLen == 0) {
8658         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8659             if (pdest_frame) {
8660                 pdest_frame->nFlags |= psource_frame->nFlags;
8661                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
8662                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8663                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8664                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
8665                 /*Push the frame to the Decoder*/
8666                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8667                     return OMX_ErrorBadParameter;
8668                 }
8669                 frame_count++;
8670                 pdest_frame = NULL;
8671             } else {
8672                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
8673                 generate_ebd = OMX_FALSE;
8674             }
8675         }
8676         if (generate_ebd) {
8677             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
8678             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8679             psource_frame = NULL;
8680 
8681             if (m_input_pending_q.m_size) {
8682                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8683                 m_input_pending_q.pop_entry(&address,&p2,&id);
8684                 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8685                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8686                         psource_frame->nTimeStamp);
8687                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8688                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8689             }
8690         }
8691     }
8692     return OMX_ErrorNone;
8693 }
8694 
push_input_h264(OMX_HANDLETYPE hComp)8695 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
8696 {
8697     OMX_U32 partial_frame = 1;
8698     unsigned long address = 0, p2 = 0, id = 0;
8699     OMX_BOOL isNewFrame = OMX_FALSE;
8700     OMX_BOOL generate_ebd = OMX_TRUE;
8701 
8702     if (h264_scratch.pBuffer == NULL) {
8703         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
8704         return OMX_ErrorBadParameter;
8705     }
8706     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
8707             "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
8708     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
8709     if (h264_scratch.nFilledLen && look_ahead_nal) {
8710         look_ahead_nal = false;
8711         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8712                 h264_scratch.nFilledLen) {
8713             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8714                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
8715             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8716             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
8717             h264_scratch.nFilledLen = 0;
8718         } else {
8719             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
8720             return OMX_ErrorBadParameter;
8721         }
8722     }
8723 
8724     /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
8725        in EOS flag getting associated with the destination
8726     */
8727     if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
8728             pdest_frame->nFilledLen) {
8729         DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
8730         generate_ebd = OMX_FALSE;
8731     }
8732 
8733     if (nal_length == 0) {
8734         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
8735         if (m_frame_parser.parse_sc_frame(psource_frame,
8736                     &h264_scratch,&partial_frame) == -1) {
8737             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8738             return OMX_ErrorBadParameter;
8739         }
8740     } else {
8741         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
8742         if (m_frame_parser.parse_h264_nallength(psource_frame,
8743                     &h264_scratch,&partial_frame) == -1) {
8744             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
8745             return OMX_ErrorBadParameter;
8746         }
8747     }
8748 
8749     if (partial_frame == 0) {
8750         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
8751             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
8752             nal_count++;
8753             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
8754             h264_scratch.nFlags = psource_frame->nFlags;
8755         } else {
8756             DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
8757             if (h264_scratch.nFilledLen) {
8758                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
8759                         NALU_TYPE_SPS);
8760 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8761                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
8762                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8763                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
8764                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8765                     // If timeinfo is present frame info from SEI is already processed
8766                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8767                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
8768 #endif
8769                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8770                 nal_count++;
8771                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
8772                     pdest_frame->nTimeStamp = h264_last_au_ts;
8773                     pdest_frame->nFlags = h264_last_au_flags;
8774 #ifdef PANSCAN_HDLR
8775                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8776                         h264_parser->update_panscan_data(h264_last_au_ts);
8777 #endif
8778                 }
8779                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
8780                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
8781                     h264_last_au_ts = h264_scratch.nTimeStamp;
8782                     h264_last_au_flags = h264_scratch.nFlags;
8783 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8784                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
8785                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
8786                         if (!VALID_TS(h264_last_au_ts))
8787                             h264_last_au_ts = ts_in_sei;
8788                     }
8789 #endif
8790                 } else
8791                     h264_last_au_ts = LLONG_MAX;
8792             }
8793 
8794             if (!isNewFrame) {
8795                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8796                         h264_scratch.nFilledLen) {
8797                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
8798                             (unsigned int)h264_scratch.nFilledLen);
8799                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8800                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
8801                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8802                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
8803                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8804                     h264_scratch.nFilledLen = 0;
8805                 } else {
8806                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
8807                     return OMX_ErrorBadParameter;
8808                 }
8809             } else if(h264_scratch.nFilledLen) {
8810                 look_ahead_nal = true;
8811                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
8812                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8813                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8814                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
8815 
8816                 if (pdest_frame->nFilledLen == 0) {
8817                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
8818                     look_ahead_nal = false;
8819                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8820                             h264_scratch.nFilledLen) {
8821                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8822                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8823                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8824                         h264_scratch.nFilledLen = 0;
8825                     } else {
8826                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
8827                         return OMX_ErrorBadParameter;
8828                     }
8829                 } else {
8830                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
8831                         DEBUG_PRINT_LOW("Reset the EOS Flag");
8832                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8833                     }
8834                     /*Push the frame to the Decoder*/
8835                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8836                         return OMX_ErrorBadParameter;
8837                     }
8838                     //frame_count++;
8839                     pdest_frame = NULL;
8840                     if (m_input_free_q.m_size) {
8841                         m_input_free_q.pop_entry(&address,&p2,&id);
8842                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8843                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
8844                         pdest_frame->nFilledLen = 0;
8845                         pdest_frame->nFlags = 0;
8846                         pdest_frame->nTimeStamp = LLONG_MAX;
8847                     }
8848                 }
8849             }
8850         }
8851     } else {
8852         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
8853         /*Check if Destination Buffer is full*/
8854         if (h264_scratch.nAllocLen ==
8855                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
8856             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
8857             return OMX_ErrorStreamCorrupt;
8858         }
8859     }
8860 
8861     if (!psource_frame->nFilledLen) {
8862         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
8863 
8864         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8865             if (pdest_frame) {
8866                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
8867                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8868                         h264_scratch.nFilledLen) {
8869                     if(pdest_frame->nFilledLen == 0) {
8870                         /* No residual frame from before, send whatever
8871                          * we have left */
8872                         memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8873                                 h264_scratch.pBuffer, h264_scratch.nFilledLen);
8874                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8875                         h264_scratch.nFilledLen = 0;
8876                         pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
8877                     } else {
8878                         m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8879                         if(!isNewFrame) {
8880                             /* Have a residual frame, but we know that the
8881                              * AU in this frame is belonging to whatever
8882                              * frame we had left over.  So append it */
8883                              memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8884                                      h264_scratch.pBuffer,h264_scratch.nFilledLen);
8885                              pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8886                              h264_scratch.nFilledLen = 0;
8887                              if (h264_last_au_ts != LLONG_MAX)
8888                                  pdest_frame->nTimeStamp = h264_last_au_ts;
8889                         } else {
8890                             /* Completely new frame, let's just push what
8891                              * we have now.  The resulting EBD would trigger
8892                              * another push */
8893                             generate_ebd = OMX_FALSE;
8894                             pdest_frame->nTimeStamp = h264_last_au_ts;
8895                             h264_last_au_ts = h264_scratch.nTimeStamp;
8896                         }
8897                     }
8898                 } else {
8899                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
8900                     return OMX_ErrorBadParameter;
8901                 }
8902 
8903                 /* Iff we coalesced two buffers, inherit the flags of both bufs */
8904                 if(generate_ebd == OMX_TRUE) {
8905                      pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
8906                 }
8907 
8908                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
8909                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8910                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
8911 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8912                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
8913                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
8914                     if (!VALID_TS(pdest_frame->nTimeStamp))
8915                         pdest_frame->nTimeStamp = ts_in_sei;
8916                 }
8917 #endif
8918                 /*Push the frame to the Decoder*/
8919                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8920                     return OMX_ErrorBadParameter;
8921                 }
8922                 frame_count++;
8923                 pdest_frame = NULL;
8924             } else {
8925                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
8926                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
8927                 generate_ebd = OMX_FALSE;
8928             }
8929         }
8930     }
8931     if (generate_ebd && !psource_frame->nFilledLen) {
8932         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8933         psource_frame = NULL;
8934         if (m_input_pending_q.m_size) {
8935             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8936             m_input_pending_q.pop_entry(&address,&p2,&id);
8937             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8938             DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
8939                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8940         }
8941     }
8942     return OMX_ErrorNone;
8943 }
8944 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)8945 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
8946 {
8947     OMX_ERRORTYPE rc = OMX_ErrorNone;
8948     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
8949         memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
8950         if (pDst->nTimeStamp == LLONG_MAX) {
8951             pDst->nTimeStamp = pSrc->nTimeStamp;
8952             DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
8953         }
8954         pDst->nFilledLen += pSrc->nFilledLen;
8955         pSrc->nFilledLen = 0;
8956     } else {
8957         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
8958         rc = OMX_ErrorBadParameter;
8959     }
8960     return rc;
8961 }
8962 
push_input_hevc(OMX_HANDLETYPE hComp)8963 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
8964 {
8965     OMX_U32 partial_frame = 1;
8966     unsigned long address,p2,id;
8967     OMX_BOOL isNewFrame = OMX_FALSE;
8968     OMX_BOOL generate_ebd = OMX_TRUE;
8969     OMX_ERRORTYPE rc = OMX_ErrorNone;
8970     if (h264_scratch.pBuffer == NULL) {
8971         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
8972         return OMX_ErrorBadParameter;
8973     }
8974 
8975     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
8976             pdest_frame nFilledLen %u nTimeStamp %lld",
8977             (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
8978 
8979     if (h264_scratch.nFilledLen && look_ahead_nal) {
8980         look_ahead_nal = false;
8981         rc = copy_buffer(pdest_frame, &h264_scratch);
8982         if (rc != OMX_ErrorNone) {
8983             return rc;
8984         }
8985     }
8986 
8987     if (nal_length == 0) {
8988         if (m_frame_parser.parse_sc_frame(psource_frame,
8989                     &h264_scratch,&partial_frame) == -1) {
8990             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8991             return OMX_ErrorBadParameter;
8992         }
8993     } else {
8994         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
8995         if (m_frame_parser.parse_h264_nallength(psource_frame,
8996                     &h264_scratch,&partial_frame) == -1) {
8997             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
8998             return OMX_ErrorBadParameter;
8999         }
9000     }
9001 
9002     if (partial_frame == 0) {
9003         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9004             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9005             nal_count++;
9006             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9007             h264_scratch.nFlags = psource_frame->nFlags;
9008         } else {
9009             DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9010             if (h264_scratch.nFilledLen) {
9011                 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9012                 nal_count++;
9013             }
9014 
9015             if (!isNewFrame) {
9016                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9017                         nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9018                         (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9019                         (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9020                 rc = copy_buffer(pdest_frame, &h264_scratch);
9021                 if (rc != OMX_ErrorNone) {
9022                     return rc;
9023                 }
9024             } else {
9025                 look_ahead_nal = true;
9026                 if (pdest_frame->nFilledLen == 0) {
9027                     look_ahead_nal = false;
9028                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9029                     rc = copy_buffer(pdest_frame, &h264_scratch);
9030                     if (rc != OMX_ErrorNone) {
9031                         return OMX_ErrorBadParameter;
9032                     }
9033                 } else {
9034                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9035                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9036                     }
9037                     DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9038                             nTimeStamp %lld, look_ahead_nal in h264_scratch \
9039                             nFilledLen %u nTimeStamp %lld",
9040                             frame_count++, (unsigned int)pdest_frame->nFilledLen,
9041                             pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9042                             h264_scratch.nTimeStamp);
9043                     if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9044                         return OMX_ErrorBadParameter;
9045                     }
9046                     pdest_frame = NULL;
9047                     if (m_input_free_q.m_size) {
9048                         m_input_free_q.pop_entry(&address, &p2, &id);
9049                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9050                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9051                         pdest_frame->nFilledLen = 0;
9052                         pdest_frame->nFlags = 0;
9053                         pdest_frame->nTimeStamp = LLONG_MAX;
9054                     }
9055                 }
9056             }
9057         }
9058     } else {
9059         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9060                 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9061                 nFilledLen %u nTimeStamp %lld",
9062                 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9063                 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9064                 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9065 
9066         if (h264_scratch.nAllocLen ==
9067                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9068             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9069             return OMX_ErrorStreamCorrupt;
9070         }
9071     }
9072 
9073     if (!psource_frame->nFilledLen) {
9074         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9075         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9076             if (pdest_frame) {
9077                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9078                 rc = copy_buffer(pdest_frame, &h264_scratch);
9079                 if ( rc != OMX_ErrorNone ) {
9080                     return rc;
9081                 }
9082                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9083                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9084                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9085                         frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9086                 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9087                     return OMX_ErrorBadParameter;
9088                 }
9089                 frame_count++;
9090                 pdest_frame = NULL;
9091             } else {
9092                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9093                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9094                 generate_ebd = OMX_FALSE;
9095             }
9096         }
9097     }
9098 
9099     if (generate_ebd && !psource_frame->nFilledLen) {
9100         m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9101         psource_frame = NULL;
9102         if (m_input_pending_q.m_size) {
9103             m_input_pending_q.pop_entry(&address, &p2, &id);
9104             psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9105             DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9106                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9107         }
9108     }
9109     return OMX_ErrorNone;
9110 }
9111 
push_input_vc1(OMX_HANDLETYPE hComp)9112 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
9113 {
9114     OMX_U8 *buf, *pdest;
9115     OMX_U32 partial_frame = 1;
9116     OMX_U32 buf_len, dest_len;
9117 
9118     if (first_frame == 0) {
9119         first_frame = 1;
9120         DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
9121         if (!m_vendor_config.pData) {
9122             DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
9123             buf = psource_frame->pBuffer;
9124             buf_len = psource_frame->nFilledLen;
9125 
9126             if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
9127                     VC1_SP_MP_START_CODE) {
9128                 m_vc1_profile = VC1_SP_MP_RCV;
9129             } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
9130                 m_vc1_profile = VC1_AP;
9131             } else {
9132                 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
9133                 return OMX_ErrorStreamCorrupt;
9134             }
9135         } else {
9136             pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
9137                 pdest_frame->nOffset;
9138             dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
9139                     pdest_frame->nOffset);
9140 
9141             if (dest_len < m_vendor_config.nDataSize) {
9142                 DEBUG_PRINT_ERROR("Destination buffer full");
9143                 return OMX_ErrorBadParameter;
9144             } else {
9145                 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
9146                 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
9147             }
9148         }
9149     }
9150 
9151     switch (m_vc1_profile) {
9152         case VC1_AP:
9153             DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
9154             if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
9155                 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
9156                 return OMX_ErrorBadParameter;
9157             }
9158             break;
9159 
9160         case VC1_SP_MP_RCV:
9161         default:
9162             DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
9163             return OMX_ErrorBadParameter;
9164     }
9165     return OMX_ErrorNone;
9166 }
9167 
9168 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9169 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9170         OMX_U32 alignment)
9171 {
9172     struct pmem_allocation allocation;
9173     allocation.size = buffer_size;
9174     allocation.align = clip2(alignment);
9175     if (allocation.align < 4096) {
9176         allocation.align = 4096;
9177     }
9178     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9179         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9180                 allocation.align, allocation.size);
9181         return false;
9182     }
9183     return true;
9184 }
9185 #endif
9186 #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)9187 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
9188         OMX_U32 alignment, struct ion_allocation_data *alloc_data,
9189         struct ion_fd_data *fd_data, int flag)
9190 {
9191     int fd = -EINVAL;
9192     int rc = -EINVAL;
9193     int ion_dev_flag;
9194     struct vdec_ion ion_buf_info;
9195     if (!alloc_data || buffer_size <= 0 || !fd_data) {
9196         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9197         return -EINVAL;
9198     }
9199     ion_dev_flag = O_RDONLY;
9200     fd = open (MEM_DEVICE, ion_dev_flag);
9201     if (fd < 0) {
9202         DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
9203         return fd;
9204     }
9205 
9206     alloc_data->flags = flag;
9207     alloc_data->len = buffer_size;
9208     alloc_data->align = clip2(alignment);
9209     if (alloc_data->align < 4096) {
9210         alloc_data->align = 4096;
9211     }
9212 
9213     alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
9214     if (secure_mode && (alloc_data->flags & ION_SECURE)) {
9215         alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9216     }
9217 
9218     /* Use secure display cma heap for obvious reasons. */
9219     if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
9220         alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9221     }
9222 
9223     rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
9224     if (rc || !alloc_data->handle) {
9225         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9226         alloc_data->handle = 0;
9227         close(fd);
9228         fd = -ENOMEM;
9229         return fd;
9230     }
9231     fd_data->handle = alloc_data->handle;
9232     rc = ioctl(fd,ION_IOC_MAP,fd_data);
9233     if (rc) {
9234         DEBUG_PRINT_ERROR("ION MAP failed ");
9235         ion_buf_info.ion_alloc_data = *alloc_data;
9236         ion_buf_info.ion_device_fd = fd;
9237         ion_buf_info.fd_ion_data = *fd_data;
9238         free_ion_memory(&ion_buf_info);
9239         fd_data->fd =-1;
9240         fd = -ENOMEM;
9241     }
9242 
9243     return fd;
9244 }
9245 
free_ion_memory(struct vdec_ion * buf_ion_info)9246 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9247 {
9248 
9249     if (!buf_ion_info) {
9250         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9251         return;
9252     }
9253     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
9254                 &buf_ion_info->ion_alloc_data.handle)) {
9255         DEBUG_PRINT_ERROR("ION: free failed" );
9256     }
9257     close(buf_ion_info->ion_device_fd);
9258     buf_ion_info->ion_device_fd = -1;
9259     buf_ion_info->ion_alloc_data.handle = 0;
9260     buf_ion_info->fd_ion_data.fd = -1;
9261 }
9262 #endif
free_output_buffer_header()9263 void omx_vdec::free_output_buffer_header()
9264 {
9265     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
9266     output_use_buffer = false;
9267     ouput_egl_buffers = false;
9268 
9269     if (m_out_mem_ptr) {
9270         free (m_out_mem_ptr);
9271         m_out_mem_ptr = NULL;
9272     }
9273 
9274     if (m_platform_list) {
9275         free(m_platform_list);
9276         m_platform_list = NULL;
9277     }
9278 
9279     if (drv_ctx.ptr_respbuffer) {
9280         free (drv_ctx.ptr_respbuffer);
9281         drv_ctx.ptr_respbuffer = NULL;
9282     }
9283     if (drv_ctx.ptr_outputbuffer) {
9284         free (drv_ctx.ptr_outputbuffer);
9285         drv_ctx.ptr_outputbuffer = NULL;
9286     }
9287 #ifdef USE_ION
9288     if (drv_ctx.op_buf_ion_info) {
9289         DEBUG_PRINT_LOW("Free o/p ion context");
9290         free(drv_ctx.op_buf_ion_info);
9291         drv_ctx.op_buf_ion_info = NULL;
9292     }
9293 #endif
9294     buf_ref_remove();
9295 }
9296 
free_input_buffer_header()9297 void omx_vdec::free_input_buffer_header()
9298 {
9299     input_use_buffer = false;
9300     if (arbitrary_bytes) {
9301         if (m_inp_heap_ptr) {
9302             DEBUG_PRINT_LOW("Free input Heap Pointer");
9303             free (m_inp_heap_ptr);
9304             m_inp_heap_ptr = NULL;
9305         }
9306 
9307         if (m_phdr_pmem_ptr) {
9308             DEBUG_PRINT_LOW("Free input pmem header Pointer");
9309             free (m_phdr_pmem_ptr);
9310             m_phdr_pmem_ptr = NULL;
9311         }
9312     }
9313     if (m_inp_mem_ptr) {
9314         DEBUG_PRINT_LOW("Free input pmem Pointer area");
9315         free (m_inp_mem_ptr);
9316         m_inp_mem_ptr = NULL;
9317     }
9318     /* We just freed all the buffer headers, every thing in m_input_free_q,
9319      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
9320     while (m_input_free_q.m_size) {
9321         unsigned long address, p2, id;
9322         m_input_free_q.pop_entry(&address, &p2, &id);
9323     }
9324     while (m_input_pending_q.m_size) {
9325         unsigned long address, p2, id;
9326         m_input_pending_q.pop_entry(&address, &p2, &id);
9327     }
9328     pdest_frame = NULL;
9329     psource_frame = NULL;
9330     if (drv_ctx.ptr_inputbuffer) {
9331         DEBUG_PRINT_LOW("Free Driver Context pointer");
9332         free (drv_ctx.ptr_inputbuffer);
9333         drv_ctx.ptr_inputbuffer = NULL;
9334     }
9335 #ifdef USE_ION
9336     if (drv_ctx.ip_buf_ion_info) {
9337         DEBUG_PRINT_LOW("Free ion context");
9338         free(drv_ctx.ip_buf_ion_info);
9339         drv_ctx.ip_buf_ion_info = NULL;
9340     }
9341 #endif
9342 }
9343 
stream_off(OMX_U32 port)9344 int omx_vdec::stream_off(OMX_U32 port)
9345 {
9346     enum v4l2_buf_type btype;
9347     int rc = 0;
9348     enum v4l2_ports v4l2_port = OUTPUT_PORT;
9349 
9350     if (port == OMX_CORE_INPUT_PORT_INDEX) {
9351         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9352         v4l2_port = OUTPUT_PORT;
9353     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
9354         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9355         v4l2_port = CAPTURE_PORT;
9356     } else if (port == OMX_ALL) {
9357         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
9358         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
9359 
9360         if (!rc_input)
9361             return rc_input;
9362         else
9363             return rc_output;
9364     }
9365 
9366     if (!streaming[v4l2_port]) {
9367         // already streamed off, warn and move on
9368         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
9369                 " which is already streamed off", v4l2_port);
9370         return 0;
9371     }
9372 
9373     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
9374 
9375     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
9376     if (rc) {
9377         /*TODO: How to handle this case */
9378         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
9379     } else {
9380         streaming[v4l2_port] = false;
9381     }
9382 
9383     return rc;
9384 }
9385 
get_buffer_req(vdec_allocatorproperty * buffer_prop)9386 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
9387 {
9388     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9389     struct v4l2_requestbuffers bufreq;
9390     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
9391     unsigned int final_extra_data_size = 0;
9392     struct v4l2_format fmt;
9393     int ret = 0;
9394     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9395             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9396     bufreq.memory = V4L2_MEMORY_USERPTR;
9397     bufreq.count = 1;
9398     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9399         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9400         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9401         fmt.fmt.pix_mp.pixelformat = output_capability;
9402     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9403         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9404         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9405         fmt.fmt.pix_mp.pixelformat = capture_capability;
9406     } else {
9407         eRet = OMX_ErrorBadParameter;
9408     }
9409     if (eRet==OMX_ErrorNone) {
9410         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9411     }
9412     if (ret) {
9413         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9414         /*TODO: How to handle this case */
9415         eRet = OMX_ErrorInsufficientResources;
9416         return eRet;
9417     } else {
9418         buffer_prop->actualcount = bufreq.count;
9419         buffer_prop->mincount = bufreq.count;
9420         DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
9421     }
9422     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9423             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9424 
9425     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9426     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9427 
9428     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9429 
9430     update_resolution(fmt.fmt.pix_mp.width,
9431             fmt.fmt.pix_mp.height,
9432             fmt.fmt.pix_mp.plane_fmt[0].bytesperline,
9433             fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
9434     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
9435         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
9436     DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
9437 
9438     if (ret) {
9439         /*TODO: How to handle this case */
9440         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9441         eRet = OMX_ErrorInsufficientResources;
9442     } else {
9443         int extra_idx = 0;
9444 
9445         eRet = is_video_session_supported();
9446         if (eRet)
9447             return eRet;
9448 
9449         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
9450         buf_size = buffer_prop->buffer_size;
9451         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
9452         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
9453             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
9454         } else if (extra_idx >= VIDEO_MAX_PLANES) {
9455             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
9456             return OMX_ErrorBadParameter;
9457         }
9458 
9459         default_extra_data_size = VENUS_EXTRADATA_SIZE(
9460                 drv_ctx.video_resolution.frame_height,
9461                 drv_ctx.video_resolution.frame_width);
9462         final_extra_data_size = extra_data_size > default_extra_data_size ?
9463             extra_data_size : default_extra_data_size;
9464 
9465         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
9466             (~(buffer_prop->alignment - 1));
9467 
9468         drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
9469         drv_ctx.extradata_info.count = buffer_prop->actualcount;
9470         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
9471         if (!secure_mode)
9472             buf_size += final_extra_data_size;
9473         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9474         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
9475                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
9476         if (extra_data_size)
9477             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
9478                 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
9479 
9480         if (in_reconfig) // BufReq will be set to driver when port is disabled
9481             buffer_prop->buffer_size = buf_size;
9482         else if (buf_size != buffer_prop->buffer_size) {
9483             buffer_prop->buffer_size = buf_size;
9484             eRet = set_buffer_req(buffer_prop);
9485         }
9486     }
9487     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
9488             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9489     return eRet;
9490 }
9491 
set_buffer_req(vdec_allocatorproperty * buffer_prop)9492 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
9493 {
9494     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9495     unsigned buf_size = 0;
9496     struct v4l2_format fmt;
9497     struct v4l2_requestbuffers bufreq;
9498     int ret;
9499     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
9500             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9501     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9502     if (buf_size != buffer_prop->buffer_size) {
9503         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
9504                 (unsigned int)buffer_prop->buffer_size, buf_size);
9505         eRet = OMX_ErrorBadParameter;
9506     } else {
9507         memset(&fmt, 0x0, sizeof(struct v4l2_format));
9508         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9509         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9510         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
9511 
9512         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9513             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9514             fmt.fmt.pix_mp.pixelformat = output_capability;
9515         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9516             fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9517             fmt.fmt.pix_mp.pixelformat = capture_capability;
9518         } else {
9519             eRet = OMX_ErrorBadParameter;
9520         }
9521 
9522         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
9523         if (ret) {
9524             /*TODO: How to handle this case */
9525             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
9526             eRet = OMX_ErrorInsufficientResources;
9527         }
9528 
9529         bufreq.memory = V4L2_MEMORY_USERPTR;
9530         bufreq.count = buffer_prop->actualcount;
9531         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9532             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9533         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9534             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9535         } else {
9536             eRet = OMX_ErrorBadParameter;
9537         }
9538 
9539         if (eRet==OMX_ErrorNone) {
9540             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9541         }
9542 
9543         if (ret) {
9544             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
9545             /*TODO: How to handle this case */
9546             eRet = OMX_ErrorInsufficientResources;
9547         } else if (bufreq.count < buffer_prop->actualcount) {
9548             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
9549                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
9550                     buffer_prop->actualcount, bufreq.count);
9551             eRet = OMX_ErrorInsufficientResources;
9552         } else {
9553             if (!client_buffers.update_buffer_req()) {
9554                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
9555                 eRet = OMX_ErrorInsufficientResources;
9556             }
9557         }
9558     }
9559     return eRet;
9560 }
9561 
update_picture_resolution()9562 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
9563 {
9564     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9565     return eRet;
9566 }
9567 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)9568 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
9569 {
9570     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9571     struct v4l2_format fmt;
9572     if (!portDefn) {
9573         return OMX_ErrorBadParameter;
9574     }
9575     DEBUG_PRINT_LOW("omx_vdec::update_portdef");
9576     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
9577     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9578     portDefn->eDomain    = OMX_PortDomainVideo;
9579     if (drv_ctx.frame_rate.fps_denominator > 0)
9580         portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
9581             drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
9582     else {
9583         DEBUG_PRINT_ERROR("Error: Divide by zero");
9584         return OMX_ErrorBadParameter;
9585     }
9586     memset(&fmt, 0x0, sizeof(struct v4l2_format));
9587     if (0 == portDefn->nPortIndex) {
9588         portDefn->eDir =  OMX_DirInput;
9589         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
9590         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
9591         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
9592         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9593         portDefn->format.video.eCompressionFormat = eCompressionFormat;
9594         portDefn->bEnabled   = m_inp_bEnabled;
9595         portDefn->bPopulated = m_inp_bPopulated;
9596 
9597         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9598         fmt.fmt.pix_mp.pixelformat = output_capability;
9599     } else if (1 == portDefn->nPortIndex) {
9600         unsigned int buf_size = 0;
9601         if (!client_buffers.update_buffer_req()) {
9602             DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
9603             return OMX_ErrorHardware;
9604         }
9605         if (!client_buffers.get_buffer_req(buf_size)) {
9606             DEBUG_PRINT_ERROR("update buffer requirements");
9607             return OMX_ErrorHardware;
9608         }
9609         portDefn->nBufferSize = buf_size;
9610         portDefn->eDir =  OMX_DirOutput;
9611         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
9612         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
9613         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9614         portDefn->bEnabled   = m_out_bEnabled;
9615         portDefn->bPopulated = m_out_bPopulated;
9616         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
9617             DEBUG_PRINT_ERROR("Error in getting color format");
9618             return OMX_ErrorHardware;
9619         }
9620         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9621         fmt.fmt.pix_mp.pixelformat = capture_capability;
9622     } else {
9623         portDefn->eDir = OMX_DirMax;
9624         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
9625                 (int)portDefn->nPortIndex);
9626         eRet = OMX_ErrorBadPortIndex;
9627     }
9628     if (is_down_scalar_enabled) {
9629         int ret = 0;
9630         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9631         if (ret) {
9632             DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution");
9633             return OMX_ErrorHardware;
9634         } else {
9635             portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width;
9636             portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height;
9637             portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
9638             portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
9639         }
9640     } else {
9641         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
9642         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
9643         portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9644         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9645     }
9646 
9647     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
9648        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
9649            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
9650            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
9651     }
9652     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
9653             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
9654             (unsigned int)portDefn->nPortIndex,
9655             (unsigned int)portDefn->format.video.nFrameWidth,
9656             (unsigned int)portDefn->format.video.nFrameHeight,
9657             (int)portDefn->format.video.nStride,
9658             (unsigned int)portDefn->format.video.nSliceHeight,
9659             (unsigned int)portDefn->format.video.eColorFormat,
9660             (unsigned int)portDefn->nBufferSize,
9661             (unsigned int)portDefn->nBufferCountActual);
9662 
9663     return eRet;
9664 }
9665 
allocate_output_headers()9666 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
9667 {
9668     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9669     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
9670     unsigned i= 0;
9671 
9672     if (!m_out_mem_ptr) {
9673         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
9674         int nBufHdrSize        = 0;
9675         int nPlatformEntrySize = 0;
9676         int nPlatformListSize  = 0;
9677         int nPMEMInfoSize = 0;
9678         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
9679         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
9680         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
9681 
9682         DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
9683                 drv_ctx.op_buf.actualcount);
9684         nBufHdrSize        = drv_ctx.op_buf.actualcount *
9685             sizeof(OMX_BUFFERHEADERTYPE);
9686 
9687         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
9688             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9689         nPlatformListSize  = drv_ctx.op_buf.actualcount *
9690             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9691         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9692             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9693 
9694         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
9695                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
9696                 nPMEMInfoSize,
9697                 nPlatformListSize);
9698         DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
9699                 m_out_bm_count);
9700         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
9701         // Alloc mem for platform specific info
9702         char *pPtr=NULL;
9703         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9704                 nPMEMInfoSize,1);
9705         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9706                        calloc (sizeof(struct vdec_bufferpayload),
9707                                drv_ctx.op_buf.actualcount);
9708         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
9709                      calloc (sizeof (struct vdec_output_frameinfo),
9710                              drv_ctx.op_buf.actualcount);
9711         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9712             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
9713             return OMX_ErrorInsufficientResources;
9714         }
9715 
9716 #ifdef USE_ION
9717         drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9718                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9719         if (!drv_ctx.op_buf_ion_info) {
9720             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9721             return OMX_ErrorInsufficientResources;
9722         }
9723 #endif
9724         if (dynamic_buf_mode) {
9725             out_dynamic_list = (struct dynamic_buf_list *) \
9726                 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
9727             if (out_dynamic_list) {
9728                for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
9729                   out_dynamic_list[i].dup_fd = -1;
9730             }
9731         }
9732 
9733         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9734                 && drv_ctx.ptr_respbuffer) {
9735             bufHdr          =  m_out_mem_ptr;
9736             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9737             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9738                 (((char *) m_platform_list)  + nPlatformListSize);
9739             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
9740                 (((char *) m_platform_entry) + nPlatformEntrySize);
9741             pPlatformList   = m_platform_list;
9742             pPlatformEntry  = m_platform_entry;
9743             pPMEMInfo       = m_pmem_info;
9744 
9745             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
9746 
9747             // Settting the entire storage nicely
9748             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
9749                     m_out_mem_ptr,pPlatformEntry);
9750             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
9751             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
9752                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
9753                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
9754                 // Set the values when we determine the right HxW param
9755                 bufHdr->nAllocLen          = 0;
9756                 bufHdr->nFilledLen         = 0;
9757                 bufHdr->pAppPrivate        = NULL;
9758                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
9759                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
9760                 pPlatformEntry->entry      = pPMEMInfo;
9761                 // Initialize the Platform List
9762                 pPlatformList->nEntries    = 1;
9763                 pPlatformList->entryList   = pPlatformEntry;
9764                 // Keep pBuffer NULL till vdec is opened
9765                 bufHdr->pBuffer            = NULL;
9766                 pPMEMInfo->offset          =  0;
9767                 pPMEMInfo->pmem_fd = -1;
9768                 bufHdr->pPlatformPrivate = pPlatformList;
9769                 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
9770 #ifdef USE_ION
9771                 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
9772 #endif
9773                 /*Create a mapping between buffers*/
9774                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
9775                 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
9776                                     &drv_ctx.ptr_outputbuffer[i];
9777                 // Move the buffer and buffer header pointers
9778                 bufHdr++;
9779                 pPMEMInfo++;
9780                 pPlatformEntry++;
9781                 pPlatformList++;
9782             }
9783         } else {
9784             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
9785                     m_out_mem_ptr, pPtr);
9786             if (m_out_mem_ptr) {
9787                 free(m_out_mem_ptr);
9788                 m_out_mem_ptr = NULL;
9789             }
9790             if (pPtr) {
9791                 free(pPtr);
9792                 pPtr = NULL;
9793             }
9794             if (drv_ctx.ptr_outputbuffer) {
9795                 free(drv_ctx.ptr_outputbuffer);
9796                 drv_ctx.ptr_outputbuffer = NULL;
9797             }
9798             if (drv_ctx.ptr_respbuffer) {
9799                 free(drv_ctx.ptr_respbuffer);
9800                 drv_ctx.ptr_respbuffer = NULL;
9801             }
9802 #ifdef USE_ION
9803             if (drv_ctx.op_buf_ion_info) {
9804                 DEBUG_PRINT_LOW("Free o/p ion context");
9805                 free(drv_ctx.op_buf_ion_info);
9806                 drv_ctx.op_buf_ion_info = NULL;
9807             }
9808 #endif
9809             eRet =  OMX_ErrorInsufficientResources;
9810         }
9811     } else {
9812         eRet =  OMX_ErrorInsufficientResources;
9813     }
9814     return eRet;
9815 }
9816 
complete_pending_buffer_done_cbs()9817 void omx_vdec::complete_pending_buffer_done_cbs()
9818 {
9819     unsigned long p1, p2, ident;
9820     omx_cmd_queue tmp_q, pending_bd_q;
9821     pthread_mutex_lock(&m_lock);
9822     // pop all pending GENERATE FDB from ftb queue
9823     while (m_ftb_q.m_size) {
9824         m_ftb_q.pop_entry(&p1,&p2,&ident);
9825         if (ident == OMX_COMPONENT_GENERATE_FBD) {
9826             pending_bd_q.insert_entry(p1,p2,ident);
9827         } else {
9828             tmp_q.insert_entry(p1,p2,ident);
9829         }
9830     }
9831     //return all non GENERATE FDB to ftb queue
9832     while (tmp_q.m_size) {
9833         tmp_q.pop_entry(&p1,&p2,&ident);
9834         m_ftb_q.insert_entry(p1,p2,ident);
9835     }
9836     // pop all pending GENERATE EDB from etb queue
9837     while (m_etb_q.m_size) {
9838         m_etb_q.pop_entry(&p1,&p2,&ident);
9839         if (ident == OMX_COMPONENT_GENERATE_EBD) {
9840             pending_bd_q.insert_entry(p1,p2,ident);
9841         } else {
9842             tmp_q.insert_entry(p1,p2,ident);
9843         }
9844     }
9845     //return all non GENERATE FDB to etb queue
9846     while (tmp_q.m_size) {
9847         tmp_q.pop_entry(&p1,&p2,&ident);
9848         m_etb_q.insert_entry(p1,p2,ident);
9849     }
9850     pthread_mutex_unlock(&m_lock);
9851     // process all pending buffer dones
9852     while (pending_bd_q.m_size) {
9853         pending_bd_q.pop_entry(&p1,&p2,&ident);
9854         switch (ident) {
9855             case OMX_COMPONENT_GENERATE_EBD:
9856                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
9857                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
9858                     omx_report_error ();
9859                 }
9860                 break;
9861 
9862             case OMX_COMPONENT_GENERATE_FBD:
9863                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
9864                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
9865                     omx_report_error ();
9866                 }
9867                 break;
9868         }
9869     }
9870 }
9871 
set_frame_rate(OMX_S64 act_timestamp)9872 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
9873 {
9874     OMX_U32 new_frame_interval = 0;
9875     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
9876             && llabs(act_timestamp - prev_ts) > 2000) {
9877         new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
9878             llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
9879         if (new_frame_interval != frm_int || frm_int == 0) {
9880             frm_int = new_frame_interval;
9881             if (frm_int) {
9882                 drv_ctx.frame_rate.fps_numerator = 1e6;
9883                 drv_ctx.frame_rate.fps_denominator = frm_int;
9884                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
9885                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
9886                         (float)drv_ctx.frame_rate.fps_denominator);
9887                 m_perf_control.request_cores(frm_int);
9888                 /* We need to report the difference between this FBD and the previous FBD
9889                  * back to the driver for clock scaling purposes. */
9890                 struct v4l2_outputparm oparm;
9891                 /*XXX: we're providing timing info as seconds per frame rather than frames
9892                  * per second.*/
9893                 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
9894                 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
9895 
9896                 struct v4l2_streamparm sparm;
9897                 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9898                 sparm.parm.output = oparm;
9899                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
9900                     DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
9901                             performance might be affected");
9902                 }
9903 
9904             }
9905         }
9906     }
9907     prev_ts = act_timestamp;
9908 }
9909 
adjust_timestamp(OMX_S64 & act_timestamp)9910 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
9911 {
9912     if (rst_prev_ts && VALID_TS(act_timestamp)) {
9913         prev_ts = act_timestamp;
9914         prev_ts_actual = act_timestamp;
9915         rst_prev_ts = false;
9916     } else if (VALID_TS(prev_ts)) {
9917         bool codec_cond = (drv_ctx.timestamp_adjust)?
9918             (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
9919             (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
9920              prev_ts_actual = act_timestamp; //unadjusted previous timestamp
9921         if (frm_int > 0 && codec_cond) {
9922             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
9923             act_timestamp = prev_ts + frm_int;
9924             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
9925             prev_ts = act_timestamp;
9926         } else {
9927             if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
9928                 // ensure that timestamps can never step backwards when in display order
9929                 act_timestamp = prev_ts;
9930             }
9931             set_frame_rate(act_timestamp);
9932         }
9933     } else if (frm_int > 0)          // In this case the frame rate was set along
9934     {                               // with the port definition, start ts with 0
9935         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
9936         rst_prev_ts = true;
9937     }
9938 }
9939 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)9940 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
9941 {
9942     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
9943     OMX_U32 num_conceal_MB = 0;
9944     OMX_TICKS time_stamp = 0;
9945     OMX_U32 frame_rate = 0;
9946     unsigned long consumed_len = 0;
9947     OMX_U32 num_MB_in_frame;
9948     OMX_U32 recovery_sei_flags = 1;
9949     int enable = 0;
9950 
9951     int buf_index = p_buf_hdr - m_out_mem_ptr;
9952     if (buf_index >= drv_ctx.extradata_info.count) {
9953         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
9954                 buf_index, drv_ctx.extradata_info.count);
9955         return;
9956     }
9957     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
9958 
9959     if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
9960         DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
9961         return;
9962     }
9963 
9964     OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
9965         p_buf_hdr->nOffset;
9966 
9967     if (!drv_ctx.extradata_info.uaddr) {
9968         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
9969         return;
9970     }
9971     if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
9972         DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
9973         p_extra = NULL;
9974         return;
9975     }
9976     if (!secure_mode)
9977         p_extra = (OMX_OTHER_EXTRADATATYPE *)
9978             ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
9979     else
9980         p_extra = m_other_extradata;
9981     char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
9982 
9983     if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
9984         p_extra = NULL;
9985         DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
9986         return;
9987     }
9988     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
9989     if (data && p_extra) {
9990         while ((consumed_len < drv_ctx.extradata_info.buffer_size)
9991                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
9992             if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
9993                 DEBUG_PRINT_LOW("Invalid extra data size");
9994                 break;
9995             }
9996 
9997             if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
9998                 p_extra = NULL;
9999                 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10000                 return;
10001             }
10002 
10003             DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType);
10004             switch ((unsigned long)data->eType) {
10005                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
10006                     struct msm_vidc_interlace_payload *payload;
10007                     OMX_U32 interlace_color_format;
10008                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
10009                     if (payload) {
10010                         enable = 1;
10011                         switch (payload->format) {
10012                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
10013                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10014                                 enable = 0;
10015                                 break;
10016                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
10017                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10018                                 break;
10019                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
10020                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
10021                                 break;
10022                             default:
10023                                 DEBUG_PRINT_LOW("default case - set interlace to topfield");
10024                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10025                         }
10026                         switch (payload->color_format) {
10027                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
10028                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10029                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
10030                                break;
10031                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
10032                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
10033                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
10034                                break;
10035                            default:
10036                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10037                                DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
10038                         }
10039                     }
10040 
10041                     if (m_enable_android_native_buffers) {
10042                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
10043                                          payload->format, interlace_color_format ,enable,
10044                                         (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
10045 
10046                         setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10047                                PP_PARAM_INTERLACED, (void*)&enable);
10048 
10049                         if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
10050                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10051                                LINEAR_FORMAT, (void*)&interlace_color_format);
10052                         }
10053                     }
10054                     if (client_extradata & OMX_INTERLACE_EXTRADATA) {
10055                         append_interlace_extradata(p_extra, payload->format,
10056                                       p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF);
10057                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10058                     }
10059                     break;
10060                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
10061                     struct msm_vidc_framerate_payload *frame_rate_payload;
10062                     frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
10063                     frame_rate = frame_rate_payload->frame_rate;
10064                     break;
10065                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
10066                     struct msm_vidc_ts_payload *time_stamp_payload;
10067                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
10068                     time_stamp = time_stamp_payload->timestamp_lo;
10069                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
10070                     p_buf_hdr->nTimeStamp = time_stamp;
10071                     break;
10072                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
10073                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
10074                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
10075                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10076                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10077                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
10078                     break;
10079                 case MSM_VIDC_EXTRADATA_INDEX:
10080                     int *etype;
10081                     etype  = (int *)(void *)data->data;
10082                     if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
10083                         struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
10084                         aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
10085                         if (aspect_ratio_payload) {
10086                             ((struct vdec_output_frameinfo *)
10087                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
10088                             ((struct vdec_output_frameinfo *)
10089                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
10090                         }
10091                     }
10092                     break;
10093                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
10094                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
10095                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
10096                     recovery_sei_flags = recovery_sei_payload->flags;
10097                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
10098                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
10099                         DEBUG_PRINT_HIGH("***************************************************");
10100                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
10101                         DEBUG_PRINT_HIGH("***************************************************");
10102                     }
10103                     break;
10104                case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
10105                     panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
10106                     if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
10107                         DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
10108                         DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
10109                             MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
10110                         return;
10111                     }
10112                     break;
10113                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
10114                     struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10115                     seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)(void *)data->data;
10116                     if (seqdisp_payload) {
10117                         m_disp_hor_size = seqdisp_payload->disp_width;
10118                         m_disp_vert_size = seqdisp_payload->disp_height;
10119                     }
10120                     break;
10121                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
10122                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
10123                     s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
10124                     if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
10125                         append_framepack_extradata(p_extra, s3d_frame_packing_payload);
10126                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10127                     }
10128                     break;
10129                 case MSM_VIDC_EXTRADATA_FRAME_QP:
10130                     struct msm_vidc_frame_qp_payload *qp_payload;
10131                     qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
10132                     if (client_extradata & OMX_QP_EXTRADATA) {
10133                         append_qp_extradata(p_extra, qp_payload);
10134                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10135                     }
10136                     break;
10137                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
10138                     struct msm_vidc_frame_bits_info_payload *bits_info_payload;
10139                     bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
10140                     if (client_extradata & OMX_BITSINFO_EXTRADATA) {
10141                         append_bitsinfo_extradata(p_extra, bits_info_payload);
10142                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10143                     }
10144                     break;
10145                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
10146                     if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
10147                         append_user_extradata(p_extra, data);
10148                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10149                     }
10150                     break;
10151                 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
10152                     struct msm_vidc_vqzip_sei_payload *vqzip_payload;
10153                     vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
10154                     if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
10155                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10156                         append_vqzip_extradata(p_extra, vqzip_payload);
10157                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10158                     }
10159                     break;
10160                 default:
10161                     DEBUG_PRINT_LOW("Unrecognized extradata");
10162                     goto unrecognized_extradata;
10163             }
10164             consumed_len += data->nSize;
10165             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
10166         }
10167         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
10168             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10169             append_frame_info_extradata(p_extra,
10170                     num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10171                     time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10172                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10173             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10174         }
10175         if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
10176             append_frame_dimension_extradata(p_extra);
10177             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10178         }
10179     }
10180 unrecognized_extradata:
10181     if (client_extradata && p_extra) {
10182         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10183         append_terminator_extradata(p_extra);
10184     }
10185     if (secure_mode && p_extradata && m_other_extradata) {
10186         struct vdec_output_frameinfo  *ptr_extradatabuff = NULL;
10187         memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
10188         ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
10189         ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
10190         ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
10191     }
10192     return;
10193 }
10194 
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)10195 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
10196         bool is_internal, bool enable)
10197 {
10198     OMX_ERRORTYPE ret = OMX_ErrorNone;
10199     struct v4l2_control control;
10200     if (m_state != OMX_StateLoaded) {
10201         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
10202         return OMX_ErrorIncorrectStateOperation;
10203     }
10204     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
10205             (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
10206 
10207     if (!is_internal) {
10208         if (enable)
10209             client_extradata |= requested_extradata;
10210         else
10211             client_extradata = client_extradata & ~requested_extradata;
10212     }
10213 
10214     if (enable) {
10215         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
10216             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10217             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
10218             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10219                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
10220                         " Quality of interlaced clips might be impacted.");
10221             }
10222         }
10223         if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
10224             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10225             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
10226             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10227                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
10228             }
10229             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10230             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
10231             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10232                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
10233             }
10234             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10235             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
10236             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10237                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
10238             }
10239             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10240             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
10241             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10242                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10243             }
10244             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10245             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
10246             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10247                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10248             }
10249             if (output_capability == V4L2_PIX_FMT_MPEG2) {
10250                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10251                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10252                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10253                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10254                 }
10255             }
10256         }
10257         if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
10258             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10259             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
10260             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10261                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
10262             }
10263         }
10264         if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
10265             if (output_capability == V4L2_PIX_FMT_H264) {
10266                 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
10267                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10268                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
10269                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10270                     DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
10271                 }
10272             } else {
10273                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
10274             }
10275         }
10276         if (requested_extradata & OMX_QP_EXTRADATA) {
10277             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10278             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10279             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10280                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10281             }
10282         }
10283         if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
10284             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10285             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
10286             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10287                 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
10288             }
10289         }
10290         if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
10291             if (secure_mode) {
10292                 DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions");
10293                 return OMX_ErrorUnsupportedSetting;
10294             }
10295             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10296             control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
10297             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10298                 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
10299             }
10300         }
10301         if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
10302             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10303             control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
10304             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10305                 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
10306             }
10307             client_extradata |= OMX_VQZIPSEI_EXTRADATA;
10308 
10309             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10310             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10311             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10312                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10313             }
10314             client_extradata |= OMX_QP_EXTRADATA;
10315         }
10316     }
10317     ret = get_buffer_req(&drv_ctx.op_buf);
10318     return ret;
10319 }
10320 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)10321 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10322 {
10323     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
10324     OMX_U8 *data_ptr = extra->data, data = 0;
10325     while (byte_count < extra->nDataSize) {
10326         data = *data_ptr;
10327         while (data) {
10328             num_MB += (data&0x01);
10329             data >>= 1;
10330         }
10331         data_ptr++;
10332         byte_count++;
10333     }
10334     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10335             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10336     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
10337 }
10338 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)10339 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10340 {
10341     if (!m_debug_extradata || !extra)
10342         return;
10343 
10344 
10345     DEBUG_PRINT_HIGH(
10346             "============== Extra Data ==============\n"
10347             "           Size: %u\n"
10348             "        Version: %u\n"
10349             "      PortIndex: %u\n"
10350             "           Type: %x\n"
10351             "       DataSize: %u",
10352             (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
10353             (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
10354 
10355     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
10356         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10357         DEBUG_PRINT_HIGH(
10358                 "------ Interlace Format ------\n"
10359                 "                Size: %u\n"
10360                 "             Version: %u\n"
10361                 "           PortIndex: %u\n"
10362                 " Is Interlace Format: %d\n"
10363                 "   Interlace Formats: %u\n"
10364                 "=========== End of Interlace ===========",
10365                 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
10366                 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
10367     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
10368         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10369 
10370         DEBUG_PRINT_HIGH(
10371                 "-------- Frame Format --------\n"
10372                 "             Picture Type: %d\n"
10373                 "           Interlace Type: %d\n"
10374                 " Pan Scan Total Frame Num: %u\n"
10375                 "   Concealed Macro Blocks: %u\n"
10376                 "               frame rate: %u\n"
10377                 "               Time Stamp: %llu\n"
10378                 "           Aspect Ratio X: %u\n"
10379                 "           Aspect Ratio Y: %u",
10380                 fminfo->ePicType,
10381                 fminfo->interlaceType,
10382                 (unsigned int)fminfo->panScan.numWindows,
10383                 (unsigned int)fminfo->nConcealedMacroblocks,
10384                 (unsigned int)fminfo->nFrameRate,
10385                 fminfo->nTimeStamp,
10386                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
10387                 (unsigned int)fminfo->aspectRatio.aspectRatioY);
10388 
10389         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
10390             DEBUG_PRINT_HIGH(
10391                     "------------------------------"
10392                     "     Pan Scan Frame Num: %u\n"
10393                     "            Rectangle x: %d\n"
10394                     "            Rectangle y: %d\n"
10395                     "           Rectangle dx: %d\n"
10396                     "           Rectangle dy: %d",
10397                     (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
10398                     (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
10399         }
10400 
10401         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
10402     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
10403         OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10404         DEBUG_PRINT_HIGH(
10405                 "------------------ Framepack Format ----------\n"
10406                 "                           id: %u \n"
10407                 "                  cancel_flag: %u \n"
10408                 "                         type: %u \n"
10409                 " quincunx_sampling_flagFormat: %u \n"
10410                 "  content_interpretation_type: %u \n"
10411                 "        spatial_flipping_flag: %u \n"
10412                 "          frame0_flipped_flag: %u \n"
10413                 "             field_views_flag: %u \n"
10414                 " current_frame_is_frame0_flag: %u \n"
10415                 "   frame0_self_contained_flag: %u \n"
10416                 "   frame1_self_contained_flag: %u \n"
10417                 "       frame0_grid_position_x: %u \n"
10418                 "       frame0_grid_position_y: %u \n"
10419                 "       frame1_grid_position_x: %u \n"
10420                 "       frame1_grid_position_y: %u \n"
10421                 "                reserved_byte: %u \n"
10422                 "            repetition_period: %u \n"
10423                 "               extension_flag: %u \n"
10424                 "================== End of Framepack ===========",
10425                 (unsigned int)framepack->id,
10426                 (unsigned int)framepack->cancel_flag,
10427                 (unsigned int)framepack->type,
10428                 (unsigned int)framepack->quincunx_sampling_flag,
10429                 (unsigned int)framepack->content_interpretation_type,
10430                 (unsigned int)framepack->spatial_flipping_flag,
10431                 (unsigned int)framepack->frame0_flipped_flag,
10432                 (unsigned int)framepack->field_views_flag,
10433                 (unsigned int)framepack->current_frame_is_frame0_flag,
10434                 (unsigned int)framepack->frame0_self_contained_flag,
10435                 (unsigned int)framepack->frame1_self_contained_flag,
10436                 (unsigned int)framepack->frame0_grid_position_x,
10437                 (unsigned int)framepack->frame0_grid_position_y,
10438                 (unsigned int)framepack->frame1_grid_position_x,
10439                 (unsigned int)framepack->frame1_grid_position_y,
10440                 (unsigned int)framepack->reserved_byte,
10441                 (unsigned int)framepack->repetition_period,
10442                 (unsigned int)framepack->extension_flag);
10443     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
10444         OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
10445         DEBUG_PRINT_HIGH(
10446                 "---- QP (Frame quantization parameter) ----\n"
10447                 "    Frame QP: %u \n"
10448                 "================ End of QP ================\n",
10449                 (unsigned int)qp->nQP);
10450     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
10451         OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
10452         DEBUG_PRINT_HIGH(
10453                 "--------- Input bits information --------\n"
10454                 "    Header bits: %u \n"
10455                 "     Frame bits: %u \n"
10456                 "===== End of Input bits information =====\n",
10457                 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
10458     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
10459         OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
10460         OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
10461         OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
10462         OMX_U32 i = 0;
10463         DEBUG_PRINT_HIGH(
10464                 "--------------  Userdata  -------------\n"
10465                 "    Stream userdata type: %u\n"
10466                 "          userdata size: %u\n"
10467                 "    STREAM_USERDATA:",
10468                 (unsigned int)userdata->type, (unsigned int)userdata_size);
10469                 for (i = 0; i < userdata_size; i+=4) {
10470                     DEBUG_PRINT_HIGH("        %x %x %x %x",
10471                         data_ptr[i], data_ptr[i+1],
10472                         data_ptr[i+2], data_ptr[i+3]);
10473                 }
10474         DEBUG_PRINT_HIGH(
10475                 "=========== End of Userdata ===========");
10476     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
10477         OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
10478         DEBUG_PRINT_HIGH(
10479                 "--------------  VQZip  -------------\n"
10480                 "    Size: %u\n",
10481                 (unsigned int)vq->nSize);
10482         DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
10483     } else if (extra->eType == OMX_ExtraDataNone) {
10484         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
10485     } else {
10486         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
10487     }
10488 }
10489 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type,bool is_mbaff)10490 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10491         OMX_U32 interlaced_format_type, bool is_mbaff)
10492 {
10493     OMX_STREAMINTERLACEFORMAT *interlace_format;
10494 
10495     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
10496         return;
10497     }
10498     if (!extra) {
10499        DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
10500        return;
10501     }
10502     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
10503     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10504     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10505     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
10506     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10507     interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10508     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10509     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
10510     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10511 
10512     if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) {
10513         interlace_format->bInterlaceFormat = OMX_FALSE;
10514         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
10515         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10516     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) {
10517         interlace_format->bInterlaceFormat = OMX_TRUE;
10518         interlace_format->nInterlaceFormats =  OMX_InterlaceInterleaveFrameTopFieldFirst;
10519         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10520     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) {
10521         interlace_format->bInterlaceFormat = OMX_TRUE;
10522         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
10523         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10524     } else {
10525         interlace_format->bInterlaceFormat = OMX_TRUE;
10526         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
10527         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10528     }
10529     print_debug_extradata(extra);
10530 }
10531 
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)10532 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10533 {
10534     OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
10535     if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
10536         return;
10537     }
10538     extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
10539     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10540     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10541     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
10542     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
10543     frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
10544     frame_dimension->nDecWidth = rectangle.nLeft;
10545     frame_dimension->nDecHeight = rectangle.nTop;
10546     frame_dimension->nActualWidth = rectangle.nWidth;
10547     frame_dimension->nActualHeight = rectangle.nHeight;
10548 }
10549 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)10550 void omx_vdec::fill_aspect_ratio_info(
10551         struct vdec_aspectratioinfo *aspect_ratio_info,
10552         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
10553 {
10554     m_extradata = frame_info;
10555     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
10556     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
10557     DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
10558             (unsigned int)m_extradata->aspectRatio.aspectRatioY);
10559 }
10560 
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)10561 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10562         OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
10563         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
10564         struct vdec_aspectratioinfo *aspect_ratio_info)
10565 {
10566     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
10567     struct msm_vidc_panscan_window *panscan_window;
10568     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
10569         return;
10570     }
10571     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
10572     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10573     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10574     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
10575     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
10576     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10577     switch (picture_type) {
10578         case PICTURE_TYPE_I:
10579             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
10580             break;
10581         case PICTURE_TYPE_P:
10582             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
10583             break;
10584         case PICTURE_TYPE_B:
10585             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
10586             break;
10587         default:
10588             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
10589     }
10590     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
10591         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
10592     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
10593         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
10594     else
10595         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
10596     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
10597     frame_info->nConcealedMacroblocks = num_conceal_mb;
10598     frame_info->nFrameRate = frame_rate;
10599     frame_info->nTimeStamp = time_stamp;
10600     frame_info->panScan.numWindows = 0;
10601     if (output_capability == V4L2_PIX_FMT_MPEG2) {
10602         if (m_disp_hor_size && m_disp_vert_size) {
10603             frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
10604             frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
10605         } else {
10606             frame_info->displayAspectRatio.displayHorizontalSize = 0;
10607             frame_info->displayAspectRatio.displayVerticalSize = 0;
10608         }
10609     }
10610 
10611     if (panscan_payload) {
10612         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
10613         panscan_window = &panscan_payload->wnd[0];
10614         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
10615             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
10616             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
10617             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
10618             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
10619             panscan_window++;
10620         }
10621     }
10622     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
10623     print_debug_extradata(extra);
10624 }
10625 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)10626 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10627 {
10628     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
10629     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
10630     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10631     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10632     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
10633     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10634     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
10635     *portDefn = m_port_def;
10636     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
10637             "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
10638             (unsigned int)portDefn->format.video.nFrameWidth,
10639             (unsigned int)portDefn->format.video.nStride,
10640             (unsigned int)portDefn->format.video.nSliceHeight);
10641 }
10642 
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)10643 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10644         struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
10645 {
10646     OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
10647     if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
10648         DEBUG_PRINT_ERROR("frame packing size mismatch");
10649         return;
10650     }
10651     extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
10652     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10653     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10654     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
10655     extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
10656     framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10657     framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
10658     framepack->nVersion.nVersion = OMX_SPEC_VERSION;
10659     framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10660     memcpy(&framepack->id, s3d_frame_packing_payload,
10661         sizeof(struct msm_vidc_s3d_frame_packing_payload));
10662     memcpy(&m_frame_pack_arrangement, framepack,
10663         sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
10664     print_debug_extradata(extra);
10665 }
10666 
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)10667 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10668             struct msm_vidc_frame_qp_payload *qp_payload)
10669 {
10670     OMX_QCOM_EXTRADATA_QP * qp = NULL;
10671     if (!qp_payload) {
10672         DEBUG_PRINT_ERROR("QP payload is NULL");
10673         return;
10674     }
10675     extra->nSize = OMX_QP_EXTRADATA_SIZE;
10676     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10677     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10678     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
10679     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
10680     qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
10681     qp->nQP = qp_payload->frame_qp;
10682     print_debug_extradata(extra);
10683 }
10684 
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)10685 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10686             struct msm_vidc_frame_bits_info_payload *bits_payload)
10687 {
10688     OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
10689     if (!bits_payload) {
10690         DEBUG_PRINT_ERROR("bits info payload is NULL");
10691         return;
10692     }
10693     extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
10694     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10695     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10696     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
10697     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
10698     bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
10699     bits->frame_bits = bits_payload->frame_bits;
10700     bits->header_bits = bits_payload->header_bits;
10701     print_debug_extradata(extra);
10702 }
10703 
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)10704 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10705             OMX_OTHER_EXTRADATATYPE *p_user)
10706 {
10707     int userdata_size = 0;
10708     struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
10709     userdata_payload =
10710         (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
10711     userdata_size = p_user->nDataSize;
10712     extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
10713     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10714     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10715     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
10716     extra->nDataSize = userdata_size;
10717     if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
10718         memcpy(extra->data, p_user->data, extra->nDataSize);
10719     print_debug_extradata(extra);
10720 }
10721 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)10722 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10723 {
10724     if (!client_extradata) {
10725         return;
10726     }
10727     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
10728     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10729     extra->eType = OMX_ExtraDataNone;
10730     extra->nDataSize = 0;
10731     extra->data[0] = 0;
10732 
10733     print_debug_extradata(extra);
10734 }
10735 
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)10736 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10737         struct msm_vidc_vqzip_sei_payload *vqzip_payload)
10738 {
10739     OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
10740 
10741     extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
10742     extra->nVersion.nVersion = OMX_SPEC_VERSION;
10743     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10744     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
10745     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
10746 
10747     vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
10748     vq->nSize = vqzip_payload->size;
10749     memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
10750 
10751     print_debug_extradata(extra);
10752 }
10753 
allocate_desc_buffer(OMX_U32 index)10754 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
10755 {
10756     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10757     if (index >= drv_ctx.ip_buf.actualcount) {
10758         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
10759         return OMX_ErrorInsufficientResources;
10760     }
10761     if (m_desc_buffer_ptr == NULL) {
10762         m_desc_buffer_ptr = (desc_buffer_hdr*) \
10763                     calloc( (sizeof(desc_buffer_hdr)),
10764                             drv_ctx.ip_buf.actualcount);
10765         if (m_desc_buffer_ptr == NULL) {
10766             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
10767             return OMX_ErrorInsufficientResources;
10768         }
10769     }
10770 
10771     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
10772     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
10773         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
10774         return OMX_ErrorInsufficientResources;
10775     }
10776 
10777     return eRet;
10778 }
10779 
insert_demux_addr_offset(OMX_U32 address_offset)10780 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
10781 {
10782     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
10783     if (m_demux_entries < 8192) {
10784         m_demux_offsets[m_demux_entries++] = address_offset;
10785     }
10786     return;
10787 }
10788 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)10789 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
10790 {
10791     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
10792     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
10793     OMX_U32 index = 0;
10794 
10795     m_demux_entries = 0;
10796 
10797     while (index < bytes_to_parse) {
10798         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
10799                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
10800                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
10801                  (buf[index+2] == 0x01)) ) {
10802             //Found start code, insert address offset
10803             insert_demux_addr_offset(index);
10804             if (buf[index+2] == 0x01) // 3 byte start code
10805                 index += 3;
10806             else                      //4 byte start code
10807                 index += 4;
10808         } else
10809             index++;
10810     }
10811     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
10812     return;
10813 }
10814 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)10815 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
10816 {
10817     //fix this, handle 3 byte start code, vc1 terminator entry
10818     OMX_U8 *p_demux_data = NULL;
10819     OMX_U32 desc_data = 0;
10820     OMX_U32 start_addr = 0;
10821     OMX_U32 nal_size = 0;
10822     OMX_U32 suffix_byte = 0;
10823     OMX_U32 demux_index = 0;
10824     OMX_U32 buffer_index = 0;
10825 
10826     if (m_desc_buffer_ptr == NULL) {
10827         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
10828         return OMX_ErrorBadParameter;
10829     }
10830 
10831     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
10832     if (buffer_index > drv_ctx.ip_buf.actualcount) {
10833         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
10834         return OMX_ErrorBadParameter;
10835     }
10836 
10837     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
10838 
10839     if ( ((OMX_U8*)p_demux_data == NULL) ||
10840             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
10841         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
10842         return OMX_ErrorBadParameter;
10843     } else {
10844         for (; demux_index < m_demux_entries; demux_index++) {
10845             desc_data = 0;
10846             start_addr = m_demux_offsets[demux_index];
10847             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
10848                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
10849             } else {
10850                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
10851             }
10852             if (demux_index < (m_demux_entries - 1)) {
10853                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
10854             } else {
10855                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
10856             }
10857             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
10858                     (unsigned int)start_addr,
10859                     (unsigned int)suffix_byte,
10860                     (unsigned int)nal_size,
10861                     (unsigned int)demux_index);
10862             desc_data = (start_addr >> 3) << 1;
10863             desc_data |= (start_addr & 7) << 21;
10864             desc_data |= suffix_byte << 24;
10865 
10866             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
10867             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
10868             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
10869             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
10870 
10871             p_demux_data += 16;
10872         }
10873         if (codec_type_parse == CODEC_TYPE_VC1) {
10874             DEBUG_PRINT_LOW("VC1 terminator entry");
10875             desc_data = 0;
10876             desc_data = 0x82 << 24;
10877             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
10878             memset(p_demux_data + 4, 0, sizeof(OMX_U32));
10879             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
10880             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
10881             p_demux_data += 16;
10882             m_demux_entries++;
10883         }
10884         //Add zero word to indicate end of descriptors
10885         memset(p_demux_data, 0, sizeof(OMX_U32));
10886 
10887         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
10888         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
10889     }
10890     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
10891     m_demux_entries = 0;
10892     DEBUG_PRINT_LOW("Demux table complete!");
10893     return OMX_ErrorNone;
10894 }
10895 
request_perf_level(enum vidc_perf_level perf_level)10896 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
10897 {
10898     struct v4l2_control control;
10899     char property_value[PROPERTY_VALUE_MAX] = {0};
10900 
10901     property_get("vidc.debug.turbo", property_value, "0");
10902     memset(&control, 0, sizeof(v4l2_control));
10903     control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
10904     switch (perf_level) {
10905     case VIDC_NOMINAL:
10906         if (atoi(property_value))
10907             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
10908         else
10909             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
10910         break;
10911     case VIDC_TURBO:
10912         control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
10913         break;
10914      default:
10915         DEBUG_PRINT_ERROR("Requested PERF level not supported");
10916         break;
10917     }
10918     if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
10919         return;
10920 
10921     DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
10922     if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10923         current_perf_level = control.value;
10924     } else {
10925         DEBUG_PRINT_ERROR("Failed to set PERF level");
10926     }
10927 }
10928 
allocate_color_convert_buf()10929 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
10930 {
10931     enabled = false;
10932     omx = NULL;
10933     init_members();
10934     ColorFormat = OMX_COLOR_FormatMax;
10935     dest_format = YCbCr420P;
10936 }
10937 
set_vdec_client(void * client)10938 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
10939 {
10940     omx = reinterpret_cast<omx_vdec*>(client);
10941 }
10942 
init_members()10943 void omx_vdec::allocate_color_convert_buf::init_members()
10944 {
10945     allocated_count = 0;
10946     buffer_size_req = 0;
10947     buffer_alignment_req = 0;
10948     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
10949     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
10950     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
10951     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
10952 #ifdef USE_ION
10953     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
10954 #endif
10955     for (int i = 0; i < MAX_COUNT; i++)
10956         pmem_fd[i] = -1;
10957 }
10958 
~allocate_color_convert_buf()10959 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
10960 {
10961     c2d.destroy();
10962 }
10963 
update_buffer_req()10964 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
10965 {
10966     bool status = true;
10967     unsigned int src_size = 0, destination_size = 0;
10968     OMX_COLOR_FORMATTYPE drv_color_format;
10969     if (!omx) {
10970         DEBUG_PRINT_ERROR("Invalid client in color convert");
10971         return false;
10972     }
10973     if (!enabled) {
10974         DEBUG_PRINT_HIGH("No color conversion required");
10975         return status;
10976     }
10977     pthread_mutex_lock(&omx->c_lock);
10978     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
10979             ColorFormat != OMX_COLOR_FormatYUV420Planar) {
10980         DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
10981         status = false;
10982         goto fail_update_buf_req;
10983     }
10984     c2d.close();
10985     status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
10986             omx->drv_ctx.video_resolution.frame_width,
10987             NV12_128m,dest_format);
10988     if (status) {
10989         status = c2d.get_buffer_size(C2D_INPUT,src_size);
10990         if (status)
10991             status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
10992     }
10993     if (status) {
10994         if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
10995                 !destination_size) {
10996             DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
10997                     "driver size %u destination size %d",
10998                     src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
10999                     destination_size);
11000             status = false;
11001             c2d.close();
11002             buffer_size_req = 0;
11003         } else {
11004             buffer_size_req = destination_size;
11005             if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
11006                 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
11007             if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11008                 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11009         }
11010     }
11011 fail_update_buf_req:
11012     pthread_mutex_unlock(&omx->c_lock);
11013     return status;
11014 }
11015 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)11016 bool omx_vdec::allocate_color_convert_buf::set_color_format(
11017         OMX_COLOR_FORMATTYPE dest_color_format)
11018 {
11019     bool status = true;
11020     OMX_COLOR_FORMATTYPE drv_color_format;
11021     if (!omx) {
11022         DEBUG_PRINT_ERROR("Invalid client in color convert");
11023         return false;
11024     }
11025     pthread_mutex_lock(&omx->c_lock);
11026     if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
11027         if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11028             drv_color_format = (OMX_COLOR_FORMATTYPE)
11029                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11030         else
11031             drv_color_format = (OMX_COLOR_FORMATTYPE)
11032                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11033      else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
11034          drv_color_format = (OMX_COLOR_FORMATTYPE)
11035                   QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11036      } else {
11037         DEBUG_PRINT_ERROR("Incorrect color format");
11038         status = false;
11039     }
11040     if (status &&
11041         drv_color_format != dest_color_format &&
11042         drv_color_format != (OMX_COLOR_FORMATTYPE)
11043                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView &&
11044         drv_color_format != (OMX_COLOR_FORMATTYPE)
11045                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed &&
11046         dest_color_format != (OMX_COLOR_FORMATTYPE)
11047                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11048         DEBUG_PRINT_LOW("Enabling C2D");
11049         if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
11050            (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
11051             DEBUG_PRINT_ERROR("Unsupported color format for c2d");
11052             status = false;
11053         } else {
11054             ColorFormat = dest_color_format;
11055             dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
11056                     YCbCr420P : YCbCr420SP;
11057             if (enabled)
11058                 c2d.destroy();
11059             enabled = false;
11060             if (!c2d.init()) {
11061                 DEBUG_PRINT_ERROR("open failed for c2d");
11062                 status = false;
11063             } else
11064                 enabled = true;
11065         }
11066     } else {
11067         if (enabled)
11068             c2d.destroy();
11069         enabled = false;
11070     }
11071     pthread_mutex_unlock(&omx->c_lock);
11072     return status;
11073 }
11074 
get_il_buf_hdr()11075 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
11076 {
11077     if (!omx) {
11078         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11079         return NULL;
11080     }
11081     if (!enabled)
11082         return omx->m_out_mem_ptr;
11083     return m_out_mem_ptr_client;
11084 }
11085 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11086     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
11087 (OMX_BUFFERHEADERTYPE *bufadd)
11088 {
11089     if (!omx) {
11090         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11091         return NULL;
11092     }
11093     if (!enabled)
11094         return bufadd;
11095 
11096     unsigned index = 0;
11097     index = bufadd - omx->m_out_mem_ptr;
11098     if (index < omx->drv_ctx.op_buf.actualcount) {
11099         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
11100         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
11101         bool status;
11102         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
11103             pthread_mutex_lock(&omx->c_lock);
11104             cache_clean_buffer(index);
11105             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
11106                     omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
11107                     pmem_baseaddress[index], pmem_baseaddress[index]);
11108             if (!status) {
11109                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
11110                 m_out_mem_ptr_client[index].nFilledLen = 0;
11111                 pthread_mutex_unlock(&omx->c_lock);
11112                 return &m_out_mem_ptr_client[index];
11113             } else {
11114                 unsigned int filledLen = 0;
11115                 c2d.get_output_filled_length(filledLen);
11116                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
11117                 cache_clean_invalidate_buffer(index);
11118             }
11119             pthread_mutex_unlock(&omx->c_lock);
11120         } else
11121             m_out_mem_ptr_client[index].nFilledLen = 0;
11122         return &m_out_mem_ptr_client[index];
11123     }
11124     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
11125     return NULL;
11126 }
11127 
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11128     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
11129 (OMX_BUFFERHEADERTYPE *bufadd)
11130 {
11131     if (!omx) {
11132         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11133         return NULL;
11134     }
11135     if (!enabled)
11136         return bufadd;
11137     unsigned index = 0;
11138     index = bufadd - m_out_mem_ptr_client;
11139     if (index < omx->drv_ctx.op_buf.actualcount) {
11140         return &omx->m_out_mem_ptr[index];
11141     }
11142     DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
11143     return NULL;
11144 }
get_buffer_req(unsigned int & buffer_size)11145     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
11146 (unsigned int &buffer_size)
11147 {
11148     bool status = true;
11149     pthread_mutex_lock(&omx->c_lock);
11150     if (!enabled)
11151         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11152     else {
11153         if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
11154             DEBUG_PRINT_ERROR("Get buffer size failed");
11155             status = false;
11156             goto fail_get_buffer_size;
11157         }
11158     }
11159     if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
11160         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11161     if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11162         buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11163 fail_get_buffer_size:
11164     pthread_mutex_unlock(&omx->c_lock);
11165     return status;
11166 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)11167 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
11168         OMX_BUFFERHEADERTYPE *bufhdr)
11169 {
11170     unsigned int index = 0;
11171 
11172     if (!enabled)
11173         return omx->free_output_buffer(bufhdr);
11174     if (enabled && omx->is_component_secure())
11175         return OMX_ErrorNone;
11176     if (!allocated_count || !bufhdr) {
11177         DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
11178         return OMX_ErrorBadParameter;
11179     }
11180     index = bufhdr - m_out_mem_ptr_client;
11181     if (index >= omx->drv_ctx.op_buf.actualcount) {
11182         DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
11183         return OMX_ErrorBadParameter;
11184     }
11185     if (pmem_fd[index] >= 0) {
11186         munmap(pmem_baseaddress[index], buffer_size_req);
11187         close(pmem_fd[index]);
11188     }
11189     pmem_fd[index] = -1;
11190 #ifdef USE_ION
11191     omx->free_ion_memory(&op_buf_ion_info[index]);
11192 #endif
11193     m_heap_ptr[index].video_heap_ptr = NULL;
11194     if (allocated_count > 0)
11195         allocated_count--;
11196     else
11197         allocated_count = 0;
11198     if (!allocated_count) {
11199         pthread_mutex_lock(&omx->c_lock);
11200         c2d.close();
11201         init_members();
11202         pthread_mutex_unlock(&omx->c_lock);
11203     }
11204     return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
11205 }
11206 
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)11207 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
11208         OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
11209 {
11210     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11211     if (!enabled) {
11212         eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
11213         return eRet;
11214     }
11215     if (enabled && omx->is_component_secure()) {
11216         DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
11217                 omx->is_component_secure());
11218         return OMX_ErrorUnsupportedSetting;
11219     }
11220     if (!bufferHdr || bytes > buffer_size_req) {
11221         DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
11222         DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
11223                 (unsigned int)buffer_size_req, (unsigned int)bytes);
11224         return OMX_ErrorBadParameter;
11225     }
11226     if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
11227         DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
11228         return OMX_ErrorInsufficientResources;
11229     }
11230     OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
11231     eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
11232             port,appData,omx->drv_ctx.op_buf.buffer_size);
11233     if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
11234         DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
11235         return eRet;
11236     }
11237     if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
11238             (int)omx->drv_ctx.op_buf.actualcount) {
11239         DEBUG_PRINT_ERROR("Invalid header index %ld",
11240                (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
11241         return OMX_ErrorUndefined;
11242     }
11243     unsigned int i = allocated_count;
11244 #ifdef USE_ION
11245     // Allocate color-conversion buffers as cached to improve software-reading
11246     // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
11247     // cache invalidation.
11248     op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
11249             buffer_size_req,buffer_alignment_req,
11250             &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
11251             ION_FLAG_CACHED);
11252     pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
11253     if (op_buf_ion_info[i].ion_device_fd < 0) {
11254         DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
11255         return OMX_ErrorInsufficientResources;
11256     }
11257     pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
11258             PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
11259 
11260     if (pmem_baseaddress[i] == MAP_FAILED) {
11261         DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
11262         close(pmem_fd[i]);
11263         omx->free_ion_memory(&op_buf_ion_info[i]);
11264         return OMX_ErrorInsufficientResources;
11265     }
11266     m_heap_ptr[i].video_heap_ptr = new VideoHeap (
11267             op_buf_ion_info[i].ion_device_fd,buffer_size_req,
11268             pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
11269 #endif
11270     m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
11271     m_pmem_info_client[i].offset = 0;
11272     m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
11273     m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
11274     m_platform_list_client[i].nEntries = 1;
11275     m_platform_list_client[i].entryList = &m_platform_entry_client[i];
11276     m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
11277     m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
11278     m_out_mem_ptr_client[i].nFilledLen = 0;
11279     m_out_mem_ptr_client[i].nFlags = 0;
11280     m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11281     m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
11282     m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
11283     m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
11284     m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
11285     m_out_mem_ptr_client[i].pAppPrivate = appData;
11286     *bufferHdr = &m_out_mem_ptr_client[i];
11287     DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
11288     allocated_count++;
11289     return eRet;
11290 }
11291 
is_component_secure()11292 bool omx_vdec::is_component_secure()
11293 {
11294     return secure_mode;
11295 }
11296 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)11297 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
11298 {
11299     bool status = true;
11300     if (!enabled) {
11301         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
11302             if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11303                     dest_color_format = (OMX_COLOR_FORMATTYPE)
11304                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11305                 else
11306                     dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11307         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
11308              dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11309         } else
11310             status = false;
11311     } else {
11312         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
11313             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
11314             dest_color_format = ColorFormat;
11315         } else
11316             status = false;
11317     }
11318     return status;
11319 }
11320 
cache_ops(unsigned int index,unsigned int cmd)11321 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
11322         unsigned int index, unsigned int cmd)
11323 {
11324     if (!enabled) {
11325         return OMX_ErrorNone;
11326     }
11327 
11328     if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
11329         DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
11330         return OMX_ErrorBadParameter;
11331     }
11332 
11333     struct ion_flush_data flush_data;
11334     struct ion_custom_data custom_data;
11335 
11336     memset(&flush_data, 0x0, sizeof(flush_data));
11337     memset(&custom_data, 0x0, sizeof(custom_data));
11338 
11339     flush_data.vaddr = pmem_baseaddress[index];
11340     flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
11341     flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
11342     flush_data.length = buffer_size_req;
11343     custom_data.cmd = cmd;
11344     custom_data.arg = (unsigned long)&flush_data;
11345 
11346     DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
11347             (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11348             flush_data.fd, flush_data.handle, flush_data.vaddr,
11349             flush_data.length);
11350     int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
11351     if (ret < 0) {
11352         DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
11353                 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11354                 strerror(errno));
11355         return OMX_ErrorUndefined;
11356     }
11357     return OMX_ErrorNone;
11358 }
11359 
buf_ref_add(int nPortIndex)11360 void omx_vdec::buf_ref_add(int nPortIndex)
11361 {
11362     unsigned long i = 0;
11363     bool buf_present = false;
11364     long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
11365     OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
11366 
11367     if (!dynamic_buf_mode || !out_dynamic_list) {
11368         return;
11369     }
11370 
11371     pthread_mutex_lock(&m_lock);
11372     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11373         //check the buffer fd, offset, uv addr with list contents
11374         //If present increment reference.
11375         if ((out_dynamic_list[i].fd == fd) &&
11376             (out_dynamic_list[i].offset == offset)) {
11377                DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
11378                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11379                if (!secure_mode) {
11380                    drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
11381                }
11382                buf_present = true;
11383                break;
11384         }
11385     }
11386     if (!buf_present) {
11387         for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11388             //search for a entry to insert details of the new buffer
11389             if (out_dynamic_list[i].dup_fd < 0) {
11390                 out_dynamic_list[i].fd = fd;
11391                 out_dynamic_list[i].offset = offset;
11392                 out_dynamic_list[i].dup_fd = dup(fd);
11393                 out_dynamic_list[i].ref_count++;
11394                 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
11395                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11396 
11397                 if (!secure_mode) {
11398                     drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
11399                             (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
11400                                           PROT_READ|PROT_WRITE, MAP_SHARED,
11401                                           drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
11402                     //mmap returns (void *)-1 on failure and sets error code in errno.
11403                     if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
11404                         DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
11405                         drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
11406                         break;
11407                     }
11408                     out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
11409                     out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
11410                     DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11411                 }
11412                 break;
11413             }
11414         }
11415     }
11416    pthread_mutex_unlock(&m_lock);
11417 }
11418 
buf_ref_remove()11419 void omx_vdec::buf_ref_remove()
11420 {
11421     unsigned long i = 0;
11422 
11423     if (!dynamic_buf_mode || !out_dynamic_list) {
11424         return;
11425     }
11426 
11427     pthread_mutex_lock(&m_lock);
11428     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11429         if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
11430             DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11431             munmap(out_dynamic_list[i].buffaddr,
11432                         out_dynamic_list[i].mapped_size);
11433         }
11434 
11435          DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
11436                  (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11437          close(out_dynamic_list[i].dup_fd);
11438          out_dynamic_list[i].dup_fd = -1;
11439     }
11440     pthread_mutex_unlock(&m_lock);
11441 
11442     if (out_dynamic_list) {
11443         free(out_dynamic_list);
11444         out_dynamic_list = NULL;
11445     }
11446 }
11447 
11448 #ifdef _MSM8974_
send_codec_config()11449 void omx_vdec::send_codec_config() {
11450     if (codec_config_flag) {
11451         unsigned long p1 = 0; // Parameter - 1
11452         unsigned long p2 = 0; // Parameter - 2
11453         unsigned long ident = 0;
11454         pthread_mutex_lock(&m_lock);
11455         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
11456         while (m_etb_q.m_size) {
11457             m_etb_q.pop_entry(&p1,&p2,&ident);
11458             if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
11459                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
11460                     if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
11461                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
11462                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
11463                         omx_report_error();
11464                     }
11465                 } else {
11466                     DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
11467                     m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
11468                 }
11469             } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
11470                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
11471                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
11472                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
11473                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
11474                         omx_report_error ();
11475                     }
11476                 } else {
11477                     pending_input_buffers++;
11478                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
11479                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
11480                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
11481                 }
11482             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
11483                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
11484                         (OMX_BUFFERHEADERTYPE *)p1);
11485                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
11486             }
11487         }
11488         pthread_mutex_unlock(&m_lock);
11489     }
11490 }
11491 #endif
11492 
perf_control()11493 omx_vdec::perf_control::perf_control()
11494 {
11495     m_perf_lib = NULL;
11496     m_perf_handle = 0;
11497     m_perf_lock_acquire = NULL;
11498     m_perf_lock_release = NULL;
11499 }
11500 
~perf_control()11501 omx_vdec::perf_control::~perf_control()
11502 {
11503     if (m_perf_handle != 0 && m_perf_lock_release) {
11504         DEBUG_PRINT_LOW("NOTE2: release perf lock");
11505         m_perf_lock_release(m_perf_handle);
11506     }
11507     if (m_perf_lib) {
11508         dlclose(m_perf_lib);
11509     }
11510 }
11511 
11512 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
11513 
11514 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
11515 
send_hint_to_mpctl(bool state)11516 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
11517 {
11518     if (load_lib() == false) {
11519        return;
11520     }
11521     m_perf_lock.lock();
11522     /* 0x4401 maps to video decode playback hint
11523      * in perflock, enum number is 44 and state
11524      * being sent on perflock acquire is 01 (true)
11525      */
11526     int arg = 0x4401;
11527 
11528     if (state == true) {
11529         mpctl_obj.vid_inst_count++;
11530     } else if (state == false) {
11531         mpctl_obj.vid_inst_count--;
11532     }
11533 
11534     if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
11535         mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
11536         mpctl_obj.vid_acquired = true;
11537         DEBUG_PRINT_INFO("Video slvp perflock acquired");
11538     } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
11539         m_perf_lock_release(mpctl_obj.vid_disp_handle);
11540         mpctl_obj.vid_acquired = false;
11541         DEBUG_PRINT_INFO("Video slvp perflock released");
11542     }
11543     m_perf_lock.unlock();
11544 }
11545 
request_cores(int frame_duration_us)11546 void omx_vdec::perf_control::request_cores(int frame_duration_us)
11547 {
11548     if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
11549         return;
11550     }
11551     bool retVal = load_lib();
11552     if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
11553         int arg = 0x700 /*base value*/ + 2 /*cores*/;
11554         m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
11555         if (m_perf_handle) {
11556             DEBUG_PRINT_HIGH("perf lock acquired");
11557         }
11558     }
11559 }
11560 
load_lib()11561 bool omx_vdec::perf_control::load_lib()
11562 {
11563     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
11564     if (m_perf_lib)
11565         return true;
11566 
11567     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
11568         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
11569         goto handle_err;
11570     }
11571 
11572     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
11573         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
11574         goto handle_err;
11575     } else {
11576         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
11577         if (m_perf_lock_acquire == NULL) {
11578             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
11579             goto handle_err;
11580         }
11581         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
11582         if (m_perf_lock_release == NULL) {
11583             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
11584             goto handle_err;
11585         }
11586     }
11587     return true;
11588 
11589 handle_err:
11590     if (m_perf_lib) {
11591         dlclose(m_perf_lib);
11592     }
11593     m_perf_lib = NULL;
11594     return false;
11595 }
11596 
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)11597 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
11598                             unsigned long nMaxFrameHeight)
11599 {
11600 
11601     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11602     int ret = 0;
11603     unsigned long min_res_buf_count = 0;
11604 
11605     eRet = enable_smoothstreaming();
11606     if (eRet != OMX_ErrorNone) {
11607          DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
11608          return eRet;
11609      }
11610 
11611      DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
11612              nMaxFrameWidth,
11613              nMaxFrameHeight);
11614      m_smoothstreaming_mode = true;
11615      m_smoothstreaming_width = nMaxFrameWidth;
11616      m_smoothstreaming_height = nMaxFrameHeight;
11617 
11618      //Get upper limit buffer count for min supported resolution
11619      struct v4l2_format fmt;
11620      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
11621      fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
11622      fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
11623      fmt.fmt.pix_mp.pixelformat = output_capability;
11624 
11625      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
11626      if (ret) {
11627          DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
11628                            m_decoder_capability.min_height,
11629                            m_decoder_capability.min_width);
11630          return OMX_ErrorUnsupportedSetting;
11631      }
11632 
11633      eRet = get_buffer_req(&drv_ctx.op_buf);
11634      if (eRet != OMX_ErrorNone) {
11635          DEBUG_PRINT_ERROR("failed to get_buffer_req");
11636          return eRet;
11637      }
11638 
11639      min_res_buf_count = drv_ctx.op_buf.mincount;
11640      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
11641                      min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
11642 
11643      update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
11644                        m_smoothstreaming_width, m_smoothstreaming_height);
11645      eRet = is_video_session_supported();
11646      if (eRet != OMX_ErrorNone) {
11647          DEBUG_PRINT_ERROR("video session is not supported");
11648          return eRet;
11649      }
11650 
11651      //Get upper limit buffer size for max smooth streaming resolution set
11652      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
11653      fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
11654      fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
11655      fmt.fmt.pix_mp.pixelformat = output_capability;
11656      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
11657      if (ret) {
11658          DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
11659          return OMX_ErrorUnsupportedSetting;
11660      }
11661 
11662      eRet = get_buffer_req(&drv_ctx.op_buf);
11663      if (eRet != OMX_ErrorNone) {
11664          DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
11665          return eRet;
11666      }
11667      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
11668                      (unsigned int)drv_ctx.op_buf.buffer_size);
11669 
11670      drv_ctx.op_buf.mincount = min_res_buf_count;
11671      drv_ctx.op_buf.actualcount = min_res_buf_count;
11672      drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
11673      eRet = set_buffer_req(&drv_ctx.op_buf);
11674      if (eRet != OMX_ErrorNone) {
11675          DEBUG_PRINT_ERROR("failed to set_buffer_req");
11676          return eRet;
11677      }
11678 
11679      eRet = get_buffer_req(&drv_ctx.op_buf);
11680      if (eRet != OMX_ErrorNone) {
11681          DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
11682          return eRet;
11683      }
11684      DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
11685                       drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
11686      return eRet;
11687 }
11688 
11689 //static
describeColorFormat(OMX_PTR pParam)11690 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
11691 
11692 #ifndef FLEXYUV_SUPPORTED
11693     return OMX_ErrorUndefined;
11694 #else
11695 
11696     if (pParam == NULL) {
11697         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
11698         return OMX_ErrorBadParameter;
11699     }
11700 
11701     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
11702 
11703     MediaImage *img = &(params->sMediaImage);
11704     switch(params->eColorFormat) {
11705         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
11706         {
11707             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
11708             img->mNumPlanes = 3;
11709             // mWidth and mHeight represent the W x H of the largest plane
11710             // In our case, this happens to be the Stride x Scanlines of Y plane
11711             img->mWidth = params->nFrameWidth;
11712             img->mHeight = params->nFrameHeight;
11713             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11714             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
11715             img->mBitDepth = 8;
11716             //Plane 0 (Y)
11717             img->mPlane[MediaImage::Y].mOffset = 0;
11718             img->mPlane[MediaImage::Y].mColInc = 1;
11719             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
11720             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
11721             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
11722             //Plane 1 (U)
11723             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
11724             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
11725             img->mPlane[MediaImage::U].mRowInc =
11726                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11727             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
11728             img->mPlane[MediaImage::U].mVertSubsampling = 2;
11729             //Plane 2 (V)
11730             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
11731             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
11732             img->mPlane[MediaImage::V].mRowInc =
11733                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11734             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
11735             img->mPlane[MediaImage::V].mVertSubsampling = 2;
11736             break;
11737         }
11738 
11739         case OMX_COLOR_FormatYUV420Planar:
11740         case OMX_COLOR_FormatYUV420SemiPlanar:
11741             // We need not describe the standard OMX linear formats as these are
11742             // understood by client. Fail this deliberately to let client fill-in
11743             return OMX_ErrorUnsupportedSetting;
11744 
11745         default:
11746             // Rest all formats which are non-linear cannot be described
11747             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
11748             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
11749             return OMX_ErrorNone;
11750     };
11751 
11752     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
11753     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
11754     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
11755     for (size_t i = 0; i < img->mNumPlanes; ++i) {
11756         DEBUG_PRINT_LOW("    Plane[%zd] : offset=%d / xStep=%d / yStep = %d",
11757                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
11758     }
11759     return OMX_ErrorNone;
11760 #endif //FLEXYUV_SUPPORTED
11761 }
11762 
11763