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