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