1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2016, 2018, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 /*============================================================================
30                             O p e n M A X   w r a p p e r s
31                              O p e n  M A X   C o r e
32 
33   This module contains the implementation of the OpenMAX core & component.
34 
35 *//*========================================================================*/
36 
37 //////////////////////////////////////////////////////////////////////////////
38 //                             Include Files
39 //////////////////////////////////////////////////////////////////////////////
40 
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43 
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <media/hardware/HardwareAPI.h>
55 #include <media/msm_media_info.h>
56 #include <sys/eventfd.h>
57 #include <nativebase/nativebase.h>
58 
59 #ifndef _ANDROID_
60 #include <sys/ioctl.h>
61 #include <sys/mman.h>
62 #endif //_ANDROID_
63 
64 #ifdef _ANDROID_
65 #include <cutils/properties.h>
66 #undef USE_EGL_IMAGE_GPU
67 #endif
68 
69 #include <qdMetaData.h>
70 
71 #ifdef ANDROID_JELLYBEAN_MR2
72 #include "QComOMXMetadata.h"
73 #endif
74 
75 #ifdef USE_EGL_IMAGE_GPU
76 #include <EGL/egl.h>
77 #include <EGL/eglQCOM.h>
78 #define EGL_BUFFER_HANDLE 0x4F00
79 #define EGL_BUFFER_OFFSET 0x4F01
80 #endif
81 
82 #define BUFFER_LOG_LOC "/data/misc/media"
83 
84 #ifdef OUTPUT_EXTRADATA_LOG
85 FILE *outputExtradataFile;
86 char output_extradata_filename [] = "/data/misc/media/extradata";
87 #endif
88 
89 #define DEFAULT_FPS 30
90 #define MAX_SUPPORTED_FPS 120
91 #define DEFAULT_WIDTH_ALIGNMENT 128
92 #define DEFAULT_HEIGHT_ALIGNMENT 32
93 
94 #define VC1_SP_MP_START_CODE        0xC5000000
95 #define VC1_SP_MP_START_CODE_MASK   0xFF000000
96 #define VC1_AP_SEQ_START_CODE       0x0F010000
97 #define VC1_STRUCT_C_PROFILE_MASK   0xF0
98 #define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
99 #define VC1_SIMPLE_PROFILE          0
100 #define VC1_MAIN_PROFILE            1
101 #define VC1_ADVANCE_PROFILE         3
102 #define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
103 #define VC1_SIMPLE_PROFILE_MED_LEVEL  2
104 #define VC1_STRUCT_C_LEN            4
105 #define VC1_STRUCT_C_POS            8
106 #define VC1_STRUCT_A_POS            12
107 #define VC1_STRUCT_B_POS            24
108 #define VC1_SEQ_LAYER_SIZE          36
109 #define POLL_TIMEOUT 0x7fffffff
110 
111 #define MEM_DEVICE "/dev/ion"
112 
113 #ifdef _ANDROID_
114 extern "C" {
115 #include<utils/Log.h>
116 }
117 #endif//_ANDROID_
118 
119 #define SZ_4K 0x1000
120 #define SZ_1M 0x100000
121 
122 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
123 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
124 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
125 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
126 
127 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA)
128 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
129 
130 #ifndef ION_FLAG_CP_BITSTREAM
131 #define ION_FLAG_CP_BITSTREAM 0
132 #endif
133 
134 #ifndef ION_FLAG_CP_PIXEL
135 #define ION_FLAG_CP_PIXEL 0
136 #endif
137 
138 #ifdef MASTER_SIDE_CP
139 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
140 #define SECURE_ALIGN SZ_4K
141 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
142 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
143 #else //SLAVE_SIDE_CP
144 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
145 #define SECURE_ALIGN SZ_1M
146 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
147 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
148 #endif
149 
150 static OMX_U32 maxSmoothStreamingWidth = 1920;
151 static OMX_U32 maxSmoothStreamingHeight = 1088;
152 
async_message_thread(void * input)153 void* async_message_thread (void *input)
154 {
155     OMX_BUFFERHEADERTYPE *buffer;
156     struct v4l2_plane plane[VIDEO_MAX_PLANES];
157     struct pollfd pfds[2];
158     struct v4l2_buffer v4l2_buf;
159     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
160     struct v4l2_event dqevent;
161     omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
162     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
163     pfds[1].events = POLLIN | POLLERR;
164     pfds[0].fd = omx->drv_ctx.video_driver_fd;
165     pfds[1].fd = omx->m_poll_efd;
166     int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
167     DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
168     prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
169     while (!omx->async_thread_force_stop) {
170         rc = poll(pfds, 2, POLL_TIMEOUT);
171         if (!rc) {
172             DEBUG_PRINT_ERROR("Poll timedout");
173             break;
174         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
175             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
176             break;
177         }
178         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
179             DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
180             break;
181         }
182         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
183             struct vdec_msginfo vdec_msg;
184             memset(&vdec_msg, 0, sizeof(vdec_msg));
185             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
186             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
187             v4l2_buf.length = omx->drv_ctx.num_planes;
188             v4l2_buf.m.planes = plane;
189             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
190                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
191                 vdec_msg.status_code=VDEC_S_SUCCESS;
192                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
193                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
194                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
195                 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
196                     (uint64_t)v4l2_buf.timestamp.tv_usec;
197                 if (vdec_msg.msgdata.output_frame.len) {
198                     vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
199                     vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
200                     vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
201                     vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
202                     vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
203                     vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
204                 }
205                 if (omx->async_message_process(input,&vdec_msg) < 0) {
206                     DEBUG_PRINT_HIGH("async_message_thread Exited");
207                     break;
208                 }
209             }
210         }
211         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
212             struct vdec_msginfo vdec_msg;
213             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
214             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
215             v4l2_buf.length = 1;
216             v4l2_buf.m.planes = plane;
217             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
218                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
219                 vdec_msg.status_code=VDEC_S_SUCCESS;
220                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
221                 if (omx->async_message_process(input,&vdec_msg) < 0) {
222                     DEBUG_PRINT_HIGH("async_message_thread Exited");
223                     break;
224                 }
225             }
226         }
227         if (pfds[0].revents & POLLPRI) {
228             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
229             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
230                 struct vdec_msginfo vdec_msg;
231                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
232 
233                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
234                 vdec_msg.status_code=VDEC_S_SUCCESS;
235                 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
236                 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
237                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
238                 if (omx->async_message_process(input,&vdec_msg) < 0) {
239                     DEBUG_PRINT_HIGH("async_message_thread Exited");
240                     break;
241                 }
242             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT ) {
243                 struct vdec_msginfo vdec_msg;
244                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
245                 vdec_msg.status_code=VDEC_S_SUCCESS;
246                 omx->dpb_bit_depth = dqevent.u.data[0];
247                 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", dqevent.u.data[0]);
248                 if (omx->async_message_process(input,&vdec_msg) < 0) {
249                     DEBUG_PRINT_HIGH("async_message_thread Exited");
250                     break;
251                 }
252             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
253                 struct vdec_msginfo vdec_msg;
254                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
255                 vdec_msg.status_code=VDEC_S_SUCCESS;
256                 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
257                 if (omx->async_message_process(input,&vdec_msg) < 0) {
258                     DEBUG_PRINT_HIGH("async_message_thread Exited");
259                     break;
260                 }
261                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
262                 vdec_msg.status_code=VDEC_S_SUCCESS;
263                 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
264                 if (omx->async_message_process(input,&vdec_msg) < 0) {
265                     DEBUG_PRINT_HIGH("async_message_thread Exited");
266                     break;
267                 }
268             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
269                 struct vdec_msginfo vdec_msg;
270                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
271                 vdec_msg.status_code=VDEC_S_SUCCESS;
272                 DEBUG_PRINT_ERROR("HW Overload received");
273                 if (omx->async_message_process(input,&vdec_msg) < 0) {
274                     DEBUG_PRINT_HIGH("async_message_thread Exited");
275                     break;
276                 }
277             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
278                 struct vdec_msginfo vdec_msg;
279                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
280                 vdec_msg.status_code=VDEC_S_SUCCESS;
281                 DEBUG_PRINT_ERROR("HW Unsupported received");
282                 if (omx->async_message_process(input,&vdec_msg) < 0) {
283                     DEBUG_PRINT_HIGH("async_message_thread Exited");
284                     break;
285                 }
286             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
287                 struct vdec_msginfo vdec_msg;
288                 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
289                 vdec_msg.status_code = VDEC_S_SUCCESS;
290                 DEBUG_PRINT_HIGH("SYS Error Recieved");
291                 if (omx->async_message_process(input,&vdec_msg) < 0) {
292                     DEBUG_PRINT_HIGH("async_message_thread Exited");
293                     break;
294                 }
295             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
296                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
297 
298                 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
299             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
300                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
301                 struct vdec_msginfo vdec_msg;
302 
303                 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
304 
305                 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
306                 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
307                 v4l2_buf.length = omx->drv_ctx.num_planes;
308                 v4l2_buf.m.planes = plane;
309                 v4l2_buf.index = ptr[5];
310                 v4l2_buf.flags = 0;
311 
312                 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
313                 vdec_msg.status_code = VDEC_S_SUCCESS;
314                 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
315                 vdec_msg.msgdata.output_frame.len = 0;
316                 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
317                 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
318                     (uint64_t)ptr[4];
319                 if (omx->async_message_process(input,&vdec_msg) < 0) {
320                     DEBUG_PRINT_HIGH("async_message_thread Exitedn");
321                     break;
322                 }
323             } else {
324                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
325                 continue;
326             }
327         }
328     }
329     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
330     return NULL;
331 }
332 
message_thread(void * input)333 void* message_thread(void *input)
334 {
335     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
336     unsigned char id;
337     int n;
338 
339     fd_set readFds;
340     int res = 0;
341     struct timeval tv;
342 
343     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
344     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
345     while (!omx->message_thread_stop) {
346 
347         tv.tv_sec = 2;
348         tv.tv_usec = 0;
349 
350         FD_ZERO(&readFds);
351         FD_SET(omx->m_pipe_in, &readFds);
352 
353         res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
354         if (res < 0) {
355             DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
356             continue;
357         } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
358             continue;
359         }
360 
361         n = read(omx->m_pipe_in, &id, 1);
362 
363         if (0 == n) {
364             break;
365         }
366 
367         if (1 == n) {
368             omx->process_event_cb(omx, id);
369         }
370 
371         if ((n < 0) && (errno != EINTR)) {
372             DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
373             break;
374         }
375     }
376     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
377     return 0;
378 }
379 
post_message(omx_vdec * omx,unsigned char id)380 void post_message(omx_vdec *omx, unsigned char id)
381 {
382     int ret_value;
383     DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
384     ret_value = write(omx->m_pipe_out, &id, 1);
385     if (ret_value <= 0) {
386         DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
387     } else {
388         DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
389     }
390 }
391 
392 // omx_cmd_queue destructor
~omx_cmd_queue()393 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
394 {
395     // Nothing to do
396 }
397 
398 // omx cmd queue constructor
omx_cmd_queue()399 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
400 {
401     memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
402 }
403 
404 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)405 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
406 {
407     bool ret = true;
408     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
409         m_q[m_write].id       = id;
410         m_q[m_write].param1   = p1;
411         m_q[m_write].param2   = p2;
412         m_write++;
413         m_size ++;
414         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
415             m_write = 0;
416         }
417     } else {
418         ret = false;
419         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
420     }
421     return ret;
422 }
423 
424 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)425 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
426 {
427     bool ret = true;
428     if (m_size > 0) {
429         *id = m_q[m_read].id;
430         *p1 = m_q[m_read].param1;
431         *p2 = m_q[m_read].param2;
432         // Move the read pointer ahead
433         ++m_read;
434         --m_size;
435         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
436             m_read = 0;
437         }
438     } else {
439         ret = false;
440     }
441     return ret;
442 }
443 
444 // Retrieve the first mesg type in the queue
get_q_msg_type()445 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
446 {
447     return m_q[m_read].id;
448 }
449 
450 #ifdef _ANDROID_
ts_arr_list()451 omx_vdec::ts_arr_list::ts_arr_list()
452 {
453     //initialize timestamps array
454     memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
455 }
~ts_arr_list()456 omx_vdec::ts_arr_list::~ts_arr_list()
457 {
458     //free m_ts_arr_list?
459 }
460 
insert_ts(OMX_TICKS ts)461 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
462 {
463     bool ret = true;
464     bool duplicate_ts = false;
465     int idx = 0;
466 
467     //insert at the first available empty location
468     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
469         if (!m_ts_arr_list[idx].valid) {
470             //found invalid or empty entry, save timestamp
471             m_ts_arr_list[idx].valid = true;
472             m_ts_arr_list[idx].timestamp = ts;
473             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
474                     ts, idx);
475             break;
476         }
477     }
478 
479     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
480         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
481         ret = false;
482     }
483     return ret;
484 }
485 
pop_min_ts(OMX_TICKS & ts)486 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
487 {
488     bool ret = true;
489     int min_idx = -1;
490     OMX_TICKS min_ts = 0;
491     int idx = 0;
492 
493     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
494 
495         if (m_ts_arr_list[idx].valid) {
496             //found valid entry, save index
497             if (min_idx < 0) {
498                 //first valid entry
499                 min_ts = m_ts_arr_list[idx].timestamp;
500                 min_idx = idx;
501             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
502                 min_ts = m_ts_arr_list[idx].timestamp;
503                 min_idx = idx;
504             }
505         }
506 
507     }
508 
509     if (min_idx < 0) {
510         //no valid entries found
511         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
512         ts = 0;
513         ret = false;
514     } else {
515         ts = m_ts_arr_list[min_idx].timestamp;
516         m_ts_arr_list[min_idx].valid = false;
517         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
518                 ts, min_idx);
519     }
520 
521     return ret;
522 
523 }
524 
525 
reset_ts_list()526 bool omx_vdec::ts_arr_list::reset_ts_list()
527 {
528     bool ret = true;
529     int idx = 0;
530 
531     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
532     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
533         m_ts_arr_list[idx].valid = false;
534     }
535     return ret;
536 }
537 #endif
538 
539 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)540 void *get_omx_component_factory_fn(void)
541 {
542     return (new omx_vdec);
543 }
544 
545 #ifdef _ANDROID_
546 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,ion_user_handle_t handle,int ionMapfd)547 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
548         ion_user_handle_t handle, int ionMapfd)
549 {
550     (void) devicefd;
551     (void) size;
552     (void) base;
553     (void) handle;
554     (void) ionMapfd;
555     //    ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
556 }
557 #else
VideoHeap(int fd,size_t size,void * base)558 VideoHeap::VideoHeap(int fd, size_t size, void* base)
559 {
560     // dup file descriptor, map once, use pmem
561     init(dup(fd), base, size, 0 , MEM_DEVICE);
562 }
563 #endif
564 #endif // _ANDROID_
565 /* ======================================================================
566    FUNCTION
567    omx_vdec::omx_vdec
568 
569    DESCRIPTION
570    Constructor
571 
572    PARAMETERS
573    None
574 
575    RETURN VALUE
576    None.
577    ========================================================================== */
omx_vdec()578 omx_vdec::omx_vdec(): m_error_propogated(false),
579     m_state(OMX_StateInvalid),
580     m_app_data(NULL),
581     m_inp_mem_ptr(NULL),
582     m_out_mem_ptr(NULL),
583     input_flush_progress (false),
584     output_flush_progress (false),
585     input_use_buffer (false),
586     output_use_buffer (false),
587     ouput_egl_buffers(false),
588     m_use_output_pmem(OMX_FALSE),
589     m_out_mem_region_smi(OMX_FALSE),
590     m_out_pvt_entry_pmem(OMX_FALSE),
591     pending_input_buffers(0),
592     pending_output_buffers(0),
593     m_out_bm_count(0),
594     m_inp_bm_count(0),
595     m_inp_bPopulated(OMX_FALSE),
596     m_out_bPopulated(OMX_FALSE),
597     m_flags(0),
598 #ifdef _ANDROID_
599     m_heap_ptr(NULL),
600 #endif
601     m_inp_bEnabled(OMX_TRUE),
602     m_out_bEnabled(OMX_TRUE),
603     m_in_alloc_cnt(0),
604     m_platform_list(NULL),
605     m_platform_entry(NULL),
606     m_pmem_info(NULL),
607     h264_parser(NULL),
608     arbitrary_bytes (true),
609     psource_frame (NULL),
610     pdest_frame (NULL),
611     m_inp_heap_ptr (NULL),
612     m_phdr_pmem_ptr(NULL),
613     m_heap_inp_bm_count (0),
614     codec_type_parse ((codec_type)0),
615     first_frame_meta (true),
616     frame_count (0),
617     nal_count (0),
618     nal_length(0),
619     look_ahead_nal (false),
620     first_frame(0),
621     first_buffer(NULL),
622     first_frame_size (0),
623     m_device_file_ptr(NULL),
624     m_vc1_profile((vc1_profile_type)0),
625     h264_last_au_ts(LLONG_MAX),
626     h264_last_au_flags(0),
627     m_disp_hor_size(0),
628     m_disp_vert_size(0),
629     prev_ts(LLONG_MAX),
630     prev_ts_actual(LLONG_MAX),
631     rst_prev_ts(true),
632     frm_int(0),
633     in_reconfig(false),
634     m_display_id(NULL),
635     client_extradata(0),
636     m_reject_avc_1080p_mp (0),
637 #ifdef _ANDROID_
638     m_enable_android_native_buffers(OMX_FALSE),
639     m_use_android_native_buffers(OMX_FALSE),
640 #endif
641     m_desc_buffer_ptr(NULL),
642     secure_mode(false),
643     allocate_native_handle(false),
644     m_other_extradata(NULL),
645     m_profile(0),
646     client_set_fps(false),
647     m_last_rendered_TS(-1),
648     m_queued_codec_config_count(0),
649     current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
650     secure_scaling_to_non_secure_opb(false),
651     m_force_compressed_for_dpb(false),
652     m_buffer_error(false)
653 {
654     m_pipe_in = -1;
655     m_pipe_out = -1;
656     m_poll_efd = -1;
657     drv_ctx.video_driver_fd = -1;
658     drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
659     /* Assumption is that , to begin with , we have all the frames with decoder */
660     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
661     memset(&m_debug,0,sizeof(m_debug));
662 #ifdef _ANDROID_
663     char property_value[PROPERTY_VALUE_MAX] = {0};
664     property_get("vidc.debug.level", property_value, "1");
665     debug_level = atoi(property_value);
666     property_value[0] = '\0';
667 
668     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
669 
670     property_get("vidc.dec.debug.perf", property_value, "0");
671     perf_flag = atoi(property_value);
672     if (perf_flag) {
673         DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
674         dec_time.start();
675         proc_frms = latency = 0;
676     }
677     prev_n_filled_len = 0;
678     property_value[0] = '\0';
679     property_get("vidc.dec.debug.ts", property_value, "0");
680     m_debug_timestamp = atoi(property_value);
681     DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
682     if (m_debug_timestamp) {
683         time_stamp_dts.set_timestamp_reorder_mode(true);
684         time_stamp_dts.enable_debug_print(true);
685     }
686 
687     property_value[0] = '\0';
688     property_get("vidc.dec.debug.concealedmb", property_value, "0");
689     m_debug_concealedmb = atoi(property_value);
690     DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
691 
692     property_value[0] = '\0';
693     property_get("vidc.dec.profile.check", property_value, "0");
694     m_reject_avc_1080p_mp = atoi(property_value);
695     DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
696 
697     property_value[0] = '\0';
698     property_get("vidc.dec.log.in", property_value, "0");
699     m_debug.in_buffer_log = atoi(property_value);
700 
701     property_value[0] = '\0';
702     property_get("vidc.dec.log.out", property_value, "0");
703     m_debug.out_buffer_log = atoi(property_value);
704     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
705 
706     property_value[0] = '\0';
707     property_get("vidc.dec.meta.log.out", property_value, "0");
708     m_debug.out_meta_buffer_log = atoi(property_value);
709     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
710 
711     property_value[0] = '\0';
712     property_get("vidc.log.loc", property_value, "");
713     if (*property_value)
714         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
715 
716     property_value[0] = '\0';
717     property_get("vidc.dec.120fps.enabled", property_value, "0");
718 
719     //if this feature is not enabled then reset this value -ve
720     if(atoi(property_value)) {
721         DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
722         m_last_rendered_TS = 0;
723     }
724 
725     property_value[0] = '\0';
726     property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
727     m_disable_dynamic_buf_mode = atoi(property_value);
728     DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
729 
730 #ifdef _UBWC_
731     property_value[0] = '\0';
732     property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
733     m_disable_ubwc_mode = atoi(property_value);
734     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
735 #else
736     m_disable_ubwc_mode = true;
737 #endif
738 #endif
739     memset(&m_cmp,0,sizeof(m_cmp));
740     memset(&m_cb,0,sizeof(m_cb));
741     memset (&drv_ctx,0,sizeof(drv_ctx));
742     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
743     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
744     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
745     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
746     memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
747     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
748     m_demux_entries = 0;
749     msg_thread_id = 0;
750     async_thread_id = 0;
751     msg_thread_created = false;
752     async_thread_created = false;
753     async_thread_force_stop = false;
754     message_thread_stop = false;
755 #ifdef _ANDROID_ICS_
756     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
757 #endif
758     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
759 
760     /* invalidate m_frame_pack_arrangement */
761     memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
762     m_frame_pack_arrangement.cancel_flag = 1;
763 
764     drv_ctx.timestamp_adjust = false;
765     m_vendor_config.pData = NULL;
766     pthread_mutex_init(&m_lock, NULL);
767     pthread_mutex_init(&c_lock, NULL);
768     pthread_mutex_init(&buf_lock, NULL);
769     sem_init(&m_cmd_lock,0,0);
770     sem_init(&m_safe_flush, 0, 0);
771     streaming[CAPTURE_PORT] =
772         streaming[OUTPUT_PORT] = false;
773 #ifdef _ANDROID_
774     char extradata_value[PROPERTY_VALUE_MAX] = {0};
775     property_get("vidc.dec.debug.extradata", extradata_value, "0");
776     m_debug_extradata = atoi(extradata_value);
777     DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
778 #endif
779     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
780     client_buffers.set_vdec_client(this);
781     dynamic_buf_mode = false;
782     out_dynamic_list = NULL;
783     is_down_scalar_enabled = false;
784     m_downscalar_width = 0;
785     m_downscalar_height = 0;
786     m_force_down_scalar = 0;
787     m_reconfig_height = 0;
788     m_reconfig_width = 0;
789     m_smoothstreaming_mode = false;
790     m_smoothstreaming_width = 0;
791     m_smoothstreaming_height = 0;
792     m_decode_order_mode = false;
793     is_q6_platform = false;
794     m_perf_control.send_hint_to_mpctl(true);
795     m_input_pass_buffer_fd = false;
796     m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
797     m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
798     m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
799     m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
800     m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
801 
802     m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
803     m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
804     m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
805     m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
806     m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
807     m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
808 }
809 
810 static const int event_type[] = {
811     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
812     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
813     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
814     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
815     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
816     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
817     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
818     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
819     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
820 };
821 
subscribe_to_events(int fd)822 static OMX_ERRORTYPE subscribe_to_events(int fd)
823 {
824     OMX_ERRORTYPE eRet = OMX_ErrorNone;
825     struct v4l2_event_subscription sub;
826     int array_sz = sizeof(event_type)/sizeof(int);
827     int i,rc;
828     if (fd < 0) {
829         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
830         return OMX_ErrorBadParameter;
831     }
832 
833     for (i = 0; i < array_sz; ++i) {
834         memset(&sub, 0, sizeof(sub));
835         sub.type = event_type[i];
836         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
837         if (rc) {
838             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
839             break;
840         }
841     }
842     if (i < array_sz) {
843         for (--i; i >=0 ; i--) {
844             memset(&sub, 0, sizeof(sub));
845             sub.type = event_type[i];
846             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
847             if (rc)
848                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
849         }
850         eRet = OMX_ErrorNotImplemented;
851     }
852     return eRet;
853 }
854 
855 
unsubscribe_to_events(int fd)856 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
857 {
858     OMX_ERRORTYPE eRet = OMX_ErrorNone;
859     struct v4l2_event_subscription sub;
860     int array_sz = sizeof(event_type)/sizeof(int);
861     int i,rc;
862     if (fd < 0) {
863         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
864         return OMX_ErrorBadParameter;
865     }
866 
867     for (i = 0; i < array_sz; ++i) {
868         memset(&sub, 0, sizeof(sub));
869         sub.type = event_type[i];
870         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
871         if (rc) {
872             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
873             break;
874         }
875     }
876     return eRet;
877 }
878 
879 /* ======================================================================
880    FUNCTION
881    omx_vdec::~omx_vdec
882 
883    DESCRIPTION
884    Destructor
885 
886    PARAMETERS
887    None
888 
889    RETURN VALUE
890    None.
891    ========================================================================== */
~omx_vdec()892 omx_vdec::~omx_vdec()
893 {
894     m_pmem_info = NULL;
895     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
896     if (msg_thread_created) {
897         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
898         message_thread_stop = true;
899         post_message(this, OMX_COMPONENT_CLOSE_MSG);
900         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
901         pthread_join(msg_thread_id,NULL);
902     }
903     close(m_pipe_in);
904     close(m_pipe_out);
905     m_pipe_in = -1;
906     m_pipe_out = -1;
907     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
908     if(eventfd_write(m_poll_efd, 1)) {
909          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
910          async_thread_force_stop = true;
911     }
912 
913     if (async_thread_created)
914         pthread_join(async_thread_id,NULL);
915     unsubscribe_to_events(drv_ctx.video_driver_fd);
916     close(m_poll_efd);
917     close(drv_ctx.video_driver_fd);
918     pthread_mutex_destroy(&m_lock);
919     pthread_mutex_destroy(&c_lock);
920     pthread_mutex_destroy(&buf_lock);
921     sem_destroy(&m_cmd_lock);
922     if (perf_flag) {
923         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
924         dec_time.end();
925     }
926     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
927     m_perf_control.send_hint_to_mpctl(false);
928 }
929 
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)930 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
931 {
932     struct v4l2_requestbuffers bufreq;
933     int rc = 0;
934     if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
935         bufreq.memory = V4L2_MEMORY_USERPTR;
936         bufreq.count = 0;
937         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
938         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
939     } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
940         bufreq.memory = V4L2_MEMORY_USERPTR;
941         bufreq.count = 0;
942         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
943         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
944     }
945     return rc;
946 }
947 
set_dpb(bool is_split_mode,int dpb_color_format)948 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
949 {
950     int rc = 0;
951     struct v4l2_ext_control ctrl[2];
952     struct v4l2_ext_controls controls;
953 
954     DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
955          is_split_mode ? "split" : "combined",
956          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
957          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
958          dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
959          "unknown",
960          capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
961          capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
962          "unknown");
963 
964     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
965     if (is_split_mode) {
966         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
967     } else {
968         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
969     }
970 
971     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
972     ctrl[1].value = dpb_color_format;
973 
974     controls.count = 2;
975     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
976     controls.controls = ctrl;
977 
978     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
979     if (rc) {
980         DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
981         return OMX_ErrorUnsupportedSetting;
982     }
983     return OMX_ErrorNone;
984 }
985 
986 
decide_dpb_buffer_mode(bool force_split_mode)987 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
988 {
989     OMX_ERRORTYPE eRet = OMX_ErrorNone;
990 
991     bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC;
992 
993     bool is_res_above_1080p = (drv_ctx.video_resolution.frame_width > 1920 &&
994             drv_ctx.video_resolution.frame_height > 1088) ||
995             (drv_ctx.video_resolution.frame_height > 1088 &&
996              drv_ctx.video_resolution.frame_width > 1920);
997 
998     if (cpu_access) {
999         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1000             if ((m_force_compressed_for_dpb || is_res_above_1080p) &&
1001                 !force_split_mode) {
1002                 //split DPB-OPB
1003                 //DPB -> UBWC , OPB -> Linear
1004                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1005             } else if (force_split_mode) {
1006                         //DPB -> Linear, OPB -> Linear
1007                         eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1008             } else {
1009                         //DPB-OPB combined linear
1010                         eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1011            }
1012         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1013             //split DPB-OPB
1014             //DPB -> UBWC, OPB -> Linear
1015             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1016         }
1017     } else { //no cpu access
1018         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1019             if (force_split_mode) {
1020                 //split DPB-OPB
1021                 //DPB -> UBWC, OPB -> UBWC
1022                 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1023             } else {
1024                 //DPB-OPB combined UBWC
1025                 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1026             }
1027         } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1028             //split DPB-OPB
1029             //DPB -> UBWC, OPB -> UBWC
1030             eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1031         }
1032     }
1033     if (eRet) {
1034         DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1035     }
1036     return eRet;
1037 }
1038 
enable_downscalar()1039 int omx_vdec::enable_downscalar()
1040 {
1041     int rc = 0;
1042     struct v4l2_control control;
1043     struct v4l2_format fmt;
1044 
1045     if (is_down_scalar_enabled) {
1046         DEBUG_PRINT_LOW("%s: already enabled", __func__);
1047         return 0;
1048     }
1049 
1050     DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1051     rc = decide_dpb_buffer_mode(true);
1052     if (rc) {
1053         DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1054         return rc;
1055     }
1056     is_down_scalar_enabled = true;
1057 
1058     memset(&control, 0x0, sizeof(struct v4l2_control));
1059     control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1060     control.value = 1;
1061     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1062     if (rc) {
1063         DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1064         return rc;
1065     }
1066 
1067     return 0;
1068 }
1069 
disable_downscalar()1070 int omx_vdec::disable_downscalar()
1071 {
1072     int rc = 0;
1073     struct v4l2_control control;
1074 
1075     if (!is_down_scalar_enabled) {
1076         DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1077         return 0;
1078     }
1079 
1080     rc = decide_dpb_buffer_mode(false);
1081     if (rc < 0) {
1082         DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1083         return rc;
1084     }
1085     is_down_scalar_enabled = false;
1086 
1087     return rc;
1088 }
1089 
decide_downscalar()1090 int omx_vdec::decide_downscalar()
1091 {
1092     int rc = 0;
1093     struct v4l2_format fmt;
1094     enum color_fmts color_format;
1095 
1096     if  (!m_downscalar_width || !m_downscalar_height) {
1097         DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1098         return 0;
1099     }
1100 
1101     if (m_force_down_scalar) {
1102         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1103         return 0;
1104     }
1105 
1106     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1107     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1108     fmt.fmt.pix_mp.pixelformat = capture_capability;
1109     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1110     if (rc < 0) {
1111        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1112        return rc;
1113     }
1114 
1115     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__,
1116         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height);
1117 
1118     if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) {
1119         rc = enable_downscalar();
1120         if (rc < 0) {
1121             DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1122             return rc;
1123         }
1124 
1125         OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1126                             fmt.fmt.pix_mp.width : m_downscalar_width;
1127         OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1128                             fmt.fmt.pix_mp.height : m_downscalar_height;
1129         switch (capture_capability) {
1130             case V4L2_PIX_FMT_NV12:
1131                 color_format = COLOR_FMT_NV12;
1132                 break;
1133             case V4L2_PIX_FMT_NV12_UBWC:
1134                 color_format = COLOR_FMT_NV12_UBWC;
1135                 break;
1136             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1137                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1138                 break;
1139             default:
1140                 DEBUG_PRINT_ERROR("Color format not recognized\n");
1141                 rc = OMX_ErrorUndefined;
1142                 return rc;
1143         }
1144 
1145         rc = update_resolution(width, height,
1146                 VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height));
1147         if (rc < 0) {
1148             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height);
1149             return rc;
1150         }
1151     } else {
1152 
1153         rc = disable_downscalar();
1154         if (rc < 0) {
1155             DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1156             return rc;
1157         }
1158 
1159         rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1160                 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
1161         if (rc < 0) {
1162             DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width,
1163                 fmt.fmt.pix_mp.height);
1164             return rc;
1165         }
1166     }
1167 
1168     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1169     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1170     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1171     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1172     fmt.fmt.pix_mp.pixelformat = capture_capability;
1173     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1174     if (rc) {
1175         DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1176         return rc;
1177     }
1178 
1179     rc = get_buffer_req(&drv_ctx.op_buf);
1180     if (rc) {
1181         DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1182         return rc;
1183     }
1184 
1185     return rc;
1186 }
1187 
1188 /* ======================================================================
1189    FUNCTION
1190    omx_vdec::OMXCntrlProcessMsgCb
1191 
1192    DESCRIPTION
1193    IL Client callbacks are generated through this routine. The decoder
1194    provides the thread context for this routine.
1195 
1196    PARAMETERS
1197    ctxt -- Context information related to the self.
1198    id   -- Event identifier. This could be any of the following:
1199    1. Command completion event
1200    2. Buffer done callback event
1201    3. Frame done callback event
1202 
1203    RETURN VALUE
1204    None.
1205 
1206    ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1207 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1208 {
1209     unsigned long p1; // Parameter - 1
1210     unsigned long p2; // Parameter - 2
1211     unsigned long ident;
1212     unsigned qsize=0; // qsize
1213     omx_vdec *pThis = (omx_vdec *) ctxt;
1214 
1215     if (!pThis) {
1216         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1217                 __func__);
1218         return;
1219     }
1220 
1221     // Protect the shared queue data structure
1222     do {
1223         /*Read the message id's from the queue*/
1224         pthread_mutex_lock(&pThis->m_lock);
1225         qsize = pThis->m_cmd_q.m_size;
1226         if (qsize) {
1227             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1228         }
1229 
1230         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1231             qsize = pThis->m_ftb_q.m_size;
1232             if (qsize) {
1233                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1234             }
1235         }
1236 
1237         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1238             qsize = pThis->m_etb_q.m_size;
1239             if (qsize) {
1240                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1241             }
1242         }
1243         pthread_mutex_unlock(&pThis->m_lock);
1244 
1245         /*process message if we have one*/
1246         if (qsize > 0) {
1247             id = ident;
1248             switch (id) {
1249                 case OMX_COMPONENT_GENERATE_EVENT:
1250                     if (pThis->m_cb.EventHandler) {
1251                         switch (p1) {
1252                             case OMX_CommandStateSet:
1253                                 pThis->m_state = (OMX_STATETYPE) p2;
1254                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1255                                         pThis->m_state);
1256                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1257                                         OMX_EventCmdComplete, p1, p2, NULL);
1258                                 break;
1259 
1260                             case OMX_EventError:
1261                                 if (p2 == OMX_StateInvalid) {
1262                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1263                                     pThis->m_state = (OMX_STATETYPE) p2;
1264                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1265                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1266                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1267                                     pThis->omx_report_error();
1268                                 } else {
1269                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1270                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
1271                                 }
1272                                 break;
1273 
1274                             case OMX_CommandPortDisable:
1275                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1276                                 if (BITMASK_PRESENT(&pThis->m_flags,
1277                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1278                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1279                                     break;
1280                                 }
1281                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1282                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1283                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1284                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1285                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
1286                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1287                                     pThis->in_reconfig = false;
1288                                     if (eRet !=  OMX_ErrorNone) {
1289                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1290                                         pThis->omx_report_error();
1291                                         break;
1292                                     }
1293                                 }
1294                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1295                                         OMX_EventCmdComplete, p1, p2, NULL );
1296                                 break;
1297                             case OMX_CommandPortEnable:
1298                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1299                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1300                                         OMX_EventCmdComplete, p1, p2, NULL );
1301                                 break;
1302 
1303                             default:
1304                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1305                                         OMX_EventCmdComplete, p1, p2, NULL );
1306                                 break;
1307 
1308                         }
1309                     } else {
1310                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1311                     }
1312                     break;
1313                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1314                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1315                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1316                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1317                         pThis->omx_report_error ();
1318                     }
1319                     break;
1320                 case OMX_COMPONENT_GENERATE_ETB: {
1321                         OMX_ERRORTYPE iret;
1322                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1323                         if (iret == OMX_ErrorInsufficientResources) {
1324                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1325                             pThis->omx_report_hw_overload ();
1326                         } else if (iret != OMX_ErrorNone) {
1327                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1328                             pThis->omx_report_error ();
1329                         }
1330                     }
1331                     break;
1332 
1333                 case OMX_COMPONENT_GENERATE_FTB:
1334                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1335                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1336                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1337                         pThis->omx_report_error ();
1338                     }
1339                     break;
1340 
1341                 case OMX_COMPONENT_GENERATE_COMMAND:
1342                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1343                             (OMX_U32)p2,(OMX_PTR)NULL);
1344                     break;
1345 
1346                 case OMX_COMPONENT_GENERATE_EBD:
1347 
1348                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1349                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1350                         pThis->omx_report_error ();
1351                     } else {
1352                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1353                             pThis->time_stamp_dts.remove_time_stamp(
1354                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1355                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1356                                     ?true:false);
1357                         }
1358 
1359                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1360                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1361                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1362                             pThis->omx_report_error ();
1363                         }
1364                     }
1365                     break;
1366                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1367                                             int64_t *timestamp = (int64_t *)(intptr_t)p1;
1368                                             if (p1) {
1369                                                 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1370                                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1371                                                         ?true:false);
1372                                                 free(timestamp);
1373                                             }
1374                                         }
1375                                         break;
1376                 case OMX_COMPONENT_GENERATE_FBD:
1377                                         if (p2 != VDEC_S_SUCCESS) {
1378                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1379                                             pThis->omx_report_error ();
1380                                         } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1381                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1382                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
1383                                             pThis->omx_report_error ();
1384                                         }
1385                                         break;
1386 
1387                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1388                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1389                                         if (!pThis->input_flush_progress) {
1390                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1391                                         } else {
1392                                             pThis->execute_input_flush();
1393                                             if (pThis->m_cb.EventHandler) {
1394                                                 if (p2 != VDEC_S_SUCCESS) {
1395                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1396                                                     pThis->omx_report_error ();
1397                                                 } else {
1398                                                     /*Check if we need generate event for Flush done*/
1399                                                     pThis->notify_flush_done(ctxt);
1400 
1401                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1402                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1403                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1404                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1405                                                             pThis->omx_report_error ();
1406                                                         } else {
1407                                                             pThis->streaming[OUTPUT_PORT] = false;
1408                                                         }
1409                                                         if (!pThis->output_flush_progress) {
1410                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1411                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1412                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1413                                                         }
1414                                                     }
1415                                                 }
1416                                             } else {
1417                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1418                                             }
1419                                         }
1420                                         break;
1421 
1422                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1423                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1424                                         if (!pThis->output_flush_progress) {
1425                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1426                                         } else {
1427                                             pThis->execute_output_flush();
1428                                             if (pThis->m_cb.EventHandler) {
1429                                                 if (p2 != VDEC_S_SUCCESS) {
1430                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1431                                                     pThis->omx_report_error ();
1432                                                 } else {
1433                                                     /*Check if we need generate event for Flush done*/
1434                                                     pThis->notify_flush_done(ctxt);
1435 
1436                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1437                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1438                                                         DEBUG_PRINT_LOW("Internal flush complete");
1439                                                         BITMASK_CLEAR (&pThis->m_flags,
1440                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1441                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1442                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1443                                                             pThis->post_event(OMX_CommandPortDisable,
1444                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1445                                                                     OMX_COMPONENT_GENERATE_EVENT);
1446                                                             BITMASK_CLEAR (&pThis->m_flags,
1447                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1448                                                             BITMASK_CLEAR (&pThis->m_flags,
1449                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1450 
1451                                                         }
1452                                                     }
1453 
1454                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1455                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1456                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1457                                                             pThis->omx_report_error ();
1458                                                             break;
1459                                                         }
1460                                                         pThis->streaming[CAPTURE_PORT] = false;
1461                                                         if (!pThis->input_flush_progress) {
1462                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1463                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1464                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1465                                                         }
1466                                                     }
1467                                                 }
1468                                             } else {
1469                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1470                                             }
1471                                         }
1472                                         break;
1473 
1474                 case OMX_COMPONENT_GENERATE_START_DONE:
1475                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1476 
1477                                         if (pThis->m_cb.EventHandler) {
1478                                             if (p2 != VDEC_S_SUCCESS) {
1479                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1480                                                 pThis->omx_report_error ();
1481                                             } else {
1482                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1483                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1484                                                     DEBUG_PRINT_LOW("Move to executing");
1485                                                     // Send the callback now
1486                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1487                                                     pThis->m_state = OMX_StateExecuting;
1488                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1489                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1490                                                             OMX_StateExecuting, NULL);
1491                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1492                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1493                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1494                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1495                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1496                                                         pThis->omx_report_error ();
1497                                                     }
1498                                                 }
1499                                             }
1500                                         } else {
1501                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1502                                         }
1503                                         break;
1504 
1505                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1506                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1507                                         if (pThis->m_cb.EventHandler) {
1508                                             if (p2 != VDEC_S_SUCCESS) {
1509                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1510                                                 pThis->omx_report_error ();
1511                                             } else {
1512                                                 pThis->complete_pending_buffer_done_cbs();
1513                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1514                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1515                                                     //Send the callback now
1516                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1517                                                     pThis->m_state = OMX_StatePause;
1518                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1519                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1520                                                             OMX_StatePause, NULL);
1521                                                 }
1522                                             }
1523                                         } else {
1524                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1525                                         }
1526 
1527                                         break;
1528 
1529                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1530                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1531                                         if (pThis->m_cb.EventHandler) {
1532                                             if (p2 != VDEC_S_SUCCESS) {
1533                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1534                                                 pThis->omx_report_error ();
1535                                             } else {
1536                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1537                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1538                                                     // Send the callback now
1539                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1540                                                     pThis->m_state = OMX_StateExecuting;
1541                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1542                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1543                                                             OMX_StateExecuting,NULL);
1544                                                 }
1545                                             }
1546                                         } else {
1547                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1548                                         }
1549 
1550                                         break;
1551 
1552                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1553                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1554                                         if (pThis->m_cb.EventHandler) {
1555                                             if (p2 != VDEC_S_SUCCESS) {
1556                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1557                                                 pThis->omx_report_error ();
1558                                             } else {
1559                                                 pThis->complete_pending_buffer_done_cbs();
1560                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1561                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1562                                                     // Send the callback now
1563                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1564                                                     pThis->m_state = OMX_StateIdle;
1565                                                     DEBUG_PRINT_LOW("Move to Idle State");
1566                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1567                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1568                                                             OMX_StateIdle,NULL);
1569                                                 }
1570                                             }
1571                                         } else {
1572                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1573                                         }
1574 
1575                                         break;
1576 
1577                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1578                                         if (p2 == OMX_IndexParamPortDefinition) {
1579                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1580                                             pThis->in_reconfig = true;
1581                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1582                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1583 
1584                                             /* Check if resolution is changed in smooth streaming mode */
1585                                             if (pThis->m_smoothstreaming_mode &&
1586                                                 (pThis->framesize.nWidth !=
1587                                                     pThis->drv_ctx.video_resolution.frame_width) ||
1588                                                 (pThis->framesize.nHeight !=
1589                                                     pThis->drv_ctx.video_resolution.frame_height)) {
1590 
1591                                                 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1592                                                         pThis->framesize.nWidth,
1593                                                         pThis->framesize.nHeight,
1594                                                         pThis->drv_ctx.video_resolution.frame_width,
1595                                                         pThis->drv_ctx.video_resolution.frame_height);
1596 
1597                                                 /* Update new resolution */
1598                                                 pThis->framesize.nWidth =
1599                                                        pThis->drv_ctx.video_resolution.frame_width;
1600                                                 pThis->framesize.nHeight =
1601                                                        pThis->drv_ctx.video_resolution.frame_height;
1602 
1603                                                 /* Update C2D with new resolution */
1604                                                 if (!pThis->client_buffers.update_buffer_req()) {
1605                                                     DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1606                                                 }
1607                                             }
1608 
1609                                             /* Update new crop information */
1610                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1611                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1612                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1613                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1614 
1615                                             /* Validate the new crop information */
1616                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1617                                                 pThis->drv_ctx.video_resolution.frame_width) {
1618 
1619                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1620                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1621                                                         pThis->drv_ctx.video_resolution.frame_width);
1622                                                 pThis->rectangle.nLeft = 0;
1623 
1624                                                 if (pThis->rectangle.nWidth >
1625                                                     pThis->drv_ctx.video_resolution.frame_width) {
1626 
1627                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1628                                                             pThis->rectangle.nWidth,
1629                                                             pThis->drv_ctx.video_resolution.frame_width);
1630                                                     pThis->rectangle.nWidth =
1631                                                         pThis->drv_ctx.video_resolution.frame_width;
1632                                                 }
1633                                             }
1634                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1635                                                 pThis->drv_ctx.video_resolution.frame_height) {
1636 
1637                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1638                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1639                                                     pThis->drv_ctx.video_resolution.frame_height);
1640                                                 pThis->rectangle.nTop = 0;
1641 
1642                                                 if (pThis->rectangle.nHeight >
1643                                                     pThis->drv_ctx.video_resolution.frame_height) {
1644 
1645                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1646                                                         pThis->rectangle.nHeight,
1647                                                         pThis->drv_ctx.video_resolution.frame_height);
1648                                                     pThis->rectangle.nHeight =
1649                                                         pThis->drv_ctx.video_resolution.frame_height;
1650                                                 }
1651                                             }
1652                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1653                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1654                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1655                                         } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1656                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1657                                         } else {
1658                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1659                                             break;
1660                                         }
1661                                         if (pThis->m_debug.outfile) {
1662                                             fclose(pThis->m_debug.outfile);
1663                                             pThis->m_debug.outfile = NULL;
1664                                         }
1665                                         if (pThis->m_debug.out_ymeta_file) {
1666                                             fclose(pThis->m_debug.out_ymeta_file);
1667                                             pThis->m_debug.out_ymeta_file = NULL;
1668                                         }
1669                                         if (pThis->m_debug.out_uvmeta_file) {
1670                                             fclose(pThis->m_debug.out_uvmeta_file);
1671                                             pThis->m_debug.out_uvmeta_file = NULL;
1672                                         }
1673 
1674                                         if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1675                                             pThis->prefetchNewBuffers();
1676                                         }
1677 
1678                                         if (pThis->m_cb.EventHandler) {
1679                                             uint32_t frame_data[2];
1680                                             frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1681                                                 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1682                                             frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1683                                                 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1684                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1685                                                     OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1686                                         } else {
1687                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1688                                         }
1689                                         break;
1690 
1691                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1692                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1693                                         if (pThis->m_cb.EventHandler) {
1694                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1695                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1696                                         } else {
1697                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1698                                         }
1699                                         pThis->prev_ts = LLONG_MAX;
1700                                         pThis->rst_prev_ts = true;
1701                                         break;
1702 
1703                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1704                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1705                                         pThis->omx_report_error();
1706                                         break;
1707 
1708                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1709                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1710                                         pThis->omx_report_unsupported_setting();
1711                                         break;
1712 
1713                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1714                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1715                                         pThis->omx_report_hw_overload();
1716                                         break;
1717 
1718                 default:
1719                                         break;
1720             }
1721         }
1722         pthread_mutex_lock(&pThis->m_lock);
1723         qsize = pThis->m_cmd_q.m_size;
1724         if (pThis->m_state != OMX_StatePause)
1725             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1726         pthread_mutex_unlock(&pThis->m_lock);
1727     } while (qsize>0);
1728 
1729 }
1730 
update_resolution(int width,int height,int stride,int scan_lines)1731 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1732 {
1733     int format_changed = 0;
1734     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1735             (width != (int)drv_ctx.video_resolution.frame_width)) {
1736         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1737                 width, drv_ctx.video_resolution.frame_width,
1738                 height,drv_ctx.video_resolution.frame_height);
1739         format_changed = 1;
1740     }
1741     drv_ctx.video_resolution.frame_height = height;
1742     drv_ctx.video_resolution.frame_width = width;
1743     drv_ctx.video_resolution.scan_lines = scan_lines;
1744     drv_ctx.video_resolution.stride = stride;
1745     if(!is_down_scalar_enabled) {
1746         rectangle.nLeft = 0;
1747         rectangle.nTop = 0;
1748         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1749         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1750     }
1751     return format_changed;
1752 }
1753 
is_video_session_supported()1754 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1755 {
1756     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1757                 OMX_MAX_STRINGNAME_SIZE) &&
1758             (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1759         m_decoder_capability.max_width = 1280;
1760         m_decoder_capability.max_height = 720;
1761         DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1762     }
1763 
1764     if ((drv_ctx.video_resolution.frame_width *
1765                 drv_ctx.video_resolution.frame_height >
1766                 m_decoder_capability.max_width *
1767                 m_decoder_capability.max_height) ||
1768             (drv_ctx.video_resolution.frame_width*
1769              drv_ctx.video_resolution.frame_height <
1770              m_decoder_capability.min_width *
1771              m_decoder_capability.min_height)) {
1772         DEBUG_PRINT_ERROR(
1773                 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1774                 drv_ctx.video_resolution.frame_width,
1775                 drv_ctx.video_resolution.frame_height,
1776                 m_decoder_capability.min_width,
1777                 m_decoder_capability.min_height,
1778                 m_decoder_capability.max_width,
1779                 m_decoder_capability.max_height);
1780         return OMX_ErrorUnsupportedSetting;
1781     }
1782     DEBUG_PRINT_HIGH("video session supported");
1783     return OMX_ErrorNone;
1784 }
1785 
log_input_buffers(const char * buffer_addr,int buffer_len)1786 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1787 {
1788     if (m_debug.in_buffer_log && !m_debug.infile) {
1789         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1790            snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1791                    m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1792         } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1793                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1794                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1795         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
1796                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
1797                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1798         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1799                     !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1800                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
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.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1803                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1804                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1805         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
1806                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1807                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1808         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
1809                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1810                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1811         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1812                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1813                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1814         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1815                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1816                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1817         } else {
1818                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
1819                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1820         }
1821         m_debug.infile = fopen (m_debug.infile_name, "ab");
1822         if (!m_debug.infile) {
1823             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1824             m_debug.infile_name[0] = '\0';
1825             return -1;
1826         }
1827         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1828                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1829             struct ivf_file_header {
1830                 OMX_U8 signature[4]; //='DKIF';
1831                 OMX_U8 version         ; //= 0;
1832                 OMX_U8 headersize      ; //= 32;
1833                 OMX_U32 FourCC;
1834                 OMX_U8 width;
1835                 OMX_U8 height;
1836                 OMX_U32 rate;
1837                 OMX_U32 scale;
1838                 OMX_U32 length;
1839                 OMX_U8 unused[4];
1840             } file_header;
1841 
1842             memset((void *)&file_header,0,sizeof(file_header));
1843             file_header.signature[0] = 'D';
1844             file_header.signature[1] = 'K';
1845             file_header.signature[2] = 'I';
1846             file_header.signature[3] = 'F';
1847             file_header.version = 0;
1848             file_header.headersize = 32;
1849             switch (drv_ctx.decoder_format) {
1850                 case VDEC_CODECTYPE_VP8:
1851                     file_header.FourCC = 0x30385056;
1852                     break;
1853                 case VDEC_CODECTYPE_VP9:
1854                     file_header.FourCC = 0x30395056;
1855                     break;
1856                 default:
1857                     DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
1858                     break;
1859             }
1860             fwrite((const char *)&file_header,
1861                     sizeof(file_header),1,m_debug.infile);
1862          }
1863     }
1864     if (m_debug.infile && buffer_addr && buffer_len) {
1865         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1866                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1867             struct vpx_ivf_frame_header {
1868                 OMX_U32 framesize;
1869                 OMX_U32 timestamp_lo;
1870                 OMX_U32 timestamp_hi;
1871             } vpx_frame_header;
1872             vpx_frame_header.framesize = buffer_len;
1873             /* Currently FW doesn't use timestamp values */
1874             vpx_frame_header.timestamp_lo = 0;
1875             vpx_frame_header.timestamp_hi = 0;
1876             fwrite((const char *)&vpx_frame_header,
1877                     sizeof(vpx_frame_header),1,m_debug.infile);
1878         }
1879         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1880     }
1881     return 0;
1882 }
1883 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1884 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
1885     int buf_index = 0;
1886     char *temp = NULL;
1887 
1888     if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
1889         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
1890                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1891         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1892         if (!m_debug.outfile) {
1893             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1894             m_debug.outfile_name[0] = '\0';
1895             return -1;
1896         }
1897     }
1898 
1899     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
1900         && buffer->nFilledLen) {
1901         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
1902                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1903         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
1904                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1905         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
1906         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
1907         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
1908             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
1909             m_debug.out_ymetafile_name[0] = '\0';
1910             m_debug.out_uvmetafile_name[0] = '\0';
1911             return -1;
1912         }
1913     }
1914 
1915     if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
1916         return 0;
1917 
1918     buf_index = buffer - m_out_mem_ptr;
1919     temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1920 
1921     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
1922         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
1923             drv_ctx.video_resolution.frame_width,
1924             drv_ctx.video_resolution.frame_height);
1925 
1926         if (m_debug.outfile)
1927             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
1928 
1929         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
1930             unsigned int width = 0, height = 0;
1931             unsigned int y_plane, y_meta_plane;
1932             int y_stride = 0, y_sclines = 0;
1933             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
1934             int color_fmt = COLOR_FMT_NV12_UBWC;
1935             int i;
1936             int bytes_written = 0;
1937 
1938             width = drv_ctx.video_resolution.frame_width;
1939             height = drv_ctx.video_resolution.frame_height;
1940             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
1941             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
1942             y_stride = VENUS_Y_STRIDE(color_fmt, width);
1943             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
1944             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
1945             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
1946 
1947             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
1948             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
1949 
1950             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1951             for (i = 0; i < y_meta_scanlines; i++) {
1952                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
1953                  temp += y_meta_stride;
1954             }
1955 
1956             temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
1957             for(i = 0; i < uv_meta_scanlines; i++) {
1958                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
1959                 temp += uv_meta_stride;
1960             }
1961         }
1962     } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) {
1963         int stride = drv_ctx.video_resolution.stride;
1964         int scanlines = drv_ctx.video_resolution.scan_lines;
1965         if (m_smoothstreaming_mode) {
1966             stride = drv_ctx.video_resolution.frame_width;
1967             scanlines = drv_ctx.video_resolution.frame_height;
1968             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
1969             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
1970         }
1971         unsigned i;
1972         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1973             drv_ctx.video_resolution.frame_width,
1974             drv_ctx.video_resolution.frame_height, stride, scanlines);
1975         int bytes_written = 0;
1976         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1977              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1978              temp += stride;
1979         }
1980         temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
1981         int stride_c = stride;
1982         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1983             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1984             temp += stride_c;
1985         }
1986     }
1987     return 0;
1988 }
1989 
1990 /* ======================================================================
1991    FUNCTION
1992    omx_vdec::ComponentInit
1993 
1994    DESCRIPTION
1995    Initialize the component.
1996 
1997    PARAMETERS
1998    ctxt -- Context information related to the self.
1999    id   -- Event identifier. This could be any of the following:
2000    1. Command completion event
2001    2. Buffer done callback event
2002    3. Frame done callback event
2003 
2004    RETURN VALUE
2005    None.
2006 
2007    ========================================================================== */
component_init(OMX_STRING role)2008 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2009 {
2010 
2011     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2012     struct v4l2_fmtdesc fdesc;
2013     struct v4l2_format fmt;
2014     struct v4l2_requestbuffers bufreq;
2015     struct v4l2_control control;
2016     struct v4l2_frmsizeenum frmsize;
2017     unsigned int   alignment = 0,buffer_size = 0;
2018     int fds[2];
2019     int r,ret=0;
2020     bool codec_ambiguous = false;
2021     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2022     char property_value[PROPERTY_VALUE_MAX] = {0};
2023     FILE *soc_file = NULL;
2024     char buffer[10];
2025 
2026 #ifdef _ANDROID_
2027     char platform_name[PROPERTY_VALUE_MAX];
2028     property_get("ro.board.platform", platform_name, "0");
2029     if (!strncmp(platform_name, "msm8610", 7)) {
2030         device_name = (OMX_STRING)"/dev/video/q6_dec";
2031         is_q6_platform = true;
2032         maxSmoothStreamingWidth = 1280;
2033         maxSmoothStreamingHeight = 720;
2034     }
2035 #endif
2036 
2037     is_thulium_v1 = false;
2038     soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2039     if (soc_file) {
2040         fread(buffer, 1, 4, soc_file);
2041         fclose(soc_file);
2042         if (atoi(buffer) == 246) {
2043             soc_file = fopen("/sys/devices/soc0/revision", "r");
2044             if (soc_file) {
2045                 fread(buffer, 1, 4, soc_file);
2046                 fclose(soc_file);
2047                 if (atoi(buffer) == 1) {
2048                     is_thulium_v1 = true;
2049                     DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2050                 }
2051             }
2052         }
2053     }
2054 
2055 #ifdef _ANDROID_
2056     /*
2057      * turn off frame parsing for Android by default.
2058      * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2059      */
2060     arbitrary_bytes = false;
2061     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2062     if (atoi(property_value)) {
2063         DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2064         arbitrary_bytes = true;
2065     }
2066 #endif
2067 
2068     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2069                 OMX_MAX_STRINGNAME_SIZE)) {
2070         secure_mode = true;
2071         arbitrary_bytes = false;
2072         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2073     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2074                 OMX_MAX_STRINGNAME_SIZE)) {
2075         secure_mode = true;
2076         arbitrary_bytes = false;
2077         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2078     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2079                 OMX_MAX_STRINGNAME_SIZE)) {
2080         secure_mode = true;
2081         arbitrary_bytes = false;
2082         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2083     } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2084                 OMX_MAX_STRINGNAME_SIZE)) {
2085         secure_mode = true;
2086         arbitrary_bytes = false;
2087         role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2088     } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2089                 OMX_MAX_STRINGNAME_SIZE)) {
2090         secure_mode = true;
2091         arbitrary_bytes = false;
2092         role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2093     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2094                 OMX_MAX_STRINGNAME_SIZE)) {
2095         secure_mode = true;
2096         arbitrary_bytes = false;
2097         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2098     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2099                 OMX_MAX_STRINGNAME_SIZE)) {
2100         secure_mode = true;
2101         arbitrary_bytes = false;
2102         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2103     }
2104 
2105     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2106 
2107     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2108 
2109     if (drv_ctx.video_driver_fd < 0) {
2110         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2111         return OMX_ErrorInsufficientResources;
2112     }
2113     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2114     drv_ctx.frame_rate.fps_denominator = 1;
2115     m_poll_efd = eventfd(0, 0);
2116     if (m_poll_efd < 0) {
2117         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2118         return OMX_ErrorInsufficientResources;
2119     }
2120     ret = subscribe_to_events(drv_ctx.video_driver_fd);
2121     if (!ret) {
2122         async_thread_created = true;
2123         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2124     }
2125     if (ret) {
2126         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2127         async_thread_created = false;
2128         return OMX_ErrorInsufficientResources;
2129     }
2130 
2131 #ifdef OUTPUT_EXTRADATA_LOG
2132     outputExtradataFile = fopen (output_extradata_filename, "ab");
2133 #endif
2134 
2135     // Copy the role information which provides the decoder kind
2136     strlcpy(drv_ctx.kind,role,128);
2137 
2138     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2139                 OMX_MAX_STRINGNAME_SIZE)) {
2140         strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2141                 OMX_MAX_STRINGNAME_SIZE);
2142         drv_ctx.timestamp_adjust = true;
2143         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2144         eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2145         output_capability=V4L2_PIX_FMT_MPEG4;
2146         /*Initialize Start Code for MPEG4*/
2147         codec_type_parse = CODEC_TYPE_MPEG4;
2148         m_frame_parser.init_start_codes(codec_type_parse);
2149     } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2150                 OMX_MAX_STRINGNAME_SIZE)) {
2151         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2152                 OMX_MAX_STRINGNAME_SIZE);
2153         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2154         output_capability = V4L2_PIX_FMT_MPEG2;
2155         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2156         /*Initialize Start Code for MPEG2*/
2157         codec_type_parse = CODEC_TYPE_MPEG2;
2158         m_frame_parser.init_start_codes(codec_type_parse);
2159     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2160                 OMX_MAX_STRINGNAME_SIZE)) {
2161         strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2162         DEBUG_PRINT_LOW("H263 Decoder selected");
2163         drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2164         eCompressionFormat = OMX_VIDEO_CodingH263;
2165         output_capability = V4L2_PIX_FMT_H263;
2166         codec_type_parse = CODEC_TYPE_H263;
2167         m_frame_parser.init_start_codes(codec_type_parse);
2168     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2169                 OMX_MAX_STRINGNAME_SIZE)) {
2170         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2171         DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2172         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2173         output_capability = V4L2_PIX_FMT_DIVX_311;
2174         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2175         codec_type_parse = CODEC_TYPE_DIVX;
2176         m_frame_parser.init_start_codes(codec_type_parse);
2177 
2178     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2179                 OMX_MAX_STRINGNAME_SIZE)) {
2180         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2181         DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2182         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2183         output_capability = V4L2_PIX_FMT_DIVX;
2184         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2185         codec_type_parse = CODEC_TYPE_DIVX;
2186         codec_ambiguous = true;
2187         m_frame_parser.init_start_codes(codec_type_parse);
2188 
2189     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2190                 OMX_MAX_STRINGNAME_SIZE)) {
2191         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2192         DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2193         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2194         output_capability = V4L2_PIX_FMT_DIVX;
2195         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2196         codec_type_parse = CODEC_TYPE_DIVX;
2197         codec_ambiguous = true;
2198         m_frame_parser.init_start_codes(codec_type_parse);
2199 
2200     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2201                 OMX_MAX_STRINGNAME_SIZE)) {
2202         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2203         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2204         output_capability=V4L2_PIX_FMT_H264;
2205         eCompressionFormat = OMX_VIDEO_CodingAVC;
2206         codec_type_parse = CODEC_TYPE_H264;
2207         m_frame_parser.init_start_codes(codec_type_parse);
2208         m_frame_parser.init_nal_length(nal_length);
2209         if (is_thulium_v1) {
2210             arbitrary_bytes = true;
2211             DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2212         }
2213     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2214                 OMX_MAX_STRINGNAME_SIZE)) {
2215         strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2216         drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2217         output_capability = V4L2_PIX_FMT_H264_MVC;
2218         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2219         codec_type_parse = CODEC_TYPE_H264;
2220         m_frame_parser.init_start_codes(codec_type_parse);
2221         m_frame_parser.init_nal_length(nal_length);
2222     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2223                 OMX_MAX_STRINGNAME_SIZE)) {
2224         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2225         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2226         output_capability = V4L2_PIX_FMT_HEVC;
2227         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2228         codec_type_parse = CODEC_TYPE_HEVC;
2229         m_frame_parser.init_start_codes(codec_type_parse);
2230         m_frame_parser.init_nal_length(nal_length);
2231     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2232                 OMX_MAX_STRINGNAME_SIZE)) {
2233         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2234         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2235         eCompressionFormat = OMX_VIDEO_CodingWMV;
2236         codec_type_parse = CODEC_TYPE_VC1;
2237         output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2238         m_frame_parser.init_start_codes(codec_type_parse);
2239     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2240                 OMX_MAX_STRINGNAME_SIZE)) {
2241         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2242         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2243         eCompressionFormat = OMX_VIDEO_CodingWMV;
2244         codec_type_parse = CODEC_TYPE_VC1;
2245         output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2246         m_frame_parser.init_start_codes(codec_type_parse);
2247     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2248                 OMX_MAX_STRINGNAME_SIZE)) {
2249         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2250         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2251         output_capability = V4L2_PIX_FMT_VP8;
2252         eCompressionFormat = OMX_VIDEO_CodingVP8;
2253         codec_type_parse = CODEC_TYPE_VP8;
2254         arbitrary_bytes = false;
2255     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2256                 OMX_MAX_STRINGNAME_SIZE)) {
2257         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2258         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2259         output_capability = V4L2_PIX_FMT_VP9;
2260         eCompressionFormat = OMX_VIDEO_CodingVP9;
2261         codec_type_parse = CODEC_TYPE_VP9;
2262         arbitrary_bytes = false;
2263     } else {
2264         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2265         eRet = OMX_ErrorInvalidComponentName;
2266     }
2267 
2268     if (eRet == OMX_ErrorNone) {
2269         OMX_COLOR_FORMATTYPE dest_color_format;
2270         if (m_disable_ubwc_mode) {
2271             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2272         } else {
2273             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2274         }
2275         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2276             dest_color_format = (OMX_COLOR_FORMATTYPE)
2277                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2278         else
2279             dest_color_format = (OMX_COLOR_FORMATTYPE)
2280                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2281         if (!client_buffers.set_color_format(dest_color_format)) {
2282             DEBUG_PRINT_ERROR("Setting color format failed");
2283             eRet = OMX_ErrorInsufficientResources;
2284         }
2285 
2286         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2287 
2288         if (m_disable_ubwc_mode) {
2289             capture_capability = V4L2_PIX_FMT_NV12;
2290         } else {
2291             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2292         }
2293 
2294         struct v4l2_capability cap;
2295         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2296         if (ret) {
2297             DEBUG_PRINT_ERROR("Failed to query capabilities");
2298             /*TODO: How to handle this case */
2299         } else {
2300             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2301                 " version = %d, capabilities = %x", cap.driver, cap.card,
2302                 cap.bus_info, cap.version, cap.capabilities);
2303         }
2304         ret=0;
2305         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2306         fdesc.index=0;
2307         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2308             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2309                     fdesc.pixelformat, fdesc.flags);
2310             fdesc.index++;
2311         }
2312         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2313         fdesc.index=0;
2314         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2315 
2316             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2317                     fdesc.pixelformat, fdesc.flags);
2318             fdesc.index++;
2319         }
2320         update_resolution(320, 240, 320, 240);
2321         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2322         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2323         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2324         fmt.fmt.pix_mp.pixelformat = output_capability;
2325         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2326         if (ret) {
2327             /*TODO: How to handle this case */
2328             DEBUG_PRINT_ERROR("Failed to set format on output port");
2329             return OMX_ErrorInsufficientResources;
2330         }
2331         DEBUG_PRINT_HIGH("Set Format was successful");
2332         if (codec_ambiguous) {
2333             if (output_capability == V4L2_PIX_FMT_DIVX) {
2334                 struct v4l2_control divx_ctrl;
2335 
2336                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2337                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2338                 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2339                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2340                 } else {
2341                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2342                 }
2343 
2344                 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2345                 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2346                 if (ret) {
2347                     DEBUG_PRINT_ERROR("Failed to set divx version");
2348                 }
2349             } else {
2350                 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2351             }
2352         }
2353 
2354         property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2355         m_conceal_color= atoi(property_value);
2356         DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2357         control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2358         control.value = m_conceal_color;
2359         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2360         if (ret) {
2361             DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2362         }
2363 
2364         //Get the hardware capabilities
2365         memset((void *)&frmsize,0,sizeof(frmsize));
2366         frmsize.index = 0;
2367         frmsize.pixel_format = output_capability;
2368         ret = ioctl(drv_ctx.video_driver_fd,
2369                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2370         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2371             DEBUG_PRINT_ERROR("Failed to get framesizes");
2372             return OMX_ErrorHardware;
2373         }
2374 
2375         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2376             m_decoder_capability.min_width = frmsize.stepwise.min_width;
2377             m_decoder_capability.max_width = frmsize.stepwise.max_width;
2378             m_decoder_capability.min_height = frmsize.stepwise.min_height;
2379             m_decoder_capability.max_height = frmsize.stepwise.max_height;
2380         }
2381 
2382         memset(&fmt, 0x0, sizeof(struct v4l2_format));
2383         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2384         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2385         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2386         fmt.fmt.pix_mp.pixelformat = capture_capability;
2387         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2388         if (ret) {
2389             /*TODO: How to handle this case */
2390             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2391         }
2392         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2393         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2394         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2395 
2396         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2397         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2398         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2399 
2400         DEBUG_PRINT_HIGH("Set Format was successful");
2401         if (secure_mode) {
2402             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2403             control.value = 1;
2404             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2405             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2406             if (ret) {
2407                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2408                 return OMX_ErrorInsufficientResources;
2409             }
2410         }
2411         if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2412             control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2413             control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2414             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2415             if (ret) {
2416                 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2417                 return OMX_ErrorInsufficientResources;
2418             }
2419         }
2420 
2421         if (is_thulium_v1) {
2422             eRet = enable_smoothstreaming();
2423             if (eRet != OMX_ErrorNone) {
2424                DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2425                return eRet;
2426             }
2427         }
2428 
2429         /*Get the Buffer requirements for input and output ports*/
2430         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2431         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2432 
2433         if (secure_mode) {
2434             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2435             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2436         } else {
2437             drv_ctx.op_buf.alignment = SZ_4K;
2438             drv_ctx.ip_buf.alignment = SZ_4K;
2439         }
2440 
2441         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2442         drv_ctx.extradata = 0;
2443         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2444         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2445         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2446         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2447         drv_ctx.idr_only_decoding = 0;
2448 
2449 #ifdef _ANDROID_
2450         property_get("vidc.dec.downscalar_width",property_value,"0");
2451         if (atoi(property_value)) {
2452             m_downscalar_width = atoi(property_value);
2453         }
2454         property_get("vidc.dec.downscalar_height",property_value,"0");
2455         if (atoi(property_value)) {
2456             m_downscalar_height = atoi(property_value);
2457         }
2458 
2459         if (m_downscalar_width < m_decoder_capability.min_width ||
2460             m_downscalar_height < m_decoder_capability.min_height) {
2461             m_downscalar_width = 0;
2462             m_downscalar_height = 0;
2463         }
2464 
2465         DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2466             m_downscalar_width, m_downscalar_height);
2467 #endif
2468         m_state = OMX_StateLoaded;
2469 #ifdef DEFAULT_EXTRADATA
2470         if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",
2471                     OMX_MAX_STRINGNAME_SIZE) &&
2472                 strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",
2473                         OMX_MAX_STRINGNAME_SIZE)) &&
2474                 (eRet == OMX_ErrorNone))
2475                 enable_extradata(DEFAULT_EXTRADATA, true, true);
2476 #endif
2477         eRet = get_buffer_req(&drv_ctx.ip_buf);
2478         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2479         get_buffer_req(&drv_ctx.op_buf);
2480         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2481                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2482                 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2483                     h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2484                     h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2485                     h264_scratch.nFilledLen = 0;
2486                     h264_scratch.nOffset = 0;
2487 
2488                     if (h264_scratch.pBuffer == NULL) {
2489                         DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2490                         return OMX_ErrorInsufficientResources;
2491                     }
2492         }
2493         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2494             drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2495             if (m_frame_parser.mutils == NULL) {
2496                 m_frame_parser.mutils = new H264_Utils();
2497                 if (m_frame_parser.mutils == NULL) {
2498                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2499                     eRet = OMX_ErrorInsufficientResources;
2500                 } else {
2501                     m_frame_parser.mutils->initialize_frame_checking_environment();
2502                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2503                 }
2504             }
2505 
2506             h264_parser = new h264_stream_parser();
2507             if (!h264_parser) {
2508                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2509                 eRet = OMX_ErrorInsufficientResources;
2510             }
2511         }
2512 
2513         if (pipe(fds)) {
2514             DEBUG_PRINT_ERROR("pipe creation failed");
2515             eRet = OMX_ErrorInsufficientResources;
2516         } else {
2517             m_pipe_in = fds[0];
2518             m_pipe_out = fds[1];
2519             msg_thread_created = true;
2520             r = pthread_create(&msg_thread_id,0,message_thread,this);
2521 
2522             if (r < 0) {
2523                 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
2524                 msg_thread_created = false;
2525                 eRet = OMX_ErrorInsufficientResources;
2526             }
2527         }
2528     }
2529 
2530     {
2531         VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2532         init_vendor_extensions(*extStore);
2533         mVendorExtensionStore.dumpExtensions((const char *)role);
2534     }
2535 
2536     if (eRet != OMX_ErrorNone) {
2537         DEBUG_PRINT_ERROR("Component Init Failed");
2538     } else {
2539         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2540                 drv_ctx.video_driver_fd);
2541     }
2542     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2543     return eRet;
2544 }
2545 
2546 /* ======================================================================
2547    FUNCTION
2548    omx_vdec::GetComponentVersion
2549 
2550    DESCRIPTION
2551    Returns the component version.
2552 
2553    PARAMETERS
2554    TBD.
2555 
2556    RETURN VALUE
2557    OMX_ErrorNone.
2558 
2559    ========================================================================== */
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)2560 OMX_ERRORTYPE  omx_vdec::get_component_version
2561 (
2562  OMX_IN OMX_HANDLETYPE hComp,
2563  OMX_OUT OMX_STRING componentName,
2564  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2565  OMX_OUT OMX_VERSIONTYPE* specVersion,
2566  OMX_OUT OMX_UUIDTYPE* componentUUID
2567  )
2568 {
2569     (void) hComp;
2570     (void) componentName;
2571     (void) componentVersion;
2572     (void) componentUUID;
2573     if (m_state == OMX_StateInvalid) {
2574         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2575         return OMX_ErrorInvalidState;
2576     }
2577     /* TBD -- Return the proper version */
2578     if (specVersion) {
2579         specVersion->nVersion = OMX_SPEC_VERSION;
2580     }
2581     return OMX_ErrorNone;
2582 }
2583 /* ======================================================================
2584    FUNCTION
2585    omx_vdec::SendCommand
2586 
2587    DESCRIPTION
2588    Returns zero if all the buffers released..
2589 
2590    PARAMETERS
2591    None.
2592 
2593    RETURN VALUE
2594    true/false
2595 
2596    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2597 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2598         OMX_IN OMX_COMMANDTYPE cmd,
2599         OMX_IN OMX_U32 param1,
2600         OMX_IN OMX_PTR cmdData
2601         )
2602 {
2603     (void) hComp;
2604     (void) cmdData;
2605     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2606     if (m_state == OMX_StateInvalid) {
2607         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2608         return OMX_ErrorInvalidState;
2609     }
2610     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2611             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2612         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2613                 "to invalid port: %u", (unsigned int)param1);
2614         return OMX_ErrorBadPortIndex;
2615     }
2616 
2617     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2618     sem_wait(&m_cmd_lock);
2619     DEBUG_PRINT_LOW("send_command: Command Processed");
2620     return OMX_ErrorNone;
2621 }
2622 
2623 /* ======================================================================
2624    FUNCTION
2625    omx_vdec::SendCommand
2626 
2627    DESCRIPTION
2628    Returns zero if all the buffers released..
2629 
2630    PARAMETERS
2631    None.
2632 
2633    RETURN VALUE
2634    true/false
2635 
2636    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2637 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2638         OMX_IN OMX_COMMANDTYPE cmd,
2639         OMX_IN OMX_U32 param1,
2640         OMX_IN OMX_PTR cmdData
2641         )
2642 {
2643     (void) hComp;
2644     (void) cmdData;
2645     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2646     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2647     int bFlag = 1,sem_posted = 0,ret=0;
2648 
2649     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2650     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2651             m_state, eState);
2652 
2653     if (cmd == OMX_CommandStateSet) {
2654         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2655         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2656         /***************************/
2657         /* Current State is Loaded */
2658         /***************************/
2659         if (m_state == OMX_StateLoaded) {
2660             if (eState == OMX_StateIdle) {
2661                 //if all buffers are allocated or all ports disabled
2662                 if (allocate_done() ||
2663                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2664                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2665                 } else {
2666                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2667                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2668                     // Skip the event notification
2669                     bFlag = 0;
2670                 }
2671             }
2672             /* Requesting transition from Loaded to Loaded */
2673             else if (eState == OMX_StateLoaded) {
2674                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2675                 post_event(OMX_EventError,OMX_ErrorSameState,\
2676                         OMX_COMPONENT_GENERATE_EVENT);
2677                 eRet = OMX_ErrorSameState;
2678             }
2679             /* Requesting transition from Loaded to WaitForResources */
2680             else if (eState == OMX_StateWaitForResources) {
2681                 /* Since error is None , we will post an event
2682                    at the end of this function definition */
2683                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2684             }
2685             /* Requesting transition from Loaded to Executing */
2686             else if (eState == OMX_StateExecuting) {
2687                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2688                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2689                         OMX_COMPONENT_GENERATE_EVENT);
2690                 eRet = OMX_ErrorIncorrectStateTransition;
2691             }
2692             /* Requesting transition from Loaded to Pause */
2693             else if (eState == OMX_StatePause) {
2694                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2695                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2696                         OMX_COMPONENT_GENERATE_EVENT);
2697                 eRet = OMX_ErrorIncorrectStateTransition;
2698             }
2699             /* Requesting transition from Loaded to Invalid */
2700             else if (eState == OMX_StateInvalid) {
2701                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2702                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2703                 eRet = OMX_ErrorInvalidState;
2704             } else {
2705                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2706                         eState);
2707                 eRet = OMX_ErrorBadParameter;
2708             }
2709         }
2710 
2711         /***************************/
2712         /* Current State is IDLE */
2713         /***************************/
2714         else if (m_state == OMX_StateIdle) {
2715             if (eState == OMX_StateLoaded) {
2716                 if (release_done()) {
2717                     /*
2718                        Since error is None , we will post an event at the end
2719                        of this function definition
2720                      */
2721                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2722                 } else {
2723                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2724                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2725                     // Skip the event notification
2726                     bFlag = 0;
2727                 }
2728             }
2729             /* Requesting transition from Idle to Executing */
2730             else if (eState == OMX_StateExecuting) {
2731                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2732                 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2733                 bFlag = 1;
2734                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2735                 m_state=OMX_StateExecuting;
2736                 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2737             }
2738             /* Requesting transition from Idle to Idle */
2739             else if (eState == OMX_StateIdle) {
2740                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2741                 post_event(OMX_EventError,OMX_ErrorSameState,\
2742                         OMX_COMPONENT_GENERATE_EVENT);
2743                 eRet = OMX_ErrorSameState;
2744             }
2745             /* Requesting transition from Idle to WaitForResources */
2746             else if (eState == OMX_StateWaitForResources) {
2747                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2748                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2749                         OMX_COMPONENT_GENERATE_EVENT);
2750                 eRet = OMX_ErrorIncorrectStateTransition;
2751             }
2752             /* Requesting transition from Idle to Pause */
2753             else if (eState == OMX_StatePause) {
2754                 /*To pause the Video core we need to start the driver*/
2755                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2756                       NULL) < */0) {
2757                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2758                     omx_report_error ();
2759                     eRet = OMX_ErrorHardware;
2760                 } else {
2761                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2762                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2763                     bFlag = 0;
2764                 }
2765             }
2766             /* Requesting transition from Idle to Invalid */
2767             else if (eState == OMX_StateInvalid) {
2768                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2769                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2770                 eRet = OMX_ErrorInvalidState;
2771             } else {
2772                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2773                 eRet = OMX_ErrorBadParameter;
2774             }
2775         }
2776 
2777         /******************************/
2778         /* Current State is Executing */
2779         /******************************/
2780         else if (m_state == OMX_StateExecuting) {
2781             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2782             /* Requesting transition from Executing to Idle */
2783             if (eState == OMX_StateIdle) {
2784                 /* Since error is None , we will post an event
2785                    at the end of this function definition
2786                  */
2787                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2788                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2789                 if (!sem_posted) {
2790                     sem_posted = 1;
2791                     sem_post (&m_cmd_lock);
2792                     execute_omx_flush(OMX_ALL);
2793                 }
2794                 bFlag = 0;
2795             }
2796             /* Requesting transition from Executing to Paused */
2797             else if (eState == OMX_StatePause) {
2798                 DEBUG_PRINT_LOW("PAUSE Command Issued");
2799                 m_state = OMX_StatePause;
2800                 bFlag = 1;
2801             }
2802             /* Requesting transition from Executing to Loaded */
2803             else if (eState == OMX_StateLoaded) {
2804                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2805                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2806                         OMX_COMPONENT_GENERATE_EVENT);
2807                 eRet = OMX_ErrorIncorrectStateTransition;
2808             }
2809             /* Requesting transition from Executing to WaitForResources */
2810             else if (eState == OMX_StateWaitForResources) {
2811                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2812                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2813                         OMX_COMPONENT_GENERATE_EVENT);
2814                 eRet = OMX_ErrorIncorrectStateTransition;
2815             }
2816             /* Requesting transition from Executing to Executing */
2817             else if (eState == OMX_StateExecuting) {
2818                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2819                 post_event(OMX_EventError,OMX_ErrorSameState,\
2820                         OMX_COMPONENT_GENERATE_EVENT);
2821                 eRet = OMX_ErrorSameState;
2822             }
2823             /* Requesting transition from Executing to Invalid */
2824             else if (eState == OMX_StateInvalid) {
2825                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2826                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2827                 eRet = OMX_ErrorInvalidState;
2828             } else {
2829                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2830                 eRet = OMX_ErrorBadParameter;
2831             }
2832         }
2833         /***************************/
2834         /* Current State is Pause  */
2835         /***************************/
2836         else if (m_state == OMX_StatePause) {
2837             /* Requesting transition from Pause to Executing */
2838             if (eState == OMX_StateExecuting) {
2839                 DEBUG_PRINT_LOW("Pause --> Executing");
2840                 m_state = OMX_StateExecuting;
2841                 bFlag = 1;
2842             }
2843             /* Requesting transition from Pause to Idle */
2844             else if (eState == OMX_StateIdle) {
2845                 /* Since error is None , we will post an event
2846                    at the end of this function definition */
2847                 DEBUG_PRINT_LOW("Pause --> Idle");
2848                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2849                 if (!sem_posted) {
2850                     sem_posted = 1;
2851                     sem_post (&m_cmd_lock);
2852                     execute_omx_flush(OMX_ALL);
2853                 }
2854                 bFlag = 0;
2855             }
2856             /* Requesting transition from Pause to loaded */
2857             else if (eState == OMX_StateLoaded) {
2858                 DEBUG_PRINT_ERROR("Pause --> loaded");
2859                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2860                         OMX_COMPONENT_GENERATE_EVENT);
2861                 eRet = OMX_ErrorIncorrectStateTransition;
2862             }
2863             /* Requesting transition from Pause to WaitForResources */
2864             else if (eState == OMX_StateWaitForResources) {
2865                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2866                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2867                         OMX_COMPONENT_GENERATE_EVENT);
2868                 eRet = OMX_ErrorIncorrectStateTransition;
2869             }
2870             /* Requesting transition from Pause to Pause */
2871             else if (eState == OMX_StatePause) {
2872                 DEBUG_PRINT_ERROR("Pause --> Pause");
2873                 post_event(OMX_EventError,OMX_ErrorSameState,\
2874                         OMX_COMPONENT_GENERATE_EVENT);
2875                 eRet = OMX_ErrorSameState;
2876             }
2877             /* Requesting transition from Pause to Invalid */
2878             else if (eState == OMX_StateInvalid) {
2879                 DEBUG_PRINT_ERROR("Pause --> Invalid");
2880                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2881                 eRet = OMX_ErrorInvalidState;
2882             } else {
2883                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2884                 eRet = OMX_ErrorBadParameter;
2885             }
2886         }
2887         /***************************/
2888         /* Current State is WaitForResources  */
2889         /***************************/
2890         else if (m_state == OMX_StateWaitForResources) {
2891             /* Requesting transition from WaitForResources to Loaded */
2892             if (eState == OMX_StateLoaded) {
2893                 /* Since error is None , we will post an event
2894                    at the end of this function definition */
2895                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2896             }
2897             /* Requesting transition from WaitForResources to WaitForResources */
2898             else if (eState == OMX_StateWaitForResources) {
2899                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2900                 post_event(OMX_EventError,OMX_ErrorSameState,
2901                         OMX_COMPONENT_GENERATE_EVENT);
2902                 eRet = OMX_ErrorSameState;
2903             }
2904             /* Requesting transition from WaitForResources to Executing */
2905             else if (eState == OMX_StateExecuting) {
2906                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2907                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2908                         OMX_COMPONENT_GENERATE_EVENT);
2909                 eRet = OMX_ErrorIncorrectStateTransition;
2910             }
2911             /* Requesting transition from WaitForResources to Pause */
2912             else if (eState == OMX_StatePause) {
2913                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2914                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2915                         OMX_COMPONENT_GENERATE_EVENT);
2916                 eRet = OMX_ErrorIncorrectStateTransition;
2917             }
2918             /* Requesting transition from WaitForResources to Invalid */
2919             else if (eState == OMX_StateInvalid) {
2920                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2921                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2922                 eRet = OMX_ErrorInvalidState;
2923             }
2924             /* Requesting transition from WaitForResources to Loaded -
2925                is NOT tested by Khronos TS */
2926 
2927         } else {
2928             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2929             eRet = OMX_ErrorBadParameter;
2930         }
2931     }
2932     /********************************/
2933     /* Current State is Invalid */
2934     /*******************************/
2935     else if (m_state == OMX_StateInvalid) {
2936         /* State Transition from Invalid to any state */
2937         if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
2938             eState == OMX_StateIdle || eState == OMX_StateExecuting ||
2939             eState == OMX_StatePause || eState == OMX_StateInvalid) {
2940             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2941             post_event(OMX_EventError,OMX_ErrorInvalidState,\
2942                     OMX_COMPONENT_GENERATE_EVENT);
2943             eRet = OMX_ErrorInvalidState;
2944         }
2945     } else if (cmd == OMX_CommandFlush) {
2946         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2947                 "with param1: %u", (unsigned int)param1);
2948 #ifdef _MSM8974_
2949         send_codec_config();
2950 #endif
2951         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2952                     param1 == OMX_ALL)) {
2953             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2954                struct timespec ts;
2955 
2956                clock_gettime(CLOCK_REALTIME, &ts);
2957                ts.tv_sec += 2;
2958                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2959                        m_queued_codec_config_count);
2960                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2961                if (sem_timedwait(&m_safe_flush, &ts)) {
2962                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2963                }
2964                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2965             }
2966         }
2967 
2968         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2969             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2970         }
2971         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2972             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2973         }
2974         if (!sem_posted) {
2975             sem_posted = 1;
2976             DEBUG_PRINT_LOW("Set the Semaphore");
2977             sem_post (&m_cmd_lock);
2978             execute_omx_flush(param1);
2979         }
2980         bFlag = 0;
2981     } else if ( cmd == OMX_CommandPortEnable) {
2982         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2983                 "with param1: %u", (unsigned int)param1);
2984         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2985             m_inp_bEnabled = OMX_TRUE;
2986 
2987             if ( (m_state == OMX_StateLoaded &&
2988                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2989                     || allocate_input_done()) {
2990                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2991                         OMX_COMPONENT_GENERATE_EVENT);
2992             } else {
2993                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2994                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2995                 // Skip the event notification
2996                 bFlag = 0;
2997             }
2998         }
2999         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3000             DEBUG_PRINT_LOW("Enable output Port command recieved");
3001             m_out_bEnabled = OMX_TRUE;
3002 
3003             if ( (m_state == OMX_StateLoaded &&
3004                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3005                     || (allocate_output_done())) {
3006                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3007                         OMX_COMPONENT_GENERATE_EVENT);
3008 
3009             } else {
3010                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3011                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3012                 // Skip the event notification
3013                 bFlag = 0;
3014                 /* enable/disable downscaling if required */
3015                 ret = decide_downscalar();
3016                 if (ret) {
3017                     DEBUG_PRINT_LOW("decide_downscalar failed\n");
3018                 }
3019             }
3020         }
3021     } else if (cmd == OMX_CommandPortDisable) {
3022         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3023                 "with param1: %u", (unsigned int)param1);
3024         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3025             codec_config_flag = false;
3026             m_inp_bEnabled = OMX_FALSE;
3027             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3028                     && release_input_done()) {
3029                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3030                         OMX_COMPONENT_GENERATE_EVENT);
3031             } else {
3032                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3033                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3034                     if (!sem_posted) {
3035                         sem_posted = 1;
3036                         sem_post (&m_cmd_lock);
3037                     }
3038                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3039                 }
3040 
3041                 // Skip the event notification
3042                 bFlag = 0;
3043             }
3044         }
3045         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3046             m_out_bEnabled = OMX_FALSE;
3047             DEBUG_PRINT_LOW("Disable output Port command recieved");
3048             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3049                     && release_output_done()) {
3050                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3051                         OMX_COMPONENT_GENERATE_EVENT);
3052             } else {
3053                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3054                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3055                     if (!sem_posted) {
3056                         sem_posted = 1;
3057                         sem_post (&m_cmd_lock);
3058                     }
3059                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3060                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3061                 }
3062                 // Skip the event notification
3063                 bFlag = 0;
3064 
3065             }
3066         }
3067     } else {
3068         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3069         eRet = OMX_ErrorNotImplemented;
3070     }
3071     if (eRet == OMX_ErrorNone && bFlag) {
3072         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3073     }
3074     if (!sem_posted) {
3075         sem_post(&m_cmd_lock);
3076     }
3077 
3078     return eRet;
3079 }
3080 
3081 /* ======================================================================
3082    FUNCTION
3083    omx_vdec::ExecuteOmxFlush
3084 
3085    DESCRIPTION
3086    Executes the OMX flush.
3087 
3088    PARAMETERS
3089    flushtype - input flush(1)/output flush(0)/ both.
3090 
3091    RETURN VALUE
3092    true/false
3093 
3094    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3095 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3096 {
3097     bool bRet = false;
3098     struct v4l2_plane plane;
3099     struct v4l2_buffer v4l2_buf;
3100     struct v4l2_decoder_cmd dec;
3101     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3102     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3103     dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3104 
3105     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3106 
3107     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3108         output_flush_progress = true;
3109         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3110     } else {
3111         /* XXX: The driver/hardware does not support flushing of individual ports
3112          * in all states. So we pretty much need to flush both ports internally,
3113          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3114          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3115          * we automatically omit sending the FLUSH done for the "opposite" port. */
3116         input_flush_progress = true;
3117         output_flush_progress = true;
3118         dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3119         request_perf_level(VIDC_TURBO);
3120     }
3121 
3122     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3123         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3124         bRet = false;
3125     }
3126 
3127     return bRet;
3128 }
3129 /*=========================================================================
3130 FUNCTION : execute_output_flush
3131 
3132 DESCRIPTION
3133 Executes the OMX flush at OUTPUT PORT.
3134 
3135 PARAMETERS
3136 None.
3137 
3138 RETURN VALUE
3139 true/false
3140 ==========================================================================*/
execute_output_flush()3141 bool omx_vdec::execute_output_flush()
3142 {
3143     unsigned long p1 = 0; // Parameter - 1
3144     unsigned long p2 = 0; // Parameter - 2
3145     unsigned long ident = 0;
3146     bool bRet = true;
3147 
3148     /*Generate FBD for all Buffers in the FTBq*/
3149     pthread_mutex_lock(&m_lock);
3150     DEBUG_PRINT_LOW("Initiate Output Flush");
3151 
3152     //reset last render TS
3153     if(m_last_rendered_TS > 0) {
3154         m_last_rendered_TS = 0;
3155     }
3156 
3157     while (m_ftb_q.m_size) {
3158         DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3159                 m_ftb_q.m_size,pending_output_buffers);
3160         m_ftb_q.pop_entry(&p1,&p2,&ident);
3161         DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3162         if (ident == m_fill_output_msg ) {
3163             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3164         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3165             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3166         }
3167     }
3168     pthread_mutex_unlock(&m_lock);
3169     output_flush_progress = false;
3170 
3171     if (arbitrary_bytes) {
3172         prev_ts = LLONG_MAX;
3173         rst_prev_ts = true;
3174     }
3175     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3176     return bRet;
3177 }
3178 /*=========================================================================
3179 FUNCTION : execute_input_flush
3180 
3181 DESCRIPTION
3182 Executes the OMX flush at INPUT PORT.
3183 
3184 PARAMETERS
3185 None.
3186 
3187 RETURN VALUE
3188 true/false
3189 ==========================================================================*/
execute_input_flush()3190 bool omx_vdec::execute_input_flush()
3191 {
3192     unsigned       i =0;
3193     unsigned long p1 = 0; // Parameter - 1
3194     unsigned long p2 = 0; // Parameter - 2
3195     unsigned long ident = 0;
3196     bool bRet = true;
3197 
3198     /*Generate EBD for all Buffers in the ETBq*/
3199     DEBUG_PRINT_LOW("Initiate Input Flush");
3200 
3201     pthread_mutex_lock(&m_lock);
3202     DEBUG_PRINT_LOW("Check if the Queue is empty");
3203     while (m_etb_q.m_size) {
3204         m_etb_q.pop_entry(&p1,&p2,&ident);
3205 
3206         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3207             DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3208             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3209         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3210             pending_input_buffers++;
3211             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3212                     (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3213             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3214         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3215             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3216                     (OMX_BUFFERHEADERTYPE *)p1);
3217             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3218         }
3219     }
3220     time_stamp_dts.flush_timestamp();
3221     /*Check if Heap Buffers are to be flushed*/
3222     if (arbitrary_bytes && !(codec_config_flag)) {
3223         DEBUG_PRINT_LOW("Reset all the variables before flusing");
3224         h264_scratch.nFilledLen = 0;
3225         nal_count = 0;
3226         look_ahead_nal = false;
3227         frame_count = 0;
3228         h264_last_au_ts = LLONG_MAX;
3229         h264_last_au_flags = 0;
3230         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3231         m_demux_entries = 0;
3232         DEBUG_PRINT_LOW("Initialize parser");
3233         if (m_frame_parser.mutils) {
3234             m_frame_parser.mutils->initialize_frame_checking_environment();
3235         }
3236 
3237         while (m_input_pending_q.m_size) {
3238             m_input_pending_q.pop_entry(&p1,&p2,&ident);
3239             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3240         }
3241 
3242         if (psource_frame) {
3243             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3244             psource_frame = NULL;
3245         }
3246 
3247         if (pdest_frame) {
3248             pdest_frame->nFilledLen = 0;
3249             m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3250                     (unsigned int)NULL);
3251             pdest_frame = NULL;
3252         }
3253         m_frame_parser.flush();
3254     } else if (codec_config_flag) {
3255         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3256                 "is not sent to the driver yet");
3257     }
3258     pthread_mutex_unlock(&m_lock);
3259     input_flush_progress = false;
3260     if (!arbitrary_bytes) {
3261         prev_ts = LLONG_MAX;
3262         rst_prev_ts = true;
3263     }
3264 #ifdef _ANDROID_
3265     if (m_debug_timestamp) {
3266         m_timestamp_list.reset_ts_list();
3267     }
3268 #endif
3269     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3270     return bRet;
3271 }
3272 
3273 /*=========================================================================
3274 FUNCTION : notify_flush_done
3275 DESCRIPTION
3276 Notifies flush done to the OMX Client.
3277 PARAMETERS
3278 ctxt -- Context information related to the self..
3279 RETURN VALUE
3280 NONE
3281 ==========================================================================*/
notify_flush_done(void * ctxt)3282 void omx_vdec::notify_flush_done(void *ctxt) {
3283     omx_vdec *pThis = (omx_vdec *) ctxt;
3284     if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3285         if (BITMASK_PRESENT(&pThis->m_flags,
3286                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3287             DEBUG_PRINT_LOW("Notify Output Flush done");
3288             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3289             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3290                 OMX_EventCmdComplete,OMX_CommandFlush,
3291                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3292         }
3293 
3294         if (BITMASK_PRESENT(&pThis->m_flags,
3295                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3296             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3297             DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3298             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3299                     OMX_EventCmdComplete,OMX_CommandFlush,
3300                     OMX_CORE_INPUT_PORT_INDEX,NULL );
3301         }
3302     }
3303 }
3304 
3305 /* ======================================================================
3306    FUNCTION
3307    omx_vdec::SendCommandEvent
3308 
3309    DESCRIPTION
3310    Send the event to decoder pipe.  This is needed to generate the callbacks
3311    in decoder thread context.
3312 
3313    PARAMETERS
3314    None.
3315 
3316    RETURN VALUE
3317    true/false
3318 
3319    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3320 bool omx_vdec::post_event(unsigned long p1,
3321         unsigned long p2,
3322         unsigned long id)
3323 {
3324     bool bRet = false;
3325 
3326     /* Just drop messages typically generated by hardware (w/o client request),
3327      * if we've reported an error to client. */
3328     if (m_error_propogated) {
3329         switch (id) {
3330             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3331             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3332                 DEBUG_PRINT_ERROR("Dropping message %lx "
3333                         "since client expected to be in error state", id);
3334                 return false;
3335             default:
3336                 /* whatever */
3337                 break;
3338         }
3339     }
3340 
3341     pthread_mutex_lock(&m_lock);
3342 
3343     if (id == m_fill_output_msg ||
3344             id == OMX_COMPONENT_GENERATE_FBD ||
3345             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3346             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3347         m_ftb_q.insert_entry(p1,p2,id);
3348     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3349             id == OMX_COMPONENT_GENERATE_EBD ||
3350             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3351             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3352         m_etb_q.insert_entry(p1,p2,id);
3353     } else {
3354         m_cmd_q.insert_entry(p1,p2,id);
3355     }
3356 
3357     bRet = true;
3358     DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3359     post_message(this, id);
3360 
3361     pthread_mutex_unlock(&m_lock);
3362 
3363     return bRet;
3364 }
3365 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3366 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3367 {
3368     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3369     if (!profileLevelType)
3370         return OMX_ErrorBadParameter;
3371 
3372     if (profileLevelType->nPortIndex == 0) {
3373         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3374             if (profileLevelType->nProfileIndex == 0) {
3375                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3376                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3377 
3378             } else if (profileLevelType->nProfileIndex == 1) {
3379                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3380                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3381             } else if (profileLevelType->nProfileIndex == 2) {
3382                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3383                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel51;
3384             } else {
3385                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3386                         (unsigned int)profileLevelType->nProfileIndex);
3387                 eRet = OMX_ErrorNoMore;
3388             }
3389         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3390             if (profileLevelType->nProfileIndex == 0) {
3391                 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3392                 profileLevelType->eLevel   = QOMX_VIDEO_MVCLevel51;
3393             } else {
3394                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3395                                 (unsigned int)profileLevelType->nProfileIndex);
3396                 eRet = OMX_ErrorNoMore;
3397             }
3398         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3399             if (profileLevelType->nProfileIndex == 0) {
3400                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3401                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3402             } else if (profileLevelType->nProfileIndex == 1) {
3403                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3404                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3405             } else {
3406                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3407                         (unsigned int)profileLevelType->nProfileIndex);
3408                 eRet = OMX_ErrorNoMore;
3409             }
3410         } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3411             if (profileLevelType->nProfileIndex == 0) {
3412                 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3413                 profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
3414             } else {
3415                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3416                                 (unsigned int)profileLevelType->nProfileIndex);
3417                 eRet = OMX_ErrorNoMore;
3418             }
3419         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3420             if (profileLevelType->nProfileIndex == 0) {
3421                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3422                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3423             } else if (profileLevelType->nProfileIndex == 1) {
3424                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3425                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3426             } else {
3427                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3428                                 (unsigned int)profileLevelType->nProfileIndex);
3429                 eRet = OMX_ErrorNoMore;
3430             }
3431         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3432                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3433             eRet = OMX_ErrorNoMore;
3434         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3435             if (profileLevelType->nProfileIndex == 0) {
3436                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3437                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3438             } else if (profileLevelType->nProfileIndex == 1) {
3439                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3440                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3441             } else {
3442                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3443                                 (unsigned int)profileLevelType->nProfileIndex);
3444                 eRet = OMX_ErrorNoMore;
3445             }
3446         } else {
3447             DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3448             eRet = OMX_ErrorNoMore;
3449         }
3450     } else {
3451         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3452                           (unsigned int)profileLevelType->nPortIndex);
3453         eRet = OMX_ErrorBadPortIndex;
3454     }
3455     return eRet;
3456 }
3457 
3458 /* ======================================================================
3459    FUNCTION
3460    omx_vdec::GetParameter
3461 
3462    DESCRIPTION
3463    OMX Get Parameter method implementation
3464 
3465    PARAMETERS
3466    <TBD>.
3467 
3468    RETURN VALUE
3469    Error None if successful.
3470 
3471    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3472 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3473         OMX_IN OMX_INDEXTYPE paramIndex,
3474         OMX_INOUT OMX_PTR     paramData)
3475 {
3476     (void) hComp;
3477     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3478 
3479     DEBUG_PRINT_LOW("get_parameter:");
3480     if (m_state == OMX_StateInvalid) {
3481         DEBUG_PRINT_ERROR("Get Param in Invalid State");
3482         return OMX_ErrorInvalidState;
3483     }
3484     if (paramData == NULL) {
3485         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3486         return OMX_ErrorBadParameter;
3487     }
3488     switch ((unsigned long)paramIndex) {
3489         case OMX_IndexParamPortDefinition: {
3490                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3491                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3492                                    (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3493                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3494                                decide_dpb_buffer_mode(is_down_scalar_enabled);
3495                                eRet = update_portdef(portDefn);
3496                                if (eRet == OMX_ErrorNone)
3497                                    m_port_def = *portDefn;
3498                                break;
3499                            }
3500         case OMX_IndexParamVideoInit: {
3501                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3502                               OMX_PORT_PARAM_TYPE *portParamType =
3503                                   (OMX_PORT_PARAM_TYPE *) paramData;
3504                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3505 
3506                               portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3507                               portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3508                               portParamType->nPorts           = 2;
3509                               portParamType->nStartPortNumber = 0;
3510                               break;
3511                           }
3512         case OMX_IndexParamVideoPortFormat: {
3513                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3514                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3515                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3516                                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3517 
3518                                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3519                                 portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3520 
3521                                 if (0 == portFmt->nPortIndex) {
3522                                     if (0 == portFmt->nIndex) {
3523                                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3524                                         portFmt->eCompressionFormat = eCompressionFormat;
3525                                     } else {
3526                                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3527                                                 " NoMore compression formats");
3528                                         eRet =  OMX_ErrorNoMore;
3529                                     }
3530                                 } else if (1 == portFmt->nPortIndex) {
3531                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3532 
3533                                     // Distinguish non-surface mode from normal playback use-case based on
3534                                     // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3535                                     // For non-android, use the default list
3536                                     // Also use default format-list if FLEXIBLE YUV is supported,
3537                                     // as the client negotiates the standard color-format if it needs to
3538                                     bool useNonSurfaceMode = false;
3539 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3540                                     useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3541 #endif
3542                                     if (is_thulium_v1) {
3543                                         portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3544                                     } else {
3545                                         portFmt->eColorFormat = useNonSurfaceMode ?
3546                                             getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3547                                             getPreferredColorFormatDefaultMode(portFmt->nIndex);
3548                                     }
3549 
3550                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3551                                         eRet = OMX_ErrorNoMore;
3552                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3553                                                 " NoMore Color formats");
3554                                     }
3555                                     DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3556                                 } else {
3557                                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3558                                             (int)portFmt->nPortIndex);
3559                                     eRet = OMX_ErrorBadPortIndex;
3560                                 }
3561                                 break;
3562                             }
3563                             /*Component should support this port definition*/
3564         case OMX_IndexParamAudioInit: {
3565                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3566                               OMX_PORT_PARAM_TYPE *audioPortParamType =
3567                                   (OMX_PORT_PARAM_TYPE *) paramData;
3568                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3569                               audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3570                               audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3571                               audioPortParamType->nPorts           = 0;
3572                               audioPortParamType->nStartPortNumber = 0;
3573                               break;
3574                           }
3575                           /*Component should support this port definition*/
3576         case OMX_IndexParamImageInit: {
3577                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3578                               OMX_PORT_PARAM_TYPE *imagePortParamType =
3579                                   (OMX_PORT_PARAM_TYPE *) paramData;
3580                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3581                               imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3582                               imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3583                               imagePortParamType->nPorts           = 0;
3584                               imagePortParamType->nStartPortNumber = 0;
3585                               break;
3586 
3587                           }
3588                           /*Component should support this port definition*/
3589         case OMX_IndexParamOtherInit: {
3590                               DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3591                                       paramIndex);
3592                               eRet =OMX_ErrorUnsupportedIndex;
3593                               break;
3594                           }
3595         case OMX_IndexParamStandardComponentRole: {
3596                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3597                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
3598                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3599                                   comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3600                                   comp_role->nSize = sizeof(*comp_role);
3601 
3602                                   DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3603                                           paramIndex);
3604                                   strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3605                                           OMX_MAX_STRINGNAME_SIZE);
3606                                   break;
3607                               }
3608                               /* Added for parameter test */
3609         case OMX_IndexParamPriorityMgmt: {
3610                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3611                              OMX_PRIORITYMGMTTYPE *priorityMgmType =
3612                                  (OMX_PRIORITYMGMTTYPE *) paramData;
3613                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3614                              priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3615                              priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3616 
3617                              break;
3618                          }
3619                          /* Added for parameter test */
3620         case OMX_IndexParamCompBufferSupplier: {
3621                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3622                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3623                                        (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3624                                    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3625 
3626                                    bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3627                                    bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3628                                    if (0 == bufferSupplierType->nPortIndex)
3629                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3630                                    else if (1 == bufferSupplierType->nPortIndex)
3631                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3632                                    else
3633                                        eRet = OMX_ErrorBadPortIndex;
3634 
3635 
3636                                    break;
3637                                }
3638         case OMX_IndexParamVideoAvc: {
3639                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3640                                      paramIndex);
3641                              break;
3642                          }
3643         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3644                              DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3645                                      paramIndex);
3646                              break;
3647                          }
3648         case OMX_IndexParamVideoH263: {
3649                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3650                                       paramIndex);
3651                               break;
3652                           }
3653         case OMX_IndexParamVideoMpeg4: {
3654                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3655                                        paramIndex);
3656                                break;
3657                            }
3658         case OMX_IndexParamVideoMpeg2: {
3659                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3660                                        paramIndex);
3661                                break;
3662                            }
3663         case OMX_IndexParamVideoProfileLevelQuerySupported: {
3664                                         VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3665                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3666                                         OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3667                                             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3668                                         eRet = get_supported_profile_level(profileLevelType);
3669                                         break;
3670                                     }
3671 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3672         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3673                                         VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3674                                         DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3675                                         GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3676                                         if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3677 
3678                                             if (secure_mode && !secure_scaling_to_non_secure_opb) {
3679                                                 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3680                                                         GRALLOC_USAGE_PRIVATE_UNCACHED);
3681                                             } else {
3682                                                 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3683                                             }
3684                                         } else {
3685                                             DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3686                                             eRet = OMX_ErrorBadParameter;
3687                                         }
3688                                     }
3689                                     break;
3690 #endif
3691 
3692 #ifdef FLEXYUV_SUPPORTED
3693         case OMX_QcomIndexFlexibleYUVDescription: {
3694                 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3695                 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3696                 eRet = describeColorFormat(paramData);
3697                 break;
3698             }
3699 #endif
3700         case OMX_IndexParamVideoProfileLevelCurrent: {
3701              VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3702              OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3703              struct v4l2_control profile_control, level_control;
3704 
3705              switch (drv_ctx.decoder_format) {
3706                  case VDEC_CODECTYPE_H264:
3707                      profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3708                      level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3709                      break;
3710                  default:
3711                      DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3712                      eRet = OMX_ErrorNotImplemented;
3713                      break;
3714              }
3715 
3716              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3717                 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3718                     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3719                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3720                         pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3721                         break;
3722                     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3723                         pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3724                         break;
3725                     case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3726                         pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3727                         break;
3728                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3729                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3730                         break;
3731                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3732                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3733                         break;
3734                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3735                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3736                         break;
3737                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3738                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3739                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3740                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3741                     case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3742                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3743                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3744                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3745                     case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3746                     case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3747                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3748                         eRet = OMX_ErrorUnsupportedIndex;
3749                         break;
3750                 }
3751              } else {
3752                  eRet = OMX_ErrorUnsupportedIndex;
3753              }
3754 
3755 
3756              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3757                 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3758                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3759                         pParam->eLevel = OMX_VIDEO_AVCLevel1;
3760                         break;
3761                     case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3762                         pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3763                         break;
3764                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3765                         pParam->eLevel = OMX_VIDEO_AVCLevel11;
3766                         break;
3767                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3768                         pParam->eLevel = OMX_VIDEO_AVCLevel12;
3769                         break;
3770                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3771                         pParam->eLevel = OMX_VIDEO_AVCLevel13;
3772                         break;
3773                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3774                         pParam->eLevel = OMX_VIDEO_AVCLevel2;
3775                         break;
3776                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3777                         pParam->eLevel = OMX_VIDEO_AVCLevel21;
3778                         break;
3779                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3780                         pParam->eLevel = OMX_VIDEO_AVCLevel22;
3781                         break;
3782                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
3783                         pParam->eLevel = OMX_VIDEO_AVCLevel3;
3784                         break;
3785                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
3786                         pParam->eLevel = OMX_VIDEO_AVCLevel31;
3787                         break;
3788                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
3789                         pParam->eLevel = OMX_VIDEO_AVCLevel32;
3790                         break;
3791                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
3792                         pParam->eLevel = OMX_VIDEO_AVCLevel4;
3793                         break;
3794                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
3795                         pParam->eLevel = OMX_VIDEO_AVCLevel41;
3796                         break;
3797                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
3798                         pParam->eLevel = OMX_VIDEO_AVCLevel42;
3799                         break;
3800                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
3801                         pParam->eLevel = OMX_VIDEO_AVCLevel5;
3802                         break;
3803                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
3804                         pParam->eLevel = OMX_VIDEO_AVCLevel51;
3805                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
3806                         pParam->eLevel = OMX_VIDEO_AVCLevel52;
3807                         break;
3808                 }
3809              } else {
3810                  eRet = OMX_ErrorUnsupportedIndex;
3811              }
3812 
3813              break;
3814 
3815          }
3816         default: {
3817                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3818                  eRet =OMX_ErrorUnsupportedIndex;
3819              }
3820 
3821     }
3822 
3823     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3824             drv_ctx.video_resolution.frame_width,
3825             drv_ctx.video_resolution.frame_height,
3826             drv_ctx.video_resolution.stride,
3827             drv_ctx.video_resolution.scan_lines);
3828 
3829     return eRet;
3830 }
3831 
3832 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3833 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3834 {
3835     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3836     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3837     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3838 
3839     if ((params == NULL) ||
3840             (params->nativeBuffer == NULL) ||
3841             (params->nativeBuffer->handle == NULL) ||
3842             !m_enable_android_native_buffers)
3843         return OMX_ErrorBadParameter;
3844     m_use_android_native_buffers = OMX_TRUE;
3845     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3846     private_handle_t *handle = (private_handle_t *)nBuf->handle;
3847     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3848         OMX_U8 *buffer = NULL;
3849         if (!secure_mode) {
3850             buffer = (OMX_U8*)mmap(0, handle->size,
3851                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3852             if (buffer == MAP_FAILED) {
3853                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3854                 return OMX_ErrorInsufficientResources;
3855             }
3856         }
3857         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3858     } else {
3859         eRet = OMX_ErrorBadParameter;
3860     }
3861     return eRet;
3862 }
3863 #endif
3864 
enable_smoothstreaming()3865 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3866     struct v4l2_control control;
3867     struct v4l2_format fmt;
3868     control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3869     control.value = 1;
3870     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3871     if (rc < 0) {
3872         DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3873         return OMX_ErrorHardware;
3874     }
3875     m_smoothstreaming_mode = true;
3876     return OMX_ErrorNone;
3877 }
3878 
3879 /* ======================================================================
3880    FUNCTION
3881    omx_vdec::Setparameter
3882 
3883    DESCRIPTION
3884    OMX Set Parameter method implementation.
3885 
3886    PARAMETERS
3887    <TBD>.
3888 
3889    RETURN VALUE
3890    OMX Error None if successful.
3891 
3892    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3893 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3894         OMX_IN OMX_INDEXTYPE paramIndex,
3895         OMX_IN OMX_PTR        paramData)
3896 {
3897     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3898     int ret=0;
3899     struct v4l2_format fmt;
3900 #ifdef _ANDROID_
3901     char property_value[PROPERTY_VALUE_MAX] = {0};
3902 #endif
3903     if (m_state == OMX_StateInvalid) {
3904         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3905         return OMX_ErrorInvalidState;
3906     }
3907     if (paramData == NULL) {
3908         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
3909         return OMX_ErrorBadParameter;
3910     }
3911     if ((m_state != OMX_StateLoaded) &&
3912             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
3913             (m_out_bEnabled == OMX_TRUE) &&
3914             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
3915             (m_inp_bEnabled == OMX_TRUE)) {
3916         DEBUG_PRINT_ERROR("Set Param in Invalid State");
3917         return OMX_ErrorIncorrectStateOperation;
3918     }
3919     switch ((unsigned long)paramIndex) {
3920         case OMX_IndexParamPortDefinition: {
3921                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3922                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3923                                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3924                                //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
3925                                //been called.
3926                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
3927                                        (int)portDefn->format.video.nFrameHeight,
3928                                        (int)portDefn->format.video.nFrameWidth);
3929 
3930                                if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3931                                    DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
3932                                                           portDefn->nBufferCountActual);
3933                                    eRet = OMX_ErrorBadParameter;
3934                                    break;
3935                                }
3936                                if (OMX_DirOutput == portDefn->eDir) {
3937                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
3938                                    bool port_format_changed = false;
3939                                    m_display_id = portDefn->format.video.pNativeWindow;
3940                                    unsigned int buffer_size;
3941                                    /* update output port resolution with client supplied dimensions
3942                                       in case scaling is enabled, else it follows input resolution set
3943                                    */
3944                                    decide_dpb_buffer_mode(is_down_scalar_enabled);
3945                                    if (is_down_scalar_enabled) {
3946                                        DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
3947                                                (unsigned int)portDefn->format.video.nFrameWidth,
3948                                                (unsigned int)portDefn->format.video.nFrameHeight);
3949                                        if (portDefn->format.video.nFrameHeight != 0x0 &&
3950                                                portDefn->format.video.nFrameWidth != 0x0) {
3951                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3952                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3953                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3954                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
3955                                            if (ret) {
3956                                                DEBUG_PRINT_ERROR("Get Resolution failed");
3957                                                eRet = OMX_ErrorHardware;
3958                                                break;
3959                                            }
3960                                            if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
3961                                                (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
3962                                                    port_format_changed = true;
3963                                            }
3964                                            update_resolution(portDefn->format.video.nFrameWidth,
3965                                                    portDefn->format.video.nFrameHeight,
3966                                                    portDefn->format.video.nFrameWidth,
3967                                                    portDefn->format.video.nFrameHeight);
3968 
3969                                            /* set crop info */
3970                                            rectangle.nLeft = 0;
3971                                            rectangle.nTop = 0;
3972                                            rectangle.nWidth = portDefn->format.video.nFrameWidth;
3973                                            rectangle.nHeight = portDefn->format.video.nFrameHeight;
3974 
3975                                            eRet = is_video_session_supported();
3976                                            if (eRet)
3977                                                break;
3978                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
3979                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3980                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3981                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3982                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
3983                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
3984                                                fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
3985                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3986                                            if (ret) {
3987                                                DEBUG_PRINT_ERROR("Set Resolution failed");
3988                                                eRet = OMX_ErrorUnsupportedSetting;
3989                                            } else
3990                                                eRet = get_buffer_req(&drv_ctx.op_buf);
3991                                        }
3992 
3993                                        if (eRet) {
3994                                            break;
3995                                        }
3996 
3997                                        if (secure_mode) {
3998                                            struct v4l2_control control;
3999                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
4000                                            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4001                                                DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
4002                                                eRet = OMX_ErrorHardware;
4003                                            } else {
4004                                                /* This is a workaround for a bug in fw which uses stride
4005                                                 * and slice instead of width and height to check against
4006                                                 * the threshold.
4007                                                 */
4008                                                OMX_U32 stride, slice;
4009                                                if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
4010                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
4011                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
4012                                                } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
4013                                                    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
4014                                                    slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
4015                                                } else {
4016                                                    stride = portDefn->format.video.nFrameWidth;
4017                                                    slice = portDefn->format.video.nFrameHeight;
4018                                                }
4019 
4020                                                DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
4021                                                DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
4022 
4023                                                if (stride * slice <= (OMX_U32)control.value) {
4024                                                    secure_scaling_to_non_secure_opb = true;
4025                                                    DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
4026                                                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
4027                                                    control.value = 1;
4028                                                    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4029                                                        DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4030                                                        eRet = OMX_ErrorUnsupportedSetting;
4031                                                    }
4032                                                }
4033                                            }
4034                                        }
4035                                    }
4036 
4037                                    if (eRet) {
4038                                        break;
4039                                    }
4040 
4041                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4042                                        DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4043                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4044                                        eRet = OMX_ErrorBadParameter;
4045                                    } else if (!client_buffers.get_buffer_req(buffer_size)) {
4046                                        DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4047                                        eRet = OMX_ErrorBadParameter;
4048                                    } else if (!port_format_changed) {
4049 
4050                                        // Buffer count can change only when port is unallocated
4051                                        if (m_out_mem_ptr &&
4052                                                 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4053                                                 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4054 
4055                                            DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4056                                            eRet = OMX_ErrorInvalidState;
4057                                            break;
4058                                        }
4059 
4060                                        if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
4061                                                portDefn->nBufferSize >=  drv_ctx.op_buf.buffer_size ) {
4062                                            drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
4063                                            drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
4064                                            drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount;
4065                                            drv_ctx.extradata_info.size = drv_ctx.extradata_info.count *
4066                                                drv_ctx.extradata_info.buffer_size;
4067                                            eRet = set_buffer_req(&drv_ctx.op_buf);
4068                                            if (eRet == OMX_ErrorNone)
4069                                                m_port_def = *portDefn;
4070                                        } else {
4071                                            DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4072                                                    drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size,
4073                                                    (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4074                                            eRet = OMX_ErrorBadParameter;
4075                                        }
4076                                    }
4077                                } else if (OMX_DirInput == portDefn->eDir) {
4078                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4079                                    bool port_format_changed = false;
4080                                    if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4081                                            (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4082                                        // Frame rate only should be set if this is a "known value" or to
4083                                        // activate ts prediction logic (arbitrary mode only) sending input
4084                                        // timestamps with max value (LLONG_MAX).
4085                                        DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4086                                                (unsigned int)portDefn->format.video.xFramerate >> 16);
4087                                        Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4088                                                drv_ctx.frame_rate.fps_denominator);
4089                                        if (!drv_ctx.frame_rate.fps_numerator) {
4090                                            DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4091                                            drv_ctx.frame_rate.fps_numerator = 30;
4092                                        }
4093                                        if (drv_ctx.frame_rate.fps_denominator)
4094                                            drv_ctx.frame_rate.fps_numerator = (int)
4095                                                drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4096                                        drv_ctx.frame_rate.fps_denominator = 1;
4097                                        frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4098                                            drv_ctx.frame_rate.fps_numerator;
4099                                        DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4100                                                (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4101                                                (float)drv_ctx.frame_rate.fps_denominator);
4102 
4103                                        struct v4l2_outputparm oparm;
4104                                        /*XXX: we're providing timing info as seconds per frame rather than frames
4105                                         * per second.*/
4106                                        oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4107                                        oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4108 
4109                                        struct v4l2_streamparm sparm;
4110                                        sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4111                                        sparm.parm.output = oparm;
4112                                        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4113                                            DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4114                                            eRet = OMX_ErrorHardware;
4115                                            break;
4116                                        }
4117                                        m_perf_control.request_cores(frm_int);
4118                                    }
4119 
4120                                    if (drv_ctx.video_resolution.frame_height !=
4121                                            portDefn->format.video.nFrameHeight ||
4122                                            drv_ctx.video_resolution.frame_width  !=
4123                                            portDefn->format.video.nFrameWidth) {
4124                                        DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4125                                                (unsigned int)portDefn->format.video.nFrameWidth,
4126                                                (unsigned int)portDefn->format.video.nFrameHeight);
4127                                        port_format_changed = true;
4128                                        OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4129                                        OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4130                                        if (frameHeight != 0x0 && frameWidth != 0x0) {
4131                                            if (m_smoothstreaming_mode &&
4132                                                    ((frameWidth * frameHeight) <
4133                                                    (m_smoothstreaming_width * m_smoothstreaming_height))) {
4134                                                frameWidth = m_smoothstreaming_width;
4135                                                frameHeight = m_smoothstreaming_height;
4136                                                DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4137                                                        "for adaptive-playback/smooth-streaming",
4138                                                        (unsigned int)frameWidth, (unsigned int)frameHeight);
4139                                            }
4140                                            update_resolution(frameWidth, frameHeight,
4141                                                    frameWidth, frameHeight);
4142                                            eRet = is_video_session_supported();
4143                                            if (eRet)
4144                                                break;
4145                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4146                                            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4147                                            fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4148                                            fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4149                                            fmt.fmt.pix_mp.pixelformat = output_capability;
4150                                            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);
4151                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4152                                            if (ret) {
4153                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4154                                                eRet = OMX_ErrorUnsupportedSetting;
4155                                            } else {
4156                                                if (!is_down_scalar_enabled)
4157                                                    eRet = get_buffer_req(&drv_ctx.op_buf);
4158                                            }
4159                                        }
4160                                    }
4161                                    if (m_custom_buffersize.input_buffersize
4162                                         && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4163                                        DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4164                                                m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4165                                        eRet = OMX_ErrorBadParameter;
4166                                        break;
4167                                    }
4168                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4169                                        DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4170                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4171                                        eRet = OMX_ErrorBadParameter;
4172                                        break;
4173                                    }
4174                                    // Buffer count can change only when port is unallocated
4175                                    if (m_inp_mem_ptr &&
4176                                             (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4177                                             portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4178                                        DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4179                                        eRet = OMX_ErrorInvalidState;
4180                                        break;
4181                                    }
4182 
4183                                    if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4184                                            || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4185                                        port_format_changed = true;
4186                                        vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4187                                        drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4188                                        drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4189                                            (~(buffer_prop->alignment - 1));
4190                                        eRet = set_buffer_req(buffer_prop);
4191                                    }
4192                                    if (false == port_format_changed) {
4193                                        DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4194                                                drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4195                                                (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4196                                        eRet = OMX_ErrorBadParameter;
4197                                    }
4198                                } else if (portDefn->eDir ==  OMX_DirMax) {
4199                                    DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4200                                            (int)portDefn->nPortIndex);
4201                                    eRet = OMX_ErrorBadPortIndex;
4202                                }
4203                            }
4204                            break;
4205         case OMX_IndexParamVideoPortFormat: {
4206                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4207                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4208                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4209                                 int ret=0;
4210                                 struct v4l2_format fmt;
4211                                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4212                                         portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4213 
4214                                 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4215                                 if (1 == portFmt->nPortIndex) {
4216                                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4217                                     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4218                                     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4219                                     enum vdec_output_fromat op_format;
4220                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4221                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4222                                             portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4223                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4224                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4225                                             portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4226                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4227                                     } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4228                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4229                                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4230                                     } else
4231                                         eRet = OMX_ErrorBadParameter;
4232 
4233                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4234                                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4235                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4236                                     } else {
4237                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4238                                     }
4239 
4240                                     if (eRet == OMX_ErrorNone) {
4241                                         drv_ctx.output_format = op_format;
4242                                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4243                                         if (ret) {
4244                                             DEBUG_PRINT_ERROR("Set output format failed");
4245                                             eRet = OMX_ErrorUnsupportedSetting;
4246                                             /*TODO: How to handle this case */
4247                                         } else {
4248                                             eRet = get_buffer_req(&drv_ctx.op_buf);
4249                                         }
4250                                     }
4251                                     if (eRet == OMX_ErrorNone) {
4252                                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4253                                             DEBUG_PRINT_ERROR("Set color format failed");
4254                                             eRet = OMX_ErrorBadParameter;
4255                                         }
4256                                     }
4257                                 }
4258                             }
4259                             break;
4260 
4261         case OMX_QcomIndexPortDefn: {
4262                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4263                             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4264                                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4265                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4266                                     (unsigned int)portFmt->nFramePackingFormat);
4267 
4268                             /* Input port */
4269                             if (portFmt->nPortIndex == 0) {
4270                                 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4271                                 //   - headers are allocated and
4272                                 //   - headers-indices are derived
4273                                 // Avoid changing arbitrary_bytes when the port is already allocated
4274                                 if (m_inp_mem_ptr) {
4275                                     DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4276                                     return OMX_ErrorUnsupportedSetting;
4277                                 }
4278                                 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4279                                     if (secure_mode || m_input_pass_buffer_fd) {
4280                                         arbitrary_bytes = false;
4281                                         DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4282                                         eRet = OMX_ErrorUnsupportedSetting;
4283                                     } else {
4284                                         arbitrary_bytes = true;
4285                                     }
4286                                 } else if (portFmt->nFramePackingFormat ==
4287                                         OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4288                                     arbitrary_bytes = false;
4289 #ifdef _ANDROID_
4290                                     property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4291                                     if (atoi(property_value)) {
4292                                         DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4293                                         arbitrary_bytes = true;
4294                                     }
4295 #endif
4296                                 } else {
4297                                     DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4298                                             (unsigned int)portFmt->nFramePackingFormat);
4299                                     eRet = OMX_ErrorUnsupportedSetting;
4300                                 }
4301                             } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4302                                 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4303                                 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4304                                             portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4305                                         portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4306                                     m_out_mem_region_smi = OMX_TRUE;
4307                                     if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4308                                         DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4309                                         m_use_output_pmem = OMX_TRUE;
4310                                     }
4311                                 }
4312                             }
4313                         }
4314                         if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4315                                     OMX_MAX_STRINGNAME_SIZE)) {
4316                             arbitrary_bytes = true;
4317                             DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4318                         }
4319                         break;
4320 
4321         case OMX_IndexParamStandardComponentRole: {
4322                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4323                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
4324                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4325                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4326                                           comp_role->cRole);
4327 
4328                                   if ((m_state == OMX_StateLoaded)&&
4329                                           !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4330                                       DEBUG_PRINT_LOW("Set Parameter called in valid state");
4331                                   } else {
4332                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4333                                       return OMX_ErrorIncorrectStateOperation;
4334                                   }
4335 
4336                                   if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4337                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4338                                           strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4339                                       } else {
4340                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4341                                           eRet =OMX_ErrorUnsupportedSetting;
4342                                       }
4343                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4344                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4345                                           strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4346                                       } else {
4347                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4348                                           eRet = OMX_ErrorUnsupportedSetting;
4349                                       }
4350                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4351                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4352                                           strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4353                                       } else {
4354                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4355                                           eRet = OMX_ErrorUnsupportedSetting;
4356                                       }
4357                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4358                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4359                                           strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4360                                       } else {
4361                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4362                                           eRet =OMX_ErrorUnsupportedSetting;
4363                                       }
4364                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4365                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4366                                           strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4367                                       } else {
4368                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4369                                           eRet = OMX_ErrorUnsupportedSetting;
4370                                       }
4371                                   } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4372                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4373                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4374                                         ) {
4375                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4376                                           strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4377                                       } else {
4378                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4379                                           eRet =OMX_ErrorUnsupportedSetting;
4380                                       }
4381                                   } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4382                                           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4383                                         ) {
4384                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4385                                           strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4386                                       } else {
4387                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4388                                           eRet =OMX_ErrorUnsupportedSetting;
4389                                       }
4390                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4391                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4392                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4393                                           strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4394                                       } else {
4395                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4396                                           eRet = OMX_ErrorUnsupportedSetting;
4397                                       }
4398                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4399                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4400                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4401                                           strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4402                                       } else {
4403                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4404                                           eRet = OMX_ErrorUnsupportedSetting;
4405                                       }
4406                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4407                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4408                                           strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4409                                       } else {
4410                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4411                                           eRet = OMX_ErrorUnsupportedSetting;
4412                                       }
4413                                   } else {
4414                                       DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4415                                       eRet = OMX_ErrorInvalidComponentName;
4416                                   }
4417                                   break;
4418                               }
4419 
4420         case OMX_IndexParamPriorityMgmt: {
4421                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4422                              if (m_state != OMX_StateLoaded) {
4423                                  DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4424                                  return OMX_ErrorIncorrectStateOperation;
4425                              }
4426                              OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4427                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4428                                      (unsigned int)priorityMgmtype->nGroupID);
4429 
4430                              DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4431                                      (unsigned int)priorityMgmtype->nGroupPriority);
4432 
4433                              m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4434                              m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4435 
4436                              break;
4437                          }
4438 
4439         case OMX_IndexParamCompBufferSupplier: {
4440                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4441                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4442                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4443                                            bufferSupplierType->eBufferSupplier);
4444                                    if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4445                                        m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4446 
4447                                    else
4448 
4449                                        eRet = OMX_ErrorBadPortIndex;
4450 
4451                                    break;
4452 
4453                                }
4454         case OMX_IndexParamVideoAvc: {
4455                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4456                                      paramIndex);
4457                              break;
4458                          }
4459         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4460                             DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4461                                      paramIndex);
4462                              break;
4463                         }
4464         case OMX_IndexParamVideoH263: {
4465                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4466                                       paramIndex);
4467                               break;
4468                           }
4469         case OMX_IndexParamVideoMpeg4: {
4470                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4471                                        paramIndex);
4472                                break;
4473                            }
4474         case OMX_IndexParamVideoMpeg2: {
4475                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4476                                        paramIndex);
4477                                break;
4478                            }
4479         case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4480                                      VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4481                                      QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4482                                          (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4483                                      struct v4l2_control control;
4484                                      int pic_order,rc=0;
4485                                      DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4486                                              pictureOrder->eOutputPictureOrder);
4487                                      if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4488                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4489                                      } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4490                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4491                                          time_stamp_dts.set_timestamp_reorder_mode(false);
4492                                      } else
4493                                          eRet = OMX_ErrorBadParameter;
4494                                      if (eRet == OMX_ErrorNone) {
4495                                          control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4496                                          control.value = pic_order;
4497                                          rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4498                                          if (rc) {
4499                                              DEBUG_PRINT_ERROR("Set picture order failed");
4500                                              eRet = OMX_ErrorUnsupportedSetting;
4501                                          }
4502                                      }
4503                                      m_decode_order_mode =
4504                                             pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4505                                      break;
4506                                  }
4507         case OMX_QcomIndexParamConcealMBMapExtraData:
4508                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4509                                eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4510                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4511                                break;
4512         case OMX_QcomIndexParamFrameInfoExtraData:
4513                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4514                                eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4515                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4516                                break;
4517         case OMX_ExtraDataFrameDimension:
4518                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4519                                eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4520                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4521                                break;
4522         case OMX_QcomIndexParamInterlaceExtraData:
4523                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4524                                eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4525                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4526                                break;
4527         case OMX_QcomIndexParamH264TimeInfo:
4528                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4529                                eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4530                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4531                                break;
4532         case OMX_QcomIndexParamVideoFramePackingExtradata:
4533                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4534                                eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4535                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4536                                break;
4537         case OMX_QcomIndexParamVideoQPExtraData:
4538                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4539                                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4540                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4541                                break;
4542         case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4543                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4544                                eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4545                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4546                                break;
4547         case OMX_QcomIndexEnableExtnUserData:
4548                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4549                                 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4550                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4551                                 break;
4552         case OMX_QTIIndexParamVQZipSEIExtraData:
4553                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4554                                 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4555                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4556                                 break;
4557         case OMX_QcomIndexParamVideoDivx: {
4558                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4559                           }
4560                           break;
4561         case OMX_QcomIndexPlatformPvt: {
4562                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4563                                DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4564                                OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4565                                if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4566                                    DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4567                                    eRet = OMX_ErrorUnsupportedSetting;
4568                                } else {
4569                                    m_out_pvt_entry_pmem = OMX_TRUE;
4570                                    if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4571                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4572                                        m_use_output_pmem = OMX_TRUE;
4573                                    }
4574                                }
4575 
4576                            }
4577                            break;
4578         case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4579                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4580                                        DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4581                                        struct v4l2_control control;
4582                                        int rc;
4583                                        drv_ctx.idr_only_decoding = 1;
4584                                        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4585                                        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4586                                        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4587                                        if (rc) {
4588                                            DEBUG_PRINT_ERROR("Set picture order failed");
4589                                            eRet = OMX_ErrorUnsupportedSetting;
4590                                        } else {
4591                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4592                                            control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4593                                            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4594                                            if (rc) {
4595                                                DEBUG_PRINT_ERROR("Sync frame setting failed");
4596                                                eRet = OMX_ErrorUnsupportedSetting;
4597                                            }
4598                                            /*Setting sync frame decoding on driver might change buffer
4599                                             * requirements so update them here*/
4600                                            if (get_buffer_req(&drv_ctx.ip_buf)) {
4601                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4602                                                eRet = OMX_ErrorUnsupportedSetting;
4603                                            }
4604                                            if (get_buffer_req(&drv_ctx.op_buf)) {
4605                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4606                                                eRet = OMX_ErrorUnsupportedSetting;
4607                                            }
4608                                        }
4609                                    }
4610                                    break;
4611 
4612         case OMX_QcomIndexParamIndexExtraDataType: {
4613                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4614                                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4615                                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4616                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4617                                             (extradataIndexType->nPortIndex == 1)) {
4618                                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4619                                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4620 
4621                                     }
4622                                 }
4623                                 break;
4624         case OMX_QcomIndexParamEnableSmoothStreaming: {
4625 #ifndef SMOOTH_STREAMING_DISABLED
4626                                       eRet = enable_smoothstreaming();
4627 #else
4628                                       eRet = OMX_ErrorUnsupportedSetting;
4629 #endif
4630                                   }
4631                                   break;
4632 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4633                                   /* Need to allow following two set_parameters even in Idle
4634                                    * state. This is ANDROID architecture which is not in sync
4635                                    * with openmax standard. */
4636         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4637                                            VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4638                                            EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4639                                            if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4640                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4641                                                 eRet = OMX_ErrorUnsupportedSetting;
4642                                                 break;
4643                                            } else if (m_out_mem_ptr) {
4644                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4645                                                 eRet = OMX_ErrorInvalidState;
4646                                                 break;
4647                                            }
4648                                            if (enableNativeBuffers) {
4649                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
4650                                            }
4651 #if !defined(FLEXYUV_SUPPORTED)
4652                                            if (m_enable_android_native_buffers) {
4653                                                // Use the most-preferred-native-color-format as surface-mode is hinted here
4654                                                if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4655                                                    DEBUG_PRINT_ERROR("Failed to set native color format!");
4656                                                    eRet = OMX_ErrorUnsupportedSetting;
4657                                                }
4658                                            }
4659 #endif
4660                                        }
4661                                        break;
4662         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4663                                        VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4664                                        eRet = use_android_native_buffer(hComp, paramData);
4665                                    }
4666                                    break;
4667         case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4668 
4669                 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4670                 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4671 
4672                 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4673                     DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
4674                     eRet = OMX_ErrorUnsupportedSetting;
4675                     break;
4676                 } else if (m_inp_mem_ptr) {
4677                     DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4678                     eRet = OMX_ErrorInvalidState;
4679                     break;
4680                 }
4681 
4682                 if (allocateNativeHandleParams != NULL) {
4683                     allocate_native_handle = allocateNativeHandleParams->enable;
4684                 }
4685             }
4686             break;
4687 #endif
4688         case OMX_QcomIndexParamEnableTimeStampReorder: {
4689                                        VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4690                                        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4691                                        if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4692                                            if (reorder->bEnable == OMX_TRUE) {
4693                                                frm_int =0;
4694                                                time_stamp_dts.set_timestamp_reorder_mode(true);
4695                                            } else
4696                                                time_stamp_dts.set_timestamp_reorder_mode(false);
4697                                        } else {
4698                                            time_stamp_dts.set_timestamp_reorder_mode(false);
4699                                            if (reorder->bEnable == OMX_TRUE) {
4700                                                eRet = OMX_ErrorUnsupportedSetting;
4701                                            }
4702                                        }
4703                                    }
4704                                    break;
4705         case OMX_IndexParamVideoProfileLevelCurrent: {
4706                                      VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4707                                      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4708                                          (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4709                                      if (pParam) {
4710                                          m_profile_lvl.eProfile = pParam->eProfile;
4711                                          m_profile_lvl.eLevel = pParam->eLevel;
4712                                      }
4713                                      break;
4714 
4715                                  }
4716         case OMX_QcomIndexParamVideoMetaBufferMode:
4717         {
4718             VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4719             StoreMetaDataInBuffersParams *metabuffer =
4720                 (StoreMetaDataInBuffersParams *)paramData;
4721             if (!metabuffer) {
4722                 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4723                 eRet = OMX_ErrorBadParameter;
4724                 break;
4725             }
4726             if (m_disable_dynamic_buf_mode) {
4727                 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4728                 eRet = OMX_ErrorUnsupportedSetting;
4729                 break;
4730             }
4731             if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4732 
4733                     if (m_out_mem_ptr) {
4734                         DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
4735                         eRet = OMX_ErrorInvalidState;
4736                         break;
4737                     }
4738                     //set property dynamic buffer mode to driver.
4739                     struct v4l2_control control;
4740                     struct v4l2_format fmt;
4741                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
4742                     if (metabuffer->bStoreMetaData == true) {
4743                         control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
4744                     } else {
4745                         control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
4746                     }
4747                     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4748                     if (!rc) {
4749                         DEBUG_PRINT_HIGH("%s buffer mode",
4750                            (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4751                     } else {
4752                         DEBUG_PRINT_ERROR("Failed to %s buffer mode",
4753                            (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
4754                     }
4755                     dynamic_buf_mode = metabuffer->bStoreMetaData;
4756                 } else {
4757                     DEBUG_PRINT_ERROR(
4758                        "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4759                        (unsigned int)metabuffer->nPortIndex);
4760                     eRet = OMX_ErrorUnsupportedSetting;
4761                 }
4762                 break;
4763         }
4764         case OMX_QcomIndexParamVideoDownScalar:
4765         {
4766             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4767             QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4768             struct v4l2_control control;
4769             int rc;
4770             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
4771 
4772             if (pParam && pParam->bEnable) {
4773                 rc = enable_downscalar();
4774                 if (rc < 0) {
4775                     DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
4776                     return OMX_ErrorUnsupportedSetting;
4777                 }
4778                 m_force_down_scalar = pParam->bEnable;
4779             } else {
4780                 rc = disable_downscalar();
4781                 if (rc < 0) {
4782                     DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
4783                     return OMX_ErrorUnsupportedSetting;
4784                 }
4785                 m_force_down_scalar = pParam->bEnable;
4786             }
4787             break;
4788         }
4789 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4790         case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4791         {
4792             VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4793             DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4794             PrepareForAdaptivePlaybackParams* pParams =
4795                     (PrepareForAdaptivePlaybackParams *) paramData;
4796             if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4797                 if (!pParams->bEnable) {
4798                     return OMX_ErrorNone;
4799                 }
4800                 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4801                         || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4802                     DEBUG_PRINT_ERROR(
4803                             "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4804                              (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4805                              (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4806                     eRet = OMX_ErrorBadParameter;
4807                 } else {
4808                     eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4809                 }
4810             } else {
4811                 DEBUG_PRINT_ERROR(
4812                         "Prepare for adaptive playback supported only on output port");
4813                 eRet = OMX_ErrorBadParameter;
4814             }
4815             break;
4816         }
4817 
4818         case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
4819         {
4820             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4821             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
4822             m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4823             if (m_disable_dynamic_buf_mode) {
4824                 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
4825             }
4826             break;
4827         }
4828 #endif
4829         case OMX_QcomIndexParamVideoCustomBufferSize:
4830         {
4831             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4832             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4833             QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4834             if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4835                 struct v4l2_control control;
4836                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4837                 control.value = pParam->nBufferSize;
4838                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4839                     DEBUG_PRINT_ERROR("Failed to set input buffer size");
4840                     eRet = OMX_ErrorUnsupportedSetting;
4841                 } else {
4842                     eRet = get_buffer_req(&drv_ctx.ip_buf);
4843                     if (eRet == OMX_ErrorNone) {
4844                         m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4845                         DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4846                             m_custom_buffersize.input_buffersize);
4847                     } else {
4848                         DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4849                     }
4850                 }
4851             } else {
4852                 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4853                 eRet = OMX_ErrorBadParameter;
4854             }
4855             break;
4856         }
4857         case OMX_QTIIndexParamVQZIPSEIType:
4858         {
4859             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
4860             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
4861             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
4862                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
4863                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
4864             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4865                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4866             if (eRet != OMX_ErrorNone) {
4867                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
4868                 eRet = OMX_ErrorBadParameter;
4869                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4870             } else {
4871                 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4872                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4873                 if (eRet != OMX_ErrorNone) {
4874                     DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
4875                     eRet = OMX_ErrorBadParameter;
4876                     client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4877                     client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4878                 }
4879             }
4880             break;
4881         }
4882 
4883         case OMX_QTIIndexParamPassInputBufferFd:
4884         {
4885             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4886             if (arbitrary_bytes) {
4887                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
4888                 eRet = OMX_ErrorUnsupportedSetting;
4889                 break;
4890             }
4891 
4892             m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4893             if (m_input_pass_buffer_fd)
4894                 DEBUG_PRINT_LOW("Enable passing input buffer FD");
4895             break;
4896         }
4897         case OMX_QTIIndexParamForceCompressedForDPB:
4898         {
4899             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
4900             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
4901             OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
4902                 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
4903             if (m_disable_ubwc_mode) {
4904                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
4905                 eRet = OMX_ErrorUnsupportedSetting;
4906                 break;
4907             }
4908             if (!paramData) {
4909                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
4910                eRet = OMX_ErrorBadParameter;
4911                break;
4912             }
4913 
4914             m_force_compressed_for_dpb = pParam->bEnable;
4915             break;
4916         }
4917         case OMX_QTIIndexParamForceUnCompressedForOPB:
4918         {
4919             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE);
4920             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
4921             OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
4922                 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
4923             if (!paramData) {
4924                 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
4925                 eRet = OMX_ErrorBadParameter;
4926                 break;
4927             }
4928             m_disable_ubwc_mode = pParam->bEnable;
4929             DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
4930             break;
4931         }
4932 
4933 
4934         default: {
4935                  DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4936                  eRet = OMX_ErrorUnsupportedIndex;
4937              }
4938     }
4939     if (eRet != OMX_ErrorNone)
4940         DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4941     return eRet;
4942 }
4943 
4944 /* ======================================================================
4945    FUNCTION
4946    omx_vdec::GetConfig
4947 
4948    DESCRIPTION
4949    OMX Get Config Method implementation.
4950 
4951    PARAMETERS
4952    <TBD>.
4953 
4954    RETURN VALUE
4955    OMX Error None if successful.
4956 
4957    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4958 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
4959         OMX_IN OMX_INDEXTYPE configIndex,
4960         OMX_INOUT OMX_PTR     configData)
4961 {
4962     (void) hComp;
4963     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4964 
4965     if (m_state == OMX_StateInvalid) {
4966         DEBUG_PRINT_ERROR("Get Config in Invalid State");
4967         return OMX_ErrorInvalidState;
4968     }
4969 
4970     switch ((unsigned long)configIndex) {
4971         case OMX_QcomIndexConfigInterlaced: {
4972                                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
4973                                 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
4974                                     (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
4975                                 if (configFmt->nPortIndex == 1) {
4976                                     if (configFmt->nIndex == 0) {
4977                                         configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
4978                                     } else if (configFmt->nIndex == 1) {
4979                                         configFmt->eInterlaceType =
4980                                             OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
4981                                     } else if (configFmt->nIndex == 2) {
4982                                         configFmt->eInterlaceType =
4983                                             OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
4984                                     } else {
4985                                         DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
4986                                                 " NoMore Interlaced formats");
4987                                         eRet = OMX_ErrorNoMore;
4988                                     }
4989 
4990                                 } else {
4991                                     DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
4992                                             (int)configFmt->nPortIndex);
4993                                     eRet = OMX_ErrorBadPortIndex;
4994                                 }
4995                                 break;
4996                             }
4997         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
4998                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
4999                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5000                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5001                                      decoderinstances->nNumOfInstances = 16;
5002                                      /*TODO: How to handle this case */
5003                                      break;
5004                                  }
5005         case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5006                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5007                                               VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5008                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5009                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5010                                               memcpy(configFmt, &m_frame_pack_arrangement,
5011                                                   sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5012                                           } else {
5013                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5014                                           }
5015                                           break;
5016                                       }
5017         case OMX_IndexConfigCommonOutputCrop: {
5018                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5019                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5020                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5021                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5022                                         rectangle.nLeft, rectangle.nTop,
5023                                         rectangle.nWidth, rectangle.nHeight);
5024                                   break;
5025                               }
5026         case OMX_QcomIndexConfigPerfLevel: {
5027                 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
5028                 struct v4l2_control control;
5029                 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5030                         (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5031 
5032                 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5033                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
5034                     DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
5035                     eRet = OMX_ErrorHardware;
5036                 }
5037 
5038                 if (eRet == OMX_ErrorNone) {
5039                     switch (control.value) {
5040                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
5041                             perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
5042                             break;
5043                         default:
5044                             DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
5045                             /* Fall through */
5046                         case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
5047                             perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
5048                             break;
5049                     }
5050                 }
5051 
5052                 break;
5053         }
5054         case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5055             VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5056             QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5057             struct v4l2_control control;
5058 
5059             if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5060                 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5061                 eRet = OMX_ErrorNotImplemented;
5062                 break;
5063             }
5064 
5065             control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5066             if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5067                 coding->bCabac = (OMX_BOOL)
5068                     (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5069                 /* We can't query driver at the moment for the cabac mode, so
5070                  * just use 0xff...f as a place holder for future improvement */
5071                 coding->nCabacInitIdc = ~0;
5072             } else {
5073                 eRet = OMX_ErrorUnsupportedIndex;
5074             }
5075 
5076             break;
5077         }
5078         case OMX_QTIIndexConfigDescribeColorAspects:
5079         {
5080             VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5081             DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5082 
5083             print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5084             print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5085 
5086             if (params->bRequestingDataSpace) {
5087                 DEBUG_PRINT_ERROR("Does not handle dataspace request");
5088                 return OMX_ErrorUnsupportedSetting;
5089             }
5090             if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) {
5091                 DEBUG_PRINT_LOW("Updating Client's color aspects with internal");
5092                 memcpy(&(m_client_color_space.sAspects),
5093                         &(m_internal_color_space.sAspects), sizeof(ColorAspects));
5094                 m_internal_color_space.bDataSpaceChanged = OMX_FALSE;
5095             }
5096             memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects));
5097 
5098             break;
5099         }
5100         case OMX_IndexConfigAndroidVendorExtension:
5101         {
5102             VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5103 
5104             OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5105                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5106             VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5107             return get_vendor_extension_config(ext);
5108         }
5109         default:
5110         {
5111             DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5112             eRet = OMX_ErrorBadParameter;
5113         }
5114 
5115     }
5116 
5117     return eRet;
5118 }
5119 
5120 /* ======================================================================
5121    FUNCTION
5122    omx_vdec::SetConfig
5123 
5124    DESCRIPTION
5125    OMX Set Config method implementation
5126 
5127    PARAMETERS
5128    <TBD>.
5129 
5130    RETURN VALUE
5131    OMX Error None if successful.
5132    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5133 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5134         OMX_IN OMX_INDEXTYPE configIndex,
5135         OMX_IN OMX_PTR        configData)
5136 {
5137     (void) hComp;
5138     if (m_state == OMX_StateInvalid) {
5139         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5140         return OMX_ErrorInvalidState;
5141     }
5142 
5143     OMX_ERRORTYPE ret = OMX_ErrorNone;
5144     OMX_VIDEO_CONFIG_NALSIZE *pNal;
5145 
5146     DEBUG_PRINT_LOW("Set Config Called");
5147 
5148     if (configIndex == OMX_IndexConfigVideoNalSize) {
5149         struct v4l2_control temp;
5150         temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5151 
5152         VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5153         pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5154         switch (pNal->nNaluBytes) {
5155             case 0:
5156                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5157                 break;
5158             case 2:
5159                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5160                 break;
5161             case 4:
5162                 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5163                 break;
5164             default:
5165                 return OMX_ErrorUnsupportedSetting;
5166         }
5167 
5168         if (!arbitrary_bytes) {
5169             /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5170              * with start code, so only need to notify driver in frame by frame mode */
5171             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5172                 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5173                 return OMX_ErrorHardware;
5174             }
5175         }
5176 
5177         nal_length = pNal->nNaluBytes;
5178         m_frame_parser.init_nal_length(nal_length);
5179 
5180         DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5181         return ret;
5182     } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5183         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5184         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5185 
5186         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5187             if (config->bEnabled) {
5188                 if ((config->nFps >> 16) > 0) {
5189                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5190                             (unsigned int)config->nFps >> 16);
5191                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5192                             drv_ctx.frame_rate.fps_denominator);
5193 
5194                     if (!drv_ctx.frame_rate.fps_numerator) {
5195                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5196                         drv_ctx.frame_rate.fps_numerator = 30;
5197                     }
5198 
5199                     if (drv_ctx.frame_rate.fps_denominator) {
5200                         drv_ctx.frame_rate.fps_numerator = (int)
5201                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5202                     }
5203 
5204                     drv_ctx.frame_rate.fps_denominator = 1;
5205                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5206                         drv_ctx.frame_rate.fps_numerator;
5207 
5208                     struct v4l2_outputparm oparm;
5209                     /*XXX: we're providing timing info as seconds per frame rather than frames
5210                      * per second.*/
5211                     oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5212                     oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5213 
5214                     struct v4l2_streamparm sparm;
5215                     sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5216                     sparm.parm.output = oparm;
5217                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5218                         DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5219                                 performance might be affected");
5220                         ret = OMX_ErrorHardware;
5221                     }
5222                     client_set_fps = true;
5223                 } else {
5224                     DEBUG_PRINT_ERROR("Frame rate not supported.");
5225                     ret = OMX_ErrorUnsupportedSetting;
5226                 }
5227             } else {
5228                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5229                 client_set_fps = false;
5230             }
5231         } else {
5232             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5233                     (int)config->nPortIndex);
5234             ret = OMX_ErrorBadPortIndex;
5235         }
5236 
5237         return ret;
5238     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5239         OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5240             (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5241         struct v4l2_control control;
5242 
5243         DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5244 
5245         control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5246 
5247         switch (perf->ePerfLevel) {
5248             case OMX_QCOM_PerfLevelNominal:
5249                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5250                 break;
5251             case OMX_QCOM_PerfLevelTurbo:
5252                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5253                 break;
5254             default:
5255                 ret = OMX_ErrorUnsupportedSetting;
5256                 break;
5257         }
5258 
5259         if (ret == OMX_ErrorNone) {
5260             ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5261                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5262         }
5263 
5264         return ret;
5265     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5266         OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5267             (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5268         struct v4l2_control control;
5269         DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5270         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5271 
5272         switch (config->eDecodeType) {
5273             case OMX_QCOM_PictypeDecode_I:
5274                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5275                 break;
5276             case OMX_QCOM_PictypeDecode_IPB:
5277             default:
5278                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5279                 break;
5280         }
5281 
5282         ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5283                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5284         if (ret)
5285             DEBUG_PRINT_ERROR("Failed to set picture type decode");
5286 
5287         return ret;
5288     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5289         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5290         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5291 
5292         struct v4l2_control control;
5293 
5294         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5295         if (priority->nU32 == 0)
5296             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5297         else
5298             control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5299 
5300         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5301             DEBUG_PRINT_ERROR("Failed to set Priority");
5302             ret = OMX_ErrorUnsupportedSetting;
5303         }
5304         return ret;
5305     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5306         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5307         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5308 
5309         struct v4l2_control control;
5310 
5311         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5312         control.value = rate->nU32;
5313 
5314         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5315             ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5316                     OMX_ErrorUnsupportedSetting;
5317             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5318                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5319         }
5320         return ret;
5321 
5322     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5323         VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5324         DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5325         if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5326             enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5327         }
5328 
5329         print_debug_color_aspects(&(params->sAspects), "Set Config");
5330         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5331         return ret;
5332     } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5333         VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5334 
5335         OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5336                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5337         VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5338 
5339         return set_vendor_extension_config(ext);
5340     }
5341 
5342     return OMX_ErrorNotImplemented;
5343 }
5344 
5345 #define extn_equals(param, extn) (!strcmp(param, extn))
5346 
5347 /* ======================================================================
5348    FUNCTION
5349    omx_vdec::GetExtensionIndex
5350 
5351    DESCRIPTION
5352    OMX GetExtensionIndex method implementaion.  <TBD>
5353 
5354    PARAMETERS
5355    <TBD>.
5356 
5357    RETURN VALUE
5358    OMX Error None if everything successful.
5359 
5360    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5361 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5362         OMX_IN OMX_STRING      paramName,
5363         OMX_OUT OMX_INDEXTYPE* indexType)
5364 {
5365     (void) hComp;
5366     if (m_state == OMX_StateInvalid) {
5367         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5368         return OMX_ErrorInvalidState;
5369     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5370         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5371     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5372         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5373     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5374         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5375     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5376         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5377     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5378         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5379     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5380         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5381     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5382         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5383     }
5384 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5385     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5386         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5387     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5388         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5389     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5390         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5391         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5392     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5393         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5394     } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5395         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5396     }
5397 #endif
5398     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5399         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5400     }
5401 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5402     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5403         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5404     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5405         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5406     }
5407 #endif
5408 #ifdef FLEXYUV_SUPPORTED
5409     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5410         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5411     }
5412 #endif
5413     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5414         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5415     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5416         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5417     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5418         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5419     } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5420         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5421     } else {
5422         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5423         return OMX_ErrorNotImplemented;
5424     }
5425     return OMX_ErrorNone;
5426 }
5427 
5428 /* ======================================================================
5429    FUNCTION
5430    omx_vdec::GetState
5431 
5432    DESCRIPTION
5433    Returns the state information back to the caller.<TBD>
5434 
5435    PARAMETERS
5436    <TBD>.
5437 
5438    RETURN VALUE
5439    Error None if everything is successful.
5440    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5441 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5442         OMX_OUT OMX_STATETYPE* state)
5443 {
5444     (void) hComp;
5445     *state = m_state;
5446     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5447     return OMX_ErrorNone;
5448 }
5449 
5450 /* ======================================================================
5451    FUNCTION
5452    omx_vdec::ComponentTunnelRequest
5453 
5454    DESCRIPTION
5455    OMX Component Tunnel Request method implementation. <TBD>
5456 
5457    PARAMETERS
5458    None.
5459 
5460    RETURN VALUE
5461    OMX Error None if everything successful.
5462 
5463    ========================================================================== */
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)5464 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5465         OMX_IN OMX_U32                        port,
5466         OMX_IN OMX_HANDLETYPE        peerComponent,
5467         OMX_IN OMX_U32                    peerPort,
5468         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5469 {
5470     (void) hComp;
5471     (void) port;
5472     (void) peerComponent;
5473     (void) peerPort;
5474     (void) tunnelSetup;
5475     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5476     return OMX_ErrorNotImplemented;
5477 }
5478 
5479 /* ======================================================================
5480    FUNCTION
5481    omx_vdec::UseOutputBuffer
5482 
5483    DESCRIPTION
5484    Helper function for Use buffer in the input pin
5485 
5486    PARAMETERS
5487    None.
5488 
5489    RETURN VALUE
5490    true/false
5491 
5492    ========================================================================== */
allocate_extradata()5493 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5494 {
5495 #ifdef USE_ION
5496     if (drv_ctx.extradata_info.buffer_size) {
5497         if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5498             munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5499             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5500             free_ion_memory(&drv_ctx.extradata_info.ion);
5501         }
5502         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5503         drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5504                 drv_ctx.extradata_info.size, 4096,
5505                 &drv_ctx.extradata_info.ion.ion_alloc_data,
5506                 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5507         if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5508             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5509             return OMX_ErrorInsufficientResources;
5510         }
5511         drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5512                 drv_ctx.extradata_info.size,
5513                 PROT_READ|PROT_WRITE, MAP_SHARED,
5514                 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5515         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5516             DEBUG_PRINT_ERROR("Failed to map extradata memory");
5517             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5518             free_ion_memory(&drv_ctx.extradata_info.ion);
5519             return OMX_ErrorInsufficientResources;
5520         }
5521     }
5522 #endif
5523     if (!m_other_extradata) {
5524         m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5525         if (!m_other_extradata) {
5526             DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5527             return OMX_ErrorInsufficientResources;
5528         }
5529     }
5530     return OMX_ErrorNone;
5531 }
5532 
free_extradata()5533 void omx_vdec::free_extradata()
5534 {
5535 #ifdef USE_ION
5536     if (drv_ctx.extradata_info.uaddr) {
5537         munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5538         close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5539         free_ion_memory(&drv_ctx.extradata_info.ion);
5540     }
5541     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
5542 #endif
5543     if (m_other_extradata) {
5544         free(m_other_extradata);
5545         m_other_extradata = NULL;
5546     }
5547 }
5548 
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)5549 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5550         OMX_IN OMX_HANDLETYPE            hComp,
5551         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5552         OMX_IN OMX_U32                   port,
5553         OMX_IN OMX_PTR                   appData,
5554         OMX_IN OMX_U32                   bytes,
5555         OMX_IN OMX_U8*                   buffer)
5556 {
5557     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5558     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5559     unsigned                         i= 0; // Temporary counter
5560     struct vdec_setbuffer_cmd setbuffers;
5561     OMX_PTR privateAppData = NULL;
5562     private_handle_t *handle = NULL;
5563     OMX_U8 *buff = buffer;
5564     struct v4l2_buffer buf;
5565     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5566     int extra_idx = 0;
5567     (void) hComp;
5568     (void) port;
5569 
5570     if (!m_out_mem_ptr) {
5571         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5572         eRet = allocate_output_headers();
5573         if (eRet == OMX_ErrorNone)
5574             eRet = allocate_extradata();
5575         output_use_buffer = true;
5576     }
5577 
5578     if (eRet == OMX_ErrorNone) {
5579         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5580             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5581                 break;
5582             }
5583         }
5584     }
5585 
5586     if (i >= drv_ctx.op_buf.actualcount) {
5587         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5588         eRet = OMX_ErrorInsufficientResources;
5589     }
5590 
5591     if (eRet != OMX_ErrorNone)
5592        return eRet;
5593 
5594     if (dynamic_buf_mode) {
5595         *bufferHdr = (m_out_mem_ptr + i );
5596         (*bufferHdr)->pBuffer = NULL;
5597         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5598             enum v4l2_buf_type buf_type;
5599             int rr = 0;
5600             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5601             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5602                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5603                 return OMX_ErrorInsufficientResources;
5604             } else {
5605                 streaming[CAPTURE_PORT] = true;
5606                 DEBUG_PRINT_LOW("STREAMON Successful");
5607             }
5608 
5609             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5610             request_perf_level(VIDC_TURBO);
5611         }
5612         BITMASK_SET(&m_out_bm_count,i);
5613         (*bufferHdr)->pAppPrivate = appData;
5614         (*bufferHdr)->pBuffer = buffer;
5615         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5616         return eRet;
5617     }
5618 
5619     if (eRet == OMX_ErrorNone) {
5620 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5621         if (m_enable_android_native_buffers) {
5622             if (m_use_android_native_buffers) {
5623                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5624                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5625                 handle = (private_handle_t *)nBuf->handle;
5626                 privateAppData = params->pAppPrivate;
5627             } else {
5628                 handle = (private_handle_t *)buff;
5629                 privateAppData = appData;
5630             }
5631             if (!handle) {
5632                 DEBUG_PRINT_ERROR("handle is invalid");
5633                 return OMX_ErrorBadParameter;
5634             }
5635 
5636             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5637                 if (secure_mode && secure_scaling_to_non_secure_opb) {
5638                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5639                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5640                 } else {
5641                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5642                             " expected %u, got %u",
5643                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5644                     return OMX_ErrorBadParameter;
5645                 }
5646             }
5647 
5648             drv_ctx.op_buf.buffer_size = handle->size;
5649 
5650             if (!m_use_android_native_buffers) {
5651                 if (!secure_mode) {
5652                     buff =  (OMX_U8*)mmap(0, handle->size,
5653                             PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
5654                     if (buff == MAP_FAILED) {
5655                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5656                         return OMX_ErrorInsufficientResources;
5657                     }
5658                 }
5659             }
5660 #if defined(_ANDROID_ICS_)
5661             native_buffer[i].nativehandle = handle;
5662             native_buffer[i].privatehandle = handle;
5663 #endif
5664             if (!handle) {
5665                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5666                 return OMX_ErrorBadParameter;
5667             }
5668             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5669             drv_ctx.ptr_outputbuffer[i].offset = 0;
5670             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5671             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5672             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5673         } else
5674 #endif
5675 
5676             if (!ouput_egl_buffers && !m_use_output_pmem) {
5677 #ifdef USE_ION
5678                 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5679                         drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
5680                         &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
5681                         &drv_ctx.op_buf_ion_info[i].fd_ion_data,
5682                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5683                 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
5684                     DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
5685                     return OMX_ErrorInsufficientResources;
5686                 }
5687                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5688                                       drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5689 #else
5690                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5691                                       open (MEM_DEVICE,O_RDWR);
5692 
5693                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5694                     DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5695                     return OMX_ErrorInsufficientResources;
5696                 }
5697 
5698                 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
5699                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
5700                     drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5701                                           open (MEM_DEVICE,O_RDWR);
5702                     if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5703                         DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5704                         return OMX_ErrorInsufficientResources;
5705                     }
5706                 }
5707 
5708                 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5709                             drv_ctx.op_buf.buffer_size,
5710                             drv_ctx.op_buf.alignment)) {
5711                     DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5712                     close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5713                     return OMX_ErrorInsufficientResources;
5714                 }
5715 #endif
5716                 if (!secure_mode) {
5717                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
5718                         (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
5719                                 PROT_READ|PROT_WRITE, MAP_SHARED,
5720                                 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
5721                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5722                         close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5723 #ifdef USE_ION
5724                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5725 #endif
5726                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5727                         return OMX_ErrorInsufficientResources;
5728                     }
5729                 }
5730                 drv_ctx.ptr_outputbuffer[i].offset = 0;
5731                 privateAppData = appData;
5732             } else {
5733 
5734                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5735                 if (!appData || !bytes ) {
5736                     if (!secure_mode && !buffer) {
5737                         DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
5738                         return OMX_ErrorBadParameter;
5739                     }
5740                 }
5741 
5742                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
5743                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
5744                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
5745                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
5746                         !pmem_list->nEntries ||
5747                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
5748                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
5749                     return OMX_ErrorBadParameter;
5750                 }
5751                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5752                     pmem_list->entryList->entry;
5753                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
5754                         pmem_info->pmem_fd);
5755                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
5756                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
5757                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5758                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
5759                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5760                 privateAppData = appData;
5761             }
5762         m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5763         m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5764         m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5765         m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5766         m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5767 
5768         *bufferHdr = (m_out_mem_ptr + i );
5769         if (secure_mode)
5770             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5771         //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5772         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
5773                 sizeof (vdec_bufferpayload));
5774 
5775         DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
5776                 drv_ctx.ptr_outputbuffer[i].bufferaddr,
5777                 drv_ctx.ptr_outputbuffer[i].pmem_fd );
5778 
5779         buf.index = i;
5780         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5781         buf.memory = V4L2_MEMORY_USERPTR;
5782         plane[0].length = drv_ctx.op_buf.buffer_size;
5783         plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
5784             (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
5785         plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5786         plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
5787         plane[0].data_offset = 0;
5788         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5789         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5790             plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5791             plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
5792 #ifdef USE_ION
5793             plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5794 #endif
5795             plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
5796             plane[extra_idx].data_offset = 0;
5797         } else if  (extra_idx >= VIDEO_MAX_PLANES) {
5798             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
5799             return OMX_ErrorBadParameter;
5800         }
5801         buf.m.planes = plane;
5802         buf.length = drv_ctx.num_planes;
5803 
5804         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
5805             DEBUG_PRINT_ERROR("Failed to prepare bufs");
5806             /*TODO: How to handle this case */
5807             return OMX_ErrorInsufficientResources;
5808         }
5809 
5810         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
5811             enum v4l2_buf_type buf_type;
5812             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5813             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
5814                 return OMX_ErrorInsufficientResources;
5815             } else {
5816                 streaming[CAPTURE_PORT] = true;
5817                 DEBUG_PRINT_LOW("STREAMON Successful");
5818             }
5819 
5820             DEBUG_PRINT_HIGH("Enabling Turbo mode");
5821             request_perf_level(VIDC_TURBO);
5822         }
5823 
5824         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
5825         if (m_enable_android_native_buffers) {
5826             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
5827             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
5828         } else {
5829             (*bufferHdr)->pBuffer = buff;
5830         }
5831         (*bufferHdr)->pAppPrivate = privateAppData;
5832         BITMASK_SET(&m_out_bm_count,i);
5833     }
5834     return eRet;
5835 }
5836 
5837 /* ======================================================================
5838    FUNCTION
5839    omx_vdec::use_input_heap_buffers
5840 
5841    DESCRIPTION
5842    OMX Use Buffer Heap allocation method implementation.
5843 
5844    PARAMETERS
5845    <TBD>.
5846 
5847    RETURN VALUE
5848    OMX Error None , if everything successful.
5849 
5850    ========================================================================== */
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)5851 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
5852         OMX_IN OMX_HANDLETYPE            hComp,
5853         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5854         OMX_IN OMX_U32                   port,
5855         OMX_IN OMX_PTR                   appData,
5856         OMX_IN OMX_U32                   bytes,
5857         OMX_IN OMX_U8*                   buffer)
5858 {
5859     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5860     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5861 
5862     if (secure_mode) {
5863         DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
5864         return OMX_ErrorUndefined;
5865     }
5866 
5867     if (!m_inp_heap_ptr)
5868         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5869             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5870                     drv_ctx.ip_buf.actualcount);
5871     if (!m_phdr_pmem_ptr)
5872         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5873             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5874                     drv_ctx.ip_buf.actualcount);
5875     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5876         DEBUG_PRINT_ERROR("Insufficent memory");
5877         eRet = OMX_ErrorInsufficientResources;
5878     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5879         input_use_buffer = true;
5880         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5881         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5882         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5883         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5884         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5885         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5886         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5887         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5888         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5889         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5890                     (unsigned)NULL, (unsigned)NULL)) {
5891             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5892             return OMX_ErrorInsufficientResources;
5893         }
5894         m_in_alloc_cnt++;
5895     } else {
5896         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5897         eRet = OMX_ErrorInsufficientResources;
5898     }
5899     return eRet;
5900 }
5901 
5902 /* ======================================================================
5903    FUNCTION
5904    omx_vdec::UseBuffer
5905 
5906    DESCRIPTION
5907    OMX Use Buffer method implementation.
5908 
5909    PARAMETERS
5910    <TBD>.
5911 
5912    RETURN VALUE
5913    OMX Error None , if everything successful.
5914 
5915    ========================================================================== */
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)5916 OMX_ERRORTYPE  omx_vdec::use_buffer(
5917         OMX_IN OMX_HANDLETYPE            hComp,
5918         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5919         OMX_IN OMX_U32                   port,
5920         OMX_IN OMX_PTR                   appData,
5921         OMX_IN OMX_U32                   bytes,
5922         OMX_IN OMX_U8*                   buffer)
5923 {
5924     OMX_ERRORTYPE error = OMX_ErrorNone;
5925     struct vdec_setbuffer_cmd setbuffers;
5926 
5927     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5928             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5929             return OMX_ErrorBadParameter;
5930     }
5931     if (m_state == OMX_StateInvalid) {
5932         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5933         return OMX_ErrorInvalidState;
5934     }
5935     if (port == OMX_CORE_INPUT_PORT_INDEX) {
5936         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
5937         // ensure that use-buffer was called for previous allocation.
5938         // Mix-and-match of useBuffer and allocateBuffer is not allowed
5939         if (m_inp_mem_ptr && !input_use_buffer) {
5940             DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
5941             return OMX_ErrorUndefined;
5942         }
5943         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5944     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
5945         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5946     else {
5947         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5948         error = OMX_ErrorBadPortIndex;
5949     }
5950     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5951     if (error == OMX_ErrorNone) {
5952         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5953             // Send the callback now
5954             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5955             post_event(OMX_CommandStateSet,OMX_StateIdle,
5956                     OMX_COMPONENT_GENERATE_EVENT);
5957         }
5958         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5959                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5960             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5961             post_event(OMX_CommandPortEnable,
5962                     OMX_CORE_INPUT_PORT_INDEX,
5963                     OMX_COMPONENT_GENERATE_EVENT);
5964         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
5965                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5966             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5967             post_event(OMX_CommandPortEnable,
5968                     OMX_CORE_OUTPUT_PORT_INDEX,
5969                     OMX_COMPONENT_GENERATE_EVENT);
5970         }
5971     }
5972     return error;
5973 }
5974 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)5975 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
5976         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
5977 {
5978     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
5979         if (m_inp_heap_ptr[bufferindex].pBuffer)
5980             free(m_inp_heap_ptr[bufferindex].pBuffer);
5981         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
5982     }
5983     if (pmem_bufferHdr)
5984         free_input_buffer(pmem_bufferHdr);
5985     return OMX_ErrorNone;
5986 }
5987 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5988 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5989 {
5990     unsigned int index = 0;
5991     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
5992         return OMX_ErrorBadParameter;
5993     }
5994 
5995     index = bufferHdr - m_inp_mem_ptr;
5996     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5997 
5998     bufferHdr->pInputPortPrivate = NULL;
5999 
6000     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6001         DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6002         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6003             struct vdec_setbuffer_cmd setbuffers;
6004             setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
6005             memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
6006                     sizeof (vdec_bufferpayload));
6007             if (!secure_mode) {
6008                 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
6009                         drv_ctx.ptr_inputbuffer[index].pmem_fd);
6010                 DEBUG_PRINT_LOW("unmap the input buffer size=%u  address = %p",
6011                         (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
6012                         drv_ctx.ptr_inputbuffer[index].bufferaddr);
6013                 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6014                         drv_ctx.ptr_inputbuffer[index].mmaped_size);
6015                 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
6016             } else if (allocate_native_handle){
6017                 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6018                 native_handle_close(nh);
6019                 native_handle_delete(nh);
6020             }
6021             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6022             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6023                 free(m_desc_buffer_ptr[index].buf_addr);
6024                 m_desc_buffer_ptr[index].buf_addr = NULL;
6025                 m_desc_buffer_ptr[index].desc_data_size = 0;
6026             }
6027 #ifdef USE_ION
6028             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6029 #endif
6030         }
6031     }
6032 
6033     return OMX_ErrorNone;
6034 }
6035 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6036 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6037 {
6038     unsigned int index = 0;
6039 
6040     if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6041         return OMX_ErrorBadParameter;
6042     }
6043 
6044     index = bufferHdr - m_out_mem_ptr;
6045     DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
6046 
6047     if (index < drv_ctx.op_buf.actualcount
6048             && drv_ctx.ptr_outputbuffer) {
6049         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6050                 drv_ctx.ptr_outputbuffer[index].bufferaddr);
6051 
6052         struct vdec_setbuffer_cmd setbuffers;
6053         setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6054         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
6055                 sizeof (vdec_bufferpayload));
6056 
6057         if (!dynamic_buf_mode) {
6058             if (streaming[CAPTURE_PORT] &&
6059                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6060                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6061                     DEBUG_PRINT_ERROR("STREAMOFF Failed");
6062                 } else {
6063                     DEBUG_PRINT_LOW("STREAMOFF Successful");
6064                 }
6065             }
6066 #ifdef _ANDROID_
6067             if (m_enable_android_native_buffers) {
6068                 if (!secure_mode) {
6069                     if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6070                         munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6071                                 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6072                     }
6073                 }
6074                 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6075             } else {
6076 #endif
6077                 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
6078                     if (!secure_mode) {
6079                         DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
6080                                 drv_ctx.ptr_outputbuffer[0].pmem_fd);
6081                         DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
6082                                 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
6083                                 drv_ctx.ptr_outputbuffer[0].bufferaddr);
6084                         munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
6085                                 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
6086                     }
6087                     close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
6088                     drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
6089 #ifdef USE_ION
6090                     free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
6091 #endif
6092                 }
6093 #ifdef _ANDROID_
6094             }
6095 #endif
6096         } //!dynamic_buf_mode
6097         if (release_output_done()) {
6098             free_extradata();
6099         }
6100     }
6101 
6102     return OMX_ErrorNone;
6103 
6104 }
6105 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6106 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
6107         OMX_BUFFERHEADERTYPE **bufferHdr,
6108         OMX_U32              port,
6109         OMX_PTR              appData,
6110         OMX_U32              bytes)
6111 {
6112     OMX_BUFFERHEADERTYPE *input = NULL;
6113     unsigned char *buf_addr = NULL;
6114     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6115     unsigned   i = 0;
6116 
6117     /* Sanity Check*/
6118     if (bufferHdr == NULL) {
6119         return OMX_ErrorBadParameter;
6120     }
6121 
6122     if (m_inp_heap_ptr == NULL) {
6123         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6124                  calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6125                          drv_ctx.ip_buf.actualcount);
6126         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6127                   calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6128                           drv_ctx.ip_buf.actualcount);
6129 
6130         if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6131             DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6132             return OMX_ErrorInsufficientResources;
6133         }
6134     }
6135 
6136     /*Find a Free index*/
6137     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6138         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6139             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6140             break;
6141         }
6142     }
6143 
6144     if (i < drv_ctx.ip_buf.actualcount) {
6145         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6146 
6147         if (buf_addr == NULL) {
6148             return OMX_ErrorInsufficientResources;
6149         }
6150 
6151         *bufferHdr = (m_inp_heap_ptr + i);
6152         input = *bufferHdr;
6153         BITMASK_SET(&m_heap_inp_bm_count,i);
6154 
6155         input->pBuffer           = (OMX_U8 *)buf_addr;
6156         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6157         input->nVersion.nVersion = OMX_SPEC_VERSION;
6158         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6159         input->pAppPrivate       = appData;
6160         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6161         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6162         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6163         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6164         /*Add the Buffers to freeq*/
6165         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6166                     (unsigned)NULL, (unsigned)NULL)) {
6167             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6168             return OMX_ErrorInsufficientResources;
6169         }
6170     } else {
6171         return OMX_ErrorBadParameter;
6172     }
6173 
6174     return eRet;
6175 
6176 }
6177 
6178 
6179 /* ======================================================================
6180    FUNCTION
6181    omx_vdec::AllocateInputBuffer
6182 
6183    DESCRIPTION
6184    Helper function for allocate buffer in the input pin
6185 
6186    PARAMETERS
6187    None.
6188 
6189    RETURN VALUE
6190    true/false
6191 
6192    ========================================================================== */
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)6193 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6194         OMX_IN OMX_HANDLETYPE            hComp,
6195         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6196         OMX_IN OMX_U32                   port,
6197         OMX_IN OMX_PTR                   appData,
6198         OMX_IN OMX_U32                   bytes)
6199 {
6200     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6201     struct vdec_setbuffer_cmd setbuffers;
6202     OMX_BUFFERHEADERTYPE *input = NULL;
6203     unsigned   i = 0;
6204     unsigned char *buf_addr = NULL;
6205     int pmem_fd = -1, ret = 0;
6206     unsigned int align_size = 0;
6207 
6208     (void) hComp;
6209     (void) port;
6210 
6211 
6212     if (bytes != drv_ctx.ip_buf.buffer_size) {
6213         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6214                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6215         return OMX_ErrorBadParameter;
6216     }
6217 
6218     if (!m_inp_mem_ptr) {
6219         struct v4l2_requestbuffers bufreq;
6220         bufreq.memory = V4L2_MEMORY_USERPTR;
6221         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6222         bufreq.count = drv_ctx.ip_buf.actualcount;
6223         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6224         if (ret) {
6225             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %s", strerror(errno));
6226             /*TODO: How to handle this case */
6227             eRet = OMX_ErrorInsufficientResources;
6228         } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6229             DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6230                 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6231             eRet = OMX_ErrorInsufficientResources;
6232         }
6233 
6234         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6235                 drv_ctx.ip_buf.actualcount,
6236                 (unsigned int)drv_ctx.ip_buf.buffer_size);
6237 
6238         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6239                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6240 
6241         if (m_inp_mem_ptr == NULL) {
6242             return OMX_ErrorInsufficientResources;
6243         }
6244 
6245         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6246                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6247 
6248         if (drv_ctx.ptr_inputbuffer == NULL) {
6249             return OMX_ErrorInsufficientResources;
6250         }
6251 #ifdef USE_ION
6252         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6253                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6254 
6255         if (drv_ctx.ip_buf_ion_info == NULL) {
6256             return OMX_ErrorInsufficientResources;
6257         }
6258 #endif
6259 
6260         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6261             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6262 #ifdef USE_ION
6263             drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6264 #endif
6265         }
6266     }
6267 
6268     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6269         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6270             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6271             break;
6272         }
6273     }
6274 
6275     if (i < drv_ctx.ip_buf.actualcount) {
6276         struct v4l2_buffer buf;
6277         struct v4l2_plane plane;
6278         int rc;
6279         DEBUG_PRINT_LOW("Allocate input Buffer");
6280 #ifdef USE_ION
6281         align_size = drv_ctx.ip_buf.buffer_size + 512;
6282         align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6283         drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6284                 align_size, drv_ctx.op_buf.alignment,
6285                 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6286                 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6287                 SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6288         if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6289             return OMX_ErrorInsufficientResources;
6290         }
6291         pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6292 #else
6293         pmem_fd = open (MEM_DEVICE,O_RDWR);
6294 
6295         if (pmem_fd < 0) {
6296             DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6297             return OMX_ErrorInsufficientResources;
6298         }
6299 
6300         if (pmem_fd == 0) {
6301             pmem_fd = open (MEM_DEVICE,O_RDWR);
6302 
6303             if (pmem_fd < 0) {
6304                 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6305                 return OMX_ErrorInsufficientResources;
6306             }
6307         }
6308 
6309         if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6310                     drv_ctx.ip_buf.alignment)) {
6311             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6312             close(pmem_fd);
6313             return OMX_ErrorInsufficientResources;
6314         }
6315 #endif
6316         if (!secure_mode) {
6317             buf_addr = (unsigned char *)mmap(NULL,
6318                     drv_ctx.ip_buf.buffer_size,
6319                     PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6320 
6321             if (buf_addr == MAP_FAILED) {
6322                 close(pmem_fd);
6323 #ifdef USE_ION
6324                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6325 #endif
6326                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6327                 return OMX_ErrorInsufficientResources;
6328             }
6329         }
6330         *bufferHdr = (m_inp_mem_ptr + i);
6331         if (secure_mode)
6332             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6333         else
6334             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6335         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6336         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6337         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6338         drv_ctx.ptr_inputbuffer [i].offset = 0;
6339 
6340 
6341         buf.index = i;
6342         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6343         buf.memory = V4L2_MEMORY_USERPTR;
6344         plane.bytesused = 0;
6345         plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6346         plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6347         plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6348         plane.reserved[1] = 0;
6349         plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6350         buf.m.planes = &plane;
6351         buf.length = 1;
6352 
6353         DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6354                 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6355 
6356         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6357 
6358         if (rc) {
6359             DEBUG_PRINT_ERROR("Failed to prepare bufs");
6360             /*TODO: How to handle this case */
6361             return OMX_ErrorInsufficientResources;
6362         }
6363 
6364         input = *bufferHdr;
6365         BITMASK_SET(&m_inp_bm_count,i);
6366         DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6367         if (allocate_native_handle) {
6368             native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6369             nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6370             input->pBuffer = (OMX_U8 *)nh;
6371         } else if (secure_mode || m_input_pass_buffer_fd) {
6372             /*Legacy method, pass ion fd stashed directly in pBuffer*/
6373             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6374         } else {
6375             input->pBuffer           = (OMX_U8 *)buf_addr;
6376         }
6377         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6378         input->nVersion.nVersion = OMX_SPEC_VERSION;
6379         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6380         input->pAppPrivate       = appData;
6381         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6382         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6383 
6384         if (drv_ctx.disable_dmx) {
6385             eRet = allocate_desc_buffer(i);
6386         }
6387     } else {
6388         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6389         eRet = OMX_ErrorInsufficientResources;
6390     }
6391     return eRet;
6392 }
6393 
6394 
6395 /* ======================================================================
6396    FUNCTION
6397    omx_vdec::AllocateOutputBuffer
6398 
6399    DESCRIPTION
6400    Helper fn for AllocateBuffer in the output pin
6401 
6402    PARAMETERS
6403    <TBD>.
6404 
6405    RETURN VALUE
6406    OMX Error None if everything went well.
6407 
6408    ========================================================================== */
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)6409 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6410         OMX_IN OMX_HANDLETYPE            hComp,
6411         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6412         OMX_IN OMX_U32                   port,
6413         OMX_IN OMX_PTR                   appData,
6414         OMX_IN OMX_U32                   bytes)
6415 {
6416     (void)hComp;
6417     (void)port;
6418     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6419     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6420     unsigned                         i= 0; // Temporary counter
6421     struct vdec_setbuffer_cmd setbuffers;
6422     int extra_idx = 0;
6423 #ifdef USE_ION
6424     int ion_device_fd =-1;
6425     struct ion_allocation_data ion_alloc_data;
6426     struct ion_fd_data fd_ion_data;
6427 #endif
6428     if (!m_out_mem_ptr) {
6429         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6430                 drv_ctx.op_buf.actualcount,
6431                 (unsigned int)drv_ctx.op_buf.buffer_size);
6432         int nBufHdrSize        = 0;
6433         int nPlatformEntrySize = 0;
6434         int nPlatformListSize  = 0;
6435         int nPMEMInfoSize = 0;
6436         int pmem_fd = -1;
6437         unsigned char *pmem_baseaddress = NULL;
6438 
6439         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6440         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6441         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6442 
6443         DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6444                 drv_ctx.op_buf.actualcount);
6445         nBufHdrSize        = drv_ctx.op_buf.actualcount *
6446             sizeof(OMX_BUFFERHEADERTYPE);
6447 
6448         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6449             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6450         nPlatformListSize  = drv_ctx.op_buf.actualcount *
6451             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6452         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6453             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6454 
6455         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6456                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6457                 nPMEMInfoSize,
6458                 nPlatformListSize);
6459         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6460                 drv_ctx.op_buf.actualcount);
6461 #ifdef USE_ION
6462         // Allocate output buffers as cached to improve performance of software-reading
6463         // of the YUVs. Output buffers are cache-invalidated in driver.
6464         // If color-conversion is involved, Only the C2D output buffers are cached, no
6465         // need to cache the decoder's output buffers
6466         int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6467         ion_device_fd = alloc_map_ion_memory(
6468                 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
6469                 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6470                 &ion_alloc_data, &fd_ion_data,
6471                 (secure_mode && !secure_scaling_to_non_secure_opb) ?
6472                 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6473         if (ion_device_fd < 0) {
6474             return OMX_ErrorInsufficientResources;
6475         }
6476         pmem_fd = fd_ion_data.fd;
6477 #else
6478         pmem_fd = open (MEM_DEVICE,O_RDWR);
6479 
6480         if (pmem_fd < 0) {
6481             DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6482                     drv_ctx.op_buf.buffer_size);
6483             return OMX_ErrorInsufficientResources;
6484         }
6485 
6486         if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
6487                     drv_ctx.op_buf.actualcount,
6488                     drv_ctx.op_buf.alignment)) {
6489             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6490             close(pmem_fd);
6491             return OMX_ErrorInsufficientResources;
6492         }
6493 #endif
6494         if (!secure_mode) {
6495             pmem_baseaddress = (unsigned char *)mmap(NULL,
6496                     (drv_ctx.op_buf.buffer_size *
6497                      drv_ctx.op_buf.actualcount),
6498                     PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
6499             if (pmem_baseaddress == MAP_FAILED) {
6500                 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6501                         (unsigned int)drv_ctx.op_buf.buffer_size);
6502                 close(pmem_fd);
6503 #ifdef USE_ION
6504                 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6505 #endif
6506                 return OMX_ErrorInsufficientResources;
6507             }
6508         }
6509         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
6510         // Alloc mem for platform specific info
6511         char *pPtr=NULL;
6512         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6513                 nPMEMInfoSize,1);
6514         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6515                        calloc (sizeof(struct vdec_bufferpayload),
6516                                drv_ctx.op_buf.actualcount);
6517         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
6518                      calloc (sizeof (struct vdec_output_frameinfo),
6519                              drv_ctx.op_buf.actualcount);
6520         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6521             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6522             return OMX_ErrorInsufficientResources;
6523         }
6524 
6525 #ifdef USE_ION
6526         drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6527                       calloc (sizeof(struct vdec_ion),
6528                               drv_ctx.op_buf.actualcount);
6529         if (!drv_ctx.op_buf_ion_info) {
6530             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6531             return OMX_ErrorInsufficientResources;
6532         }
6533 #endif
6534 
6535         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6536                 && drv_ctx.ptr_respbuffer) {
6537             drv_ctx.ptr_outputbuffer[0].mmaped_size =
6538                 (drv_ctx.op_buf.buffer_size *
6539                  drv_ctx.op_buf.actualcount);
6540             bufHdr          =  m_out_mem_ptr;
6541             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6542             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6543                 (((char *) m_platform_list)  + nPlatformListSize);
6544             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6545                 (((char *) m_platform_entry) + nPlatformEntrySize);
6546             pPlatformList   = m_platform_list;
6547             pPlatformEntry  = m_platform_entry;
6548             pPMEMInfo       = m_pmem_info;
6549 
6550             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6551 
6552             // Settting the entire storage nicely
6553             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
6554             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
6555             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6556                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6557                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6558                 // Set the values when we determine the right HxW param
6559                 bufHdr->nAllocLen          = bytes;
6560                 bufHdr->nFilledLen         = 0;
6561                 bufHdr->pAppPrivate        = appData;
6562                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
6563                 // Platform specific PMEM Information
6564                 // Initialize the Platform Entry
6565                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6566                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6567                 pPlatformEntry->entry      = pPMEMInfo;
6568                 // Initialize the Platform List
6569                 pPlatformList->nEntries    = 1;
6570                 pPlatformList->entryList   = pPlatformEntry;
6571                 // Keep pBuffer NULL till vdec is opened
6572                 bufHdr->pBuffer            = NULL;
6573                 bufHdr->nOffset            = 0;
6574 
6575                 pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
6576                 pPMEMInfo->pmem_fd = -1;
6577                 bufHdr->pPlatformPrivate = pPlatformList;
6578 
6579                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
6580                 m_pmem_info[i].pmem_fd = pmem_fd;
6581 #ifdef USE_ION
6582                 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
6583                 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
6584                 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
6585 #endif
6586 
6587                 /*Create a mapping between buffers*/
6588                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
6589                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
6590                                     &drv_ctx.ptr_outputbuffer[i];
6591                 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
6592                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6593                     pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
6594                 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6595                 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6596                 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6597 
6598                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
6599                         pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
6600                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
6601                 // Move the buffer and buffer header pointers
6602                 bufHdr++;
6603                 pPMEMInfo++;
6604                 pPlatformEntry++;
6605                 pPlatformList++;
6606             }
6607         } else {
6608             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6609                     m_out_mem_ptr, pPtr);
6610             if (m_out_mem_ptr) {
6611                 free(m_out_mem_ptr);
6612                 m_out_mem_ptr = NULL;
6613             }
6614             if (pPtr) {
6615                 free(pPtr);
6616                 pPtr = NULL;
6617             }
6618             if (drv_ctx.ptr_outputbuffer) {
6619                 free(drv_ctx.ptr_outputbuffer);
6620                 drv_ctx.ptr_outputbuffer = NULL;
6621             }
6622             if (drv_ctx.ptr_respbuffer) {
6623                 free(drv_ctx.ptr_respbuffer);
6624                 drv_ctx.ptr_respbuffer = NULL;
6625             }
6626 #ifdef USE_ION
6627             if (drv_ctx.op_buf_ion_info) {
6628                 DEBUG_PRINT_LOW("Free o/p ion context");
6629                 free(drv_ctx.op_buf_ion_info);
6630                 drv_ctx.op_buf_ion_info = NULL;
6631             }
6632 #endif
6633             eRet =  OMX_ErrorInsufficientResources;
6634         }
6635         if (eRet == OMX_ErrorNone)
6636             eRet = allocate_extradata();
6637     }
6638 
6639     for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6640         if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6641             DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
6642             break;
6643         }
6644     }
6645 
6646     if (eRet == OMX_ErrorNone) {
6647         if (i < drv_ctx.op_buf.actualcount) {
6648             struct v4l2_buffer buf;
6649             struct v4l2_plane plane[VIDEO_MAX_PLANES];
6650             int rc;
6651             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6652 
6653             drv_ctx.ptr_outputbuffer[i].buffer_len =
6654                 drv_ctx.op_buf.buffer_size;
6655 
6656             *bufferHdr = (m_out_mem_ptr + i );
6657             if (secure_mode) {
6658 #ifdef USE_ION
6659                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6660                     (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6661 #else
6662                 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6663 #endif
6664             }
6665             drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6666 
6667             buf.index = i;
6668             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6669             buf.memory = V4L2_MEMORY_USERPTR;
6670             plane[0].length = drv_ctx.op_buf.buffer_size;
6671             plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6672                 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6673 #ifdef USE_ION
6674             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6675 #endif
6676             plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6677             plane[0].data_offset = 0;
6678             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6679             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6680                 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6681                 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6682 #ifdef USE_ION
6683                 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6684 #endif
6685                 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6686                 plane[extra_idx].data_offset = 0;
6687             } else if (extra_idx >= VIDEO_MAX_PLANES) {
6688                 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
6689                 return OMX_ErrorBadParameter;
6690             }
6691             buf.m.planes = plane;
6692             buf.length = drv_ctx.num_planes;
6693             DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
6694             rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6695             if (rc) {
6696                 /*TODO: How to handle this case */
6697                 return OMX_ErrorInsufficientResources;
6698             }
6699 
6700             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6701                 enum v4l2_buf_type buf_type;
6702                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6703                 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6704                 if (rc) {
6705                     return OMX_ErrorInsufficientResources;
6706                 } else {
6707                     streaming[CAPTURE_PORT] = true;
6708                     DEBUG_PRINT_LOW("STREAMON Successful");
6709                 }
6710 
6711                 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6712                 request_perf_level(VIDC_TURBO);
6713             }
6714 
6715             (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
6716             (*bufferHdr)->pAppPrivate = appData;
6717             BITMASK_SET(&m_out_bm_count,i);
6718         } else {
6719             DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
6720             eRet = OMX_ErrorInsufficientResources;
6721         }
6722     }
6723 
6724     return eRet;
6725 }
6726 
6727 
6728 // AllocateBuffer  -- API Call
6729 /* ======================================================================
6730    FUNCTION
6731    omx_vdec::AllocateBuffer
6732 
6733    DESCRIPTION
6734    Returns zero if all the buffers released..
6735 
6736    PARAMETERS
6737    None.
6738 
6739    RETURN VALUE
6740    true/false
6741 
6742    ========================================================================== */
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)6743 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
6744         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6745         OMX_IN OMX_U32                        port,
6746         OMX_IN OMX_PTR                     appData,
6747         OMX_IN OMX_U32                       bytes)
6748 {
6749     unsigned i = 0;
6750     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
6751 
6752     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
6753     if (m_state == OMX_StateInvalid) {
6754         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
6755         return OMX_ErrorInvalidState;
6756     }
6757 
6758     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6759         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6760         // ensure that use-buffer was never called.
6761         // Mix-and-match of useBuffer and allocateBuffer is not allowed
6762         if (m_inp_mem_ptr && input_use_buffer) {
6763             DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
6764             return OMX_ErrorUndefined;
6765         }
6766         if (arbitrary_bytes) {
6767             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
6768         } else {
6769             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
6770         }
6771     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6772         if (output_use_buffer) {
6773             DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
6774             return OMX_ErrorBadParameter;
6775         }
6776         eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
6777                 appData,bytes);
6778     } else {
6779         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6780         eRet = OMX_ErrorBadPortIndex;
6781     }
6782     DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
6783     if (eRet == OMX_ErrorNone) {
6784         if (allocate_done()) {
6785             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6786                 // Send the callback now
6787                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6788                 post_event(OMX_CommandStateSet,OMX_StateIdle,
6789                         OMX_COMPONENT_GENERATE_EVENT);
6790             }
6791         }
6792         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
6793             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6794                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6795                 post_event(OMX_CommandPortEnable,
6796                         OMX_CORE_INPUT_PORT_INDEX,
6797                         OMX_COMPONENT_GENERATE_EVENT);
6798             }
6799         }
6800         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
6801             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6802                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6803                 post_event(OMX_CommandPortEnable,
6804                         OMX_CORE_OUTPUT_PORT_INDEX,
6805                         OMX_COMPONENT_GENERATE_EVENT);
6806             }
6807         }
6808     }
6809     DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
6810     return eRet;
6811 }
6812 
6813 // Free Buffer - API call
6814 /* ======================================================================
6815    FUNCTION
6816    omx_vdec::FreeBuffer
6817 
6818    DESCRIPTION
6819 
6820    PARAMETERS
6821    None.
6822 
6823    RETURN VALUE
6824    true/false
6825 
6826    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6827 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6828         OMX_IN OMX_U32                 port,
6829         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6830 {
6831     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6832     unsigned int nPortIndex;
6833     (void) hComp;
6834     DEBUG_PRINT_LOW("In for decoder free_buffer");
6835 
6836     auto_lock l(buf_lock);
6837     if (m_state == OMX_StateIdle &&
6838             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6839         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
6840     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
6841             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
6842         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
6843     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
6844                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
6845             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
6846              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
6847         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
6848     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
6849         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
6850         post_event(OMX_EventError,
6851                 OMX_ErrorPortUnpopulated,
6852                 OMX_COMPONENT_GENERATE_EVENT);
6853         m_buffer_error = true;
6854         return OMX_ErrorIncorrectStateOperation;
6855     } else if (m_state != OMX_StateInvalid) {
6856         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6857         post_event(OMX_EventError,
6858                 OMX_ErrorPortUnpopulated,
6859                 OMX_COMPONENT_GENERATE_EVENT);
6860     }
6861 
6862     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6863         /*Check if arbitrary bytes*/
6864         if (!arbitrary_bytes && !input_use_buffer)
6865             nPortIndex = buffer - m_inp_mem_ptr;
6866         else
6867             nPortIndex = buffer - m_inp_heap_ptr;
6868 
6869         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6870         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6871                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6872             // Clear the bit associated with it.
6873             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6874             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6875             if (input_use_buffer == true) {
6876 
6877                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6878                 if (m_phdr_pmem_ptr)
6879                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6880             } else {
6881                 if (arbitrary_bytes) {
6882                     if (m_phdr_pmem_ptr)
6883                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
6884                     else
6885                         free_input_buffer(nPortIndex,NULL);
6886                 } else
6887                     free_input_buffer(buffer);
6888             }
6889             m_inp_bPopulated = OMX_FALSE;
6890             if(release_input_done())
6891                 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
6892             /*Free the Buffer Header*/
6893             if (release_input_done()) {
6894                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6895                 free_input_buffer_header();
6896             }
6897         } else {
6898             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6899             eRet = OMX_ErrorBadPortIndex;
6900         }
6901 
6902         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6903                 && release_input_done()) {
6904             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6905             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6906             post_event(OMX_CommandPortDisable,
6907                     OMX_CORE_INPUT_PORT_INDEX,
6908                     OMX_COMPONENT_GENERATE_EVENT);
6909         }
6910     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6911         // check if the buffer is valid
6912         nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6913         if (nPortIndex < drv_ctx.op_buf.actualcount &&
6914                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6915             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6916             // Clear the bit associated with it.
6917             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6918             m_out_bPopulated = OMX_FALSE;
6919             client_buffers.free_output_buffer (buffer);
6920 
6921             if(release_output_done()) {
6922                 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
6923             }
6924             if (release_output_done()) {
6925                 free_output_buffer_header();
6926             }
6927         } else {
6928             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6929             eRet = OMX_ErrorBadPortIndex;
6930         }
6931         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6932                 && release_output_done()) {
6933             DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
6934 
6935             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6936             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6937 #ifdef _ANDROID_ICS_
6938             if (m_enable_android_native_buffers) {
6939                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6940                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6941             }
6942 #endif
6943 
6944             post_event(OMX_CommandPortDisable,
6945                     OMX_CORE_OUTPUT_PORT_INDEX,
6946                     OMX_COMPONENT_GENERATE_EVENT);
6947         }
6948     } else {
6949         eRet = OMX_ErrorBadPortIndex;
6950     }
6951     if ((eRet == OMX_ErrorNone) &&
6952             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6953         if (release_done()) {
6954             // Send the callback now
6955             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6956             post_event(OMX_CommandStateSet, OMX_StateLoaded,
6957                     OMX_COMPONENT_GENERATE_EVENT);
6958             m_buffer_error = false;
6959         }
6960     }
6961     return eRet;
6962 }
6963 
6964 
6965 /* ======================================================================
6966    FUNCTION
6967    omx_vdec::EmptyThisBuffer
6968 
6969    DESCRIPTION
6970    This routine is used to push the encoded video frames to
6971    the video decoder.
6972 
6973    PARAMETERS
6974    None.
6975 
6976    RETURN VALUE
6977    OMX Error None if everything went successful.
6978 
6979    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6980 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
6981         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6982 {
6983     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6984     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6985 
6986     if (m_state != OMX_StateExecuting &&
6987             m_state != OMX_StatePause &&
6988             m_state != OMX_StateIdle) {
6989         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6990         return OMX_ErrorInvalidState;
6991     }
6992 
6993     if (buffer == NULL) {
6994         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6995         return OMX_ErrorBadParameter;
6996     }
6997 
6998     if (!m_inp_bEnabled) {
6999         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7000         return OMX_ErrorIncorrectStateOperation;
7001     }
7002 
7003     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7004         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7005         return OMX_ErrorBadPortIndex;
7006     }
7007 
7008     if (perf_flag) {
7009         if (!latency) {
7010             dec_time.stop();
7011             latency = dec_time.processing_time_us();
7012             dec_time.start();
7013         }
7014     }
7015 
7016     if (arbitrary_bytes) {
7017         nBufferIndex = buffer - m_inp_heap_ptr;
7018     } else {
7019         if (input_use_buffer == true) {
7020             nBufferIndex = buffer - m_inp_heap_ptr;
7021             if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7022                 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7023                 return OMX_ErrorBadParameter;
7024             }
7025             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7026             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7027             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7028             buffer = &m_inp_mem_ptr[nBufferIndex];
7029             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7030                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7031         } else {
7032             nBufferIndex = buffer - m_inp_mem_ptr;
7033         }
7034     }
7035 
7036     if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7037         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7038         return OMX_ErrorBadParameter;
7039     }
7040 
7041     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7042         codec_config_flag = true;
7043         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7044     }
7045 
7046     /* The client should not set this when codec is in arbitrary bytes mode */
7047     if (m_input_pass_buffer_fd) {
7048         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7049     }
7050 
7051     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7052             buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7053     if (arbitrary_bytes) {
7054         post_event ((unsigned long)hComp,(unsigned long)buffer,
7055                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7056     } else {
7057         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7058     }
7059     time_stamp_dts.insert_timestamp(buffer);
7060     return OMX_ErrorNone;
7061 }
7062 
7063 /* ======================================================================
7064    FUNCTION
7065    omx_vdec::empty_this_buffer_proxy
7066 
7067    DESCRIPTION
7068    This routine is used to push the encoded video frames to
7069    the video decoder.
7070 
7071    PARAMETERS
7072    None.
7073 
7074    RETURN VALUE
7075    OMX Error None if everything went successful.
7076 
7077    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7078 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
7079         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7080 {
7081     (void) hComp;
7082     int push_cnt = 0,i=0;
7083     unsigned nPortIndex = 0;
7084     OMX_ERRORTYPE ret = OMX_ErrorNone;
7085     struct vdec_input_frameinfo frameinfo;
7086     struct vdec_bufferpayload *temp_buffer;
7087     struct vdec_seqheader seq_header;
7088     bool port_setting_changed = true;
7089 
7090     /*Should we generate a Aync error event*/
7091     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7092         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7093         return OMX_ErrorBadParameter;
7094     }
7095 
7096     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7097 
7098     if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7099         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7100                 nPortIndex);
7101         return OMX_ErrorBadParameter;
7102     }
7103 
7104     pending_input_buffers++;
7105 
7106     /* return zero length and not an EOS buffer */
7107     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7108             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7109         DEBUG_PRINT_HIGH("return zero legth buffer");
7110         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7111                 OMX_COMPONENT_GENERATE_EBD);
7112         return OMX_ErrorNone;
7113     }
7114 
7115     if (input_flush_progress == true) {
7116         DEBUG_PRINT_LOW("Flush in progress return buffer ");
7117         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7118                 OMX_COMPONENT_GENERATE_EBD);
7119         return OMX_ErrorNone;
7120     }
7121 
7122     auto_lock l(buf_lock);
7123     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7124 
7125     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7126         return OMX_ErrorBadParameter;
7127     }
7128 
7129     if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7130         DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7131         return OMX_ErrorBadParameter;
7132     }
7133     /* If its first frame, H264 codec and reject is true, then parse the nal
7134        and get the profile. Based on this, reject the clip playback */
7135     if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
7136             m_reject_avc_1080p_mp) {
7137         first_frame = 1;
7138         DEBUG_PRINT_ERROR("Parse nal to get the profile");
7139         h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
7140                 NALU_TYPE_SPS);
7141         m_profile = h264_parser->get_profile();
7142         ret = is_video_session_supported();
7143         if (ret) {
7144             post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7145             post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7146             /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7147             m_state = OMX_StateInvalid;
7148             return OMX_ErrorNone;
7149         }
7150     }
7151 
7152     DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7153     /*for use buffer we need to memcpy the data*/
7154     temp_buffer->buffer_len = buffer->nFilledLen;
7155 
7156     if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7157         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7158             if (arbitrary_bytes) {
7159                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7160             } else {
7161                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7162                         buffer->nFilledLen);
7163             }
7164         } else {
7165             return OMX_ErrorBadParameter;
7166         }
7167 
7168     }
7169 
7170     frameinfo.bufferaddr = temp_buffer->bufferaddr;
7171     frameinfo.client_data = (void *) buffer;
7172     frameinfo.datalen = temp_buffer->buffer_len;
7173     frameinfo.flags = 0;
7174     frameinfo.offset = buffer->nOffset;
7175     frameinfo.pmem_fd = temp_buffer->pmem_fd;
7176     frameinfo.pmem_offset = temp_buffer->offset;
7177     frameinfo.timestamp = buffer->nTimeStamp;
7178     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7179         DEBUG_PRINT_LOW("ETB: dmx enabled");
7180         if (m_demux_entries == 0) {
7181             extract_demux_addr_offsets(buffer);
7182         }
7183 
7184         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7185         handle_demux_data(buffer);
7186         frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7187         frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7188     } else {
7189         frameinfo.desc_addr = NULL;
7190         frameinfo.desc_size = 0;
7191     }
7192     if (!arbitrary_bytes) {
7193         frameinfo.flags |= buffer->nFlags;
7194     }
7195 
7196 #ifdef _ANDROID_
7197     if (m_debug_timestamp) {
7198         if (arbitrary_bytes) {
7199             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7200             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7201         } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7202             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7203             m_timestamp_list.insert_ts(buffer->nTimeStamp);
7204         }
7205     }
7206 #endif
7207 
7208     log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7209 
7210 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7211         frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7212         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7213     }
7214 
7215     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7216         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7217         frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7218         h264_scratch.nFilledLen = 0;
7219         nal_count = 0;
7220         look_ahead_nal = false;
7221         frame_count = 0;
7222         if (m_frame_parser.mutils)
7223             m_frame_parser.mutils->initialize_frame_checking_environment();
7224         m_frame_parser.flush();
7225         h264_last_au_ts = LLONG_MAX;
7226         h264_last_au_flags = 0;
7227         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7228         m_demux_entries = 0;
7229     }
7230     struct v4l2_buffer buf;
7231     struct v4l2_plane plane;
7232     memset( (void *)&buf, 0, sizeof(buf));
7233     memset( (void *)&plane, 0, sizeof(plane));
7234     int rc;
7235     unsigned long  print_count;
7236     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7237         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7238         DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7239     }
7240     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7241     buf.index = nPortIndex;
7242     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7243     buf.memory = V4L2_MEMORY_USERPTR;
7244     plane.bytesused = temp_buffer->buffer_len;
7245     plane.length = drv_ctx.ip_buf.buffer_size;
7246     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7247         (unsigned long)temp_buffer->offset;
7248     plane.reserved[0] = temp_buffer->pmem_fd;
7249     plane.reserved[1] = temp_buffer->offset;
7250     plane.data_offset = 0;
7251     buf.m.planes = &plane;
7252     buf.length = 1;
7253     if (frameinfo.timestamp >= LLONG_MAX) {
7254         buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7255     }
7256     //assumption is that timestamp is in milliseconds
7257     buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7258     buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7259     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7260     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7261 
7262     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7263         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7264         android_atomic_inc(&m_queued_codec_config_count);
7265     }
7266 
7267     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7268     if (rc) {
7269         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
7270         return OMX_ErrorHardware;
7271     }
7272 
7273     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7274         codec_config_flag = false;
7275     }
7276     if (!streaming[OUTPUT_PORT]) {
7277         enum v4l2_buf_type buf_type;
7278         int ret,r;
7279 
7280         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7281         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7282         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7283         if (!ret) {
7284             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7285             streaming[OUTPUT_PORT] = true;
7286         } else if (errno == EBUSY) {
7287             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7288             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7289                     OMX_COMPONENT_GENERATE_EBD);
7290             return OMX_ErrorInsufficientResources;
7291         } else {
7292             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7293             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7294             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7295                     OMX_COMPONENT_GENERATE_EBD);
7296             return OMX_ErrorBadParameter;
7297         }
7298     }
7299     DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7300             frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7301             (unsigned int)frameinfo.datalen);
7302 
7303     return ret;
7304 }
7305 
7306 /* ======================================================================
7307    FUNCTION
7308    omx_vdec::FillThisBuffer
7309 
7310    DESCRIPTION
7311    IL client uses this method to release the frame buffer
7312    after displaying them.
7313 
7314    PARAMETERS
7315    None.
7316 
7317    RETURN VALUE
7318    true/false
7319 
7320    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7321 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7322         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7323 {
7324     if (m_state != OMX_StateExecuting &&
7325             m_state != OMX_StatePause &&
7326             m_state != OMX_StateIdle) {
7327         DEBUG_PRINT_ERROR("FTB in Invalid State");
7328         return OMX_ErrorInvalidState;
7329     }
7330 
7331     if (!m_out_bEnabled) {
7332         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7333         return OMX_ErrorIncorrectStateOperation;
7334     }
7335 
7336     unsigned nPortIndex = 0;
7337     if (dynamic_buf_mode) {
7338         private_handle_t *handle = NULL;
7339         struct VideoDecoderOutputMetaData *meta;
7340         unsigned int nPortIndex = 0;
7341 
7342         if (!buffer || !buffer->pBuffer) {
7343             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7344             return OMX_ErrorBadParameter;
7345         }
7346 
7347         //get the buffer type and fd info
7348         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7349         handle = (private_handle_t *)meta->pHandle;
7350         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7351 
7352         if (!handle) {
7353             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7354             return OMX_ErrorBadParameter;
7355         }
7356         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7357         nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7358         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7359             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7360             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7361             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7362 
7363            //Store private handle from GraphicBuffer
7364             native_buffer[nPortIndex].privatehandle = handle;
7365             native_buffer[nPortIndex].nativehandle = handle;
7366         } else {
7367             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7368             return OMX_ErrorBadParameter;
7369         }
7370 
7371         //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7372         //this with a more sane size so that we don't compensate in rest of code
7373         //We'll restore this size later on, so that it's transparent to client
7374         buffer->nFilledLen = 0;
7375         buffer->nAllocLen = handle->size;
7376         drv_ctx.op_buf.buffer_size = handle->size;
7377     }
7378 
7379     nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7380     if (buffer == NULL ||
7381             (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7382         DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7383             nPortIndex, drv_ctx.op_buf.actualcount);
7384         return OMX_ErrorBadParameter;
7385     }
7386 
7387     if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7388         DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7389         return OMX_ErrorBadPortIndex;
7390     }
7391 
7392     DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7393     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7394     return OMX_ErrorNone;
7395 }
7396 /* ======================================================================
7397    FUNCTION
7398    omx_vdec::fill_this_buffer_proxy
7399 
7400    DESCRIPTION
7401    IL client uses this method to release the frame buffer
7402    after displaying them.
7403 
7404    PARAMETERS
7405    None.
7406 
7407    RETURN VALUE
7408    true/false
7409 
7410    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7411 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
7412         OMX_IN OMX_HANDLETYPE        hComp,
7413         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7414 {
7415     OMX_ERRORTYPE nRet = OMX_ErrorNone;
7416     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7417     unsigned nPortIndex = 0;
7418     struct vdec_fillbuffer_cmd fillbuffer;
7419     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
7420     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
7421 
7422     auto_lock l(buf_lock);
7423     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7424 
7425     if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
7426         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7427             nPortIndex, drv_ctx.op_buf.actualcount);
7428         return OMX_ErrorBadParameter;
7429     }
7430 
7431     if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
7432         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7433         return OMX_ErrorBadParameter;
7434     }
7435     DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
7436             bufferAdd, bufferAdd->pBuffer);
7437     /*Return back the output buffer to client*/
7438     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
7439         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7440         buffer->nFilledLen = 0;
7441         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7442         return OMX_ErrorNone;
7443     }
7444 
7445     if (dynamic_buf_mode) {
7446         drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7447         drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7448         buf_ref_add(nPortIndex);
7449         drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7450     }
7451 
7452     pending_output_buffers++;
7453     buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7454     if (!buffer) {
7455        DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7456        return OMX_ErrorBadParameter;
7457     }
7458     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7459     if (ptr_respbuffer) {
7460         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7461     }
7462 
7463     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7464         DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
7465         buffer->nFilledLen = 0;
7466         m_cb.FillBufferDone (hComp,m_app_data,buffer);
7467         pending_output_buffers--;
7468         return OMX_ErrorBadParameter;
7469     }
7470 
7471     int rc = 0;
7472     struct v4l2_buffer buf;
7473     struct v4l2_plane plane[VIDEO_MAX_PLANES];
7474     memset( (void *)&buf, 0, sizeof(buf));
7475     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7476     unsigned int extra_idx = 0;
7477 
7478     buf.index = nPortIndex;
7479     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7480     buf.memory = V4L2_MEMORY_USERPTR;
7481     plane[0].bytesused = buffer->nFilledLen;
7482     plane[0].length = buffer->nAllocLen;
7483     plane[0].m.userptr =
7484         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7485         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7486     plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7487     plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7488     plane[0].data_offset = 0;
7489     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7490     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7491         plane[extra_idx].bytesused = 0;
7492         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7493         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7494 #ifdef USE_ION
7495         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7496 #endif
7497         plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7498         plane[extra_idx].data_offset = 0;
7499     } else if (extra_idx >= VIDEO_MAX_PLANES) {
7500         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7501         return OMX_ErrorBadParameter;
7502     }
7503     buf.m.planes = plane;
7504     buf.length = drv_ctx.num_planes;
7505     DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
7506              plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
7507 
7508     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7509     if (rc) {
7510         /*TODO: How to handle this case */
7511         DEBUG_PRINT_ERROR("Failed to qbuf to driver");
7512     }
7513 return OMX_ErrorNone;
7514 }
7515 
7516 /* ======================================================================
7517    FUNCTION
7518    omx_vdec::SetCallbacks
7519 
7520    DESCRIPTION
7521    Set the callbacks.
7522 
7523    PARAMETERS
7524    None.
7525 
7526    RETURN VALUE
7527    OMX Error None if everything successful.
7528 
7529    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7530 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
7531         OMX_IN OMX_CALLBACKTYPE* callbacks,
7532         OMX_IN OMX_PTR             appData)
7533 {
7534     (void) hComp;
7535     m_cb       = *callbacks;
7536     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7537             m_cb.EventHandler,m_cb.FillBufferDone);
7538     m_app_data =    appData;
7539     return OMX_ErrorNotImplemented;
7540 }
7541 
7542 /* ======================================================================
7543    FUNCTION
7544    omx_vdec::ComponentDeInit
7545 
7546    DESCRIPTION
7547    Destroys the component and release memory allocated to the heap.
7548 
7549    PARAMETERS
7550    <TBD>.
7551 
7552    RETURN VALUE
7553    OMX Error None if everything successful.
7554 
7555    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7556 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7557 {
7558    (void) hComp;
7559 
7560     unsigned i = 0;
7561     if (OMX_StateLoaded != m_state) {
7562         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7563                 m_state);
7564         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7565     } else {
7566         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7567     }
7568 
7569     /*Check if the output buffers have to be cleaned up*/
7570     if (m_out_mem_ptr) {
7571         DEBUG_PRINT_LOW("Freeing the Output Memory");
7572         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7573             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7574                 BITMASK_CLEAR(&m_out_bm_count, i);
7575                 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
7576             }
7577 
7578             if (release_output_done()) {
7579                 break;
7580             }
7581         }
7582 #ifdef _ANDROID_ICS_
7583         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7584 #endif
7585     }
7586 
7587     /*Check if the input buffers have to be cleaned up*/
7588     if (m_inp_mem_ptr || m_inp_heap_ptr) {
7589         DEBUG_PRINT_LOW("Freeing the Input Memory");
7590         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7591 
7592             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7593                 BITMASK_CLEAR(&m_inp_bm_count, i);
7594                 if (m_inp_mem_ptr)
7595                     free_input_buffer (i,&m_inp_mem_ptr[i]);
7596                 else
7597                     free_input_buffer (i,NULL);
7598             }
7599 
7600             if (release_input_done()) {
7601                 break;
7602             }
7603        }
7604     }
7605     free_input_buffer_header();
7606     free_output_buffer_header();
7607     if (h264_scratch.pBuffer) {
7608         free(h264_scratch.pBuffer);
7609         h264_scratch.pBuffer = NULL;
7610     }
7611 
7612     if (h264_parser) {
7613         delete h264_parser;
7614         h264_parser = NULL;
7615     }
7616 
7617     if (m_frame_parser.mutils) {
7618         DEBUG_PRINT_LOW("Free utils parser");
7619         delete (m_frame_parser.mutils);
7620         m_frame_parser.mutils = NULL;
7621     }
7622 
7623     if (m_platform_list) {
7624         free(m_platform_list);
7625         m_platform_list = NULL;
7626     }
7627     if (m_vendor_config.pData) {
7628         free(m_vendor_config.pData);
7629         m_vendor_config.pData = NULL;
7630     }
7631 
7632     // Reset counters in mesg queues
7633     m_ftb_q.m_size=0;
7634     m_cmd_q.m_size=0;
7635     m_etb_q.m_size=0;
7636     m_ftb_q.m_read = m_ftb_q.m_write =0;
7637     m_cmd_q.m_read = m_cmd_q.m_write =0;
7638     m_etb_q.m_read = m_etb_q.m_write =0;
7639 #ifdef _ANDROID_
7640     if (m_debug_timestamp) {
7641         m_timestamp_list.reset_ts_list();
7642     }
7643 #endif
7644 
7645     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7646     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7647     // NULL);
7648     DEBUG_PRINT_HIGH("Close the driver instance");
7649 
7650     if (m_debug.infile) {
7651         fclose(m_debug.infile);
7652         m_debug.infile = NULL;
7653     }
7654     if (m_debug.outfile) {
7655         fclose(m_debug.outfile);
7656         m_debug.outfile = NULL;
7657     }
7658     if (m_debug.out_ymeta_file) {
7659         fclose(m_debug.out_ymeta_file);
7660         m_debug.out_ymeta_file = NULL;
7661     }
7662     if (m_debug.out_uvmeta_file) {
7663         fclose(m_debug.out_uvmeta_file);
7664         m_debug.out_uvmeta_file = NULL;
7665     }
7666 #ifdef OUTPUT_EXTRADATA_LOG
7667     if (outputExtradataFile)
7668         fclose (outputExtradataFile);
7669 #endif
7670     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
7671     return OMX_ErrorNone;
7672 }
7673 
7674 /* ======================================================================
7675    FUNCTION
7676    omx_vdec::UseEGLImage
7677 
7678    DESCRIPTION
7679    OMX Use EGL Image method implementation <TBD>.
7680 
7681    PARAMETERS
7682    <TBD>.
7683 
7684    RETURN VALUE
7685    Not Implemented error.
7686 
7687    ========================================================================== */
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)7688 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
7689         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7690         OMX_IN OMX_U32                        port,
7691         OMX_IN OMX_PTR                     appData,
7692         OMX_IN void*                      eglImage)
7693 {
7694     (void) appData;
7695     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
7696     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
7697     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
7698 
7699 #ifdef USE_EGL_IMAGE_GPU
7700     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
7701     EGLint fd = -1, offset = 0,pmemPtr = 0;
7702 #else
7703     int fd = -1, offset = 0;
7704 #endif
7705     DEBUG_PRINT_HIGH("use EGL image support for decoder");
7706     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
7707         DEBUG_PRINT_ERROR("Invalid EGL image");
7708     }
7709 #ifdef USE_EGL_IMAGE_GPU
7710     if (m_display_id == NULL) {
7711         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
7712         return OMX_ErrorInsufficientResources;
7713     }
7714     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
7715         eglGetProcAddress("eglQueryImageKHR");
7716     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
7717     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
7718     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
7719 #else //with OMX test app
7720     struct temp_egl {
7721         int pmem_fd;
7722         int offset;
7723     };
7724     struct temp_egl *temp_egl_id = NULL;
7725     void * pmemPtr = (void *) eglImage;
7726     temp_egl_id = (struct temp_egl *)eglImage;
7727     if (temp_egl_id != NULL) {
7728         fd = temp_egl_id->pmem_fd;
7729         offset = temp_egl_id->offset;
7730     }
7731 #endif
7732     if (fd < 0) {
7733         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
7734         return OMX_ErrorInsufficientResources;
7735     }
7736     pmem_info.pmem_fd = (OMX_U32) fd;
7737     pmem_info.offset = (OMX_U32) offset;
7738     pmem_entry.entry = (void *) &pmem_info;
7739     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7740     pmem_list.entryList = &pmem_entry;
7741     pmem_list.nEntries = 1;
7742     ouput_egl_buffers = true;
7743     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
7744                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
7745                 (OMX_U8 *)pmemPtr)) {
7746         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
7747         return OMX_ErrorInsufficientResources;
7748     }
7749     return OMX_ErrorNone;
7750 }
7751 
7752 /* ======================================================================
7753    FUNCTION
7754    omx_vdec::ComponentRoleEnum
7755 
7756    DESCRIPTION
7757    OMX Component Role Enum method implementation.
7758 
7759    PARAMETERS
7760    <TBD>.
7761 
7762    RETURN VALUE
7763    OMX Error None if everything is successful.
7764    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)7765 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
7766         OMX_OUT OMX_U8*        role,
7767         OMX_IN OMX_U32        index)
7768 {
7769     (void) hComp;
7770     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7771 
7772     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
7773         if ((0 == index) && role) {
7774             strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
7775             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7776         } else {
7777             eRet = OMX_ErrorNoMore;
7778         }
7779     }
7780     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
7781         if ((0 == index) && role) {
7782             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
7783             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7784         } else {
7785             eRet = OMX_ErrorNoMore;
7786         }
7787     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
7788         if ((0 == index) && role) {
7789             strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
7790             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7791         } else {
7792             DEBUG_PRINT_LOW("No more roles");
7793             eRet = OMX_ErrorNoMore;
7794         }
7795     }
7796 
7797     else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
7798             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
7799         if ((0 == index) && role) {
7800             strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
7801             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7802         } else {
7803             DEBUG_PRINT_LOW("No more roles");
7804             eRet = OMX_ErrorNoMore;
7805         }
7806     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
7807         if ((0 == index) && role) {
7808             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
7809             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7810         } else {
7811             DEBUG_PRINT_LOW("No more roles");
7812             eRet = OMX_ErrorNoMore;
7813         }
7814     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
7815         if ((0 == index) && role) {
7816             strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
7817             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7818         } else {
7819             DEBUG_PRINT_LOW("No more roles");
7820             eRet = OMX_ErrorNoMore;
7821         }
7822     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
7823         if ((0 == index) && role) {
7824             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
7825             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
7826         } else {
7827             DEBUG_PRINT_LOW("No more roles");
7828             eRet = OMX_ErrorNoMore;
7829         }
7830     } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
7831             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
7832           ) {
7833         if ((0 == index) && role) {
7834             strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
7835             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7836         } else {
7837             DEBUG_PRINT_LOW("No more roles");
7838             eRet = OMX_ErrorNoMore;
7839         }
7840     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7841         if ((0 == index) && role) {
7842             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7843             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7844         } else {
7845             DEBUG_PRINT_LOW("No more roles");
7846             eRet = OMX_ErrorNoMore;
7847         }
7848     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
7849         if ((0 == index) && role) {
7850             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
7851             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7852         } else {
7853             DEBUG_PRINT_LOW("No more roles");
7854             eRet = OMX_ErrorNoMore;
7855         }
7856     } else {
7857         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7858         eRet = OMX_ErrorInvalidComponentName;
7859     }
7860     return eRet;
7861 }
7862 
7863 
7864 
7865 
7866 /* ======================================================================
7867    FUNCTION
7868    omx_vdec::AllocateDone
7869 
7870    DESCRIPTION
7871    Checks if entire buffer pool is allocated by IL Client or not.
7872    Need this to move to IDLE state.
7873 
7874    PARAMETERS
7875    None.
7876 
7877    RETURN VALUE
7878    true/false.
7879 
7880    ========================================================================== */
allocate_done(void)7881 bool omx_vdec::allocate_done(void)
7882 {
7883     bool bRet = false;
7884     bool bRet_In = false;
7885     bool bRet_Out = false;
7886 
7887     bRet_In = allocate_input_done();
7888     bRet_Out = allocate_output_done();
7889 
7890     if (bRet_In && bRet_Out) {
7891         bRet = true;
7892     }
7893 
7894     return bRet;
7895 }
7896 /* ======================================================================
7897    FUNCTION
7898    omx_vdec::AllocateInputDone
7899 
7900    DESCRIPTION
7901    Checks if I/P buffer pool is allocated by IL Client or not.
7902 
7903    PARAMETERS
7904    None.
7905 
7906    RETURN VALUE
7907    true/false.
7908 
7909    ========================================================================== */
allocate_input_done(void)7910 bool omx_vdec::allocate_input_done(void)
7911 {
7912     bool bRet = false;
7913     unsigned i=0;
7914 
7915     if (m_inp_mem_ptr == NULL) {
7916         return bRet;
7917     }
7918     if (m_inp_mem_ptr ) {
7919         for (; i<drv_ctx.ip_buf.actualcount; i++) {
7920             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7921                 break;
7922             }
7923         }
7924     }
7925     if (i == drv_ctx.ip_buf.actualcount) {
7926         bRet = true;
7927         DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
7928     }
7929     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7930         m_inp_bPopulated = OMX_TRUE;
7931     }
7932     return bRet;
7933 }
7934 /* ======================================================================
7935    FUNCTION
7936    omx_vdec::AllocateOutputDone
7937 
7938    DESCRIPTION
7939    Checks if entire O/P buffer pool is allocated by IL Client or not.
7940 
7941    PARAMETERS
7942    None.
7943 
7944    RETURN VALUE
7945    true/false.
7946 
7947    ========================================================================== */
allocate_output_done(void)7948 bool omx_vdec::allocate_output_done(void)
7949 {
7950     bool bRet = false;
7951     unsigned j=0;
7952 
7953     if (m_out_mem_ptr == NULL) {
7954         return bRet;
7955     }
7956 
7957     if (m_out_mem_ptr) {
7958         for (; j < drv_ctx.op_buf.actualcount; j++) {
7959             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7960                 break;
7961             }
7962         }
7963     }
7964 
7965     if (j == drv_ctx.op_buf.actualcount) {
7966         bRet = true;
7967         DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
7968         if (m_out_bEnabled)
7969             m_out_bPopulated = OMX_TRUE;
7970     }
7971 
7972     return bRet;
7973 }
7974 
7975 /* ======================================================================
7976    FUNCTION
7977    omx_vdec::ReleaseDone
7978 
7979    DESCRIPTION
7980    Checks if IL client has released all the buffers.
7981 
7982    PARAMETERS
7983    None.
7984 
7985    RETURN VALUE
7986    true/false
7987 
7988    ========================================================================== */
release_done(void)7989 bool omx_vdec::release_done(void)
7990 {
7991     bool bRet = false;
7992 
7993     if (release_input_done()) {
7994         if (release_output_done()) {
7995             bRet = true;
7996         }
7997     }
7998     return bRet;
7999 }
8000 
8001 
8002 /* ======================================================================
8003    FUNCTION
8004    omx_vdec::ReleaseOutputDone
8005 
8006    DESCRIPTION
8007    Checks if IL client has released all the buffers.
8008 
8009    PARAMETERS
8010    None.
8011 
8012    RETURN VALUE
8013    true/false
8014 
8015    ========================================================================== */
release_output_done(void)8016 bool omx_vdec::release_output_done(void)
8017 {
8018     bool bRet = false;
8019     unsigned i=0,j=0;
8020 
8021     DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
8022     if (m_out_mem_ptr) {
8023         for (; j < drv_ctx.op_buf.actualcount ; j++) {
8024             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8025                 break;
8026             }
8027         }
8028         if (j == drv_ctx.op_buf.actualcount) {
8029             m_out_bm_count = 0;
8030             bRet = true;
8031         }
8032     } else {
8033         m_out_bm_count = 0;
8034         bRet = true;
8035     }
8036     return bRet;
8037 }
8038 /* ======================================================================
8039    FUNCTION
8040    omx_vdec::ReleaseInputDone
8041 
8042    DESCRIPTION
8043    Checks if IL client has released all the buffers.
8044 
8045    PARAMETERS
8046    None.
8047 
8048    RETURN VALUE
8049    true/false
8050 
8051    ========================================================================== */
release_input_done(void)8052 bool omx_vdec::release_input_done(void)
8053 {
8054     bool bRet = false;
8055     unsigned i=0,j=0;
8056 
8057     DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
8058     if (m_inp_mem_ptr) {
8059         for (; j<drv_ctx.ip_buf.actualcount; j++) {
8060             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8061                 break;
8062             }
8063         }
8064         if (j==drv_ctx.ip_buf.actualcount) {
8065             bRet = true;
8066         }
8067     } else {
8068         bRet = true;
8069     }
8070     return bRet;
8071 }
8072 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8073 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8074         OMX_BUFFERHEADERTYPE * buffer)
8075 {
8076     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8077     if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
8078         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8079         return OMX_ErrorBadParameter;
8080     } else if (output_flush_progress) {
8081         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8082         buffer->nFilledLen = 0;
8083         buffer->nTimeStamp = 0;
8084         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8085         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8086         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8087     }
8088 
8089     if (m_debug_extradata) {
8090         if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8091             DEBUG_PRINT_HIGH("***************************************************");
8092             DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8093             DEBUG_PRINT_HIGH("***************************************************");
8094         }
8095 
8096         if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8097             DEBUG_PRINT_HIGH("***************************************************");
8098             DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8099             DEBUG_PRINT_HIGH("***************************************************");
8100         }
8101     }
8102 
8103 
8104     DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
8105             buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
8106     pending_output_buffers --;
8107 
8108     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8109         DEBUG_PRINT_HIGH("Output EOS has been reached");
8110         if (!output_flush_progress)
8111             post_event((unsigned)NULL, (unsigned)NULL,
8112                     OMX_COMPONENT_GENERATE_EOS_DONE);
8113 
8114         if (psource_frame) {
8115             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8116             psource_frame = NULL;
8117         }
8118         if (pdest_frame) {
8119             pdest_frame->nFilledLen = 0;
8120             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8121                     (unsigned)NULL);
8122             pdest_frame = NULL;
8123         }
8124     }
8125 
8126     if (!output_flush_progress && (buffer->nFilledLen > 0)) {
8127         // set the default colorspace advised by client, since the bitstream may be
8128         // devoid of colorspace-info.
8129         if (m_enable_android_native_buffers) {
8130             ColorSpace_t color_space = ITU_R_601;
8131 
8132         // Disabled ?
8133         // WA for VP8. Vp8 encoder does not embed color-info (yet!).
8134         // Encoding RGBA results in 601-LR for all resolutions.
8135         // This conflicts with the client't defaults which are based on resolution.
8136         //   Eg: 720p will be encoded as 601-LR. Client will say 709.
8137         // Re-enable this code once vp8 encoder generates color-info and hence the
8138         // decoder will be able to override with the correct source color.
8139 #if 0
8140             switch (m_client_color_space.sAspects.mPrimaries) {
8141                 case ColorAspects::PrimariesBT601_6_625:
8142                 case ColorAspects::PrimariesBT601_6_525:
8143                 {
8144                     color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
8145                             ITU_R_601_FR : ITU_R_601;
8146                     break;
8147                 }
8148                 case ColorAspects::PrimariesBT709_5:
8149                 {
8150                     color_space = ITU_R_709;
8151                     break;
8152                 }
8153                 default:
8154                 {
8155                     break;
8156                 }
8157             }
8158 #endif
8159             DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
8160                     color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
8161             set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr);
8162         }
8163         DEBUG_PRINT_LOW("Processing extradata");
8164         handle_extradata(buffer);
8165     }
8166 
8167 #ifdef OUTPUT_EXTRADATA_LOG
8168     if (outputExtradataFile) {
8169         int buf_index = buffer - m_out_mem_ptr;
8170         OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8171 
8172         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8173         p_extra = (OMX_OTHER_EXTRADATATYPE *)
8174             ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8175 
8176         while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8177             DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8178                                     p_extra->nSize, p_extra->eType);
8179             fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8180 
8181             if (p_extra->eType == OMX_ExtraDataNone) {
8182                 break;
8183             }
8184             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8185         }
8186     }
8187 #endif
8188 
8189     /* For use buffer we need to copy the data */
8190     if (!output_flush_progress) {
8191         /* This is the error check for non-recoverable errros */
8192         bool is_duplicate_ts_valid = true;
8193         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8194 
8195         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8196                 output_capability == V4L2_PIX_FMT_MPEG2 ||
8197                 output_capability == V4L2_PIX_FMT_DIVX ||
8198                 output_capability == V4L2_PIX_FMT_DIVX_311)
8199             is_duplicate_ts_valid = false;
8200 
8201         if ((output_capability == V4L2_PIX_FMT_H264 ||
8202                 output_capability == V4L2_PIX_FMT_H264_MVC) &&
8203                 is_interlaced) {
8204             if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8205                 is_interlaced = false;
8206             }
8207         }
8208 
8209         if (buffer->nFilledLen > 0) {
8210             time_stamp_dts.get_next_timestamp(buffer,
8211                     is_interlaced && is_duplicate_ts_valid);
8212             if (m_debug_timestamp) {
8213                 {
8214                     OMX_TICKS expected_ts = 0;
8215                     m_timestamp_list.pop_min_ts(expected_ts);
8216                     if (is_interlaced && is_duplicate_ts_valid) {
8217                         m_timestamp_list.pop_min_ts(expected_ts);
8218                     }
8219                     DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8220                             buffer->nTimeStamp, expected_ts);
8221 
8222                     if (buffer->nTimeStamp != expected_ts) {
8223                         DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8224                     }
8225                 }
8226             }
8227         }
8228     }
8229 
8230     if (m_cb.FillBufferDone) {
8231         if (buffer->nFilledLen > 0) {
8232             if (arbitrary_bytes)
8233                 adjust_timestamp(buffer->nTimeStamp);
8234             else
8235                 set_frame_rate(buffer->nTimeStamp);
8236 
8237             if (perf_flag) {
8238                 if (!proc_frms) {
8239                     dec_time.stop();
8240                     latency = dec_time.processing_time_us() - latency;
8241                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8242                     dec_time.start();
8243                     fps_metrics.start();
8244                 }
8245                 proc_frms++;
8246                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8247                     OMX_U64 proc_time = 0;
8248                     fps_metrics.stop();
8249                     proc_time = fps_metrics.processing_time_us();
8250                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8251                             (unsigned int)proc_frms, (float)proc_time / 1e6,
8252                             (float)(1e6 * proc_frms) / proc_time);
8253                     proc_frms = 0;
8254                 }
8255             }
8256         }
8257         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8258             prev_ts = LLONG_MAX;
8259             rst_prev_ts = true;
8260         }
8261 
8262         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8263             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8264              buffer->pPlatformPrivate)->entryList->entry;
8265         DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8266         OMX_BUFFERHEADERTYPE *il_buffer;
8267         il_buffer = client_buffers.get_il_buf_hdr(buffer);
8268         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8269 
8270         if (il_buffer && m_last_rendered_TS >= 0) {
8271             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8272 
8273             // Current frame can be send for rendering if
8274             // (a) current FPS is <=  60
8275             // (b) is the next frame after the frame with TS 0
8276             // (c) is the first frame after seek
8277             // (d) the delta TS b\w two consecutive frames is > 16 ms
8278             // (e) its TS is equal to previous frame TS
8279             // (f) if marked EOS
8280 
8281             if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8282                il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8283                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8284                m_last_rendered_TS = il_buffer->nTimeStamp;
8285             } else {
8286                //mark for droping
8287                buffer->nFilledLen = 0;
8288             }
8289 
8290             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8291                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8292                               il_buffer->nTimeStamp,ts_delta);
8293 
8294             //above code makes sure that delta b\w two consecutive frames is not
8295             //greater than 16ms, slow-mo feature, so cap fps to max 60
8296             if (current_framerate > 60 ) {
8297                 current_framerate = 60;
8298             }
8299         }
8300 
8301         // add current framerate to gralloc meta data
8302         if (m_enable_android_native_buffers && m_out_mem_ptr) {
8303             OMX_U32 buf_index = buffer - m_out_mem_ptr;
8304             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8305                          UPDATE_REFRESH_RATE, (void*)&current_framerate);
8306         }
8307 
8308         if (il_buffer) {
8309             log_output_buffers(il_buffer);
8310             if (dynamic_buf_mode) {
8311                 unsigned int nPortIndex = 0;
8312                 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8313 
8314                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8315                 // to size of the handle. Do it _after_ log_output_buffers which
8316                 // requires the respective sizes to be accurate.
8317 
8318                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8319                 buffer->nFilledLen = buffer->nFilledLen ?
8320                         sizeof(struct VideoDecoderOutputMetaData) : 0;
8321 
8322                 //Clear graphic buffer handles in dynamic mode
8323                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8324                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8325                     native_buffer[nPortIndex].privatehandle = NULL;
8326                     native_buffer[nPortIndex].nativehandle = NULL;
8327                 } else {
8328                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8329                     return OMX_ErrorBadParameter;
8330                 }
8331             }
8332             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8333         } else {
8334             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8335             return OMX_ErrorBadParameter;
8336         }
8337         DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
8338     } else {
8339         return OMX_ErrorBadParameter;
8340     }
8341 
8342 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8343     if (m_smoothstreaming_mode && m_out_mem_ptr) {
8344         OMX_U32 buf_index = buffer - m_out_mem_ptr;
8345         BufferDim_t dim;
8346         private_handle_t *private_handle = NULL;
8347         dim.sliceWidth = framesize.nWidth;
8348         dim.sliceHeight = framesize.nHeight;
8349         if (buf_index < drv_ctx.op_buf.actualcount &&
8350             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8351             native_buffer[buf_index].privatehandle)
8352             private_handle = native_buffer[buf_index].privatehandle;
8353         if (private_handle) {
8354             DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8355                 dim.sliceWidth, dim.sliceHeight);
8356             setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8357         }
8358     }
8359 #endif
8360 
8361     return OMX_ErrorNone;
8362 }
8363 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8364 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
8365         OMX_BUFFERHEADERTYPE* buffer)
8366 {
8367 
8368     int nBufferIndex = buffer - m_inp_mem_ptr;
8369 
8370     if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8371         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8372         return OMX_ErrorBadParameter;
8373     }
8374 
8375     DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
8376             buffer, buffer->pBuffer, buffer->nFlags);
8377     pending_input_buffers--;
8378 
8379     if (arbitrary_bytes) {
8380         if (pdest_frame == NULL && input_flush_progress == false) {
8381             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8382             pdest_frame = buffer;
8383             buffer->nFilledLen = 0;
8384             buffer->nTimeStamp = LLONG_MAX;
8385             push_input_buffer (hComp);
8386         } else {
8387             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8388             buffer->nFilledLen = 0;
8389             if (!m_input_free_q.insert_entry((unsigned long)buffer,
8390                         (unsigned)NULL, (unsigned)NULL)) {
8391                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8392             }
8393         }
8394     } else if (m_cb.EmptyBufferDone) {
8395         buffer->nFilledLen = 0;
8396         if (input_use_buffer == true) {
8397             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8398         }
8399 
8400         /* Restore the FD that we over-wrote in ETB */
8401         if (m_input_pass_buffer_fd) {
8402             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8403         }
8404 
8405         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8406     }
8407     return OMX_ErrorNone;
8408 }
8409 
async_message_process(void * context,void * message)8410 int omx_vdec::async_message_process (void *context, void* message)
8411 {
8412     omx_vdec* omx = NULL;
8413     struct vdec_msginfo *vdec_msg = NULL;
8414     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8415     struct v4l2_buffer *v4l2_buf_ptr = NULL;
8416     struct vdec_output_frameinfo *output_respbuf = NULL;
8417     int rc=1;
8418     if (context == NULL || message == NULL) {
8419         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8420         return -1;
8421     }
8422     vdec_msg = (struct vdec_msginfo *)message;
8423 
8424     omx = reinterpret_cast<omx_vdec*>(context);
8425 
8426     switch (vdec_msg->msgcode) {
8427 
8428         case VDEC_MSG_EVT_HW_ERROR:
8429             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8430                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8431             break;
8432 
8433         case VDEC_MSG_EVT_HW_OVERLOAD:
8434             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8435                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8436             break;
8437 
8438         case VDEC_MSG_EVT_HW_UNSUPPORTED:
8439             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8440                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8441             break;
8442 
8443         case VDEC_MSG_RESP_START_DONE:
8444             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8445                     OMX_COMPONENT_GENERATE_START_DONE);
8446             break;
8447 
8448         case VDEC_MSG_RESP_STOP_DONE:
8449             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8450                     OMX_COMPONENT_GENERATE_STOP_DONE);
8451             break;
8452 
8453         case VDEC_MSG_RESP_RESUME_DONE:
8454             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8455                     OMX_COMPONENT_GENERATE_RESUME_DONE);
8456             break;
8457 
8458         case VDEC_MSG_RESP_PAUSE_DONE:
8459             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8460                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
8461             break;
8462 
8463         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8464             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8465                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8466             break;
8467         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8468             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8469                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8470             break;
8471         case VDEC_MSG_RESP_INPUT_FLUSHED:
8472         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8473 
8474             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8475                vdec_msg->msgdata.input_frame_clientdata; */
8476 
8477             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8478             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8479                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8480                 omxhdr = NULL;
8481                 vdec_msg->status_code = VDEC_S_EFATAL;
8482                 break;
8483 
8484             }
8485             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8486 
8487             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8488                 DEBUG_PRINT_HIGH("Unsupported input");
8489                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8490                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8491             }
8492             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8493                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8494                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8495             }
8496             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8497 
8498                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8499                 android_atomic_dec(&omx->m_queued_codec_config_count);
8500                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8501                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8502                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8503                     sem_post(&omx->m_safe_flush);
8504                 }
8505             }
8506             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8507                 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8508                 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8509             }
8510             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8511                     OMX_COMPONENT_GENERATE_EBD);
8512             break;
8513         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8514             int64_t *timestamp;
8515             timestamp = (int64_t *) malloc(sizeof(int64_t));
8516             if (timestamp) {
8517                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8518                 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8519                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8520                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8521                         (long long)vdec_msg->msgdata.output_frame.time_stamp);
8522             }
8523             break;
8524         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8525         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8526 
8527            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8528 
8529            if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8530                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8531                omxhdr = NULL;
8532                vdec_msg->status_code = VDEC_S_EFATAL;
8533                break;
8534            }
8535 
8536            omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8537 
8538             DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8539                     omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8540                     vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8541                     (unsigned int)vdec_msg->msgdata.output_frame.len,
8542                     vdec_msg->msgdata.output_frame.framesize.left,
8543                     vdec_msg->msgdata.output_frame.framesize.top,
8544                     vdec_msg->msgdata.output_frame.framesize.right,
8545                     vdec_msg->msgdata.output_frame.framesize.bottom);
8546 
8547             if (omxhdr && omxhdr->pOutputPortPrivate &&
8548                     ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8549                     (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8550                       - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8551 
8552                 if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
8553                     omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8554                     omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8555                     omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8556                     omxhdr->nFlags = 0;
8557 
8558                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8559                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8560                         //rc = -1;
8561                     }
8562                     if (omxhdr->nFilledLen) {
8563                         omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8564                     }
8565                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8566                         omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8567                     } else {
8568                         omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8569                     }
8570                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
8571                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8572                     }
8573                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8574                         omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8575                     }
8576 
8577                     if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
8578                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
8579                     }
8580 
8581                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8582                          omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8583                          DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8584                                     omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8585                     }
8586 
8587                     if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
8588                             !omx->output_flush_progress &&
8589                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
8590                             !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
8591                         unsigned int index = v4l2_buf_ptr->index;
8592                         unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
8593                         struct v4l2_plane *plane = v4l2_buf_ptr->m.planes;
8594                         omx->time_stamp_dts.remove_time_stamp(
8595                                 omxhdr->nTimeStamp,
8596                                 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
8597                                 ?true:false);
8598                         plane[0].bytesused = 0;
8599                         plane[0].m.userptr =
8600                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
8601                             (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
8602                         plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
8603                         plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
8604                         plane[0].data_offset = 0;
8605                         v4l2_buf_ptr->flags = 0x0;
8606                         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8607                             plane[extra_idx].bytesused = 0;
8608                             plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
8609                             plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
8610 #ifdef USE_ION
8611                             plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
8612 #endif
8613                             plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
8614                             plane[extra_idx].data_offset = 0;
8615                         } else if (extra_idx >= VIDEO_MAX_PLANES) {
8616                             DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8617                             return -1;
8618                         }
8619 
8620                          DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8621                                plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
8622                         if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
8623                             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]);
8624                             return -1;
8625                         }
8626                         break;
8627                     }
8628                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8629                         omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8630                     }
8631                     vdec_msg->msgdata.output_frame.bufferaddr =
8632                         omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8633 
8634                     /* Post event if resolution OR crop changed */
8635                     /* filled length will be changed if resolution changed */
8636                     /* Crop parameters can be changed even without resolution change */
8637                     if (omxhdr->nFilledLen
8638                         && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8639                         || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8640                         || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8641                         || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8642                         || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
8643                         || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
8644                         || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
8645 
8646                         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",
8647                                 omx->prev_n_filled_len,
8648                                 omx->drv_ctx.video_resolution.frame_width,
8649                                 omx->drv_ctx.video_resolution.frame_height,
8650                                 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
8651                                 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
8652                                 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
8653                                 vdec_msg->msgdata.output_frame.picsize.frame_height,
8654                                 vdec_msg->msgdata.output_frame.framesize.left,
8655                                 vdec_msg->msgdata.output_frame.framesize.top,
8656                                 vdec_msg->msgdata.output_frame.framesize.right,
8657                                 vdec_msg->msgdata.output_frame.framesize.bottom);
8658 
8659                         omx->drv_ctx.video_resolution.frame_width =
8660                                 vdec_msg->msgdata.output_frame.picsize.frame_width;
8661                         omx->drv_ctx.video_resolution.frame_height =
8662                                 vdec_msg->msgdata.output_frame.picsize.frame_height;
8663                         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
8664                             omx->drv_ctx.video_resolution.stride =
8665                                 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
8666                             omx->drv_ctx.video_resolution.scan_lines =
8667                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
8668                         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
8669                             omx->drv_ctx.video_resolution.stride =
8670                                 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
8671                             omx->drv_ctx.video_resolution.scan_lines =
8672                                 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
8673                         }
8674 
8675                         memcpy(&omx->drv_ctx.frame_size,
8676                                 &vdec_msg->msgdata.output_frame.framesize,
8677                                 sizeof(struct vdec_framesize));
8678 
8679                         omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8680                                 OMX_IndexConfigCommonOutputCrop,
8681                                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8682                     }
8683 
8684                     if (omxhdr->nFilledLen)
8685                         omx->prev_n_filled_len = omxhdr->nFilledLen;
8686 
8687                     output_respbuf = (struct vdec_output_frameinfo *)\
8688                              omxhdr->pOutputPortPrivate;
8689                     if (!output_respbuf) {
8690                       DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8691                       return -1;
8692                     }
8693                     output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8694                     output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8695 
8696                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8697                         output_respbuf->pic_type = PICTURE_TYPE_I;
8698                     }
8699                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8700                         output_respbuf->pic_type = PICTURE_TYPE_P;
8701                     }
8702                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8703                         output_respbuf->pic_type = PICTURE_TYPE_B;
8704                     }
8705                     if (omxhdr && omxhdr->nFilledLen) {
8706                         omx->request_perf_level(VIDC_NOMINAL);
8707                     }
8708                     if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
8709                         vdec_msg->msgdata.output_frame.bufferaddr)
8710                         memcpy ( omxhdr->pBuffer, (void *)
8711                                 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
8712                                  (unsigned long)vdec_msg->msgdata.output_frame.offset),
8713                                 vdec_msg->msgdata.output_frame.len);
8714                 } else {
8715                     DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
8716                             (unsigned int)vdec_msg->msgdata.output_frame.len,
8717                             omxhdr->nAllocLen, omx->prev_n_filled_len);
8718                     omxhdr->nFilledLen = 0;
8719                 }
8720 
8721                 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
8722                         OMX_COMPONENT_GENERATE_FBD);
8723 
8724             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
8725                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
8726                         OMX_COMPONENT_GENERATE_EOS_DONE);
8727             } else {
8728                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
8729                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8730             }
8731             break;
8732         case VDEC_MSG_EVT_CONFIG_CHANGED:
8733             DEBUG_PRINT_HIGH("Port settings changed");
8734             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8735             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8736             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
8737                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8738             omx->request_perf_level(VIDC_NOMINAL);
8739             break;
8740         default:
8741             break;
8742     }
8743     return rc;
8744 }
8745 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8746 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
8747         OMX_HANDLETYPE hComp,
8748         OMX_BUFFERHEADERTYPE *buffer
8749         )
8750 {
8751     unsigned address,p2,id;
8752     DEBUG_PRINT_LOW("Empty this arbitrary");
8753 
8754     if (buffer == NULL) {
8755         return OMX_ErrorBadParameter;
8756     }
8757     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8758     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
8759             (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
8760 
8761     /* return zero length and not an EOS buffer */
8762     /* return buffer if input flush in progress */
8763     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
8764                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
8765         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
8766         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
8767         return OMX_ErrorNone;
8768     }
8769 
8770     if (psource_frame == NULL) {
8771         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
8772         psource_frame = buffer;
8773         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
8774         push_input_buffer (hComp);
8775     } else {
8776         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
8777         if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
8778                     (unsigned)NULL)) {
8779             return OMX_ErrorBadParameter;
8780         }
8781     }
8782 
8783     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
8784         codec_config_flag = false;
8785     }
8786     return OMX_ErrorNone;
8787 }
8788 
push_input_buffer(OMX_HANDLETYPE hComp)8789 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
8790 {
8791     unsigned long address,p2,id;
8792     OMX_ERRORTYPE ret = OMX_ErrorNone;
8793 
8794     if (pdest_frame == NULL || psource_frame == NULL) {
8795         /*Check if we have a destination buffer*/
8796         if (pdest_frame == NULL) {
8797             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
8798             if (m_input_free_q.m_size) {
8799                 m_input_free_q.pop_entry(&address,&p2,&id);
8800                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
8801                 pdest_frame->nFilledLen = 0;
8802                 pdest_frame->nTimeStamp = LLONG_MAX;
8803                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
8804             }
8805         }
8806 
8807         /*Check if we have a destination buffer*/
8808         if (psource_frame == NULL) {
8809             DEBUG_PRINT_LOW("Get a source buffer from the queue");
8810             if (m_input_pending_q.m_size) {
8811                 m_input_pending_q.pop_entry(&address,&p2,&id);
8812                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
8813                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8814                         psource_frame->nTimeStamp);
8815                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8816                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8817 
8818             }
8819         }
8820 
8821     }
8822 
8823     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
8824         switch (codec_type_parse) {
8825             case CODEC_TYPE_MPEG4:
8826             case CODEC_TYPE_H263:
8827             case CODEC_TYPE_MPEG2:
8828                 ret =  push_input_sc_codec(hComp);
8829                 break;
8830             case CODEC_TYPE_H264:
8831                 ret = push_input_h264(hComp);
8832                 break;
8833             case CODEC_TYPE_HEVC:
8834                 ret = push_input_hevc(hComp);
8835                 break;
8836             case CODEC_TYPE_VC1:
8837                 ret = push_input_vc1(hComp);
8838                 break;
8839             default:
8840                 break;
8841         }
8842         if (ret != OMX_ErrorNone) {
8843             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
8844             omx_report_error ();
8845             break;
8846         }
8847     }
8848 
8849     return ret;
8850 }
8851 
push_input_sc_codec(OMX_HANDLETYPE hComp)8852 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
8853 {
8854     OMX_U32 partial_frame = 1;
8855     OMX_BOOL generate_ebd = OMX_TRUE;
8856     unsigned long address = 0, p2 = 0, id = 0;
8857 
8858     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
8859             psource_frame,psource_frame->nTimeStamp);
8860     if (m_frame_parser.parse_sc_frame(psource_frame,
8861                 pdest_frame,&partial_frame) == -1) {
8862         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8863         return OMX_ErrorBadParameter;
8864     }
8865 
8866     if (partial_frame == 0) {
8867         DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
8868                 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
8869 
8870 
8871         DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
8872         /*First Parsed buffer will have only header Hence skip*/
8873         if (frame_count == 0) {
8874             DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
8875 
8876             if (codec_type_parse == CODEC_TYPE_MPEG4 ||
8877                     codec_type_parse == CODEC_TYPE_DIVX) {
8878                 mp4StreamType psBits;
8879                 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
8880                 psBits.numBytes = pdest_frame->nFilledLen;
8881                 mp4_headerparser.parseHeader(&psBits);
8882             }
8883 
8884             frame_count++;
8885         } else {
8886             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8887             if (pdest_frame->nFilledLen) {
8888                 /*Push the frame to the Decoder*/
8889                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8890                     return OMX_ErrorBadParameter;
8891                 }
8892                 frame_count++;
8893                 pdest_frame = NULL;
8894 
8895                 if (m_input_free_q.m_size) {
8896                     m_input_free_q.pop_entry(&address,&p2,&id);
8897                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8898                     pdest_frame->nFilledLen = 0;
8899                 }
8900             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
8901                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
8902                 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
8903                         (unsigned)NULL);
8904                 pdest_frame = NULL;
8905             }
8906         }
8907     } else {
8908         DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
8909         /*Check if Destination Buffer is full*/
8910         if (pdest_frame->nAllocLen ==
8911                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
8912             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
8913             return OMX_ErrorStreamCorrupt;
8914         }
8915     }
8916 
8917     if (psource_frame->nFilledLen == 0) {
8918         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8919             if (pdest_frame) {
8920                 pdest_frame->nFlags |= psource_frame->nFlags;
8921                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
8922                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8923                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8924                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
8925                 /*Push the frame to the Decoder*/
8926                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8927                     return OMX_ErrorBadParameter;
8928                 }
8929                 frame_count++;
8930                 pdest_frame = NULL;
8931             } else {
8932                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
8933                 generate_ebd = OMX_FALSE;
8934             }
8935         }
8936         if (generate_ebd) {
8937             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
8938             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8939             psource_frame = NULL;
8940 
8941             if (m_input_pending_q.m_size) {
8942                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8943                 m_input_pending_q.pop_entry(&address,&p2,&id);
8944                 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8945                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8946                         psource_frame->nTimeStamp);
8947                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8948                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8949             }
8950         }
8951     }
8952     return OMX_ErrorNone;
8953 }
8954 
push_input_h264(OMX_HANDLETYPE hComp)8955 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
8956 {
8957     OMX_U32 partial_frame = 1;
8958     unsigned long address = 0, p2 = 0, id = 0;
8959     OMX_BOOL isNewFrame = OMX_FALSE;
8960     OMX_BOOL generate_ebd = OMX_TRUE;
8961 
8962     if (h264_scratch.pBuffer == NULL) {
8963         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
8964         return OMX_ErrorBadParameter;
8965     }
8966     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
8967             "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
8968     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
8969     if (h264_scratch.nFilledLen && look_ahead_nal) {
8970         look_ahead_nal = false;
8971         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8972                 h264_scratch.nFilledLen) {
8973             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8974                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
8975             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8976             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
8977             h264_scratch.nFilledLen = 0;
8978         } else {
8979             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
8980             return OMX_ErrorBadParameter;
8981         }
8982     }
8983 
8984     /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
8985        in EOS flag getting associated with the destination
8986     */
8987     if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
8988             pdest_frame->nFilledLen) {
8989         DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
8990         generate_ebd = OMX_FALSE;
8991     }
8992 
8993     if (nal_length == 0) {
8994         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
8995         if (m_frame_parser.parse_sc_frame(psource_frame,
8996                     &h264_scratch,&partial_frame) == -1) {
8997             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8998             return OMX_ErrorBadParameter;
8999         }
9000     } else {
9001         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9002         if (m_frame_parser.parse_h264_nallength(psource_frame,
9003                     &h264_scratch,&partial_frame) == -1) {
9004             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9005             return OMX_ErrorBadParameter;
9006         }
9007     }
9008 
9009     if (partial_frame == 0) {
9010         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9011             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9012             nal_count++;
9013             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9014             h264_scratch.nFlags = psource_frame->nFlags;
9015         } else {
9016             DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9017             if (h264_scratch.nFilledLen) {
9018                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9019                         NALU_TYPE_SPS);
9020 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9021                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9022                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9023                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9024                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9025                     // If timeinfo is present frame info from SEI is already processed
9026                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9027                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9028 #endif
9029                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9030                 nal_count++;
9031                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9032                     pdest_frame->nTimeStamp = h264_last_au_ts;
9033                     pdest_frame->nFlags = h264_last_au_flags;
9034 #ifdef PANSCAN_HDLR
9035                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9036                         h264_parser->update_panscan_data(h264_last_au_ts);
9037 #endif
9038                 }
9039                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9040                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9041                     h264_last_au_ts = h264_scratch.nTimeStamp;
9042                     h264_last_au_flags = h264_scratch.nFlags;
9043 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9044                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9045                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9046                         if (!VALID_TS(h264_last_au_ts))
9047                             h264_last_au_ts = ts_in_sei;
9048                     }
9049 #endif
9050                 } else
9051                     h264_last_au_ts = LLONG_MAX;
9052             }
9053 
9054             if (!isNewFrame) {
9055                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9056                         h264_scratch.nFilledLen) {
9057                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9058                             (unsigned int)h264_scratch.nFilledLen);
9059                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9060                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
9061                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9062                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9063                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9064                     h264_scratch.nFilledLen = 0;
9065                 } else {
9066                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9067                     return OMX_ErrorBadParameter;
9068                 }
9069             } else if(h264_scratch.nFilledLen) {
9070                 look_ahead_nal = true;
9071                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9072                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9073                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9074                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
9075 
9076                 if (pdest_frame->nFilledLen == 0) {
9077                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9078                     look_ahead_nal = false;
9079                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9080                             h264_scratch.nFilledLen) {
9081                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9082                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9083                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9084                         h264_scratch.nFilledLen = 0;
9085                     } else {
9086                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9087                         return OMX_ErrorBadParameter;
9088                     }
9089                 } else {
9090                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9091                         DEBUG_PRINT_LOW("Reset the EOS Flag");
9092                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9093                     }
9094                     /*Push the frame to the Decoder*/
9095                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9096                         return OMX_ErrorBadParameter;
9097                     }
9098                     //frame_count++;
9099                     pdest_frame = NULL;
9100                     if (m_input_free_q.m_size) {
9101                         m_input_free_q.pop_entry(&address,&p2,&id);
9102                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9103                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9104                         pdest_frame->nFilledLen = 0;
9105                         pdest_frame->nFlags = 0;
9106                         pdest_frame->nTimeStamp = LLONG_MAX;
9107                     }
9108                 }
9109             }
9110         }
9111     } else {
9112         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9113         /*Check if Destination Buffer is full*/
9114         if (h264_scratch.nAllocLen ==
9115                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9116             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9117             return OMX_ErrorStreamCorrupt;
9118         }
9119     }
9120 
9121     if (!psource_frame->nFilledLen) {
9122         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9123 
9124         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9125             if (pdest_frame) {
9126                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9127                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9128                         h264_scratch.nFilledLen) {
9129                     if(pdest_frame->nFilledLen == 0) {
9130                         /* No residual frame from before, send whatever
9131                          * we have left */
9132                         memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9133                                 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9134                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9135                         h264_scratch.nFilledLen = 0;
9136                         pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9137                     } else {
9138                         m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9139                         if(!isNewFrame) {
9140                             /* Have a residual frame, but we know that the
9141                              * AU in this frame is belonging to whatever
9142                              * frame we had left over.  So append it */
9143                              memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9144                                      h264_scratch.pBuffer,h264_scratch.nFilledLen);
9145                              pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9146                              h264_scratch.nFilledLen = 0;
9147                              if (h264_last_au_ts != LLONG_MAX)
9148                                  pdest_frame->nTimeStamp = h264_last_au_ts;
9149                         } else {
9150                             /* Completely new frame, let's just push what
9151                              * we have now.  The resulting EBD would trigger
9152                              * another push */
9153                             generate_ebd = OMX_FALSE;
9154                             pdest_frame->nTimeStamp = h264_last_au_ts;
9155                             h264_last_au_ts = h264_scratch.nTimeStamp;
9156                         }
9157                     }
9158                 } else {
9159                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9160                     return OMX_ErrorBadParameter;
9161                 }
9162 
9163                 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9164                 if(generate_ebd == OMX_TRUE) {
9165                      pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9166                 }
9167 
9168                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9169                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9170                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9171 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9172                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9173                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9174                     if (!VALID_TS(pdest_frame->nTimeStamp))
9175                         pdest_frame->nTimeStamp = ts_in_sei;
9176                 }
9177 #endif
9178                 /*Push the frame to the Decoder*/
9179                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9180                     return OMX_ErrorBadParameter;
9181                 }
9182                 frame_count++;
9183                 pdest_frame = NULL;
9184             } else {
9185                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9186                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9187                 generate_ebd = OMX_FALSE;
9188             }
9189         }
9190     }
9191     if (generate_ebd && !psource_frame->nFilledLen) {
9192         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9193         psource_frame = NULL;
9194         if (m_input_pending_q.m_size) {
9195             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9196             m_input_pending_q.pop_entry(&address,&p2,&id);
9197             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9198             DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9199                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9200         }
9201     }
9202     return OMX_ErrorNone;
9203 }
9204 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9205 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9206 {
9207     OMX_ERRORTYPE rc = OMX_ErrorNone;
9208     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9209         memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9210         if (pDst->nTimeStamp == LLONG_MAX) {
9211             pDst->nTimeStamp = pSrc->nTimeStamp;
9212             DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9213         }
9214         pDst->nFilledLen += pSrc->nFilledLen;
9215         pSrc->nFilledLen = 0;
9216     } else {
9217         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9218         rc = OMX_ErrorBadParameter;
9219     }
9220     return rc;
9221 }
9222 
push_input_hevc(OMX_HANDLETYPE hComp)9223 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9224 {
9225     OMX_U32 partial_frame = 1;
9226     unsigned long address,p2,id;
9227     OMX_BOOL isNewFrame = OMX_FALSE;
9228     OMX_BOOL generate_ebd = OMX_TRUE;
9229     OMX_ERRORTYPE rc = OMX_ErrorNone;
9230     if (h264_scratch.pBuffer == NULL) {
9231         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9232         return OMX_ErrorBadParameter;
9233     }
9234 
9235     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9236             pdest_frame nFilledLen %u nTimeStamp %lld",
9237             (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9238 
9239     if (h264_scratch.nFilledLen && look_ahead_nal) {
9240         look_ahead_nal = false;
9241         rc = copy_buffer(pdest_frame, &h264_scratch);
9242         if (rc != OMX_ErrorNone) {
9243             return rc;
9244         }
9245     }
9246 
9247     if (nal_length == 0) {
9248         if (m_frame_parser.parse_sc_frame(psource_frame,
9249                     &h264_scratch,&partial_frame) == -1) {
9250             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9251             return OMX_ErrorBadParameter;
9252         }
9253     } else {
9254         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9255         if (m_frame_parser.parse_h264_nallength(psource_frame,
9256                     &h264_scratch,&partial_frame) == -1) {
9257             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9258             return OMX_ErrorBadParameter;
9259         }
9260     }
9261 
9262     if (partial_frame == 0) {
9263         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9264             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9265             nal_count++;
9266             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9267             h264_scratch.nFlags = psource_frame->nFlags;
9268         } else {
9269             DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9270             if (h264_scratch.nFilledLen) {
9271                 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9272                 nal_count++;
9273             }
9274 
9275             if (!isNewFrame) {
9276                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9277                         nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9278                         (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9279                         (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9280                 rc = copy_buffer(pdest_frame, &h264_scratch);
9281                 if (rc != OMX_ErrorNone) {
9282                     return rc;
9283                 }
9284             } else {
9285                 look_ahead_nal = true;
9286                 if (pdest_frame->nFilledLen == 0) {
9287                     look_ahead_nal = false;
9288                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9289                     rc = copy_buffer(pdest_frame, &h264_scratch);
9290                     if (rc != OMX_ErrorNone) {
9291                         return OMX_ErrorBadParameter;
9292                     }
9293                 } else {
9294                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9295                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9296                     }
9297                     DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9298                             nTimeStamp %lld, look_ahead_nal in h264_scratch \
9299                             nFilledLen %u nTimeStamp %lld",
9300                             frame_count++, (unsigned int)pdest_frame->nFilledLen,
9301                             pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9302                             h264_scratch.nTimeStamp);
9303                     if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9304                         return OMX_ErrorBadParameter;
9305                     }
9306                     pdest_frame = NULL;
9307                     if (m_input_free_q.m_size) {
9308                         m_input_free_q.pop_entry(&address, &p2, &id);
9309                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9310                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9311                         pdest_frame->nFilledLen = 0;
9312                         pdest_frame->nFlags = 0;
9313                         pdest_frame->nTimeStamp = LLONG_MAX;
9314                     }
9315                 }
9316             }
9317         }
9318     } else {
9319         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9320                 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9321                 nFilledLen %u nTimeStamp %lld",
9322                 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9323                 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9324                 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9325 
9326         if (h264_scratch.nAllocLen ==
9327                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9328             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9329             return OMX_ErrorStreamCorrupt;
9330         }
9331     }
9332 
9333     if (!psource_frame->nFilledLen) {
9334         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9335         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9336             if (pdest_frame) {
9337                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9338                 rc = copy_buffer(pdest_frame, &h264_scratch);
9339                 if ( rc != OMX_ErrorNone ) {
9340                     return rc;
9341                 }
9342                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9343                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9344                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9345                         frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9346                 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9347                     return OMX_ErrorBadParameter;
9348                 }
9349                 frame_count++;
9350                 pdest_frame = NULL;
9351             } else {
9352                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9353                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9354                 generate_ebd = OMX_FALSE;
9355             }
9356         }
9357     }
9358 
9359     if (generate_ebd && !psource_frame->nFilledLen) {
9360         m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9361         psource_frame = NULL;
9362         if (m_input_pending_q.m_size) {
9363             m_input_pending_q.pop_entry(&address, &p2, &id);
9364             psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9365             DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9366                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9367         }
9368     }
9369     return OMX_ErrorNone;
9370 }
9371 
push_input_vc1(OMX_HANDLETYPE hComp)9372 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
9373 {
9374     OMX_U8 *buf, *pdest;
9375     OMX_U32 partial_frame = 1;
9376     OMX_U32 buf_len, dest_len;
9377 
9378     if (first_frame == 0) {
9379         first_frame = 1;
9380         DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
9381         if (!m_vendor_config.pData) {
9382             DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
9383             buf = psource_frame->pBuffer;
9384             buf_len = psource_frame->nFilledLen;
9385 
9386             if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
9387                     VC1_SP_MP_START_CODE) {
9388                 m_vc1_profile = VC1_SP_MP_RCV;
9389             } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
9390                 m_vc1_profile = VC1_AP;
9391             } else {
9392                 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
9393                 return OMX_ErrorStreamCorrupt;
9394             }
9395         } else {
9396             pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
9397                 pdest_frame->nOffset;
9398             dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
9399                     pdest_frame->nOffset);
9400 
9401             if (dest_len < m_vendor_config.nDataSize) {
9402                 DEBUG_PRINT_ERROR("Destination buffer full");
9403                 return OMX_ErrorBadParameter;
9404             } else {
9405                 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
9406                 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
9407             }
9408         }
9409     }
9410 
9411     switch (m_vc1_profile) {
9412         case VC1_AP:
9413             DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
9414             if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
9415                 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
9416                 return OMX_ErrorBadParameter;
9417             }
9418             break;
9419 
9420         case VC1_SP_MP_RCV:
9421         default:
9422             DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
9423             return OMX_ErrorBadParameter;
9424     }
9425     return OMX_ErrorNone;
9426 }
9427 
9428 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9429 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9430         OMX_U32 alignment)
9431 {
9432     struct pmem_allocation allocation;
9433     allocation.size = buffer_size;
9434     allocation.align = clip2(alignment);
9435     if (allocation.align < 4096) {
9436         allocation.align = 4096;
9437     }
9438     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9439         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9440                 allocation.align, allocation.size);
9441         return false;
9442     }
9443     return true;
9444 }
9445 #endif
9446 #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)9447 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
9448         OMX_U32 alignment, struct ion_allocation_data *alloc_data,
9449         struct ion_fd_data *fd_data, int flag)
9450 {
9451     int fd = -EINVAL;
9452     int rc = -EINVAL;
9453     int ion_dev_flag;
9454     struct vdec_ion ion_buf_info;
9455     if (!alloc_data || buffer_size <= 0 || !fd_data) {
9456         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9457         return -EINVAL;
9458     }
9459     ion_dev_flag = O_RDONLY;
9460     fd = open (MEM_DEVICE, ion_dev_flag);
9461     if (fd < 0) {
9462         DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
9463         return fd;
9464     }
9465 
9466     alloc_data->flags = flag;
9467     alloc_data->len = buffer_size;
9468     alloc_data->align = clip2(alignment);
9469     if (alloc_data->align < 4096) {
9470         alloc_data->align = 4096;
9471     }
9472 
9473     alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
9474     if (secure_mode && (alloc_data->flags & ION_SECURE)) {
9475         alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9476     }
9477 
9478     /* Use secure display cma heap for obvious reasons. */
9479     if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
9480         alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9481     }
9482 
9483     rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
9484     if (rc || !alloc_data->handle) {
9485         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9486         alloc_data->handle = 0;
9487         close(fd);
9488         fd = -ENOMEM;
9489         return fd;
9490     }
9491     fd_data->handle = alloc_data->handle;
9492     rc = ioctl(fd,ION_IOC_MAP,fd_data);
9493     if (rc) {
9494         DEBUG_PRINT_ERROR("ION MAP failed ");
9495         ion_buf_info.ion_alloc_data = *alloc_data;
9496         ion_buf_info.ion_device_fd = fd;
9497         ion_buf_info.fd_ion_data = *fd_data;
9498         free_ion_memory(&ion_buf_info);
9499         fd_data->fd =-1;
9500         fd = -ENOMEM;
9501     }
9502 
9503     return fd;
9504 }
9505 
free_ion_memory(struct vdec_ion * buf_ion_info)9506 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9507 {
9508 
9509     if (!buf_ion_info) {
9510         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9511         return;
9512     }
9513     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
9514                 &buf_ion_info->ion_alloc_data.handle)) {
9515         DEBUG_PRINT_ERROR("ION: free failed" );
9516     }
9517     close(buf_ion_info->ion_device_fd);
9518     buf_ion_info->ion_device_fd = -1;
9519     buf_ion_info->ion_alloc_data.handle = 0;
9520     buf_ion_info->fd_ion_data.fd = -1;
9521 }
9522 #endif
free_output_buffer_header()9523 void omx_vdec::free_output_buffer_header()
9524 {
9525     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
9526     output_use_buffer = false;
9527     ouput_egl_buffers = false;
9528 
9529     if (m_out_mem_ptr) {
9530         free (m_out_mem_ptr);
9531         m_out_mem_ptr = NULL;
9532     }
9533 
9534     if (m_platform_list) {
9535         free(m_platform_list);
9536         m_platform_list = NULL;
9537     }
9538 
9539     if (drv_ctx.ptr_respbuffer) {
9540         free (drv_ctx.ptr_respbuffer);
9541         drv_ctx.ptr_respbuffer = NULL;
9542     }
9543     if (drv_ctx.ptr_outputbuffer) {
9544         free (drv_ctx.ptr_outputbuffer);
9545         drv_ctx.ptr_outputbuffer = NULL;
9546     }
9547 #ifdef USE_ION
9548     if (drv_ctx.op_buf_ion_info) {
9549         DEBUG_PRINT_LOW("Free o/p ion context");
9550         free(drv_ctx.op_buf_ion_info);
9551         drv_ctx.op_buf_ion_info = NULL;
9552     }
9553 #endif
9554     buf_ref_remove();
9555 }
9556 
free_input_buffer_header()9557 void omx_vdec::free_input_buffer_header()
9558 {
9559     input_use_buffer = false;
9560     if (arbitrary_bytes) {
9561         if (m_inp_heap_ptr) {
9562             DEBUG_PRINT_LOW("Free input Heap Pointer");
9563             free (m_inp_heap_ptr);
9564             m_inp_heap_ptr = NULL;
9565         }
9566 
9567         if (m_phdr_pmem_ptr) {
9568             DEBUG_PRINT_LOW("Free input pmem header Pointer");
9569             free (m_phdr_pmem_ptr);
9570             m_phdr_pmem_ptr = NULL;
9571         }
9572     }
9573     if (m_inp_mem_ptr) {
9574         DEBUG_PRINT_LOW("Free input pmem Pointer area");
9575         free (m_inp_mem_ptr);
9576         m_inp_mem_ptr = NULL;
9577     }
9578     /* We just freed all the buffer headers, every thing in m_input_free_q,
9579      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
9580     while (m_input_free_q.m_size) {
9581         unsigned long address, p2, id;
9582         m_input_free_q.pop_entry(&address, &p2, &id);
9583     }
9584     while (m_input_pending_q.m_size) {
9585         unsigned long address, p2, id;
9586         m_input_pending_q.pop_entry(&address, &p2, &id);
9587     }
9588     pdest_frame = NULL;
9589     psource_frame = NULL;
9590     if (drv_ctx.ptr_inputbuffer) {
9591         DEBUG_PRINT_LOW("Free Driver Context pointer");
9592         free (drv_ctx.ptr_inputbuffer);
9593         drv_ctx.ptr_inputbuffer = NULL;
9594     }
9595 #ifdef USE_ION
9596     if (drv_ctx.ip_buf_ion_info) {
9597         DEBUG_PRINT_LOW("Free ion context");
9598         free(drv_ctx.ip_buf_ion_info);
9599         drv_ctx.ip_buf_ion_info = NULL;
9600     }
9601 #endif
9602 }
9603 
stream_off(OMX_U32 port)9604 int omx_vdec::stream_off(OMX_U32 port)
9605 {
9606     enum v4l2_buf_type btype;
9607     int rc = 0;
9608     enum v4l2_ports v4l2_port = OUTPUT_PORT;
9609 
9610     if (port == OMX_CORE_INPUT_PORT_INDEX) {
9611         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9612         v4l2_port = OUTPUT_PORT;
9613     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
9614         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9615         v4l2_port = CAPTURE_PORT;
9616     } else if (port == OMX_ALL) {
9617         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
9618         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
9619 
9620         if (!rc_input)
9621             return rc_input;
9622         else
9623             return rc_output;
9624     }
9625 
9626     if (!streaming[v4l2_port]) {
9627         // already streamed off, warn and move on
9628         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
9629                 " which is already streamed off", v4l2_port);
9630         return 0;
9631     }
9632 
9633     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
9634 
9635     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
9636     if (rc) {
9637         /*TODO: How to handle this case */
9638         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
9639     } else {
9640         streaming[v4l2_port] = false;
9641     }
9642 
9643     return rc;
9644 }
9645 
get_buffer_req(vdec_allocatorproperty * buffer_prop)9646 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
9647 {
9648     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9649     struct v4l2_requestbuffers bufreq;
9650     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
9651     unsigned int final_extra_data_size = 0;
9652     struct v4l2_format fmt;
9653     int ret = 0;
9654     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9655             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9656     bufreq.memory = V4L2_MEMORY_USERPTR;
9657     bufreq.count = 1;
9658     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9659         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9660         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9661         fmt.fmt.pix_mp.pixelformat = output_capability;
9662     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9663         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9664         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9665         fmt.fmt.pix_mp.pixelformat = capture_capability;
9666     } else {
9667         eRet = OMX_ErrorBadParameter;
9668     }
9669     if (eRet==OMX_ErrorNone) {
9670         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9671     }
9672     if (ret) {
9673         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9674         /*TODO: How to handle this case */
9675         eRet = OMX_ErrorInsufficientResources;
9676         return eRet;
9677     } else {
9678         buffer_prop->actualcount = bufreq.count;
9679         buffer_prop->mincount = bufreq.count;
9680         DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
9681     }
9682     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9683             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9684 
9685     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9686     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9687 
9688     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9689 
9690     update_resolution(fmt.fmt.pix_mp.width,
9691             fmt.fmt.pix_mp.height,
9692             fmt.fmt.pix_mp.plane_fmt[0].bytesperline,
9693             fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
9694     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
9695         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
9696     DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
9697 
9698     if (ret) {
9699         /*TODO: How to handle this case */
9700         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9701         eRet = OMX_ErrorInsufficientResources;
9702     } else {
9703         int extra_idx = 0;
9704 
9705         eRet = is_video_session_supported();
9706         if (eRet)
9707             return eRet;
9708 
9709         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
9710         buf_size = buffer_prop->buffer_size;
9711         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
9712         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
9713             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
9714         } else if (extra_idx >= VIDEO_MAX_PLANES) {
9715             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
9716             return OMX_ErrorBadParameter;
9717         }
9718 
9719         default_extra_data_size = VENUS_EXTRADATA_SIZE(
9720                 drv_ctx.video_resolution.frame_height,
9721                 drv_ctx.video_resolution.frame_width);
9722         final_extra_data_size = extra_data_size > default_extra_data_size ?
9723             extra_data_size : default_extra_data_size;
9724 
9725         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
9726             (~(buffer_prop->alignment - 1));
9727 
9728         drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
9729         drv_ctx.extradata_info.count = buffer_prop->actualcount;
9730         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
9731         if (!secure_mode)
9732             buf_size += final_extra_data_size;
9733         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9734         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
9735                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
9736         if (extra_data_size)
9737             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
9738                 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
9739 
9740         if (in_reconfig) // BufReq will be set to driver when port is disabled
9741             buffer_prop->buffer_size = buf_size;
9742         else if (buf_size != buffer_prop->buffer_size) {
9743             buffer_prop->buffer_size = buf_size;
9744             eRet = set_buffer_req(buffer_prop);
9745         }
9746     }
9747     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
9748             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9749     return eRet;
9750 }
9751 
set_buffer_req(vdec_allocatorproperty * buffer_prop)9752 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
9753 {
9754     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9755     unsigned buf_size = 0;
9756     struct v4l2_format fmt;
9757     struct v4l2_requestbuffers bufreq;
9758     int ret;
9759     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
9760             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9761     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9762     if (buf_size != buffer_prop->buffer_size) {
9763         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
9764                 (unsigned int)buffer_prop->buffer_size, buf_size);
9765         eRet = OMX_ErrorBadParameter;
9766     } else {
9767         memset(&fmt, 0x0, sizeof(struct v4l2_format));
9768         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9769         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9770         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
9771 
9772         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9773             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9774             fmt.fmt.pix_mp.pixelformat = output_capability;
9775         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9776             fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9777             fmt.fmt.pix_mp.pixelformat = capture_capability;
9778         } else {
9779             eRet = OMX_ErrorBadParameter;
9780         }
9781 
9782         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
9783         if (ret) {
9784             /*TODO: How to handle this case */
9785             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
9786             eRet = OMX_ErrorInsufficientResources;
9787         }
9788 
9789         bufreq.memory = V4L2_MEMORY_USERPTR;
9790         bufreq.count = buffer_prop->actualcount;
9791         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9792             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9793         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9794             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9795         } else {
9796             eRet = OMX_ErrorBadParameter;
9797         }
9798 
9799         if (eRet==OMX_ErrorNone) {
9800             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9801         }
9802 
9803         if (ret) {
9804             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
9805             /*TODO: How to handle this case */
9806             eRet = OMX_ErrorInsufficientResources;
9807         } else if (bufreq.count < buffer_prop->actualcount) {
9808             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
9809                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
9810                     buffer_prop->actualcount, bufreq.count);
9811             eRet = OMX_ErrorInsufficientResources;
9812         } else {
9813             if (!client_buffers.update_buffer_req()) {
9814                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
9815                 eRet = OMX_ErrorInsufficientResources;
9816             }
9817         }
9818     }
9819     return eRet;
9820 }
9821 
update_picture_resolution()9822 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
9823 {
9824     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9825     return eRet;
9826 }
9827 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)9828 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
9829 {
9830     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9831     struct v4l2_format fmt;
9832     if (!portDefn) {
9833         return OMX_ErrorBadParameter;
9834     }
9835     DEBUG_PRINT_LOW("omx_vdec::update_portdef");
9836     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
9837     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9838     portDefn->eDomain    = OMX_PortDomainVideo;
9839     if (drv_ctx.frame_rate.fps_denominator > 0)
9840         portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
9841             drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
9842     else {
9843         DEBUG_PRINT_ERROR("Error: Divide by zero");
9844         return OMX_ErrorBadParameter;
9845     }
9846     memset(&fmt, 0x0, sizeof(struct v4l2_format));
9847     if (0 == portDefn->nPortIndex) {
9848         portDefn->eDir =  OMX_DirInput;
9849         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
9850         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
9851         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
9852         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9853         portDefn->format.video.eCompressionFormat = eCompressionFormat;
9854         portDefn->bEnabled   = m_inp_bEnabled;
9855         portDefn->bPopulated = m_inp_bPopulated;
9856 
9857         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9858         fmt.fmt.pix_mp.pixelformat = output_capability;
9859     } else if (1 == portDefn->nPortIndex) {
9860         unsigned int buf_size = 0;
9861         if (!client_buffers.update_buffer_req()) {
9862             DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
9863             return OMX_ErrorHardware;
9864         }
9865         if (!client_buffers.get_buffer_req(buf_size)) {
9866             DEBUG_PRINT_ERROR("update buffer requirements");
9867             return OMX_ErrorHardware;
9868         }
9869         portDefn->nBufferSize = buf_size;
9870         portDefn->eDir =  OMX_DirOutput;
9871         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
9872         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
9873         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9874         portDefn->bEnabled   = m_out_bEnabled;
9875         portDefn->bPopulated = m_out_bPopulated;
9876         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
9877             DEBUG_PRINT_ERROR("Error in getting color format");
9878             return OMX_ErrorHardware;
9879         }
9880         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9881         fmt.fmt.pix_mp.pixelformat = capture_capability;
9882     } else {
9883         portDefn->eDir = OMX_DirMax;
9884         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
9885                 (int)portDefn->nPortIndex);
9886         eRet = OMX_ErrorBadPortIndex;
9887     }
9888     if (is_down_scalar_enabled) {
9889         int ret = 0;
9890         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9891         if (ret) {
9892             DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution");
9893             return OMX_ErrorHardware;
9894         } else {
9895             portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width;
9896             portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height;
9897             portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
9898             portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
9899         }
9900     } else {
9901         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
9902         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
9903         portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9904         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9905     }
9906 
9907     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
9908        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
9909            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
9910            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
9911     }
9912     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
9913             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
9914             (unsigned int)portDefn->nPortIndex,
9915             (unsigned int)portDefn->format.video.nFrameWidth,
9916             (unsigned int)portDefn->format.video.nFrameHeight,
9917             (int)portDefn->format.video.nStride,
9918             (unsigned int)portDefn->format.video.nSliceHeight,
9919             (unsigned int)portDefn->format.video.eColorFormat,
9920             (unsigned int)portDefn->nBufferSize,
9921             (unsigned int)portDefn->nBufferCountActual);
9922 
9923     return eRet;
9924 }
9925 
allocate_output_headers()9926 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
9927 {
9928     OMX_ERRORTYPE eRet = OMX_ErrorNone;
9929     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
9930     unsigned i= 0;
9931 
9932     if (!m_out_mem_ptr) {
9933         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
9934         int nBufHdrSize        = 0;
9935         int nPlatformEntrySize = 0;
9936         int nPlatformListSize  = 0;
9937         int nPMEMInfoSize = 0;
9938         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
9939         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
9940         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
9941 
9942         DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
9943                 drv_ctx.op_buf.actualcount);
9944         nBufHdrSize        = drv_ctx.op_buf.actualcount *
9945             sizeof(OMX_BUFFERHEADERTYPE);
9946 
9947         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
9948             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9949         nPlatformListSize  = drv_ctx.op_buf.actualcount *
9950             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9951         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9952             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9953 
9954         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
9955                 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
9956                 nPMEMInfoSize,
9957                 nPlatformListSize);
9958         DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
9959                 m_out_bm_count);
9960         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
9961         // Alloc mem for platform specific info
9962         char *pPtr=NULL;
9963         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9964                 nPMEMInfoSize,1);
9965         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9966                        calloc (sizeof(struct vdec_bufferpayload),
9967                                drv_ctx.op_buf.actualcount);
9968         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
9969                      calloc (sizeof (struct vdec_output_frameinfo),
9970                              drv_ctx.op_buf.actualcount);
9971         if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9972             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
9973             return OMX_ErrorInsufficientResources;
9974         }
9975 
9976 #ifdef USE_ION
9977         drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9978                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9979         if (!drv_ctx.op_buf_ion_info) {
9980             DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9981             return OMX_ErrorInsufficientResources;
9982         }
9983 #endif
9984         if (dynamic_buf_mode) {
9985             out_dynamic_list = (struct dynamic_buf_list *) \
9986                 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
9987             if (out_dynamic_list) {
9988                for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
9989                   out_dynamic_list[i].dup_fd = -1;
9990             }
9991         }
9992 
9993         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9994                 && drv_ctx.ptr_respbuffer) {
9995             bufHdr          =  m_out_mem_ptr;
9996             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9997             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9998                 (((char *) m_platform_list)  + nPlatformListSize);
9999             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10000                 (((char *) m_platform_entry) + nPlatformEntrySize);
10001             pPlatformList   = m_platform_list;
10002             pPlatformEntry  = m_platform_entry;
10003             pPMEMInfo       = m_pmem_info;
10004 
10005             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
10006 
10007             // Settting the entire storage nicely
10008             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10009                     m_out_mem_ptr,pPlatformEntry);
10010             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10011             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10012                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
10013                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
10014                 // Set the values when we determine the right HxW param
10015                 bufHdr->nAllocLen          = 0;
10016                 bufHdr->nFilledLen         = 0;
10017                 bufHdr->pAppPrivate        = NULL;
10018                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
10019                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10020                 pPlatformEntry->entry      = pPMEMInfo;
10021                 // Initialize the Platform List
10022                 pPlatformList->nEntries    = 1;
10023                 pPlatformList->entryList   = pPlatformEntry;
10024                 // Keep pBuffer NULL till vdec is opened
10025                 bufHdr->pBuffer            = NULL;
10026                 pPMEMInfo->offset          =  0;
10027                 pPMEMInfo->pmem_fd = -1;
10028                 bufHdr->pPlatformPrivate = pPlatformList;
10029                 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
10030 #ifdef USE_ION
10031                 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
10032 #endif
10033                 /*Create a mapping between buffers*/
10034                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
10035                 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
10036                                     &drv_ctx.ptr_outputbuffer[i];
10037                 // Move the buffer and buffer header pointers
10038                 bufHdr++;
10039                 pPMEMInfo++;
10040                 pPlatformEntry++;
10041                 pPlatformList++;
10042             }
10043         } else {
10044             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10045                     m_out_mem_ptr, pPtr);
10046             if (m_out_mem_ptr) {
10047                 free(m_out_mem_ptr);
10048                 m_out_mem_ptr = NULL;
10049             }
10050             if (pPtr) {
10051                 free(pPtr);
10052                 pPtr = NULL;
10053             }
10054             if (drv_ctx.ptr_outputbuffer) {
10055                 free(drv_ctx.ptr_outputbuffer);
10056                 drv_ctx.ptr_outputbuffer = NULL;
10057             }
10058             if (drv_ctx.ptr_respbuffer) {
10059                 free(drv_ctx.ptr_respbuffer);
10060                 drv_ctx.ptr_respbuffer = NULL;
10061             }
10062 #ifdef USE_ION
10063             if (drv_ctx.op_buf_ion_info) {
10064                 DEBUG_PRINT_LOW("Free o/p ion context");
10065                 free(drv_ctx.op_buf_ion_info);
10066                 drv_ctx.op_buf_ion_info = NULL;
10067             }
10068 #endif
10069             eRet =  OMX_ErrorInsufficientResources;
10070         }
10071     } else {
10072         eRet =  OMX_ErrorInsufficientResources;
10073     }
10074     return eRet;
10075 }
10076 
complete_pending_buffer_done_cbs()10077 void omx_vdec::complete_pending_buffer_done_cbs()
10078 {
10079     unsigned long p1, p2, ident;
10080     omx_cmd_queue tmp_q, pending_bd_q;
10081     pthread_mutex_lock(&m_lock);
10082     // pop all pending GENERATE FDB from ftb queue
10083     while (m_ftb_q.m_size) {
10084         m_ftb_q.pop_entry(&p1,&p2,&ident);
10085         if (ident == OMX_COMPONENT_GENERATE_FBD) {
10086             pending_bd_q.insert_entry(p1,p2,ident);
10087         } else {
10088             tmp_q.insert_entry(p1,p2,ident);
10089         }
10090     }
10091     //return all non GENERATE FDB to ftb queue
10092     while (tmp_q.m_size) {
10093         tmp_q.pop_entry(&p1,&p2,&ident);
10094         m_ftb_q.insert_entry(p1,p2,ident);
10095     }
10096     // pop all pending GENERATE EDB from etb queue
10097     while (m_etb_q.m_size) {
10098         m_etb_q.pop_entry(&p1,&p2,&ident);
10099         if (ident == OMX_COMPONENT_GENERATE_EBD) {
10100             pending_bd_q.insert_entry(p1,p2,ident);
10101         } else {
10102             tmp_q.insert_entry(p1,p2,ident);
10103         }
10104     }
10105     //return all non GENERATE FDB to etb queue
10106     while (tmp_q.m_size) {
10107         tmp_q.pop_entry(&p1,&p2,&ident);
10108         m_etb_q.insert_entry(p1,p2,ident);
10109     }
10110     pthread_mutex_unlock(&m_lock);
10111     // process all pending buffer dones
10112     while (pending_bd_q.m_size) {
10113         pending_bd_q.pop_entry(&p1,&p2,&ident);
10114         switch (ident) {
10115             case OMX_COMPONENT_GENERATE_EBD:
10116                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10117                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10118                     omx_report_error ();
10119                 }
10120                 break;
10121 
10122             case OMX_COMPONENT_GENERATE_FBD:
10123                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10124                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10125                     omx_report_error ();
10126                 }
10127                 break;
10128         }
10129     }
10130 }
10131 
set_frame_rate(OMX_S64 act_timestamp)10132 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10133 {
10134     OMX_U32 new_frame_interval = 0;
10135     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10136             && llabs(act_timestamp - prev_ts) > 2000) {
10137         new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10138             llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10139         if (new_frame_interval != frm_int || frm_int == 0) {
10140             frm_int = new_frame_interval;
10141             if (frm_int) {
10142                 drv_ctx.frame_rate.fps_numerator = 1e6;
10143                 drv_ctx.frame_rate.fps_denominator = frm_int;
10144                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10145                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10146                         (float)drv_ctx.frame_rate.fps_denominator);
10147                 m_perf_control.request_cores(frm_int);
10148                 /* We need to report the difference between this FBD and the previous FBD
10149                  * back to the driver for clock scaling purposes. */
10150                 struct v4l2_outputparm oparm;
10151                 /*XXX: we're providing timing info as seconds per frame rather than frames
10152                  * per second.*/
10153                 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10154                 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10155 
10156                 struct v4l2_streamparm sparm;
10157                 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10158                 sparm.parm.output = oparm;
10159                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10160                     DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10161                             performance might be affected");
10162                 }
10163 
10164             }
10165         }
10166     }
10167     prev_ts = act_timestamp;
10168 }
10169 
adjust_timestamp(OMX_S64 & act_timestamp)10170 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10171 {
10172     if (rst_prev_ts && VALID_TS(act_timestamp)) {
10173         prev_ts = act_timestamp;
10174         prev_ts_actual = act_timestamp;
10175         rst_prev_ts = false;
10176     } else if (VALID_TS(prev_ts)) {
10177         bool codec_cond = (drv_ctx.timestamp_adjust)?
10178             (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10179             (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10180              prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10181         if (frm_int > 0 && codec_cond) {
10182             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10183             act_timestamp = prev_ts + frm_int;
10184             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10185             prev_ts = act_timestamp;
10186         } else {
10187             if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10188                 // ensure that timestamps can never step backwards when in display order
10189                 act_timestamp = prev_ts;
10190             }
10191             set_frame_rate(act_timestamp);
10192         }
10193     } else if (frm_int > 0)          // In this case the frame rate was set along
10194     {                               // with the port definition, start ts with 0
10195         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
10196         rst_prev_ts = true;
10197     }
10198 }
10199 
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorSpace_t * color_space,ColorAspects * aspects)10200 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10201     OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
10202 {
10203     switch (primaries) {
10204         case MSM_VIDC_BT709_5:
10205             *color_space = ITU_R_709;
10206             aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10207             break;
10208         case MSM_VIDC_BT470_6_M:
10209             aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10210             break;
10211         case MSM_VIDC_BT601_6_625:
10212             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10213             break;
10214         case MSM_VIDC_BT601_6_525:
10215             *color_space = range ? ITU_R_601_FR : ITU_R_601;
10216             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10217             break;
10218         case MSM_VIDC_GENERIC_FILM:
10219             aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10220             break;
10221         case MSM_VIDC_BT2020:
10222             aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10223             break;
10224         case MSM_VIDC_UNSPECIFIED:
10225             //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10226         default:
10227             //aspects->mPrimaries = ColorAspects::PrimariesOther;
10228             aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10229             break;
10230     }
10231 
10232     aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10233 
10234     switch (transfer) {
10235         case MSM_VIDC_TRANSFER_BT709_5:
10236         case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10237             aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10238             break;
10239         case MSM_VIDC_TRANSFER_BT_470_6_M:
10240             aspects->mTransfer = ColorAspects::TransferGamma22;
10241             break;
10242         case MSM_VIDC_TRANSFER_BT_470_6_BG:
10243             aspects->mTransfer = ColorAspects::TransferGamma28;
10244             break;
10245         case MSM_VIDC_TRANSFER_SMPTE_240M:
10246             aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10247             break;
10248         case MSM_VIDC_TRANSFER_LINEAR:
10249             aspects->mTransfer = ColorAspects::TransferLinear;
10250             break;
10251         case MSM_VIDC_TRANSFER_IEC_61966:
10252             aspects->mTransfer = ColorAspects::TransferXvYCC;
10253             break;
10254         case MSM_VIDC_TRANSFER_BT_1361:
10255             aspects->mTransfer = ColorAspects::TransferBT1361;
10256             break;
10257         case MSM_VIDC_TRANSFER_SRGB:
10258             aspects->mTransfer = ColorAspects::TransferSRGB;
10259             break;
10260         default:
10261             //aspects->mTransfer = ColorAspects::TransferOther;
10262             aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10263             break;
10264     }
10265 
10266     switch (matrix) {
10267         case MSM_VIDC_MATRIX_BT_709_5:
10268             aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10269             break;
10270         case MSM_VIDC_MATRIX_FCC_47:
10271             aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10272             break;
10273         case MSM_VIDC_MATRIX_601_6_625:
10274         case MSM_VIDC_MATRIX_601_6_525:
10275             aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10276             break;
10277         case MSM_VIDC_MATRIX_SMPTE_240M:
10278             aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10279             break;
10280         case MSM_VIDC_MATRIX_BT_2020:
10281             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10282             break;
10283         case MSM_VIDC_MATRIX_BT_2020_CONST:
10284             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10285             break;
10286         default:
10287             //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10288             aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10289             break;
10290     }
10291 }
10292 
print_debug_color_aspects(ColorAspects * aspects,const char * prefix)10293 void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
10294         DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
10295                 prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
10296 }
10297 
handle_color_space_info(void * data,unsigned int buf_index)10298 void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
10299 {
10300     ColorSpace_t color_space = ITU_R_601;
10301     ColorAspects tempAspects;
10302     memset(&tempAspects, 0x0, sizeof(ColorAspects));
10303     ColorAspects *aspects = &tempAspects;
10304 
10305     switch(output_capability) {
10306         case V4L2_PIX_FMT_MPEG2:
10307             {
10308                 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10309                 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10310 
10311                 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10312                  * understand this code */
10313 
10314                 if (seqdisp_payload && seqdisp_payload->color_descp) {
10315 
10316                     convert_color_space_info(seqdisp_payload->color_primaries, 1,
10317                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10318                             &color_space,aspects);
10319                     m_disp_hor_size = seqdisp_payload->disp_width;
10320                     m_disp_vert_size = seqdisp_payload->disp_height;
10321                 }
10322             }
10323             break;
10324         case V4L2_PIX_FMT_H264:
10325         case V4L2_PIX_FMT_HEVC:
10326             {
10327                 struct msm_vidc_vui_display_info_payload *display_info_payload;
10328                 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10329 
10330                 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10331 
10332                 if (display_info_payload->video_signal_present_flag &&
10333                         display_info_payload->color_description_present_flag) {
10334                     convert_color_space_info(display_info_payload->color_primaries,
10335                             display_info_payload->video_full_range_flag,
10336                             display_info_payload->transfer_characteristics,
10337                             display_info_payload->matrix_coefficients,
10338                             &color_space,aspects);
10339                 }
10340             }
10341             break;
10342         case V4L2_PIX_FMT_VC1_ANNEX_G:
10343         case V4L2_PIX_FMT_VC1_ANNEX_L:
10344             {
10345                 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
10346                 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
10347 
10348                 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
10349                  * SMPTE 421M to understand this code */
10350 
10351                 if (m_enable_android_native_buffers &&
10352                         vc1_seq_disp_payload->color_primaries) {
10353 
10354                     convert_color_space_info(vc1_seq_disp_payload->color_primaries,
10355                             1,
10356                             vc1_seq_disp_payload->transfer_char,
10357                             vc1_seq_disp_payload->matrix_coeffs,
10358                             &color_space,aspects);
10359                 }
10360             }
10361             break;
10362         case V4L2_PIX_FMT_VP8:
10363             {
10364                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10365                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10366 
10367                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10368                  * to understand this code */
10369 
10370                 if (vpx_color_space_payload->color_space == 0) {
10371                     color_space = ITU_R_601;
10372                 } else {
10373                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10374                     break;
10375                 }
10376             }
10377             break;
10378         case V4L2_PIX_FMT_VP9:
10379             {
10380                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10381                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10382 
10383                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10384                  * to understand this code */
10385 
10386                 switch(vpx_color_space_payload->color_space) {
10387                     case MSM_VIDC_CS_BT_601:
10388                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10389                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10390                         aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10391                         aspects->mRange = m_client_color_space.sAspects.mRange;
10392                         break;
10393                     case MSM_VIDC_CS_BT_709:
10394                         color_space = ITU_R_709;
10395                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10396                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10397                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
10398                         aspects->mRange = m_client_color_space.sAspects.mRange;
10399                         break;
10400                     case MSM_VIDC_CS_SMPTE_170:
10401                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10402                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10403                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10404                         aspects->mRange = m_client_color_space.sAspects.mRange;
10405                         break;
10406                     case MSM_VIDC_CS_SMPTE_240:
10407                         aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10408                         aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10409                         aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10410                         aspects->mRange = m_client_color_space.sAspects.mRange;
10411                         break;
10412                     case MSM_VIDC_CS_BT_2020:
10413                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10414                         aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
10415                         aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10416                         aspects->mRange = m_client_color_space.sAspects.mRange;
10417                         break;
10418                     case MSM_VIDC_CS_RESERVED:
10419                         aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10420                         aspects->mTransfer = ColorAspects::TransferOther;
10421                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10422                         aspects->mRange = m_client_color_space.sAspects.mRange;
10423                         break;
10424                     case MSM_VIDC_CS_RGB:
10425                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10426                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10427                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10428                         aspects->mRange = m_client_color_space.sAspects.mRange;
10429                         break;
10430                     default:
10431                         break;
10432                 }
10433             }
10434             break;
10435         default:
10436             break;
10437     }
10438     if (m_enable_android_native_buffers) {
10439         DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
10440         set_colorspace_in_handle(color_space, buf_index);
10441     }
10442     print_debug_color_aspects(aspects, "Bitstream");
10443 
10444     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
10445             m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
10446             m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
10447             m_internal_color_space.sAspects.mRange != aspects->mRange) {
10448         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
10449         m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
10450 
10451         DEBUG_PRINT_HIGH("Initiating PORT Reconfig");
10452         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
10453         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
10454 
10455         post_event(OMX_CORE_OUTPUT_PORT_INDEX,
10456                 OMX_QTIIndexConfigDescribeColorAspects,
10457                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
10458     }
10459 }
10460 
set_colorspace_in_handle(ColorSpace_t color_space,unsigned int buf_index)10461 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
10462     private_handle_t *private_handle = NULL;
10463     if (buf_index < drv_ctx.op_buf.actualcount &&
10464             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
10465             native_buffer[buf_index].privatehandle) {
10466         private_handle = native_buffer[buf_index].privatehandle;
10467     }
10468     if (private_handle) {
10469         setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
10470     }
10471 }
10472 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)10473 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
10474 {
10475     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
10476     OMX_U32 num_conceal_MB = 0;
10477     OMX_TICKS time_stamp = 0;
10478     OMX_U32 frame_rate = 0;
10479     unsigned long consumed_len = 0;
10480     OMX_U32 num_MB_in_frame;
10481     OMX_U32 recovery_sei_flags = 1;
10482     int enable = 0;
10483 
10484     int buf_index = p_buf_hdr - m_out_mem_ptr;
10485     if (buf_index >= drv_ctx.extradata_info.count) {
10486         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
10487                 buf_index, drv_ctx.extradata_info.count);
10488         return;
10489     }
10490     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
10491 
10492     if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
10493         DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
10494         return;
10495     }
10496 
10497     OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
10498         p_buf_hdr->nOffset;
10499 
10500     if (!drv_ctx.extradata_info.uaddr) {
10501         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
10502         return;
10503     }
10504     if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
10505         DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
10506         p_extra = NULL;
10507         return;
10508     }
10509     if (!secure_mode)
10510         p_extra = (OMX_OTHER_EXTRADATATYPE *)
10511             ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
10512     else
10513         p_extra = m_other_extradata;
10514     char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
10515 
10516     if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10517         p_extra = NULL;
10518         DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10519         return;
10520     }
10521     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
10522     if (data && p_extra) {
10523         while ((consumed_len < drv_ctx.extradata_info.buffer_size)
10524                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
10525             if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
10526                 DEBUG_PRINT_LOW("Invalid extra data size");
10527                 break;
10528             }
10529 
10530             if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10531                 p_extra = NULL;
10532                 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10533                 return;
10534             }
10535 
10536             DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
10537             switch ((unsigned long)data->eType) {
10538                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
10539                     struct msm_vidc_interlace_payload *payload;
10540                     OMX_U32 interlace_color_format;
10541                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
10542                     if (payload) {
10543                         enable = 1;
10544                         switch (payload->format) {
10545                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
10546                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10547                                 enable = 0;
10548                                 break;
10549                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
10550                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10551                                 break;
10552                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
10553                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
10554                                 break;
10555                             default:
10556                                 DEBUG_PRINT_LOW("default case - set interlace to topfield");
10557                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10558                         }
10559                         switch (payload->color_format) {
10560                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
10561                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10562                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
10563                                break;
10564                            case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
10565                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
10566                                drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
10567                                break;
10568                            default:
10569                                interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10570                                DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
10571                         }
10572                     }
10573 
10574                     if (m_enable_android_native_buffers) {
10575                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
10576                                          payload->format, interlace_color_format ,enable,
10577                                         (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
10578 
10579                         setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10580                                PP_PARAM_INTERLACED, (void*)&enable);
10581 
10582                         if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
10583                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10584                                LINEAR_FORMAT, (void*)&interlace_color_format);
10585                         }
10586                     }
10587                     if (client_extradata & OMX_INTERLACE_EXTRADATA) {
10588                         append_interlace_extradata(p_extra, payload->format,
10589                                       p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF);
10590                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10591                     }
10592                     break;
10593                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
10594                     struct msm_vidc_framerate_payload *frame_rate_payload;
10595                     frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
10596                     frame_rate = frame_rate_payload->frame_rate;
10597                     break;
10598                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
10599                     struct msm_vidc_ts_payload *time_stamp_payload;
10600                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
10601                     time_stamp = time_stamp_payload->timestamp_lo;
10602                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
10603                     p_buf_hdr->nTimeStamp = time_stamp;
10604                     break;
10605                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
10606                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
10607                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
10608                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10609                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10610                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
10611                     break;
10612                 case MSM_VIDC_EXTRADATA_INDEX:
10613                     int *etype;
10614                     etype  = (int *)(void *)data->data;
10615                     if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
10616                         struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
10617                         aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
10618                         if (aspect_ratio_payload) {
10619                             ((struct vdec_output_frameinfo *)
10620                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
10621                             ((struct vdec_output_frameinfo *)
10622                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
10623                         }
10624                     }
10625                     break;
10626                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
10627                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
10628                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
10629                     recovery_sei_flags = recovery_sei_payload->flags;
10630                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
10631                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
10632                         DEBUG_PRINT_HIGH("***************************************************");
10633                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
10634                         DEBUG_PRINT_HIGH("***************************************************");
10635                     }
10636                     break;
10637                case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
10638                     panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
10639                     if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
10640                         DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
10641                         DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
10642                             MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
10643                         return;
10644                     }
10645                     break;
10646                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
10647                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
10648                 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
10649                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
10650                         handle_color_space_info((void *)data->data, buf_index);
10651                     break;
10652                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
10653                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
10654                     s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
10655                     if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
10656                         append_framepack_extradata(p_extra, s3d_frame_packing_payload);
10657                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10658                     }
10659                     break;
10660                 case MSM_VIDC_EXTRADATA_FRAME_QP:
10661                     struct msm_vidc_frame_qp_payload *qp_payload;
10662                     qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
10663                     if (client_extradata & OMX_QP_EXTRADATA) {
10664                         append_qp_extradata(p_extra, qp_payload);
10665                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10666                     }
10667                     break;
10668                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
10669                     struct msm_vidc_frame_bits_info_payload *bits_info_payload;
10670                     bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
10671                     if (client_extradata & OMX_BITSINFO_EXTRADATA) {
10672                         append_bitsinfo_extradata(p_extra, bits_info_payload);
10673                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10674                     }
10675                     break;
10676                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
10677                     if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
10678                         append_user_extradata(p_extra, data);
10679                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10680                     }
10681                     break;
10682                 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
10683                     struct msm_vidc_vqzip_sei_payload *vqzip_payload;
10684                     vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
10685                     if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
10686                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10687                         append_vqzip_extradata(p_extra, vqzip_payload);
10688                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10689                     }
10690                     break;
10691                 default:
10692                     DEBUG_PRINT_LOW("Unrecognized extradata");
10693                     goto unrecognized_extradata;
10694             }
10695             consumed_len += data->nSize;
10696             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
10697         }
10698         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
10699             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10700             append_frame_info_extradata(p_extra,
10701                     num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10702                     time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10703                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10704             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10705         }
10706         if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
10707             append_frame_dimension_extradata(p_extra);
10708             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10709         }
10710     }
10711 unrecognized_extradata:
10712     if (client_extradata && p_extra) {
10713         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10714         append_terminator_extradata(p_extra);
10715     }
10716     if (secure_mode && p_extradata && m_other_extradata) {
10717         struct vdec_output_frameinfo  *ptr_extradatabuff = NULL;
10718         memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
10719         ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
10720         ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
10721         ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
10722     }
10723     return;
10724 }
10725 
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)10726 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
10727         bool is_internal, bool enable)
10728 {
10729     OMX_ERRORTYPE ret = OMX_ErrorNone;
10730     struct v4l2_control control;
10731     if (m_state != OMX_StateLoaded) {
10732         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
10733         return OMX_ErrorIncorrectStateOperation;
10734     }
10735     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
10736             (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
10737 
10738     if (!is_internal) {
10739         if (enable)
10740             client_extradata |= requested_extradata;
10741         else
10742             client_extradata = client_extradata & ~requested_extradata;
10743     }
10744 
10745     if (enable) {
10746         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
10747             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10748             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
10749             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10750                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
10751                         " Quality of interlaced clips might be impacted.");
10752             }
10753         }
10754         if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
10755             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10756             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
10757             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10758                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
10759             }
10760             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10761             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
10762             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10763                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
10764             }
10765             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10766             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
10767             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10768                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
10769             }
10770             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10771             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
10772             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10773                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10774             }
10775             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10776             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
10777             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10778                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10779             }
10780             if (output_capability == V4L2_PIX_FMT_MPEG2) {
10781                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10782                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10783                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10784                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10785                 }
10786             }
10787         }
10788         if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
10789             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10790             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
10791             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10792                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
10793             }
10794         }
10795         if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
10796             if (output_capability == V4L2_PIX_FMT_H264) {
10797                 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
10798                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10799                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
10800                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10801                     DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
10802                 }
10803             } else {
10804                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
10805             }
10806         }
10807         if (requested_extradata & OMX_QP_EXTRADATA) {
10808             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10809             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10810             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10811                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10812             }
10813         }
10814         if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
10815             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10816             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
10817             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10818                 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
10819             }
10820         }
10821         if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
10822             if (secure_mode) {
10823                 DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions");
10824                 return OMX_ErrorUnsupportedSetting;
10825             }
10826             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10827             control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
10828             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10829                 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
10830             }
10831         }
10832         if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
10833             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10834             control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
10835             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10836                 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
10837             }
10838             client_extradata |= OMX_VQZIPSEI_EXTRADATA;
10839 
10840             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10841             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10842             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10843                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10844             }
10845             client_extradata |= OMX_QP_EXTRADATA;
10846         }
10847         if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
10848             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10849             switch(output_capability) {
10850                 case V4L2_PIX_FMT_H264:
10851                 case V4L2_PIX_FMT_HEVC:
10852                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
10853                     break;
10854                 case CODEC_TYPE_MPEG2:
10855                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10856                     break;
10857                 case V4L2_PIX_FMT_VP8:
10858                 case V4L2_PIX_FMT_VP9:
10859                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
10860                     break;
10861                 case V4L2_PIX_FMT_VC1_ANNEX_G:
10862                 case V4L2_PIX_FMT_VC1_ANNEX_L:
10863                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
10864                     break;
10865                 default:
10866                     DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
10867                     return ret;
10868             }
10869 
10870             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10871                 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
10872             }
10873         }
10874     }
10875     ret = get_buffer_req(&drv_ctx.op_buf);
10876     return ret;
10877 }
10878 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)10879 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10880 {
10881     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
10882     OMX_U8 *data_ptr = extra->data, data = 0;
10883     while (byte_count < extra->nDataSize) {
10884         data = *data_ptr;
10885         while (data) {
10886             num_MB += (data&0x01);
10887             data >>= 1;
10888         }
10889         data_ptr++;
10890         byte_count++;
10891     }
10892     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10893             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10894     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
10895 }
10896 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)10897 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10898 {
10899     if (!m_debug_extradata || !extra)
10900         return;
10901 
10902 
10903     DEBUG_PRINT_HIGH(
10904             "============== Extra Data ==============\n"
10905             "           Size: %u\n"
10906             "        Version: %u\n"
10907             "      PortIndex: %u\n"
10908             "           Type: %x\n"
10909             "       DataSize: %u",
10910             (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
10911             (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
10912 
10913     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
10914         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10915         DEBUG_PRINT_HIGH(
10916                 "------ Interlace Format ------\n"
10917                 "                Size: %u\n"
10918                 "             Version: %u\n"
10919                 "           PortIndex: %u\n"
10920                 " Is Interlace Format: %d\n"
10921                 "   Interlace Formats: %u\n"
10922                 "=========== End of Interlace ===========",
10923                 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
10924                 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
10925     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
10926         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10927 
10928         DEBUG_PRINT_HIGH(
10929                 "-------- Frame Format --------\n"
10930                 "             Picture Type: %d\n"
10931                 "           Interlace Type: %d\n"
10932                 " Pan Scan Total Frame Num: %u\n"
10933                 "   Concealed Macro Blocks: %u\n"
10934                 "               frame rate: %u\n"
10935                 "               Time Stamp: %llu\n"
10936                 "           Aspect Ratio X: %u\n"
10937                 "           Aspect Ratio Y: %u",
10938                 fminfo->ePicType,
10939                 fminfo->interlaceType,
10940                 (unsigned int)fminfo->panScan.numWindows,
10941                 (unsigned int)fminfo->nConcealedMacroblocks,
10942                 (unsigned int)fminfo->nFrameRate,
10943                 fminfo->nTimeStamp,
10944                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
10945                 (unsigned int)fminfo->aspectRatio.aspectRatioY);
10946 
10947         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
10948             DEBUG_PRINT_HIGH(
10949                     "------------------------------"
10950                     "     Pan Scan Frame Num: %u\n"
10951                     "            Rectangle x: %d\n"
10952                     "            Rectangle y: %d\n"
10953                     "           Rectangle dx: %d\n"
10954                     "           Rectangle dy: %d",
10955                     (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
10956                     (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
10957         }
10958 
10959         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
10960     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
10961         OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10962         DEBUG_PRINT_HIGH(
10963                 "------------------ Framepack Format ----------\n"
10964                 "                           id: %u \n"
10965                 "                  cancel_flag: %u \n"
10966                 "                         type: %u \n"
10967                 " quincunx_sampling_flagFormat: %u \n"
10968                 "  content_interpretation_type: %u \n"
10969                 "        spatial_flipping_flag: %u \n"
10970                 "          frame0_flipped_flag: %u \n"
10971                 "             field_views_flag: %u \n"
10972                 " current_frame_is_frame0_flag: %u \n"
10973                 "   frame0_self_contained_flag: %u \n"
10974                 "   frame1_self_contained_flag: %u \n"
10975                 "       frame0_grid_position_x: %u \n"
10976                 "       frame0_grid_position_y: %u \n"
10977                 "       frame1_grid_position_x: %u \n"
10978                 "       frame1_grid_position_y: %u \n"
10979                 "                reserved_byte: %u \n"
10980                 "            repetition_period: %u \n"
10981                 "               extension_flag: %u \n"
10982                 "================== End of Framepack ===========",
10983                 (unsigned int)framepack->id,
10984                 (unsigned int)framepack->cancel_flag,
10985                 (unsigned int)framepack->type,
10986                 (unsigned int)framepack->quincunx_sampling_flag,
10987                 (unsigned int)framepack->content_interpretation_type,
10988                 (unsigned int)framepack->spatial_flipping_flag,
10989                 (unsigned int)framepack->frame0_flipped_flag,
10990                 (unsigned int)framepack->field_views_flag,
10991                 (unsigned int)framepack->current_frame_is_frame0_flag,
10992                 (unsigned int)framepack->frame0_self_contained_flag,
10993                 (unsigned int)framepack->frame1_self_contained_flag,
10994                 (unsigned int)framepack->frame0_grid_position_x,
10995                 (unsigned int)framepack->frame0_grid_position_y,
10996                 (unsigned int)framepack->frame1_grid_position_x,
10997                 (unsigned int)framepack->frame1_grid_position_y,
10998                 (unsigned int)framepack->reserved_byte,
10999                 (unsigned int)framepack->repetition_period,
11000                 (unsigned int)framepack->extension_flag);
11001     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
11002         OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11003         DEBUG_PRINT_HIGH(
11004                 "---- QP (Frame quantization parameter) ----\n"
11005                 "    Frame QP: %u \n"
11006                 "================ End of QP ================\n",
11007                 (unsigned int)qp->nQP);
11008     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
11009         OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
11010         DEBUG_PRINT_HIGH(
11011                 "--------- Input bits information --------\n"
11012                 "    Header bits: %u \n"
11013                 "     Frame bits: %u \n"
11014                 "===== End of Input bits information =====\n",
11015                 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
11016     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
11017         OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
11018         OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
11019         OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
11020         OMX_U32 i = 0;
11021         DEBUG_PRINT_HIGH(
11022                 "--------------  Userdata  -------------\n"
11023                 "    Stream userdata type: %u\n"
11024                 "          userdata size: %u\n"
11025                 "    STREAM_USERDATA:",
11026                 (unsigned int)userdata->type, (unsigned int)userdata_size);
11027                 for (i = 0; i < userdata_size; i+=4) {
11028                     DEBUG_PRINT_HIGH("        %x %x %x %x",
11029                         data_ptr[i], data_ptr[i+1],
11030                         data_ptr[i+2], data_ptr[i+3]);
11031                 }
11032         DEBUG_PRINT_HIGH(
11033                 "=========== End of Userdata ===========");
11034     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
11035         OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11036         DEBUG_PRINT_HIGH(
11037                 "--------------  VQZip  -------------\n"
11038                 "    Size: %u\n",
11039                 (unsigned int)vq->nSize);
11040         DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
11041     } else if (extra->eType == OMX_ExtraDataNone) {
11042         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
11043     } else {
11044         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
11045     }
11046 }
11047 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type,bool is_mbaff)11048 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11049         OMX_U32 interlaced_format_type, bool is_mbaff)
11050 {
11051     OMX_STREAMINTERLACEFORMAT *interlace_format;
11052 
11053     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
11054         return;
11055     }
11056     if (!extra) {
11057        DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
11058        return;
11059     }
11060     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
11061     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11062     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11063     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
11064     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11065     interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11066     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11067     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
11068     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11069 
11070     if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) {
11071         interlace_format->bInterlaceFormat = OMX_FALSE;
11072         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11073         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11074     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) {
11075         interlace_format->bInterlaceFormat = OMX_TRUE;
11076         interlace_format->nInterlaceFormats =  OMX_InterlaceInterleaveFrameTopFieldFirst;
11077         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11078     } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) {
11079         interlace_format->bInterlaceFormat = OMX_TRUE;
11080         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11081         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11082     } else {
11083         interlace_format->bInterlaceFormat = OMX_TRUE;
11084         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
11085         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11086     }
11087     print_debug_extradata(extra);
11088 }
11089 
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)11090 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11091 {
11092     OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
11093     if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
11094         return;
11095     }
11096     extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
11097     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11098     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11099     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
11100     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
11101     frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
11102     frame_dimension->nDecWidth = rectangle.nLeft;
11103     frame_dimension->nDecHeight = rectangle.nTop;
11104     frame_dimension->nActualWidth = rectangle.nWidth;
11105     frame_dimension->nActualHeight = rectangle.nHeight;
11106 }
11107 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)11108 void omx_vdec::fill_aspect_ratio_info(
11109         struct vdec_aspectratioinfo *aspect_ratio_info,
11110         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
11111 {
11112     m_extradata = frame_info;
11113     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
11114     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
11115     DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
11116             (unsigned int)m_extradata->aspectRatio.aspectRatioY);
11117 }
11118 
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)11119 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11120         OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
11121         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
11122         struct vdec_aspectratioinfo *aspect_ratio_info)
11123 {
11124     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
11125     struct msm_vidc_panscan_window *panscan_window;
11126     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
11127         return;
11128     }
11129     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
11130     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11131     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11132     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
11133     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
11134     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11135     switch (picture_type) {
11136         case PICTURE_TYPE_I:
11137             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
11138             break;
11139         case PICTURE_TYPE_P:
11140             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
11141             break;
11142         case PICTURE_TYPE_B:
11143             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
11144             break;
11145         default:
11146             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
11147     }
11148     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
11149         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
11150     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
11151         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
11152     else
11153         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
11154     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
11155     frame_info->nConcealedMacroblocks = num_conceal_mb;
11156     frame_info->nFrameRate = frame_rate;
11157     frame_info->nTimeStamp = time_stamp;
11158     frame_info->panScan.numWindows = 0;
11159     if (output_capability == V4L2_PIX_FMT_MPEG2) {
11160         if (m_disp_hor_size && m_disp_vert_size) {
11161             frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
11162             frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
11163         } else {
11164             frame_info->displayAspectRatio.displayHorizontalSize = 0;
11165             frame_info->displayAspectRatio.displayVerticalSize = 0;
11166         }
11167     }
11168 
11169     if (panscan_payload) {
11170         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
11171         panscan_window = &panscan_payload->wnd[0];
11172         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
11173             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
11174             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
11175             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
11176             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
11177             panscan_window++;
11178         }
11179     }
11180     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
11181     print_debug_extradata(extra);
11182 }
11183 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)11184 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11185 {
11186     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
11187     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
11188     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11189     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11190     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
11191     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
11192     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
11193     *portDefn = m_port_def;
11194     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
11195             "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
11196             (unsigned int)portDefn->format.video.nFrameWidth,
11197             (unsigned int)portDefn->format.video.nStride,
11198             (unsigned int)portDefn->format.video.nSliceHeight);
11199 }
11200 
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)11201 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11202         struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
11203 {
11204     OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
11205     if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
11206         DEBUG_PRINT_ERROR("frame packing size mismatch");
11207         return;
11208     }
11209     extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
11210     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11211     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11212     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
11213     extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11214     framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11215     framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11216     framepack->nVersion.nVersion = OMX_SPEC_VERSION;
11217     framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11218     memcpy(&framepack->id, s3d_frame_packing_payload,
11219         sizeof(struct msm_vidc_s3d_frame_packing_payload));
11220     memcpy(&m_frame_pack_arrangement, framepack,
11221         sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
11222     print_debug_extradata(extra);
11223 }
11224 
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)11225 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11226             struct msm_vidc_frame_qp_payload *qp_payload)
11227 {
11228     OMX_QCOM_EXTRADATA_QP * qp = NULL;
11229     if (!qp_payload) {
11230         DEBUG_PRINT_ERROR("QP payload is NULL");
11231         return;
11232     }
11233     extra->nSize = OMX_QP_EXTRADATA_SIZE;
11234     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11235     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11236     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
11237     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
11238     qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11239     qp->nQP = qp_payload->frame_qp;
11240     print_debug_extradata(extra);
11241 }
11242 
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)11243 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11244             struct msm_vidc_frame_bits_info_payload *bits_payload)
11245 {
11246     OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
11247     if (!bits_payload) {
11248         DEBUG_PRINT_ERROR("bits info payload is NULL");
11249         return;
11250     }
11251     extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
11252     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11253     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11254     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
11255     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
11256     bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
11257     bits->frame_bits = bits_payload->frame_bits;
11258     bits->header_bits = bits_payload->header_bits;
11259     print_debug_extradata(extra);
11260 }
11261 
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)11262 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11263             OMX_OTHER_EXTRADATATYPE *p_user)
11264 {
11265     int userdata_size = 0;
11266     struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
11267     userdata_payload =
11268         (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
11269     userdata_size = p_user->nDataSize;
11270     extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
11271     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11272     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11273     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
11274     extra->nDataSize = userdata_size;
11275     if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
11276         memcpy(extra->data, p_user->data, extra->nDataSize);
11277     print_debug_extradata(extra);
11278 }
11279 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)11280 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11281 {
11282     if (!client_extradata) {
11283         return;
11284     }
11285     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
11286     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11287     extra->eType = OMX_ExtraDataNone;
11288     extra->nDataSize = 0;
11289     extra->data[0] = 0;
11290 
11291     print_debug_extradata(extra);
11292 }
11293 
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)11294 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11295         struct msm_vidc_vqzip_sei_payload *vqzip_payload)
11296 {
11297     OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
11298 
11299     extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
11300     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11301     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11302     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
11303     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
11304 
11305     vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11306     vq->nSize = vqzip_payload->size;
11307     memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
11308 
11309     print_debug_extradata(extra);
11310 }
11311 
allocate_desc_buffer(OMX_U32 index)11312 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
11313 {
11314     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11315     if (index >= drv_ctx.ip_buf.actualcount) {
11316         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
11317         return OMX_ErrorInsufficientResources;
11318     }
11319     if (m_desc_buffer_ptr == NULL) {
11320         m_desc_buffer_ptr = (desc_buffer_hdr*) \
11321                     calloc( (sizeof(desc_buffer_hdr)),
11322                             drv_ctx.ip_buf.actualcount);
11323         if (m_desc_buffer_ptr == NULL) {
11324             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
11325             return OMX_ErrorInsufficientResources;
11326         }
11327     }
11328 
11329     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
11330     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
11331         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
11332         return OMX_ErrorInsufficientResources;
11333     }
11334 
11335     return eRet;
11336 }
11337 
insert_demux_addr_offset(OMX_U32 address_offset)11338 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
11339 {
11340     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
11341     if (m_demux_entries < 8192) {
11342         m_demux_offsets[m_demux_entries++] = address_offset;
11343     }
11344     return;
11345 }
11346 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)11347 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
11348 {
11349     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
11350     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
11351     OMX_U32 index = 0;
11352 
11353     m_demux_entries = 0;
11354 
11355     while (index < bytes_to_parse) {
11356         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11357                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
11358                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11359                  (buf[index+2] == 0x01)) ) {
11360             //Found start code, insert address offset
11361             insert_demux_addr_offset(index);
11362             if (buf[index+2] == 0x01) // 3 byte start code
11363                 index += 3;
11364             else                      //4 byte start code
11365                 index += 4;
11366         } else
11367             index++;
11368     }
11369     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
11370     return;
11371 }
11372 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)11373 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11374 {
11375     //fix this, handle 3 byte start code, vc1 terminator entry
11376     OMX_U8 *p_demux_data = NULL;
11377     OMX_U32 desc_data = 0;
11378     OMX_U32 start_addr = 0;
11379     OMX_U32 nal_size = 0;
11380     OMX_U32 suffix_byte = 0;
11381     OMX_U32 demux_index = 0;
11382     OMX_U32 buffer_index = 0;
11383 
11384     if (m_desc_buffer_ptr == NULL) {
11385         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
11386         return OMX_ErrorBadParameter;
11387     }
11388 
11389     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
11390     if (buffer_index > drv_ctx.ip_buf.actualcount) {
11391         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
11392         return OMX_ErrorBadParameter;
11393     }
11394 
11395     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
11396 
11397     if ( ((OMX_U8*)p_demux_data == NULL) ||
11398             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
11399         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
11400         return OMX_ErrorBadParameter;
11401     } else {
11402         for (; demux_index < m_demux_entries; demux_index++) {
11403             desc_data = 0;
11404             start_addr = m_demux_offsets[demux_index];
11405             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
11406                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
11407             } else {
11408                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
11409             }
11410             if (demux_index < (m_demux_entries - 1)) {
11411                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
11412             } else {
11413                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
11414             }
11415             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
11416                     (unsigned int)start_addr,
11417                     (unsigned int)suffix_byte,
11418                     (unsigned int)nal_size,
11419                     (unsigned int)demux_index);
11420             desc_data = (start_addr >> 3) << 1;
11421             desc_data |= (start_addr & 7) << 21;
11422             desc_data |= suffix_byte << 24;
11423 
11424             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11425             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
11426             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11427             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11428 
11429             p_demux_data += 16;
11430         }
11431         if (codec_type_parse == CODEC_TYPE_VC1) {
11432             DEBUG_PRINT_LOW("VC1 terminator entry");
11433             desc_data = 0;
11434             desc_data = 0x82 << 24;
11435             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11436             memset(p_demux_data + 4, 0, sizeof(OMX_U32));
11437             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11438             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11439             p_demux_data += 16;
11440             m_demux_entries++;
11441         }
11442         //Add zero word to indicate end of descriptors
11443         memset(p_demux_data, 0, sizeof(OMX_U32));
11444 
11445         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
11446         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
11447     }
11448     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
11449     m_demux_entries = 0;
11450     DEBUG_PRINT_LOW("Demux table complete!");
11451     return OMX_ErrorNone;
11452 }
11453 
request_perf_level(enum vidc_perf_level perf_level)11454 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
11455 {
11456     struct v4l2_control control;
11457     char property_value[PROPERTY_VALUE_MAX] = {0};
11458 
11459     property_get("vidc.debug.turbo", property_value, "0");
11460     memset(&control, 0, sizeof(v4l2_control));
11461     control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
11462     switch (perf_level) {
11463     case VIDC_NOMINAL:
11464         if (atoi(property_value))
11465             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11466         else
11467             control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
11468         break;
11469     case VIDC_TURBO:
11470         control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11471         break;
11472      default:
11473         DEBUG_PRINT_ERROR("Requested PERF level not supported");
11474         break;
11475     }
11476     if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
11477         return;
11478 
11479     DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
11480     if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11481         current_perf_level = control.value;
11482     } else {
11483         DEBUG_PRINT_ERROR("Failed to set PERF level");
11484     }
11485 }
11486 
allocate_color_convert_buf()11487 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
11488 {
11489     enabled = false;
11490     omx = NULL;
11491     init_members();
11492     ColorFormat = OMX_COLOR_FormatMax;
11493     dest_format = YCbCr420P;
11494 }
11495 
set_vdec_client(void * client)11496 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
11497 {
11498     omx = reinterpret_cast<omx_vdec*>(client);
11499 }
11500 
init_members()11501 void omx_vdec::allocate_color_convert_buf::init_members()
11502 {
11503     allocated_count = 0;
11504     buffer_size_req = 0;
11505     buffer_alignment_req = 0;
11506     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
11507     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
11508     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
11509     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
11510 #ifdef USE_ION
11511     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
11512 #endif
11513     for (int i = 0; i < MAX_COUNT; i++)
11514         pmem_fd[i] = -1;
11515 }
11516 
~allocate_color_convert_buf()11517 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
11518 {
11519     c2d.destroy();
11520 }
11521 
update_buffer_req()11522 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
11523 {
11524     bool status = true;
11525     unsigned int src_size = 0, destination_size = 0;
11526     OMX_COLOR_FORMATTYPE drv_color_format;
11527     if (!omx) {
11528         DEBUG_PRINT_ERROR("Invalid client in color convert");
11529         return false;
11530     }
11531     if (!enabled) {
11532         DEBUG_PRINT_HIGH("No color conversion required");
11533         return status;
11534     }
11535     pthread_mutex_lock(&omx->c_lock);
11536     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
11537             ColorFormat != OMX_COLOR_FormatYUV420Planar) {
11538         DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
11539         status = false;
11540         goto fail_update_buf_req;
11541     }
11542     c2d.close();
11543     status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
11544             omx->drv_ctx.video_resolution.frame_width,
11545             NV12_128m,dest_format);
11546     if (status) {
11547         status = c2d.get_buffer_size(C2D_INPUT,src_size);
11548         if (status)
11549             status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
11550     }
11551     if (status) {
11552         if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
11553                 !destination_size) {
11554             DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
11555                     "driver size %u destination size %d",
11556                     src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
11557                     destination_size);
11558             status = false;
11559             c2d.close();
11560             buffer_size_req = 0;
11561         } else {
11562             buffer_size_req = destination_size;
11563             if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
11564                 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
11565             if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11566                 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11567         }
11568     }
11569 fail_update_buf_req:
11570     pthread_mutex_unlock(&omx->c_lock);
11571     return status;
11572 }
11573 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)11574 bool omx_vdec::allocate_color_convert_buf::set_color_format(
11575         OMX_COLOR_FORMATTYPE dest_color_format)
11576 {
11577     bool status = true;
11578     OMX_COLOR_FORMATTYPE drv_color_format;
11579     if (!omx) {
11580         DEBUG_PRINT_ERROR("Invalid client in color convert");
11581         return false;
11582     }
11583     pthread_mutex_lock(&omx->c_lock);
11584     if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
11585         if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11586             drv_color_format = (OMX_COLOR_FORMATTYPE)
11587                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11588         else
11589             drv_color_format = (OMX_COLOR_FORMATTYPE)
11590                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11591      else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
11592          drv_color_format = (OMX_COLOR_FORMATTYPE)
11593                   QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11594      } else {
11595         DEBUG_PRINT_ERROR("Incorrect color format");
11596         status = false;
11597     }
11598     if (status &&
11599         drv_color_format != dest_color_format &&
11600         drv_color_format != (OMX_COLOR_FORMATTYPE)
11601                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView &&
11602         drv_color_format != (OMX_COLOR_FORMATTYPE)
11603                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed &&
11604         dest_color_format != (OMX_COLOR_FORMATTYPE)
11605                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11606         DEBUG_PRINT_LOW("Enabling C2D");
11607         if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
11608            (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
11609             DEBUG_PRINT_ERROR("Unsupported color format for c2d");
11610             status = false;
11611         } else {
11612             ColorFormat = dest_color_format;
11613             dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
11614                     YCbCr420P : YCbCr420SP;
11615             if (enabled)
11616                 c2d.destroy();
11617             enabled = false;
11618             if (!c2d.init()) {
11619                 DEBUG_PRINT_ERROR("open failed for c2d");
11620                 status = false;
11621             } else
11622                 enabled = true;
11623         }
11624     } else {
11625         if (enabled)
11626             c2d.destroy();
11627         enabled = false;
11628     }
11629     pthread_mutex_unlock(&omx->c_lock);
11630     return status;
11631 }
11632 
get_il_buf_hdr()11633 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
11634 {
11635     if (!omx) {
11636         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11637         return NULL;
11638     }
11639     if (!enabled)
11640         return omx->m_out_mem_ptr;
11641     return m_out_mem_ptr_client;
11642 }
11643 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11644     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
11645 (OMX_BUFFERHEADERTYPE *bufadd)
11646 {
11647     if (!omx) {
11648         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11649         return NULL;
11650     }
11651     if (!enabled)
11652         return bufadd;
11653 
11654     unsigned index = 0;
11655     index = bufadd - omx->m_out_mem_ptr;
11656     if (index < omx->drv_ctx.op_buf.actualcount) {
11657         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
11658         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
11659         bool status;
11660         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
11661             pthread_mutex_lock(&omx->c_lock);
11662             cache_clean_buffer(index);
11663             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
11664                     omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
11665                     pmem_baseaddress[index], pmem_baseaddress[index]);
11666             if (!status) {
11667                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
11668                 m_out_mem_ptr_client[index].nFilledLen = 0;
11669                 pthread_mutex_unlock(&omx->c_lock);
11670                 return &m_out_mem_ptr_client[index];
11671             } else {
11672                 unsigned int filledLen = 0;
11673                 c2d.get_output_filled_length(filledLen);
11674                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
11675                 cache_clean_invalidate_buffer(index);
11676             }
11677             pthread_mutex_unlock(&omx->c_lock);
11678         } else
11679             m_out_mem_ptr_client[index].nFilledLen = 0;
11680         return &m_out_mem_ptr_client[index];
11681     }
11682     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
11683     return NULL;
11684 }
11685 
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11686     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
11687 (OMX_BUFFERHEADERTYPE *bufadd)
11688 {
11689     if (!omx) {
11690         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11691         return NULL;
11692     }
11693     if (!enabled)
11694         return bufadd;
11695     unsigned index = 0;
11696     index = bufadd - m_out_mem_ptr_client;
11697     if (index < omx->drv_ctx.op_buf.actualcount) {
11698         return &omx->m_out_mem_ptr[index];
11699     }
11700     DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
11701     return NULL;
11702 }
get_buffer_req(unsigned int & buffer_size)11703     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
11704 (unsigned int &buffer_size)
11705 {
11706     bool status = true;
11707     pthread_mutex_lock(&omx->c_lock);
11708     if (!enabled)
11709         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11710     else {
11711         if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
11712             DEBUG_PRINT_ERROR("Get buffer size failed");
11713             status = false;
11714             goto fail_get_buffer_size;
11715         }
11716     }
11717     if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
11718         buffer_size = omx->drv_ctx.op_buf.buffer_size;
11719     if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11720         buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11721 fail_get_buffer_size:
11722     pthread_mutex_unlock(&omx->c_lock);
11723     return status;
11724 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)11725 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
11726         OMX_BUFFERHEADERTYPE *bufhdr)
11727 {
11728     unsigned int index = 0;
11729 
11730     if (!enabled)
11731         return omx->free_output_buffer(bufhdr);
11732     if (enabled && omx->is_component_secure())
11733         return OMX_ErrorNone;
11734     if (!allocated_count || !bufhdr) {
11735         DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
11736         return OMX_ErrorBadParameter;
11737     }
11738     index = bufhdr - m_out_mem_ptr_client;
11739     if (index >= omx->drv_ctx.op_buf.actualcount) {
11740         DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
11741         return OMX_ErrorBadParameter;
11742     }
11743     if (pmem_fd[index] >= 0) {
11744         munmap(pmem_baseaddress[index], buffer_size_req);
11745         close(pmem_fd[index]);
11746     }
11747     pmem_fd[index] = -1;
11748 #ifdef USE_ION
11749     omx->free_ion_memory(&op_buf_ion_info[index]);
11750 #endif
11751     m_heap_ptr[index].video_heap_ptr = NULL;
11752     if (allocated_count > 0)
11753         allocated_count--;
11754     else
11755         allocated_count = 0;
11756     if (!allocated_count) {
11757         pthread_mutex_lock(&omx->c_lock);
11758         c2d.close();
11759         init_members();
11760         pthread_mutex_unlock(&omx->c_lock);
11761     }
11762     return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
11763 }
11764 
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)11765 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
11766         OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
11767 {
11768     OMX_ERRORTYPE eRet = OMX_ErrorNone;
11769     if (!enabled) {
11770         eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
11771         return eRet;
11772     }
11773     if (enabled && omx->is_component_secure()) {
11774         DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
11775                 omx->is_component_secure());
11776         return OMX_ErrorUnsupportedSetting;
11777     }
11778     if (!bufferHdr || bytes > buffer_size_req) {
11779         DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
11780         DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
11781                 (unsigned int)buffer_size_req, (unsigned int)bytes);
11782         return OMX_ErrorBadParameter;
11783     }
11784     if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
11785         DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
11786         return OMX_ErrorInsufficientResources;
11787     }
11788     OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
11789     eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
11790             port,appData,omx->drv_ctx.op_buf.buffer_size);
11791     if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
11792         DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
11793         return eRet;
11794     }
11795     if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
11796             (int)omx->drv_ctx.op_buf.actualcount) {
11797         DEBUG_PRINT_ERROR("Invalid header index %ld",
11798                (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
11799         return OMX_ErrorUndefined;
11800     }
11801     unsigned int i = allocated_count;
11802 #ifdef USE_ION
11803     // Allocate color-conversion buffers as cached to improve software-reading
11804     // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
11805     // cache invalidation.
11806     op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
11807             buffer_size_req,buffer_alignment_req,
11808             &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
11809             ION_FLAG_CACHED);
11810     pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
11811     if (op_buf_ion_info[i].ion_device_fd < 0) {
11812         DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
11813         return OMX_ErrorInsufficientResources;
11814     }
11815     pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
11816             PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
11817 
11818     if (pmem_baseaddress[i] == MAP_FAILED) {
11819         DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
11820         close(pmem_fd[i]);
11821         omx->free_ion_memory(&op_buf_ion_info[i]);
11822         return OMX_ErrorInsufficientResources;
11823     }
11824     m_heap_ptr[i].video_heap_ptr = new VideoHeap (
11825             op_buf_ion_info[i].ion_device_fd,buffer_size_req,
11826             pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
11827 #endif
11828     m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
11829     m_pmem_info_client[i].offset = 0;
11830     m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
11831     m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
11832     m_platform_list_client[i].nEntries = 1;
11833     m_platform_list_client[i].entryList = &m_platform_entry_client[i];
11834     m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
11835     m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
11836     m_out_mem_ptr_client[i].nFilledLen = 0;
11837     m_out_mem_ptr_client[i].nFlags = 0;
11838     m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11839     m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
11840     m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
11841     m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
11842     m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
11843     m_out_mem_ptr_client[i].pAppPrivate = appData;
11844     *bufferHdr = &m_out_mem_ptr_client[i];
11845     DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
11846     allocated_count++;
11847     return eRet;
11848 }
11849 
is_component_secure()11850 bool omx_vdec::is_component_secure()
11851 {
11852     return secure_mode;
11853 }
11854 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)11855 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
11856 {
11857     bool status = true;
11858     if (!enabled) {
11859         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
11860             if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11861                     dest_color_format = (OMX_COLOR_FORMATTYPE)
11862                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11863                 else
11864                     dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11865         } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
11866              dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11867         } else
11868             status = false;
11869     } else {
11870         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
11871             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
11872             dest_color_format = ColorFormat;
11873         } else
11874             status = false;
11875     }
11876     return status;
11877 }
11878 
cache_ops(unsigned int index,unsigned int cmd)11879 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
11880         unsigned int index, unsigned int cmd)
11881 {
11882     if (!enabled) {
11883         return OMX_ErrorNone;
11884     }
11885 
11886     if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
11887         DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
11888         return OMX_ErrorBadParameter;
11889     }
11890 
11891     struct ion_flush_data flush_data;
11892     struct ion_custom_data custom_data;
11893 
11894     memset(&flush_data, 0x0, sizeof(flush_data));
11895     memset(&custom_data, 0x0, sizeof(custom_data));
11896 
11897     flush_data.vaddr = pmem_baseaddress[index];
11898     flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
11899     flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
11900     flush_data.length = buffer_size_req;
11901     custom_data.cmd = cmd;
11902     custom_data.arg = (unsigned long)&flush_data;
11903 
11904     DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
11905             (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11906             flush_data.fd, flush_data.handle, flush_data.vaddr,
11907             flush_data.length);
11908     int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
11909     if (ret < 0) {
11910         DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
11911                 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11912                 strerror(errno));
11913         return OMX_ErrorUndefined;
11914     }
11915     return OMX_ErrorNone;
11916 }
11917 
buf_ref_add(int nPortIndex)11918 void omx_vdec::buf_ref_add(int nPortIndex)
11919 {
11920     unsigned long i = 0;
11921     bool buf_present = false;
11922     long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
11923     OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
11924 
11925     if (!dynamic_buf_mode || !out_dynamic_list) {
11926         return;
11927     }
11928 
11929     pthread_mutex_lock(&m_lock);
11930     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11931         //check the buffer fd, offset, uv addr with list contents
11932         //If present increment reference.
11933         if ((out_dynamic_list[i].fd == fd) &&
11934             (out_dynamic_list[i].offset == offset)) {
11935                DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
11936                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11937                if (!secure_mode) {
11938                    drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
11939                }
11940                buf_present = true;
11941                break;
11942         }
11943     }
11944     if (!buf_present) {
11945         for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11946             //search for a entry to insert details of the new buffer
11947             if (out_dynamic_list[i].dup_fd < 0) {
11948                 out_dynamic_list[i].fd = fd;
11949                 out_dynamic_list[i].offset = offset;
11950                 out_dynamic_list[i].dup_fd = dup(fd);
11951                 out_dynamic_list[i].ref_count++;
11952                 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
11953                      (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11954 
11955                 if (!secure_mode) {
11956                     drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
11957                             (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
11958                                           PROT_READ|PROT_WRITE, MAP_SHARED,
11959                                           drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
11960                     //mmap returns (void *)-1 on failure and sets error code in errno.
11961                     if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
11962                         DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
11963                         drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
11964                         break;
11965                     }
11966                     out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
11967                     out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
11968                     DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11969                 }
11970                 break;
11971             }
11972         }
11973     }
11974    pthread_mutex_unlock(&m_lock);
11975 }
11976 
buf_ref_remove()11977 void omx_vdec::buf_ref_remove()
11978 {
11979     unsigned long i = 0;
11980 
11981     if (!dynamic_buf_mode || !out_dynamic_list) {
11982         return;
11983     }
11984 
11985     pthread_mutex_lock(&m_lock);
11986     for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11987         if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
11988             DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11989             munmap(out_dynamic_list[i].buffaddr,
11990                         out_dynamic_list[i].mapped_size);
11991         }
11992 
11993          DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
11994                  (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11995          close(out_dynamic_list[i].dup_fd);
11996          out_dynamic_list[i].dup_fd = -1;
11997     }
11998     pthread_mutex_unlock(&m_lock);
11999 
12000     if (out_dynamic_list) {
12001         free(out_dynamic_list);
12002         out_dynamic_list = NULL;
12003     }
12004 }
12005 
12006 #ifdef _MSM8974_
send_codec_config()12007 void omx_vdec::send_codec_config() {
12008     if (codec_config_flag) {
12009         unsigned long p1 = 0; // Parameter - 1
12010         unsigned long p2 = 0; // Parameter - 2
12011         unsigned long ident = 0;
12012         pthread_mutex_lock(&m_lock);
12013         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
12014         while (m_etb_q.m_size) {
12015             m_etb_q.pop_entry(&p1,&p2,&ident);
12016             if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
12017                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12018                     if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
12019                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12020                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
12021                         omx_report_error();
12022                     }
12023                 } else {
12024                     DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
12025                     m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
12026                 }
12027             } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
12028                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12029                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
12030                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12031                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
12032                         omx_report_error ();
12033                     }
12034                 } else {
12035                     pending_input_buffers++;
12036                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
12037                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
12038                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
12039                 }
12040             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
12041                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
12042                         (OMX_BUFFERHEADERTYPE *)p1);
12043                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
12044             }
12045         }
12046         pthread_mutex_unlock(&m_lock);
12047     }
12048 }
12049 #endif
12050 
perf_control()12051 omx_vdec::perf_control::perf_control()
12052 {
12053     m_perf_lib = NULL;
12054     m_perf_handle = 0;
12055     m_perf_lock_acquire = NULL;
12056     m_perf_lock_release = NULL;
12057 }
12058 
~perf_control()12059 omx_vdec::perf_control::~perf_control()
12060 {
12061     if (m_perf_handle != 0 && m_perf_lock_release) {
12062         DEBUG_PRINT_LOW("NOTE2: release perf lock");
12063         m_perf_lock_release(m_perf_handle);
12064     }
12065     if (m_perf_lib) {
12066         dlclose(m_perf_lib);
12067     }
12068 }
12069 
12070 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
12071 
12072 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
12073 
send_hint_to_mpctl(bool state)12074 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
12075 {
12076     if (load_lib() == false) {
12077        return;
12078     }
12079     m_perf_lock.lock();
12080     /* 0x4401 maps to video decode playback hint
12081      * in perflock, enum number is 44 and state
12082      * being sent on perflock acquire is 01 (true)
12083      */
12084     int arg = 0x4401;
12085 
12086     if (state == true) {
12087         mpctl_obj.vid_inst_count++;
12088     } else if (state == false) {
12089         mpctl_obj.vid_inst_count--;
12090     }
12091 
12092     if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
12093         mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
12094         mpctl_obj.vid_acquired = true;
12095         DEBUG_PRINT_INFO("Video slvp perflock acquired");
12096     } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
12097         m_perf_lock_release(mpctl_obj.vid_disp_handle);
12098         mpctl_obj.vid_acquired = false;
12099         DEBUG_PRINT_INFO("Video slvp perflock released");
12100     }
12101     m_perf_lock.unlock();
12102 }
12103 
request_cores(int frame_duration_us)12104 void omx_vdec::perf_control::request_cores(int frame_duration_us)
12105 {
12106     if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
12107         return;
12108     }
12109     bool retVal = load_lib();
12110     if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
12111         int arg = 0x700 /*base value*/ + 2 /*cores*/;
12112         m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
12113         if (m_perf_handle) {
12114             DEBUG_PRINT_HIGH("perf lock acquired");
12115         }
12116     }
12117 }
12118 
load_lib()12119 bool omx_vdec::perf_control::load_lib()
12120 {
12121     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
12122     if (m_perf_lib)
12123         return true;
12124 
12125     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
12126         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
12127         goto handle_err;
12128     }
12129 
12130     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
12131         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
12132         goto handle_err;
12133     } else {
12134         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
12135         if (m_perf_lock_acquire == NULL) {
12136             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
12137             goto handle_err;
12138         }
12139         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
12140         if (m_perf_lock_release == NULL) {
12141             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
12142             goto handle_err;
12143         }
12144     }
12145     return true;
12146 
12147 handle_err:
12148     if (m_perf_lib) {
12149         dlclose(m_perf_lib);
12150     }
12151     m_perf_lib = NULL;
12152     return false;
12153 }
12154 
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)12155 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
12156                             unsigned long nMaxFrameHeight)
12157 {
12158 
12159     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12160     int ret = 0;
12161     unsigned long min_res_buf_count = 0;
12162 
12163     eRet = enable_smoothstreaming();
12164     if (eRet != OMX_ErrorNone) {
12165          DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
12166          return eRet;
12167      }
12168 
12169      DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
12170              nMaxFrameWidth,
12171              nMaxFrameHeight);
12172      m_smoothstreaming_mode = true;
12173      m_smoothstreaming_width = nMaxFrameWidth;
12174      m_smoothstreaming_height = nMaxFrameHeight;
12175 
12176      //Get upper limit buffer count for min supported resolution
12177      struct v4l2_format fmt;
12178      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12179      fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
12180      fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
12181      fmt.fmt.pix_mp.pixelformat = output_capability;
12182 
12183      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12184      if (ret) {
12185          DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
12186                            m_decoder_capability.min_height,
12187                            m_decoder_capability.min_width);
12188          return OMX_ErrorUnsupportedSetting;
12189      }
12190 
12191      eRet = get_buffer_req(&drv_ctx.op_buf);
12192      if (eRet != OMX_ErrorNone) {
12193          DEBUG_PRINT_ERROR("failed to get_buffer_req");
12194          return eRet;
12195      }
12196 
12197      min_res_buf_count = drv_ctx.op_buf.mincount;
12198      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
12199                      min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
12200 
12201      update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
12202                        m_smoothstreaming_width, m_smoothstreaming_height);
12203      eRet = is_video_session_supported();
12204      if (eRet != OMX_ErrorNone) {
12205          DEBUG_PRINT_ERROR("video session is not supported");
12206          return eRet;
12207      }
12208 
12209      //Get upper limit buffer size for max smooth streaming resolution set
12210      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12211      fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
12212      fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
12213      fmt.fmt.pix_mp.pixelformat = output_capability;
12214      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12215      if (ret) {
12216          DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
12217          return OMX_ErrorUnsupportedSetting;
12218      }
12219 
12220      eRet = get_buffer_req(&drv_ctx.op_buf);
12221      if (eRet != OMX_ErrorNone) {
12222          DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
12223          return eRet;
12224      }
12225      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
12226                      (unsigned int)drv_ctx.op_buf.buffer_size);
12227 
12228      drv_ctx.op_buf.mincount = min_res_buf_count;
12229      drv_ctx.op_buf.actualcount = min_res_buf_count;
12230      drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
12231      eRet = set_buffer_req(&drv_ctx.op_buf);
12232      if (eRet != OMX_ErrorNone) {
12233          DEBUG_PRINT_ERROR("failed to set_buffer_req");
12234          return eRet;
12235      }
12236 
12237      eRet = get_buffer_req(&drv_ctx.op_buf);
12238      if (eRet != OMX_ErrorNone) {
12239          DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
12240          return eRet;
12241      }
12242      DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
12243                       drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
12244      return eRet;
12245 }
12246 
12247 //static
describeColorFormat(OMX_PTR pParam)12248 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
12249 
12250 #ifndef FLEXYUV_SUPPORTED
12251     return OMX_ErrorUndefined;
12252 #else
12253 
12254     if (pParam == NULL) {
12255         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
12256         return OMX_ErrorBadParameter;
12257     }
12258 
12259     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
12260 
12261     MediaImage *img = &(params->sMediaImage);
12262     switch(params->eColorFormat) {
12263         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
12264         {
12265             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
12266             img->mNumPlanes = 3;
12267             // mWidth and mHeight represent the W x H of the largest plane
12268             // In our case, this happens to be the Stride x Scanlines of Y plane
12269             img->mWidth = params->nFrameWidth;
12270             img->mHeight = params->nFrameHeight;
12271             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12272             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
12273             img->mBitDepth = 8;
12274             //Plane 0 (Y)
12275             img->mPlane[MediaImage::Y].mOffset = 0;
12276             img->mPlane[MediaImage::Y].mColInc = 1;
12277             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
12278             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
12279             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
12280             //Plane 1 (U)
12281             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
12282             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
12283             img->mPlane[MediaImage::U].mRowInc =
12284                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12285             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
12286             img->mPlane[MediaImage::U].mVertSubsampling = 2;
12287             //Plane 2 (V)
12288             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
12289             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
12290             img->mPlane[MediaImage::V].mRowInc =
12291                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12292             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
12293             img->mPlane[MediaImage::V].mVertSubsampling = 2;
12294             break;
12295         }
12296 
12297         case OMX_COLOR_FormatYUV420Planar:
12298         case OMX_COLOR_FormatYUV420SemiPlanar:
12299             // We need not describe the standard OMX linear formats as these are
12300             // understood by client. Fail this deliberately to let client fill-in
12301             return OMX_ErrorUnsupportedSetting;
12302 
12303         default:
12304             // Rest all formats which are non-linear cannot be described
12305             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
12306             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
12307             return OMX_ErrorNone;
12308     };
12309 
12310     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
12311     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
12312     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
12313     for (size_t i = 0; i < img->mNumPlanes; ++i) {
12314         DEBUG_PRINT_LOW("    Plane[%zd] : offset=%d / xStep=%d / yStep = %d",
12315                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
12316     }
12317     return OMX_ErrorNone;
12318 #endif //FLEXYUV_SUPPORTED
12319 }
12320 
prefetchNewBuffers()12321 void omx_vdec::prefetchNewBuffers() {
12322 
12323     struct v4l2_decoder_cmd dec;
12324     uint32_t prefetch_count;
12325     uint32_t prefetch_size;
12326     uint32_t want_size;
12327     uint32_t have_size;
12328     int color_fmt, rc;
12329     uint32_t new_calculated_size;
12330     uint32_t new_buffer_size;
12331     uint32_t new_buffer_count;
12332     uint32_t old_buffer_size;
12333     uint32_t old_buffer_count;
12334 
12335     memset((void *)&dec, 0 , sizeof(dec));
12336     DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n",
12337             (int)drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
12338             drv_ctx.video_resolution.frame_width,
12339             drv_ctx.video_resolution.frame_height);
12340     dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
12341     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
12342         DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
12343     } else {
12344         DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
12345                 dec.raw.data[0], dec.raw.data[1]);
12346     }
12347 
12348     switch ((int)drv_ctx.output_format) {
12349     case VDEC_YUV_FORMAT_NV12:
12350         color_fmt = COLOR_FMT_NV12;
12351         break;
12352     case VDEC_YUV_FORMAT_NV12_UBWC:
12353         color_fmt = COLOR_FMT_NV12_UBWC;
12354         break;
12355     default:
12356         color_fmt = -1;
12357     }
12358 
12359     new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
12360     DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
12361             m_reconfig_width, m_reconfig_height, new_calculated_size);
12362     new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
12363     new_buffer_count = dec.raw.data[1];
12364     old_buffer_size = drv_ctx.op_buf.buffer_size;
12365     old_buffer_count = drv_ctx.op_buf.actualcount;
12366 
12367     new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
12368 
12369     prefetch_count = new_buffer_count;
12370     prefetch_size = new_buffer_size - old_buffer_size;
12371     want_size = new_buffer_size * new_buffer_count;
12372     have_size = old_buffer_size * old_buffer_count;
12373 
12374     if (want_size > have_size) {
12375         DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
12376         DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
12377 
12378         int ion_fd = open(MEM_DEVICE, O_RDONLY);
12379         if (ion_fd < 0) {
12380             DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
12381             return;
12382         }
12383 
12384         struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
12385         struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
12386         struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
12387         size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
12388 
12389         if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
12390             DEBUG_PRINT_ERROR("prefetch data allocation failed");
12391             goto prefetch_exit;
12392         }
12393 
12394         for (uint32_t i = 0; i < prefetch_count; i++) {
12395             sizes[i] = prefetch_size;
12396         }
12397 
12398         regions[0].nr_sizes = prefetch_count;
12399         regions[0].sizes = sizes;
12400         regions[0].vmid = ION_FLAG_CP_PIXEL;
12401 
12402         prefetch_data->nr_regions = 1;
12403         prefetch_data->regions = regions;
12404         prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
12405 
12406         custom_data->cmd = ION_IOC_PREFETCH;
12407         custom_data->arg = (unsigned long )prefetch_data;
12408 
12409         rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
12410         if (rc) {
12411             DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
12412         }
12413 
12414 prefetch_exit:
12415         close(ion_fd);
12416         free(sizes);
12417         free(regions);
12418         free(prefetch_data);
12419         free(custom_data);
12420     }
12421 }
12422 
12423 // No code beyond this !
12424 
12425 // inline import of vendor-extensions implementation
12426 #include "omx_vdec_extensions.hpp"
12427