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