• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*--------------------------------------------------------------------------
2 Copyright (c) 2013-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 #include <string.h>
43 #include <pthread.h>
44 #include <sys/prctl.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include "omx_vdec_hevc.h"
49 #include <fcntl.h>
50 #include <limits.h>
51 #include <media/msm_media_info.h>
52 #include <qdMetaData.h>
53 
54 #ifndef _ANDROID_
55 #include <sys/ioctl.h>
56 #include <sys/mman.h>
57 #endif //_ANDROID_
58 
59 #ifdef _ANDROID_
60 #include <cutils/properties.h>
61 #undef USE_EGL_IMAGE_GPU
62 #endif
63 
64 #if  defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
65 #include <gralloc_priv.h>
66 #endif
67 
68 #ifdef _ANDROID_
69 #include "DivXDrmDecrypt.h"
70 #endif //_ANDROID_
71 
72 #ifdef USE_EGL_IMAGE_GPU
73 #include <EGL/egl.h>
74 #include <EGL/eglQCOM.h>
75 #define EGL_BUFFER_HANDLE_QCOM 0x4F00
76 #define EGL_BUFFER_OFFSET_QCOM 0x4F01
77 #endif
78 
79 #ifdef INPUT_BUFFER_LOG
80 #define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0"
81 #define INPUT_BUFFER_FILE_NAME_LEN 30
82 FILE *inputBufferFile1;
83 char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0";
84 #endif
85 #ifdef OUTPUT_BUFFER_LOG
86 FILE *outputBufferFile1;
87 char outputfilename [] = "/data/output.yuv";
88 #endif
89 #ifdef OUTPUT_EXTRADATA_LOG
90 FILE *outputExtradataFile;
91 char ouputextradatafilename [] = "/data/extradata";
92 #endif
93 
94 #ifdef VENUS_HEVC
95 #define DEVICE_NAME "/dev/video/venus_dec"
96 #else
97 #define DEVICE_NAME "/dev/video/q6_dec"
98 #endif
99 
100 #define DEFAULT_FPS 30
101 #define MAX_INPUT_ERROR DEFAULT_FPS
102 #define MAX_SUPPORTED_FPS 120
103 
104 #define VC1_SP_MP_START_CODE        0xC5000000
105 #define VC1_SP_MP_START_CODE_MASK   0xFF000000
106 #define VC1_AP_SEQ_START_CODE       0x0F010000
107 #define VC1_STRUCT_C_PROFILE_MASK   0xF0
108 #define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
109 #define VC1_SIMPLE_PROFILE          0
110 #define VC1_MAIN_PROFILE            1
111 #define VC1_ADVANCE_PROFILE         3
112 #define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
113 #define VC1_SIMPLE_PROFILE_MED_LEVEL  2
114 #define VC1_STRUCT_C_LEN            4
115 #define VC1_STRUCT_C_POS            8
116 #define VC1_STRUCT_A_POS            12
117 #define VC1_STRUCT_B_POS            24
118 #define VC1_SEQ_LAYER_SIZE          36
119 #define POLL_TIMEOUT 0x7fffffff
120 
121 #define MEM_DEVICE "/dev/ion"
122 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
123 
124 #ifdef _ANDROID_
125 extern "C" {
126 #include<utils/Log.h>
127 }
128 #endif//_ANDROID_
129 
130 #define SZ_4K 0x1000
131 #define SZ_1M 0x100000
132 
133 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
134 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
135 #define EXTRADATA_IDX(__num_planes) (__num_planes  - 1)
136 
137 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA)
138 
139 int debug_level = PRIO_ERROR;
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             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
167             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
168             v4l2_buf.length = omx->drv_ctx.num_planes;
169             v4l2_buf.m.planes = plane;
170             while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
171                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
172                 vdec_msg.status_code=VDEC_S_SUCCESS;
173                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
174                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
175                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
176                 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
177                     (uint64_t)v4l2_buf.timestamp.tv_usec;
178                 if (vdec_msg.msgdata.output_frame.len) {
179                     vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
180                     vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
181                     vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
182                     vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
183                 }
184                 if (omx->async_message_process(input,&vdec_msg) < 0) {
185                     DEBUG_PRINT_HIGH("async_message_thread Exited");
186                     break;
187                 }
188             }
189         }
190         if ((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) {
191             struct vdec_msginfo vdec_msg;
192             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
193             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
194             v4l2_buf.length = 1;
195             v4l2_buf.m.planes = plane;
196             while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
197                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
198                 vdec_msg.status_code=VDEC_S_SUCCESS;
199                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
200                 if (omx->async_message_process(input,&vdec_msg) < 0) {
201                     DEBUG_PRINT_HIGH("async_message_thread Exited");
202                     break;
203                 }
204             }
205         }
206         if (pfd.revents & POLLPRI) {
207             rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent);
208             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
209                 struct vdec_msginfo vdec_msg;
210                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
211                 vdec_msg.status_code=VDEC_S_SUCCESS;
212                 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved");
213                 if (omx->async_message_process(input,&vdec_msg) < 0) {
214                     DEBUG_PRINT_HIGH("async_message_thread Exited");
215                     break;
216                 }
217             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT ) {
218                 struct vdec_msginfo vdec_msg;
219                 vdec_msg.msgcode=VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
220                 vdec_msg.status_code=VDEC_S_SUCCESS;
221                 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved");
222                 if (omx->async_message_process(input,&vdec_msg) < 0) {
223                     DEBUG_PRINT_HIGH("async_message_thread Exited");
224                     break;
225                 }
226             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
227                 struct vdec_msginfo vdec_msg;
228                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
229                 vdec_msg.status_code=VDEC_S_SUCCESS;
230                 DEBUG_PRINT_HIGH("VIDC Flush Done Recieved");
231                 if (omx->async_message_process(input,&vdec_msg) < 0) {
232                     DEBUG_PRINT_HIGH("async_message_thread Exited");
233                     break;
234                 }
235                 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
236                 vdec_msg.status_code=VDEC_S_SUCCESS;
237                 DEBUG_PRINT_HIGH("VIDC Flush Done Recieved");
238                 if (omx->async_message_process(input,&vdec_msg) < 0) {
239                     DEBUG_PRINT_HIGH("async_message_thread Exited");
240                     break;
241                 }
242             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
243                 DEBUG_PRINT_HIGH("VIDC Close Done Recieved and async_message_thread Exited");
244                 break;
245             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
246                 struct vdec_msginfo vdec_msg;
247                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
248                 vdec_msg.status_code=VDEC_S_SUCCESS;
249                 DEBUG_PRINT_HIGH("SYS Error Recieved");
250                 if (omx->async_message_process(input,&vdec_msg) < 0) {
251                     DEBUG_PRINT_HIGH("async_message_thread Exited");
252                     break;
253                 }
254             } else {
255                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
256                 continue;
257             }
258         }
259     }
260     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
261     return NULL;
262 }
263 
message_thread(void * input)264 void* message_thread(void *input)
265 {
266     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
267     unsigned char id;
268     int n;
269     if (omx == NULL) {
270         DEBUG_PRINT_ERROR("message thread null pointer rxd");
271         return NULL;
272     }
273 
274     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
275     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
276     while (1) {
277 
278         n = read(omx->m_pipe_in, &id, 1);
279 
280         if (0 == n) {
281             break;
282         }
283 
284         if (1 == n) {
285             omx->process_event_cb(omx, id);
286         }
287         if ((n < 0) && (errno != EINTR)) {
288             DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
289             break;
290         }
291     }
292     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
293     return NULL;
294 }
295 
post_message(omx_vdec * omx,unsigned char id)296 void post_message(omx_vdec *omx, unsigned char id)
297 {
298     int ret_value;
299 
300     if (omx == NULL) {
301         DEBUG_PRINT_ERROR("message thread null pointer rxd");
302         return;
303     }
304     DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
305     ret_value = write(omx->m_pipe_out, &id, 1);
306     DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
307 }
308 
309 // omx_cmd_queue destructor
~omx_cmd_queue()310 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
311 {
312     // Nothing to do
313 }
314 
315 // omx cmd queue constructor
omx_cmd_queue()316 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
317 {
318     memset(m_q,0,sizeof(m_q));
319 }
320 
321 // omx cmd queue insert
insert_entry(unsigned p1,unsigned p2,unsigned id)322 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
323 {
324     bool ret = true;
325     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
326         m_q[m_write].id       = id;
327         m_q[m_write].param1   = p1;
328         m_q[m_write].param2   = p2;
329         m_write++;
330         m_size ++;
331         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
332             m_write = 0;
333         }
334     } else {
335         ret = false;
336         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
337     }
338     return ret;
339 }
340 
341 // omx cmd queue pop
pop_entry(unsigned * p1,unsigned * p2,unsigned * id)342 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
343 {
344     bool ret = true;
345     if (m_size > 0) {
346         *id = m_q[m_read].id;
347         *p1 = m_q[m_read].param1;
348         *p2 = m_q[m_read].param2;
349         // Move the read pointer ahead
350         ++m_read;
351         --m_size;
352         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
353             m_read = 0;
354         }
355     } else {
356         ret = false;
357     }
358     return ret;
359 }
360 
361 // Retrieve the first mesg type in the queue
get_q_msg_type()362 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
363 {
364     return m_q[m_read].id;
365 }
366 
367 #ifdef _ANDROID_
ts_arr_list()368 omx_vdec::ts_arr_list::ts_arr_list()
369 {
370     //initialize timestamps array
371     memset(m_ts_arr_list, 0, sizeof(m_ts_arr_list) );
372 }
~ts_arr_list()373 omx_vdec::ts_arr_list::~ts_arr_list()
374 {
375     //free m_ts_arr_list?
376 }
377 
insert_ts(OMX_TICKS ts)378 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
379 {
380     bool ret = true;
381     bool duplicate_ts = false;
382     int idx = 0;
383 
384     //insert at the first available empty location
385     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
386         if (!m_ts_arr_list[idx].valid) {
387             //found invalid or empty entry, save timestamp
388             m_ts_arr_list[idx].valid = true;
389             m_ts_arr_list[idx].timestamp = ts;
390             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
391                     ts, idx);
392             break;
393         }
394     }
395 
396     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
397         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
398         ret = false;
399     }
400     return ret;
401 }
402 
pop_min_ts(OMX_TICKS & ts)403 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
404 {
405     bool ret = true;
406     int min_idx = -1;
407     OMX_TICKS min_ts = 0;
408     int idx = 0;
409 
410     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
411 
412         if (m_ts_arr_list[idx].valid) {
413             //found valid entry, save index
414             if (min_idx < 0) {
415                 //first valid entry
416                 min_ts = m_ts_arr_list[idx].timestamp;
417                 min_idx = idx;
418             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
419                 min_ts = m_ts_arr_list[idx].timestamp;
420                 min_idx = idx;
421             }
422         }
423 
424     }
425 
426     if (min_idx < 0) {
427         //no valid entries found
428         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
429         ts = 0;
430         ret = false;
431     } else {
432         ts = m_ts_arr_list[min_idx].timestamp;
433         m_ts_arr_list[min_idx].valid = false;
434         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
435                 ts, min_idx);
436     }
437 
438     return ret;
439 
440 }
441 
442 
reset_ts_list()443 bool omx_vdec::ts_arr_list::reset_ts_list()
444 {
445     bool ret = true;
446     int idx = 0;
447 
448     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
449     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
450         m_ts_arr_list[idx].valid = false;
451     }
452     return ret;
453 }
454 #endif
455 
456 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)457 void *get_omx_component_factory_fn(void)
458 {
459     return (new omx_vdec);
460 }
461 
462 #ifdef _ANDROID_
463 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,struct ion_handle * handle,int ionMapfd)464 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
465         struct ion_handle *handle, int ionMapfd)
466 {
467     //    ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
468 }
469 #else
VideoHeap(int fd,size_t size,void * base)470 VideoHeap::VideoHeap(int fd, size_t size, void* base)
471 {
472     // dup file descriptor, map once, use pmem
473     init(dup(fd), base, size, 0 , MEM_DEVICE);
474 }
475 #endif
476 #endif // _ANDROID_
477 /* ======================================================================
478    FUNCTION
479    omx_vdec::omx_vdec
480 
481    DESCRIPTION
482    Constructor
483 
484    PARAMETERS
485    None
486 
487    RETURN VALUE
488    None.
489    ========================================================================== */
omx_vdec()490 omx_vdec::omx_vdec(): m_error_propogated(false),
491     m_state(OMX_StateInvalid),
492     m_app_data(NULL),
493     m_inp_mem_ptr(NULL),
494     m_out_mem_ptr(NULL),
495     m_inp_err_count(0),
496     input_flush_progress (false),
497     output_flush_progress (false),
498     input_use_buffer (false),
499     output_use_buffer (false),
500     ouput_egl_buffers(false),
501     m_use_output_pmem(OMX_FALSE),
502     m_out_mem_region_smi(OMX_FALSE),
503     m_out_pvt_entry_pmem(OMX_FALSE),
504     pending_input_buffers(0),
505     pending_output_buffers(0),
506     m_out_bm_count(0),
507     m_inp_bm_count(0),
508     m_inp_bPopulated(OMX_FALSE),
509     m_out_bPopulated(OMX_FALSE),
510     m_flags(0),
511 #ifdef _ANDROID_
512     m_heap_ptr(NULL),
513 #endif
514     m_inp_bEnabled(OMX_TRUE),
515     m_out_bEnabled(OMX_TRUE),
516     m_in_alloc_cnt(0),
517     m_platform_list(NULL),
518     m_platform_entry(NULL),
519     m_pmem_info(NULL),
520     arbitrary_bytes (true),
521     psource_frame (NULL),
522     pdest_frame (NULL),
523     m_inp_heap_ptr (NULL),
524     m_phdr_pmem_ptr(NULL),
525     m_heap_inp_bm_count (0),
526     codec_type_parse ((codec_type)0),
527     first_frame_meta (true),
528     frame_count (0),
529     nal_count (0),
530     nal_length(0),
531     look_ahead_nal (false),
532     first_frame(0),
533     first_buffer(NULL),
534     first_frame_size (0),
535     m_device_file_ptr(NULL),
536     m_vc1_profile((vc1_profile_type)0),
537     h264_last_au_ts(LLONG_MAX),
538     h264_last_au_flags(0),
539     prev_ts(LLONG_MAX),
540     rst_prev_ts(true),
541     frm_int(0),
542     in_reconfig(false),
543     m_display_id(NULL),
544     h264_parser(NULL),
545     client_extradata(0),
546 #ifdef _ANDROID_
547     m_enable_android_native_buffers(OMX_FALSE),
548     m_use_android_native_buffers(OMX_FALSE),
549     iDivXDrmDecrypt(NULL),
550 #endif
551     m_desc_buffer_ptr(NULL),
552     secure_mode(false)
553 {
554     /* Assumption is that , to begin with , we have all the frames with decoder */
555     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
556 #ifdef _ANDROID_
557     char property_value[PROPERTY_VALUE_MAX] = {0};
558     property_get("vidc.debug.level", property_value, "1");
559     debug_level = atoi(property_value);
560     property_value[0] = '\0';
561 
562     property_get("vidc.dec.debug.perf", property_value, "0");
563     perf_flag = atoi(property_value);
564     if (perf_flag) {
565         DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
566         dec_time.start();
567         proc_frms = latency = 0;
568     }
569     property_value[0] = '\0';
570     property_get("vidc.dec.debug.ts", property_value, "0");
571     m_debug_timestamp = atoi(property_value);
572     DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
573     if (m_debug_timestamp) {
574         time_stamp_dts.set_timestamp_reorder_mode(true);
575         time_stamp_dts.enable_debug_print(true);
576     }
577 
578     property_value[0] = '\0';
579     property_get("vidc.dec.debug.concealedmb", property_value, "0");
580     m_debug_concealedmb = atoi(property_value);
581     DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
582 
583 #endif
584     memset(&m_cmp,0,sizeof(m_cmp));
585     memset(&m_cb,0,sizeof(m_cb));
586     memset (&drv_ctx,0,sizeof(drv_ctx));
587     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
588     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
589     memset(m_demux_offsets, 0, sizeof(m_demux_offsets) );
590     m_demux_entries = 0;
591 #ifdef _ANDROID_ICS_
592     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
593 #endif
594     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
595     drv_ctx.timestamp_adjust = false;
596     drv_ctx.video_driver_fd = -1;
597     m_vendor_config.pData = NULL;
598     pthread_mutex_init(&m_lock, NULL);
599     pthread_mutex_init(&c_lock, NULL);
600     sem_init(&m_cmd_lock,0,0);
601     streaming[CAPTURE_PORT] =
602         streaming[OUTPUT_PORT] = false;
603 #ifdef _ANDROID_
604     char extradata_value[PROPERTY_VALUE_MAX] = {0};
605     property_get("vidc.dec.debug.extradata", extradata_value, "0");
606     m_debug_extradata = atoi(extradata_value);
607     DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
608 #endif
609     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
610     client_buffers.set_vdec_client(this);
611 }
612 
613 static const int event_type[] = {
614     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
615     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
616     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
617     V4L2_EVENT_MSM_VIDC_CLOSE_DONE,
618     V4L2_EVENT_MSM_VIDC_SYS_ERROR
619 };
620 
subscribe_to_events(int fd)621 static OMX_ERRORTYPE subscribe_to_events(int fd)
622 {
623     OMX_ERRORTYPE eRet = OMX_ErrorNone;
624     struct v4l2_event_subscription sub;
625     int array_sz = sizeof(event_type)/sizeof(int);
626     int i,rc;
627     if (fd < 0) {
628         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
629         return OMX_ErrorBadParameter;
630     }
631 
632     for (i = 0; i < array_sz; ++i) {
633         memset(&sub, 0, sizeof(sub));
634         sub.type = event_type[i];
635         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
636         if (rc) {
637             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
638             break;
639         }
640     }
641     if (i < array_sz) {
642         for (--i; i >=0 ; i--) {
643             memset(&sub, 0, sizeof(sub));
644             sub.type = event_type[i];
645             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
646             if (rc)
647                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
648         }
649         eRet = OMX_ErrorNotImplemented;
650     }
651     return eRet;
652 }
653 
654 
unsubscribe_to_events(int fd)655 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
656 {
657     OMX_ERRORTYPE eRet = OMX_ErrorNone;
658     struct v4l2_event_subscription sub;
659     int array_sz = sizeof(event_type)/sizeof(int);
660     int i,rc;
661     if (fd < 0) {
662         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
663         return OMX_ErrorBadParameter;
664     }
665 
666     for (i = 0; i < array_sz; ++i) {
667         memset(&sub, 0, sizeof(sub));
668         sub.type = event_type[i];
669         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
670         if (rc) {
671             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
672             break;
673         }
674     }
675     return eRet;
676 }
677 
678 /* ======================================================================
679    FUNCTION
680    omx_vdec::~omx_vdec
681 
682    DESCRIPTION
683    Destructor
684 
685    PARAMETERS
686    None
687 
688    RETURN VALUE
689    None.
690    ========================================================================== */
~omx_vdec()691 omx_vdec::~omx_vdec()
692 {
693     m_pmem_info = NULL;
694     struct v4l2_decoder_cmd dec;
695     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
696     if (m_pipe_in) close(m_pipe_in);
697     if (m_pipe_out) close(m_pipe_out);
698     m_pipe_in = -1;
699     m_pipe_out = -1;
700     DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
701     pthread_join(msg_thread_id,NULL);
702     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
703     dec.cmd = V4L2_DEC_CMD_STOP;
704     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
705         DEBUG_PRINT_ERROR("STOP Command failed");
706     }
707     pthread_join(async_thread_id,NULL);
708     unsubscribe_to_events(drv_ctx.video_driver_fd);
709     close(drv_ctx.video_driver_fd);
710     pthread_mutex_destroy(&m_lock);
711     pthread_mutex_destroy(&c_lock);
712     sem_destroy(&m_cmd_lock);
713     if (perf_flag) {
714         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
715         dec_time.end();
716     }
717     DEBUG_PRINT_HIGH("Exit OMX vdec Destructor");
718 }
719 
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)720 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
721 {
722     struct v4l2_requestbuffers bufreq;
723     int rc = 0;
724     if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
725         bufreq.memory = V4L2_MEMORY_USERPTR;
726         bufreq.count = 0;
727         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
728         rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
729     }
730     return rc;
731 }
732 
733 /* ======================================================================
734    FUNCTION
735    omx_vdec::OMXCntrlProcessMsgCb
736 
737    DESCRIPTION
738    IL Client callbacks are generated through this routine. The decoder
739    provides the thread context for this routine.
740 
741    PARAMETERS
742    ctxt -- Context information related to the self.
743    id   -- Event identifier. This could be any of the following:
744    1. Command completion event
745    2. Buffer done callback event
746    3. Frame done callback event
747 
748    RETURN VALUE
749    None.
750 
751    ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)752 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
753 {
754     signed int p1; // Parameter - 1
755     signed int p2; // Parameter - 2
756     unsigned int ident;
757     unsigned int qsize=0; // qsize
758     omx_vdec *pThis = (omx_vdec *) ctxt;
759 
760     if (!pThis) {
761         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
762                 __func__);
763         return;
764     }
765 
766     // Protect the shared queue data structure
767     do {
768         /*Read the message id's from the queue*/
769         pthread_mutex_lock(&pThis->m_lock);
770         qsize = pThis->m_cmd_q.m_size;
771         if (qsize) {
772             pThis->m_cmd_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
773         }
774 
775         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
776             qsize = pThis->m_ftb_q.m_size;
777             if (qsize) {
778                 pThis->m_ftb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
779             }
780         }
781 
782         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
783             qsize = pThis->m_etb_q.m_size;
784             if (qsize) {
785                 pThis->m_etb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
786             }
787         }
788         pthread_mutex_unlock(&pThis->m_lock);
789 
790         /*process message if we have one*/
791         if (qsize > 0) {
792             id = ident;
793             switch (id) {
794                 case OMX_COMPONENT_GENERATE_EVENT:
795                     if (pThis->m_cb.EventHandler) {
796                         switch (p1) {
797                             case OMX_CommandStateSet:
798                                 pThis->m_state = (OMX_STATETYPE) p2;
799                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
800                                         pThis->m_state);
801                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
802                                         OMX_EventCmdComplete, p1, p2, NULL);
803                                 break;
804 
805                             case OMX_EventError:
806                                 if (p2 == OMX_StateInvalid) {
807                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
808                                     pThis->m_state = (OMX_STATETYPE) p2;
809                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
810                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
811                                 } else if (p2 == OMX_ErrorHardware) {
812                                     pThis->omx_report_error();
813                                 } else {
814                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
815                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
816                                 }
817                                 break;
818 
819                             case OMX_CommandPortDisable:
820                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%d]", p2);
821                                 if (BITMASK_PRESENT(&pThis->m_flags,
822                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
823                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
824                                     break;
825                                 }
826                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) {
827                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
828                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
829                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
830                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
831                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
832                                     pThis->in_reconfig = false;
833                                     if (eRet !=  OMX_ErrorNone) {
834                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
835                                         pThis->omx_report_error();
836                                         break;
837                                     }
838                                 }
839                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
840                                         OMX_EventCmdComplete, p1, p2, NULL );
841                                 break;
842                             case OMX_CommandPortEnable:
843                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%d]", p2);
844                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
845                                         OMX_EventCmdComplete, p1, p2, NULL );
846                                 break;
847 
848                             default:
849                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
850                                         OMX_EventCmdComplete, p1, p2, NULL );
851                                 break;
852 
853                         }
854                     } else {
855                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
856                     }
857                     break;
858                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
859                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
860                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
861                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
862                         pThis->omx_report_error ();
863                     }
864                     break;
865                 case OMX_COMPONENT_GENERATE_ETB:
866                     if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
867                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
868                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
869                         pThis->omx_report_error ();
870                     }
871                     break;
872 
873                 case OMX_COMPONENT_GENERATE_FTB:
874                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
875                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
876                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
877                         pThis->omx_report_error ();
878                     }
879                     break;
880 
881                 case OMX_COMPONENT_GENERATE_COMMAND:
882                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
883                             (OMX_U32)p2,(OMX_PTR)NULL);
884                     break;
885 
886                 case OMX_COMPONENT_GENERATE_EBD:
887 
888                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
889                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
890                         pThis->omx_report_error ();
891                     } else {
892                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
893                             pThis->m_inp_err_count++;
894                             pThis->time_stamp_dts.remove_time_stamp(
895                                     ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp,
896                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
897                                     ?true:false);
898                         } else {
899                             pThis->m_inp_err_count = 0;
900                         }
901                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
902                                     (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
903                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
904                             pThis->omx_report_error ();
905                         }
906                         if (pThis->m_inp_err_count >= MAX_INPUT_ERROR) {
907                             DEBUG_PRINT_ERROR("Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR);
908                             pThis->omx_report_error ();
909                         }
910                     }
911                     break;
912                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED:
913                     {
914                         int64_t *timestamp = (int64_t *)p1;
915                         if (p1) {
916                             pThis->time_stamp_dts.remove_time_stamp(*timestamp,
917                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
918                                     ?true:false);
919                             free(timestamp);
920                         }
921                     }
922                     break;
923                 case OMX_COMPONENT_GENERATE_FBD:
924                     if (p2 != VDEC_S_SUCCESS) {
925                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
926                         pThis->omx_report_error ();
927                     } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
928                                 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
929                         DEBUG_PRINT_ERROR("fill_buffer_done failure");
930                         pThis->omx_report_error ();
931                     }
932                     break;
933 
934                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
935                     DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
936                     if (!pThis->input_flush_progress) {
937                         DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
938                     } else {
939                         pThis->execute_input_flush();
940                         if (pThis->m_cb.EventHandler) {
941                             if (p2 != VDEC_S_SUCCESS) {
942                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
943                                 pThis->omx_report_error ();
944                             } else {
945                                 /*Check if we need generate event for Flush done*/
946                                 if (BITMASK_PRESENT(&pThis->m_flags,
947                                             OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
948                                     BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
949                                     DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
950                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
951                                             OMX_EventCmdComplete,OMX_CommandFlush,
952                                             OMX_CORE_INPUT_PORT_INDEX,NULL );
953                                 }
954                                 if (BITMASK_PRESENT(&pThis->m_flags,
955                                             OMX_COMPONENT_IDLE_PENDING)) {
956                                     if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
957                                         DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
958                                         pThis->omx_report_error ();
959                                     } else {
960                                         pThis->streaming[OUTPUT_PORT] = false;
961                                     }
962                                     if (!pThis->output_flush_progress) {
963                                         DEBUG_PRINT_LOW("Input flush done hence issue stop");
964                                         pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
965                                                 OMX_COMPONENT_GENERATE_STOP_DONE);
966                                     }
967                                 }
968                             }
969                         } else {
970                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
971                         }
972                     }
973                     break;
974 
975                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
976                     DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
977                     if (!pThis->output_flush_progress) {
978                         DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
979                     } else {
980                         pThis->execute_output_flush();
981                         if (pThis->m_cb.EventHandler) {
982                             if (p2 != VDEC_S_SUCCESS) {
983                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
984                                 pThis->omx_report_error ();
985                             } else {
986                                 /*Check if we need generate event for Flush done*/
987                                 if (BITMASK_PRESENT(&pThis->m_flags,
988                                             OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
989                                     DEBUG_PRINT_LOW("Notify Output Flush done");
990                                     BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
991                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
992                                             OMX_EventCmdComplete,OMX_CommandFlush,
993                                             OMX_CORE_OUTPUT_PORT_INDEX,NULL );
994                                 }
995                                 if (BITMASK_PRESENT(&pThis->m_flags,
996                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
997                                     DEBUG_PRINT_LOW("Internal flush complete");
998                                     BITMASK_CLEAR (&pThis->m_flags,
999                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1000                                     if (BITMASK_PRESENT(&pThis->m_flags,
1001                                                 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1002                                         pThis->post_event(OMX_CommandPortDisable,
1003                                                 OMX_CORE_OUTPUT_PORT_INDEX,
1004                                                 OMX_COMPONENT_GENERATE_EVENT);
1005                                         BITMASK_CLEAR (&pThis->m_flags,
1006                                                 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1007 
1008                                     }
1009                                 }
1010 
1011                                 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1012                                     if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1013                                         DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1014                                         pThis->omx_report_error ();
1015                                         break;
1016                                     }
1017                                     pThis->streaming[CAPTURE_PORT] = false;
1018                                     if (!pThis->input_flush_progress) {
1019                                         DEBUG_PRINT_LOW("Output flush done hence issue stop");
1020                                         pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1021                                                 OMX_COMPONENT_GENERATE_STOP_DONE);
1022                                     }
1023                                 }
1024                             }
1025                         } else {
1026                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1027                         }
1028                     }
1029                     break;
1030 
1031                 case OMX_COMPONENT_GENERATE_START_DONE:
1032                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1033 
1034                     if (pThis->m_cb.EventHandler) {
1035                         if (p2 != VDEC_S_SUCCESS) {
1036                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1037                             pThis->omx_report_error ();
1038                         } else {
1039                             DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1040                             if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1041                                 DEBUG_PRINT_LOW("Move to executing");
1042                                 // Send the callback now
1043                                 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1044                                 pThis->m_state = OMX_StateExecuting;
1045                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1046                                         OMX_EventCmdComplete,OMX_CommandStateSet,
1047                                         OMX_StateExecuting, NULL);
1048                             } else if (BITMASK_PRESENT(&pThis->m_flags,
1049                                         OMX_COMPONENT_PAUSE_PENDING)) {
1050                                 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1051                                       VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1052                                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1053                                     pThis->omx_report_error ();
1054                                 }
1055                             }
1056                         }
1057                     } else {
1058                         DEBUG_PRINT_LOW("Event Handler callback is NULL");
1059                     }
1060                     break;
1061 
1062                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1063                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1064                     if (pThis->m_cb.EventHandler) {
1065                         if (p2 != VDEC_S_SUCCESS) {
1066                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1067                             pThis->omx_report_error ();
1068                         } else {
1069                             pThis->complete_pending_buffer_done_cbs();
1070                             if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1071                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1072                                 //Send the callback now
1073                                 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1074                                 pThis->m_state = OMX_StatePause;
1075                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1076                                         OMX_EventCmdComplete,OMX_CommandStateSet,
1077                                         OMX_StatePause, NULL);
1078                             }
1079                         }
1080                     } else {
1081                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1082                     }
1083 
1084                     break;
1085 
1086                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1087                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1088                     if (pThis->m_cb.EventHandler) {
1089                         if (p2 != VDEC_S_SUCCESS) {
1090                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1091                             pThis->omx_report_error ();
1092                         } else {
1093                             if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1094                                 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1095                                 // Send the callback now
1096                                 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1097                                 pThis->m_state = OMX_StateExecuting;
1098                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1099                                         OMX_EventCmdComplete,OMX_CommandStateSet,
1100                                         OMX_StateExecuting,NULL);
1101                             }
1102                         }
1103                     } else {
1104                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1105                     }
1106 
1107                     break;
1108 
1109                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1110                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1111                     if (pThis->m_cb.EventHandler) {
1112                         if (p2 != VDEC_S_SUCCESS) {
1113                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1114                             pThis->omx_report_error ();
1115                         } else {
1116                             pThis->complete_pending_buffer_done_cbs();
1117                             if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1118                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1119                                 // Send the callback now
1120                                 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1121                                 pThis->m_state = OMX_StateIdle;
1122                                 DEBUG_PRINT_LOW("Move to Idle State");
1123                                 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1124                                         OMX_EventCmdComplete,OMX_CommandStateSet,
1125                                         OMX_StateIdle,NULL);
1126                             }
1127                         }
1128                     } else {
1129                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1130                     }
1131 
1132                     break;
1133 
1134                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1135                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG");
1136 
1137                     if (p2 == OMX_IndexParamPortDefinition) {
1138                         pThis->in_reconfig = true;
1139                     }
1140                     if (pThis->m_cb.EventHandler) {
1141                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1142                                 OMX_EventPortSettingsChanged, p1, p2, NULL );
1143                     } else {
1144                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1145                     }
1146 
1147                     if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) {
1148                         OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1;
1149                         OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged;
1150                         if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
1151                             format = OMX_InterlaceInterleaveFrameTopFieldFirst;
1152                         else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
1153                             format = OMX_InterlaceInterleaveFrameBottomFieldFirst;
1154                         else //unsupported interlace format; raise a error
1155                             event = OMX_EventError;
1156                         if (pThis->m_cb.EventHandler) {
1157                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1158                                     event, format, 0, NULL );
1159                         } else {
1160                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1161                         }
1162                     }
1163                     break;
1164 
1165                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1166                     DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1167                     if (pThis->m_cb.EventHandler) {
1168                         pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1169                                 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1170                     } else {
1171                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1172                     }
1173                     pThis->prev_ts = LLONG_MAX;
1174                     pThis->rst_prev_ts = true;
1175                     break;
1176 
1177                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1178                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1179                     pThis->omx_report_error ();
1180                     break;
1181                 case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG:
1182                     {
1183                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG");
1184                         if (pThis->m_cb.EventHandler) {
1185                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1186                                     (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
1187                         } else {
1188                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1189                         }
1190                     }
1191                 default:
1192                     break;
1193             }
1194         }
1195         pthread_mutex_lock(&pThis->m_lock);
1196         qsize = pThis->m_cmd_q.m_size;
1197         if (pThis->m_state != OMX_StatePause)
1198             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1199         pthread_mutex_unlock(&pThis->m_lock);
1200     } while (qsize>0);
1201 
1202 }
1203 
update_resolution(int width,int height)1204 void omx_vdec::update_resolution(int width, int height)
1205 {
1206     drv_ctx.video_resolution.frame_height = height;
1207     drv_ctx.video_resolution.frame_width = width;
1208     drv_ctx.video_resolution.scan_lines = height;
1209     drv_ctx.video_resolution.stride = width;
1210     rectangle.nLeft = 0;
1211     rectangle.nTop = 0;
1212     rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1213     rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1214 }
1215 
1216 /* ======================================================================
1217    FUNCTION
1218    omx_vdec::ComponentInit
1219 
1220    DESCRIPTION
1221    Initialize the component.
1222 
1223    PARAMETERS
1224    ctxt -- Context information related to the self.
1225    id   -- Event identifier. This could be any of the following:
1226    1. Command completion event
1227    2. Buffer done callback event
1228    3. Frame done callback event
1229 
1230    RETURN VALUE
1231    None.
1232 
1233    ========================================================================== */
component_init(OMX_STRING role)1234 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1235 {
1236 
1237     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1238     struct v4l2_fmtdesc fdesc;
1239     struct v4l2_format fmt;
1240     struct v4l2_requestbuffers bufreq;
1241     struct v4l2_control control;
1242     unsigned int   alignment = 0,buffer_size = 0;
1243     int fds[2];
1244     int r,ret=0;
1245     bool codec_ambiguous = false;
1246     OMX_STRING device_name = (OMX_STRING)DEVICE_NAME;
1247     DEBUG_PRINT_LOW("Opening device %s", device_name);
1248     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1249 
1250     DEBUG_PRINT_HIGH("omx_vdec::component_init(): Open device %s returned fd %d, errno %d",
1251             device_name, drv_ctx.video_driver_fd, errno);
1252 
1253     if (drv_ctx.video_driver_fd == 0) {
1254         drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1255     }
1256 
1257     if (drv_ctx.video_driver_fd < 0) {
1258         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
1259         return OMX_ErrorInsufficientResources;
1260     }
1261     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1262     drv_ctx.frame_rate.fps_denominator = 1;
1263 
1264     ret = pthread_create(&async_thread_id,0,async_message_thread,this);
1265     if (ret < 0) {
1266         close(drv_ctx.video_driver_fd);
1267         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
1268         return OMX_ErrorInsufficientResources;
1269     }
1270 
1271 #ifdef INPUT_BUFFER_LOG
1272     strcpy(inputfilename, INPUT_BUFFER_FILE_NAME);
1273 #endif
1274 #ifdef OUTPUT_BUFFER_LOG
1275     outputBufferFile1 = fopen (outputfilename, "ab");
1276 #endif
1277 #ifdef OUTPUT_EXTRADATA_LOG
1278     outputExtradataFile = fopen (ouputextradatafilename, "ab");
1279 #endif
1280 
1281     // Copy the role information which provides the decoder kind
1282     strlcpy(drv_ctx.kind,role,128);
1283 
1284     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
1285                 OMX_MAX_STRINGNAME_SIZE)) {
1286         strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
1287                 OMX_MAX_STRINGNAME_SIZE);
1288         drv_ctx.timestamp_adjust = true;
1289         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
1290         eCompressionFormat = OMX_VIDEO_CodingMPEG4;
1291         output_capability=V4L2_PIX_FMT_MPEG4;
1292         /*Initialize Start Code for MPEG4*/
1293         codec_type_parse = CODEC_TYPE_MPEG4;
1294         m_frame_parser.init_start_codes (codec_type_parse);
1295 #ifdef INPUT_BUFFER_LOG
1296         strcat(inputfilename, "m4v");
1297 #endif
1298     } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
1299                 OMX_MAX_STRINGNAME_SIZE)) {
1300         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
1301                 OMX_MAX_STRINGNAME_SIZE);
1302         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
1303         output_capability = V4L2_PIX_FMT_MPEG2;
1304         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
1305         /*Initialize Start Code for MPEG2*/
1306         codec_type_parse = CODEC_TYPE_MPEG2;
1307         m_frame_parser.init_start_codes (codec_type_parse);
1308 #ifdef INPUT_BUFFER_LOG
1309         strcat(inputfilename, "mpg");
1310 #endif
1311     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
1312                 OMX_MAX_STRINGNAME_SIZE)) {
1313         strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
1314         DEBUG_PRINT_LOW("H263 Decoder selected");
1315         drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
1316         eCompressionFormat = OMX_VIDEO_CodingH263;
1317         output_capability = V4L2_PIX_FMT_H263;
1318         codec_type_parse = CODEC_TYPE_H263;
1319         m_frame_parser.init_start_codes (codec_type_parse);
1320 #ifdef INPUT_BUFFER_LOG
1321         strcat(inputfilename, "263");
1322 #endif
1323     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
1324                 OMX_MAX_STRINGNAME_SIZE)) {
1325         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1326         DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
1327         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
1328         output_capability = V4L2_PIX_FMT_DIVX_311;
1329         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1330         codec_type_parse = CODEC_TYPE_DIVX;
1331         m_frame_parser.init_start_codes (codec_type_parse);
1332 
1333         eRet = createDivxDrmContext();
1334         if (eRet != OMX_ErrorNone) {
1335             DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1336             return eRet;
1337         }
1338     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
1339                 OMX_MAX_STRINGNAME_SIZE)) {
1340         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1341         DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
1342         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
1343         output_capability = V4L2_PIX_FMT_DIVX;
1344         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1345         codec_type_parse = CODEC_TYPE_DIVX;
1346         codec_ambiguous = true;
1347         m_frame_parser.init_start_codes (codec_type_parse);
1348 
1349         eRet = createDivxDrmContext();
1350         if (eRet != OMX_ErrorNone) {
1351             DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1352             return eRet;
1353         }
1354     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
1355                 OMX_MAX_STRINGNAME_SIZE)) {
1356         strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1357         DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
1358         drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
1359         output_capability = V4L2_PIX_FMT_DIVX;
1360         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1361         codec_type_parse = CODEC_TYPE_DIVX;
1362         codec_ambiguous = true;
1363         m_frame_parser.init_start_codes (codec_type_parse);
1364 
1365         eRet = createDivxDrmContext();
1366         if (eRet != OMX_ErrorNone) {
1367             DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1368             return eRet;
1369         }
1370 
1371     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
1372                 OMX_MAX_STRINGNAME_SIZE)) {
1373         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
1374         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
1375         output_capability=V4L2_PIX_FMT_H264;
1376         eCompressionFormat = OMX_VIDEO_CodingAVC;
1377         codec_type_parse = CODEC_TYPE_H264;
1378         m_frame_parser.init_start_codes (codec_type_parse);
1379         m_frame_parser.init_nal_length(nal_length);
1380 #ifdef INPUT_BUFFER_LOG
1381         strcat(inputfilename, "264");
1382 #endif
1383     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
1384                 OMX_MAX_STRINGNAME_SIZE)) {
1385         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
1386         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
1387         output_capability=V4L2_PIX_FMT_HEVC;
1388         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
1389         codec_type_parse = CODEC_TYPE_HEVC;
1390         m_frame_parser.init_start_codes (codec_type_parse);
1391         m_frame_parser.init_nal_length(nal_length);
1392 #ifdef INPUT_BUFFER_LOG
1393         strcat(inputfilename, "265");
1394 #endif
1395     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
1396                 OMX_MAX_STRINGNAME_SIZE)) {
1397         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1398         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
1399         eCompressionFormat = OMX_VIDEO_CodingWMV;
1400         codec_type_parse = CODEC_TYPE_VC1;
1401         output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
1402         m_frame_parser.init_start_codes (codec_type_parse);
1403 #ifdef INPUT_BUFFER_LOG
1404         strcat(inputfilename, "vc1");
1405 #endif
1406     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
1407                 OMX_MAX_STRINGNAME_SIZE)) {
1408         strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1409         drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
1410         eCompressionFormat = OMX_VIDEO_CodingWMV;
1411         codec_type_parse = CODEC_TYPE_VC1;
1412         output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
1413         m_frame_parser.init_start_codes (codec_type_parse);
1414 #ifdef INPUT_BUFFER_LOG
1415         strcat(inputfilename, "vc1");
1416 #endif
1417     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",\
1418                 OMX_MAX_STRINGNAME_SIZE)) {
1419         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
1420         output_capability=V4L2_PIX_FMT_VP8;
1421         eCompressionFormat = OMX_VIDEO_CodingVP8;
1422         codec_type_parse = CODEC_TYPE_VP8;
1423         arbitrary_bytes = false;
1424     } else {
1425         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
1426         eRet = OMX_ErrorInvalidComponentName;
1427     }
1428 #ifdef INPUT_BUFFER_LOG
1429     inputBufferFile1 = fopen (inputfilename, "ab");
1430 #endif
1431     if (eRet == OMX_ErrorNone) {
1432 
1433         drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
1434         OMX_COLOR_FORMATTYPE dest_color_format = (OMX_COLOR_FORMATTYPE)
1435             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
1436         if (!client_buffers.set_color_format(dest_color_format)) {
1437             DEBUG_PRINT_ERROR("Setting color format failed");
1438             eRet = OMX_ErrorInsufficientResources;
1439         }
1440 
1441         capture_capability= V4L2_PIX_FMT_NV12;
1442         ret = subscribe_to_events(drv_ctx.video_driver_fd);
1443         if (ret) {
1444             DEBUG_PRINT_ERROR("Subscribe Event Failed");
1445             return OMX_ErrorInsufficientResources;
1446         }
1447 
1448         struct v4l2_capability cap;
1449         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
1450         if (ret) {
1451             DEBUG_PRINT_ERROR("Failed to query capabilities");
1452             /*TODO: How to handle this case */
1453         } else {
1454             DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1455                     " version = %d, capabilities = %x", cap.driver, cap.card,
1456                     cap.bus_info, cap.version, cap.capabilities);
1457         }
1458         ret=0;
1459         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1460         fdesc.index=0;
1461         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1462             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1463                     fdesc.pixelformat, fdesc.flags);
1464             fdesc.index++;
1465         }
1466         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1467         fdesc.index=0;
1468         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1469 
1470             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1471                     fdesc.pixelformat, fdesc.flags);
1472             fdesc.index++;
1473         }
1474         update_resolution(320, 240);
1475         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1476         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1477         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1478         fmt.fmt.pix_mp.pixelformat = output_capability;
1479         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1480         if (ret) {
1481             /*TODO: How to handle this case */
1482             DEBUG_PRINT_ERROR("Failed to set format on output port");
1483         }
1484         DEBUG_PRINT_HIGH("Set Format was successful");
1485         if (codec_ambiguous) {
1486             if (output_capability == V4L2_PIX_FMT_DIVX) {
1487                 struct v4l2_control divx_ctrl;
1488 
1489                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
1490                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
1491                 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
1492                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
1493                 } else {
1494                     divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
1495                 }
1496 
1497                 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
1498                 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
1499                 if (ret) {
1500                     DEBUG_PRINT_ERROR("Failed to set divx version");
1501                 }
1502             } else {
1503                 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
1504             }
1505         }
1506 
1507         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1508         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1509         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1510         fmt.fmt.pix_mp.pixelformat = capture_capability;
1511         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1512         if (ret) {
1513             /*TODO: How to handle this case */
1514             DEBUG_PRINT_ERROR("Failed to set format on capture port");
1515         }
1516         DEBUG_PRINT_HIGH("Set Format was successful");
1517         if (secure_mode) {
1518             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1519             control.value = 1;
1520             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
1521             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
1522             if (ret) {
1523                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
1524                 close(drv_ctx.video_driver_fd);
1525                 return OMX_ErrorInsufficientResources;
1526             }
1527         }
1528 
1529         /*Get the Buffer requirements for input and output ports*/
1530         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
1531         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
1532         if (secure_mode) {
1533             drv_ctx.op_buf.alignment=SZ_1M;
1534             drv_ctx.ip_buf.alignment=SZ_1M;
1535         } else {
1536             drv_ctx.op_buf.alignment=SZ_4K;
1537             drv_ctx.ip_buf.alignment=SZ_4K;
1538         }
1539         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
1540         drv_ctx.extradata = 0;
1541         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
1542         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
1543         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
1544         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1545         drv_ctx.idr_only_decoding = 0;
1546 
1547         m_state = OMX_StateLoaded;
1548 #ifdef DEFAULT_EXTRADATA
1549         if (eRet == OMX_ErrorNone && !secure_mode)
1550             enable_extradata(DEFAULT_EXTRADATA, true, true);
1551 #endif
1552         eRet=get_buffer_req(&drv_ctx.ip_buf);
1553         DEBUG_PRINT_HIGH("Input Buffer Size =%d",drv_ctx.ip_buf.buffer_size);
1554         get_buffer_req(&drv_ctx.op_buf);
1555         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
1556                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC) {
1557             h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
1558             h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
1559             h264_scratch.nFilledLen = 0;
1560             h264_scratch.nOffset = 0;
1561 
1562             if (h264_scratch.pBuffer == NULL) {
1563                 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
1564                 return OMX_ErrorInsufficientResources;
1565             }
1566         }
1567 
1568         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
1569             if (m_frame_parser.mutils == NULL) {
1570                 m_frame_parser.mutils = new H264_Utils();
1571 
1572                 if (m_frame_parser.mutils == NULL) {
1573                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
1574                     eRet = OMX_ErrorInsufficientResources;
1575                 } else {
1576                     m_frame_parser.mutils->initialize_frame_checking_environment();
1577                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
1578                 }
1579             }
1580 
1581             h264_parser = new h264_stream_parser();
1582             if (!h264_parser) {
1583                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
1584                 eRet = OMX_ErrorInsufficientResources;
1585             }
1586         }
1587 
1588         if (pipe(fds)) {
1589             DEBUG_PRINT_ERROR("pipe creation failed");
1590             eRet = OMX_ErrorInsufficientResources;
1591         } else {
1592             int temp1[2];
1593             if (fds[0] == 0 || fds[1] == 0) {
1594                 if (pipe (temp1)) {
1595                     DEBUG_PRINT_ERROR("pipe creation failed");
1596                     return OMX_ErrorInsufficientResources;
1597                 }
1598                 //close (fds[0]);
1599                 //close (fds[1]);
1600                 fds[0] = temp1 [0];
1601                 fds[1] = temp1 [1];
1602             }
1603             m_pipe_in = fds[0];
1604             m_pipe_out = fds[1];
1605             r = pthread_create(&msg_thread_id,0,message_thread,this);
1606 
1607             if (r < 0) {
1608                 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
1609                 eRet = OMX_ErrorInsufficientResources;
1610             }
1611         }
1612     }
1613 
1614     if (eRet != OMX_ErrorNone) {
1615         DEBUG_PRINT_ERROR("Component Init Failed");
1616         DEBUG_PRINT_HIGH("Calling VDEC_IOCTL_STOP_NEXT_MSG");
1617         (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
1618                 NULL);
1619         DEBUG_PRINT_HIGH("Calling close() on Video Driver");
1620         close (drv_ctx.video_driver_fd);
1621         drv_ctx.video_driver_fd = -1;
1622     } else {
1623         DEBUG_PRINT_HIGH("omx_vdec::component_init() success");
1624     }
1625     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
1626     return eRet;
1627 }
1628 
1629 /* ======================================================================
1630    FUNCTION
1631    omx_vdec::GetComponentVersion
1632 
1633    DESCRIPTION
1634    Returns the component version.
1635 
1636    PARAMETERS
1637    TBD.
1638 
1639    RETURN VALUE
1640    OMX_ErrorNone.
1641 
1642    ========================================================================== */
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)1643 OMX_ERRORTYPE  omx_vdec::get_component_version
1644 (
1645  OMX_IN OMX_HANDLETYPE hComp,
1646  OMX_OUT OMX_STRING componentName,
1647  OMX_OUT OMX_VERSIONTYPE* componentVersion,
1648  OMX_OUT OMX_VERSIONTYPE* specVersion,
1649  OMX_OUT OMX_UUIDTYPE* componentUUID
1650  )
1651 {
1652     if (m_state == OMX_StateInvalid) {
1653         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
1654         return OMX_ErrorInvalidState;
1655     }
1656     /* TBD -- Return the proper version */
1657     if (specVersion) {
1658         specVersion->nVersion = OMX_SPEC_VERSION;
1659     }
1660     return OMX_ErrorNone;
1661 }
1662 /* ======================================================================
1663    FUNCTION
1664    omx_vdec::SendCommand
1665 
1666    DESCRIPTION
1667    Returns zero if all the buffers released..
1668 
1669    PARAMETERS
1670    None.
1671 
1672    RETURN VALUE
1673    true/false
1674 
1675    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1676 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
1677         OMX_IN OMX_COMMANDTYPE cmd,
1678         OMX_IN OMX_U32 param1,
1679         OMX_IN OMX_PTR cmdData
1680         )
1681 {
1682     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
1683     if (m_state == OMX_StateInvalid) {
1684         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
1685         return OMX_ErrorInvalidState;
1686     }
1687     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
1688             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
1689         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
1690                 "to invalid port: %lu", param1);
1691         return OMX_ErrorBadPortIndex;
1692     }
1693     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
1694     sem_wait(&m_cmd_lock);
1695     DEBUG_PRINT_LOW("send_command: Command Processed");
1696     return OMX_ErrorNone;
1697 }
1698 
1699 /* ======================================================================
1700    FUNCTION
1701    omx_vdec::SendCommand
1702 
1703    DESCRIPTION
1704    Returns zero if all the buffers released..
1705 
1706    PARAMETERS
1707    None.
1708 
1709    RETURN VALUE
1710    true/false
1711 
1712    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1713 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
1714         OMX_IN OMX_COMMANDTYPE cmd,
1715         OMX_IN OMX_U32 param1,
1716         OMX_IN OMX_PTR cmdData
1717         )
1718 {
1719     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1720     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
1721     int bFlag = 1,sem_posted = 0,ret=0;
1722 
1723     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
1724     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
1725             m_state, eState);
1726 
1727     if (cmd == OMX_CommandStateSet) {
1728         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
1729         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
1730         /***************************/
1731         /* Current State is Loaded */
1732         /***************************/
1733         if (m_state == OMX_StateLoaded) {
1734             if (eState == OMX_StateIdle) {
1735                 //if all buffers are allocated or all ports disabled
1736                 if (allocate_done() ||
1737                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
1738                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
1739                 } else {
1740                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
1741                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
1742                     // Skip the event notification
1743                     bFlag = 0;
1744                 }
1745             }
1746             /* Requesting transition from Loaded to Loaded */
1747             else if (eState == OMX_StateLoaded) {
1748                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
1749                 post_event(OMX_EventError,OMX_ErrorSameState,\
1750                         OMX_COMPONENT_GENERATE_EVENT);
1751                 eRet = OMX_ErrorSameState;
1752             }
1753             /* Requesting transition from Loaded to WaitForResources */
1754             else if (eState == OMX_StateWaitForResources) {
1755                 /* Since error is None , we will post an event
1756                    at the end of this function definition */
1757                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
1758             }
1759             /* Requesting transition from Loaded to Executing */
1760             else if (eState == OMX_StateExecuting) {
1761                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
1762                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1763                         OMX_COMPONENT_GENERATE_EVENT);
1764                 eRet = OMX_ErrorIncorrectStateTransition;
1765             }
1766             /* Requesting transition from Loaded to Pause */
1767             else if (eState == OMX_StatePause) {
1768                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
1769                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1770                         OMX_COMPONENT_GENERATE_EVENT);
1771                 eRet = OMX_ErrorIncorrectStateTransition;
1772             }
1773             /* Requesting transition from Loaded to Invalid */
1774             else if (eState == OMX_StateInvalid) {
1775                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
1776                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1777                 eRet = OMX_ErrorInvalidState;
1778             } else {
1779                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
1780                         eState);
1781                 eRet = OMX_ErrorBadParameter;
1782             }
1783         }
1784 
1785         /***************************/
1786         /* Current State is IDLE */
1787         /***************************/
1788         else if (m_state == OMX_StateIdle) {
1789             if (eState == OMX_StateLoaded) {
1790                 if (release_done()) {
1791                     /*
1792                        Since error is None , we will post an event at the end
1793                        of this function definition
1794                      */
1795                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
1796                 } else {
1797                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
1798                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
1799                     // Skip the event notification
1800                     bFlag = 0;
1801                 }
1802             }
1803             /* Requesting transition from Idle to Executing */
1804             else if (eState == OMX_StateExecuting) {
1805                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
1806                 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
1807                 bFlag = 1;
1808                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
1809                 m_state=OMX_StateExecuting;
1810                 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
1811             }
1812             /* Requesting transition from Idle to Idle */
1813             else if (eState == OMX_StateIdle) {
1814                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
1815                 post_event(OMX_EventError,OMX_ErrorSameState,\
1816                         OMX_COMPONENT_GENERATE_EVENT);
1817                 eRet = OMX_ErrorSameState;
1818             }
1819             /* Requesting transition from Idle to WaitForResources */
1820             else if (eState == OMX_StateWaitForResources) {
1821                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
1822                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1823                         OMX_COMPONENT_GENERATE_EVENT);
1824                 eRet = OMX_ErrorIncorrectStateTransition;
1825             }
1826             /* Requesting transition from Idle to Pause */
1827             else if (eState == OMX_StatePause) {
1828                 /*To pause the Video core we need to start the driver*/
1829                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
1830                       NULL) < */0) {
1831                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
1832                     omx_report_error ();
1833                     eRet = OMX_ErrorHardware;
1834                 } else {
1835                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
1836                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
1837                     bFlag = 0;
1838                 }
1839             }
1840             /* Requesting transition from Idle to Invalid */
1841             else if (eState == OMX_StateInvalid) {
1842                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
1843                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1844                 eRet = OMX_ErrorInvalidState;
1845             } else {
1846                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
1847                 eRet = OMX_ErrorBadParameter;
1848             }
1849         }
1850 
1851         /******************************/
1852         /* Current State is Executing */
1853         /******************************/
1854         else if (m_state == OMX_StateExecuting) {
1855             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
1856             /* Requesting transition from Executing to Idle */
1857             if (eState == OMX_StateIdle) {
1858                 /* Since error is None , we will post an event
1859                    at the end of this function definition
1860                  */
1861                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
1862                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
1863                 if (!sem_posted) {
1864                     sem_posted = 1;
1865                     sem_post (&m_cmd_lock);
1866                     execute_omx_flush(OMX_ALL);
1867                 }
1868                 bFlag = 0;
1869             }
1870             /* Requesting transition from Executing to Paused */
1871             else if (eState == OMX_StatePause) {
1872                 DEBUG_PRINT_LOW("PAUSE Command Issued");
1873                 m_state = OMX_StatePause;
1874                 bFlag = 1;
1875             }
1876             /* Requesting transition from Executing to Loaded */
1877             else if (eState == OMX_StateLoaded) {
1878                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
1879                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1880                         OMX_COMPONENT_GENERATE_EVENT);
1881                 eRet = OMX_ErrorIncorrectStateTransition;
1882             }
1883             /* Requesting transition from Executing to WaitForResources */
1884             else if (eState == OMX_StateWaitForResources) {
1885                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
1886                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1887                         OMX_COMPONENT_GENERATE_EVENT);
1888                 eRet = OMX_ErrorIncorrectStateTransition;
1889             }
1890             /* Requesting transition from Executing to Executing */
1891             else if (eState == OMX_StateExecuting) {
1892                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
1893                 post_event(OMX_EventError,OMX_ErrorSameState,\
1894                         OMX_COMPONENT_GENERATE_EVENT);
1895                 eRet = OMX_ErrorSameState;
1896             }
1897             /* Requesting transition from Executing to Invalid */
1898             else if (eState == OMX_StateInvalid) {
1899                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
1900                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1901                 eRet = OMX_ErrorInvalidState;
1902             } else {
1903                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
1904                 eRet = OMX_ErrorBadParameter;
1905             }
1906         }
1907         /***************************/
1908         /* Current State is Pause  */
1909         /***************************/
1910         else if (m_state == OMX_StatePause) {
1911             /* Requesting transition from Pause to Executing */
1912             if (eState == OMX_StateExecuting) {
1913                 DEBUG_PRINT_LOW("Pause --> Executing");
1914                 m_state = OMX_StateExecuting;
1915                 bFlag = 1;
1916             }
1917             /* Requesting transition from Pause to Idle */
1918             else if (eState == OMX_StateIdle) {
1919                 /* Since error is None , we will post an event
1920                    at the end of this function definition */
1921                 DEBUG_PRINT_LOW("Pause --> Idle");
1922                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
1923                 if (!sem_posted) {
1924                     sem_posted = 1;
1925                     sem_post (&m_cmd_lock);
1926                     execute_omx_flush(OMX_ALL);
1927                 }
1928                 bFlag = 0;
1929             }
1930             /* Requesting transition from Pause to loaded */
1931             else if (eState == OMX_StateLoaded) {
1932                 DEBUG_PRINT_ERROR("Pause --> loaded");
1933                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1934                         OMX_COMPONENT_GENERATE_EVENT);
1935                 eRet = OMX_ErrorIncorrectStateTransition;
1936             }
1937             /* Requesting transition from Pause to WaitForResources */
1938             else if (eState == OMX_StateWaitForResources) {
1939                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
1940                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1941                         OMX_COMPONENT_GENERATE_EVENT);
1942                 eRet = OMX_ErrorIncorrectStateTransition;
1943             }
1944             /* Requesting transition from Pause to Pause */
1945             else if (eState == OMX_StatePause) {
1946                 DEBUG_PRINT_ERROR("Pause --> Pause");
1947                 post_event(OMX_EventError,OMX_ErrorSameState,\
1948                         OMX_COMPONENT_GENERATE_EVENT);
1949                 eRet = OMX_ErrorSameState;
1950             }
1951             /* Requesting transition from Pause to Invalid */
1952             else if (eState == OMX_StateInvalid) {
1953                 DEBUG_PRINT_ERROR("Pause --> Invalid");
1954                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1955                 eRet = OMX_ErrorInvalidState;
1956             } else {
1957                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
1958                 eRet = OMX_ErrorBadParameter;
1959             }
1960         }
1961         /***************************/
1962         /* Current State is WaitForResources  */
1963         /***************************/
1964         else if (m_state == OMX_StateWaitForResources) {
1965             /* Requesting transition from WaitForResources to Loaded */
1966             if (eState == OMX_StateLoaded) {
1967                 /* Since error is None , we will post an event
1968                    at the end of this function definition */
1969                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
1970             }
1971             /* Requesting transition from WaitForResources to WaitForResources */
1972             else if (eState == OMX_StateWaitForResources) {
1973                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
1974                 post_event(OMX_EventError,OMX_ErrorSameState,
1975                         OMX_COMPONENT_GENERATE_EVENT);
1976                 eRet = OMX_ErrorSameState;
1977             }
1978             /* Requesting transition from WaitForResources to Executing */
1979             else if (eState == OMX_StateExecuting) {
1980                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
1981                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1982                         OMX_COMPONENT_GENERATE_EVENT);
1983                 eRet = OMX_ErrorIncorrectStateTransition;
1984             }
1985             /* Requesting transition from WaitForResources to Pause */
1986             else if (eState == OMX_StatePause) {
1987                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
1988                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1989                         OMX_COMPONENT_GENERATE_EVENT);
1990                 eRet = OMX_ErrorIncorrectStateTransition;
1991             }
1992             /* Requesting transition from WaitForResources to Invalid */
1993             else if (eState == OMX_StateInvalid) {
1994                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
1995                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1996                 eRet = OMX_ErrorInvalidState;
1997             }
1998             /* Requesting transition from WaitForResources to Loaded -
1999                is NOT tested by Khronos TS */
2000 
2001         } else {
2002             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2003             eRet = OMX_ErrorBadParameter;
2004         }
2005     }
2006     /********************************/
2007     /* Current State is Invalid */
2008     /*******************************/
2009     else if (m_state == OMX_StateInvalid) {
2010         /* State Transition from Inavlid to any state */
2011         if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
2012                     || OMX_StateIdle || OMX_StateExecuting
2013                     || OMX_StatePause || OMX_StateInvalid)) {
2014             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2015             post_event(OMX_EventError,OMX_ErrorInvalidState,\
2016                     OMX_COMPONENT_GENERATE_EVENT);
2017             eRet = OMX_ErrorInvalidState;
2018         }
2019     } else if (cmd == OMX_CommandFlush) {
2020         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2021                 "with param1: %lu", param1);
2022         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2023             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2024         }
2025         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2026             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2027         }
2028         if (!sem_posted) {
2029             sem_posted = 1;
2030             DEBUG_PRINT_LOW("Set the Semaphore");
2031             sem_post (&m_cmd_lock);
2032             execute_omx_flush(param1);
2033         }
2034         bFlag = 0;
2035     } else if ( cmd == OMX_CommandPortEnable) {
2036         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2037                 "with param1: %lu", param1);
2038         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2039             m_inp_bEnabled = OMX_TRUE;
2040 
2041             if ( (m_state == OMX_StateLoaded &&
2042                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2043                     || allocate_input_done()) {
2044                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2045                         OMX_COMPONENT_GENERATE_EVENT);
2046             } else {
2047                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2048                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2049                 // Skip the event notification
2050                 bFlag = 0;
2051             }
2052         }
2053         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2054             DEBUG_PRINT_LOW("Enable output Port command recieved");
2055             m_out_bEnabled = OMX_TRUE;
2056 
2057             if ( (m_state == OMX_StateLoaded &&
2058                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2059                     || (allocate_output_done())) {
2060                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2061                         OMX_COMPONENT_GENERATE_EVENT);
2062 
2063             } else {
2064                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2065                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2066                 // Skip the event notification
2067                 bFlag = 0;
2068             }
2069         }
2070     } else if (cmd == OMX_CommandPortDisable) {
2071         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
2072                 "with param1: %lu", param1);
2073         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2074             m_inp_bEnabled = OMX_FALSE;
2075             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2076                     && release_input_done()) {
2077                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2078                         OMX_COMPONENT_GENERATE_EVENT);
2079             } else {
2080                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2081                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2082                     if (!sem_posted) {
2083                         sem_posted = 1;
2084                         sem_post (&m_cmd_lock);
2085                     }
2086                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2087                 }
2088 
2089                 // Skip the event notification
2090                 bFlag = 0;
2091             }
2092         }
2093         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2094             m_out_bEnabled = OMX_FALSE;
2095             DEBUG_PRINT_LOW("Disable output Port command recieved");
2096             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2097                     && release_output_done()) {
2098                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2099                         OMX_COMPONENT_GENERATE_EVENT);
2100             } else {
2101                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2102                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2103                     if (!sem_posted) {
2104                         sem_posted = 1;
2105                         sem_post (&m_cmd_lock);
2106                     }
2107                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2108                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2109                 }
2110                 // Skip the event notification
2111                 bFlag = 0;
2112 
2113             }
2114         }
2115     } else {
2116         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
2117         eRet = OMX_ErrorNotImplemented;
2118     }
2119     if (eRet == OMX_ErrorNone && bFlag) {
2120         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2121     }
2122     if (!sem_posted) {
2123         sem_post(&m_cmd_lock);
2124     }
2125 
2126     return eRet;
2127 }
2128 
2129 /* ======================================================================
2130    FUNCTION
2131    omx_vdec::ExecuteOmxFlush
2132 
2133    DESCRIPTION
2134    Executes the OMX flush.
2135 
2136    PARAMETERS
2137    flushtype - input flush(1)/output flush(0)/ both.
2138 
2139    RETURN VALUE
2140    true/false
2141 
2142    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)2143 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
2144 {
2145     bool bRet = false;
2146     struct v4l2_plane plane;
2147     struct v4l2_buffer v4l2_buf;
2148     struct v4l2_decoder_cmd dec;
2149     DEBUG_PRINT_LOW("in %s", __func__);
2150     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
2151     dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
2152     switch (flushType) {
2153         case OMX_CORE_INPUT_PORT_INDEX:
2154             input_flush_progress = true;
2155             dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT;
2156             break;
2157         case OMX_CORE_OUTPUT_PORT_INDEX:
2158             output_flush_progress = true;
2159             dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2160             break;
2161         default:
2162             input_flush_progress = true;
2163             output_flush_progress = true;
2164             dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT |
2165                 V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2166     }
2167 
2168     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
2169         DEBUG_PRINT_ERROR("Flush Port (%lu) Failed ", flushType);
2170         bRet = false;
2171     }
2172 
2173     return bRet;
2174 }
2175 /*=========================================================================
2176 FUNCTION : execute_output_flush
2177 
2178 DESCRIPTION
2179 Executes the OMX flush at OUTPUT PORT.
2180 
2181 PARAMETERS
2182 None.
2183 
2184 RETURN VALUE
2185 true/false
2186 ==========================================================================*/
execute_output_flush()2187 bool omx_vdec::execute_output_flush()
2188 {
2189     unsigned      p1 = 0; // Parameter - 1
2190     unsigned      p2 = 0; // Parameter - 2
2191     unsigned      ident = 0;
2192     bool bRet = true;
2193 
2194     /*Generate FBD for all Buffers in the FTBq*/
2195     pthread_mutex_lock(&m_lock);
2196     DEBUG_PRINT_LOW("Initiate Output Flush");
2197     while (m_ftb_q.m_size) {
2198         DEBUG_PRINT_LOW("Buffer queue size %d pending buf cnt %d",
2199                 m_ftb_q.m_size,pending_output_buffers);
2200         m_ftb_q.pop_entry(&p1,&p2,&ident);
2201         DEBUG_PRINT_LOW("ID(%x) P1(%x) P2(%x)", ident, p1, p2);
2202         if (ident == m_fill_output_msg ) {
2203             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2204         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
2205             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2206         }
2207     }
2208     pthread_mutex_unlock(&m_lock);
2209     output_flush_progress = false;
2210 
2211     if (arbitrary_bytes) {
2212         prev_ts = LLONG_MAX;
2213         rst_prev_ts = true;
2214     }
2215     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
2216     return bRet;
2217 }
2218 /*=========================================================================
2219 FUNCTION : execute_input_flush
2220 
2221 DESCRIPTION
2222 Executes the OMX flush at INPUT PORT.
2223 
2224 PARAMETERS
2225 None.
2226 
2227 RETURN VALUE
2228 true/false
2229 ==========================================================================*/
execute_input_flush()2230 bool omx_vdec::execute_input_flush()
2231 {
2232     unsigned       i =0;
2233     unsigned      p1 = 0; // Parameter - 1
2234     unsigned      p2 = 0; // Parameter - 2
2235     unsigned      ident = 0;
2236     bool bRet = true;
2237 
2238     /*Generate EBD for all Buffers in the ETBq*/
2239     DEBUG_PRINT_LOW("Initiate Input Flush");
2240 
2241     pthread_mutex_lock(&m_lock);
2242     DEBUG_PRINT_LOW("Check if the Queue is empty");
2243     while (m_etb_q.m_size) {
2244         m_etb_q.pop_entry(&p1,&p2,&ident);
2245 
2246         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2247             DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
2248             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2249         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
2250             pending_input_buffers++;
2251             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
2252                     (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
2253             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2254         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
2255             DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
2256                     (OMX_BUFFERHEADERTYPE *)p1);
2257             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2258         }
2259     }
2260     time_stamp_dts.flush_timestamp();
2261     /*Check if Heap Buffers are to be flushed*/
2262     if (arbitrary_bytes && !(codec_config_flag)) {
2263         DEBUG_PRINT_LOW("Reset all the variables before flusing");
2264         h264_scratch.nFilledLen = 0;
2265         nal_count = 0;
2266         look_ahead_nal = false;
2267         frame_count = 0;
2268         h264_last_au_ts = LLONG_MAX;
2269         h264_last_au_flags = 0;
2270         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
2271         m_demux_entries = 0;
2272         DEBUG_PRINT_LOW("Initialize parser");
2273         if (m_frame_parser.mutils) {
2274             m_frame_parser.mutils->initialize_frame_checking_environment();
2275         }
2276 
2277         while (m_input_pending_q.m_size) {
2278             m_input_pending_q.pop_entry(&p1,&p2,&ident);
2279             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
2280         }
2281 
2282         if (psource_frame) {
2283             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
2284             psource_frame = NULL;
2285         }
2286 
2287         if (pdest_frame) {
2288             pdest_frame->nFilledLen = 0;
2289             m_input_free_q.insert_entry((unsigned) pdest_frame, (unsigned int)NULL,
2290                     (unsigned int)NULL);
2291             pdest_frame = NULL;
2292         }
2293         m_frame_parser.flush();
2294     } else if (codec_config_flag) {
2295         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
2296             "is not sent to the driver yet");
2297     }
2298     pthread_mutex_unlock(&m_lock);
2299     input_flush_progress = false;
2300     if (!arbitrary_bytes) {
2301         prev_ts = LLONG_MAX;
2302         rst_prev_ts = true;
2303     }
2304 #ifdef _ANDROID_
2305     if (m_debug_timestamp) {
2306         m_timestamp_list.reset_ts_list();
2307     }
2308 #endif
2309     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
2310     return bRet;
2311 }
2312 
2313 
2314 /* ======================================================================
2315    FUNCTION
2316    omx_vdec::SendCommandEvent
2317 
2318    DESCRIPTION
2319    Send the event to decoder pipe.  This is needed to generate the callbacks
2320    in decoder thread context.
2321 
2322    PARAMETERS
2323    None.
2324 
2325    RETURN VALUE
2326    true/false
2327 
2328    ========================================================================== */
post_event(unsigned int p1,unsigned int p2,unsigned int id)2329 bool omx_vdec::post_event(unsigned int p1,
2330         unsigned int p2,
2331         unsigned int id)
2332 {
2333     bool bRet      =                      false;
2334 
2335 
2336     pthread_mutex_lock(&m_lock);
2337 
2338     if (id == m_fill_output_msg ||
2339             id == OMX_COMPONENT_GENERATE_FBD) {
2340         m_ftb_q.insert_entry(p1,p2,id);
2341     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
2342             id == OMX_COMPONENT_GENERATE_EBD ||
2343             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2344         m_etb_q.insert_entry(p1,p2,id);
2345     } else {
2346         m_cmd_q.insert_entry(p1,p2,id);
2347     }
2348 
2349     bRet = true;
2350     DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
2351     post_message(this, id);
2352 
2353     pthread_mutex_unlock(&m_lock);
2354 
2355     return bRet;
2356 }
2357 
get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)2358 OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
2359 {
2360     OMX_ERRORTYPE eRet = OMX_ErrorNoMore;
2361     if (!profileLevelType)
2362         return OMX_ErrorBadParameter;
2363 
2364     if (profileLevelType->nPortIndex == 0) {
2365         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2366             if (profileLevelType->nProfileIndex == 0) {
2367                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
2368                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
2369 
2370             } else if (profileLevelType->nProfileIndex == 1) {
2371                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
2372                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
2373             } else if (profileLevelType->nProfileIndex == 2) {
2374                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
2375                 profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
2376             } else {
2377                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
2378                         profileLevelType->nProfileIndex);
2379                 eRet = OMX_ErrorNoMore;
2380             }
2381         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2382             // TODO
2383             {
2384                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
2385                         profileLevelType->nProfileIndex);
2386                 eRet = OMX_ErrorNoMore;
2387             }
2388         } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
2389             if (profileLevelType->nProfileIndex == 0) {
2390                 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
2391                 profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
2392             } else {
2393                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2394                 eRet = OMX_ErrorNoMore;
2395             }
2396         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2397             if (profileLevelType->nProfileIndex == 0) {
2398                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2399                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
2400             } else if (profileLevelType->nProfileIndex == 1) {
2401                 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2402                 profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
2403             } else {
2404                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2405                 eRet = OMX_ErrorNoMore;
2406             }
2407         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
2408             eRet = OMX_ErrorNoMore;
2409         } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2410             if (profileLevelType->nProfileIndex == 0) {
2411                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
2412                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
2413             } else if (profileLevelType->nProfileIndex == 1) {
2414                 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
2415                 profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
2416             } else {
2417                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2418                 eRet = OMX_ErrorNoMore;
2419             }
2420         }
2421     } else {
2422         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %lu", profileLevelType->nPortIndex);
2423         eRet = OMX_ErrorBadPortIndex;
2424     }
2425     return eRet;
2426 }
2427 
2428 /* ======================================================================
2429    FUNCTION
2430    omx_vdec::GetParameter
2431 
2432    DESCRIPTION
2433    OMX Get Parameter method implementation
2434 
2435    PARAMETERS
2436    <TBD>.
2437 
2438    RETURN VALUE
2439    Error None if successful.
2440 
2441    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)2442 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
2443         OMX_IN OMX_INDEXTYPE paramIndex,
2444         OMX_INOUT OMX_PTR     paramData)
2445 {
2446     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2447 
2448     DEBUG_PRINT_LOW("get_parameter:");
2449     if (m_state == OMX_StateInvalid) {
2450         DEBUG_PRINT_ERROR("Get Param in Invalid State");
2451         return OMX_ErrorInvalidState;
2452     }
2453     if (paramData == NULL) {
2454         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
2455         return OMX_ErrorBadParameter;
2456     }
2457     switch ((unsigned long)paramIndex) {
2458         case OMX_IndexParamPortDefinition:
2459             {
2460                 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
2461                     (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2462                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
2463                 eRet = update_portdef(portDefn);
2464                 if (eRet == OMX_ErrorNone)
2465                     m_port_def = *portDefn;
2466                 break;
2467             }
2468         case OMX_IndexParamVideoInit:
2469             {
2470                 OMX_PORT_PARAM_TYPE *portParamType =
2471                     (OMX_PORT_PARAM_TYPE *) paramData;
2472                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
2473 
2474                 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2475                 portParamType->nSize = sizeof(portParamType);
2476                 portParamType->nPorts           = 2;
2477                 portParamType->nStartPortNumber = 0;
2478                 break;
2479             }
2480         case OMX_IndexParamVideoPortFormat:
2481             {
2482                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2483                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2484                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
2485 
2486                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
2487                 portFmt->nSize             = sizeof(portFmt);
2488 
2489                 if (0 == portFmt->nPortIndex) {
2490                     if (0 == portFmt->nIndex) {
2491                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
2492                         portFmt->eCompressionFormat = eCompressionFormat;
2493                     } else {
2494                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
2495                                 " NoMore compression formats");
2496                         eRet =  OMX_ErrorNoMore;
2497                     }
2498                 } else if (1 == portFmt->nPortIndex) {
2499                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
2500 
2501                     if (0 == portFmt->nIndex)
2502                         portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
2503                             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2504                     else if (1 == portFmt->nIndex)
2505                         portFmt->eColorFormat = OMX_COLOR_FormatYUV420Planar;
2506                     else {
2507                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
2508                                 " NoMore Color formats");
2509                         eRet =  OMX_ErrorNoMore;
2510                     }
2511                     DEBUG_PRINT_LOW("returning %d", portFmt->eColorFormat);
2512                 } else {
2513                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
2514                             (int)portFmt->nPortIndex);
2515                     eRet = OMX_ErrorBadPortIndex;
2516                 }
2517                 break;
2518             }
2519             /*Component should support this port definition*/
2520         case OMX_IndexParamAudioInit:
2521             {
2522                 OMX_PORT_PARAM_TYPE *audioPortParamType =
2523                     (OMX_PORT_PARAM_TYPE *) paramData;
2524                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
2525                 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2526                 audioPortParamType->nSize = sizeof(audioPortParamType);
2527                 audioPortParamType->nPorts           = 0;
2528                 audioPortParamType->nStartPortNumber = 0;
2529                 break;
2530             }
2531             /*Component should support this port definition*/
2532         case OMX_IndexParamImageInit:
2533             {
2534                 OMX_PORT_PARAM_TYPE *imagePortParamType =
2535                     (OMX_PORT_PARAM_TYPE *) paramData;
2536                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
2537                 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2538                 imagePortParamType->nSize = sizeof(imagePortParamType);
2539                 imagePortParamType->nPorts           = 0;
2540                 imagePortParamType->nStartPortNumber = 0;
2541                 break;
2542 
2543             }
2544             /*Component should support this port definition*/
2545         case OMX_IndexParamOtherInit:
2546             {
2547                 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
2548                         paramIndex);
2549                 eRet =OMX_ErrorUnsupportedIndex;
2550                 break;
2551             }
2552         case OMX_IndexParamStandardComponentRole:
2553             {
2554                 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2555                 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2556                 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
2557                 comp_role->nSize = sizeof(*comp_role);
2558 
2559                 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
2560                         paramIndex);
2561                 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
2562                         OMX_MAX_STRINGNAME_SIZE);
2563                 break;
2564             }
2565             /* Added for parameter test */
2566         case OMX_IndexParamPriorityMgmt:
2567             {
2568 
2569                 OMX_PRIORITYMGMTTYPE *priorityMgmType =
2570                     (OMX_PRIORITYMGMTTYPE *) paramData;
2571                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
2572                 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
2573                 priorityMgmType->nSize = sizeof(priorityMgmType);
2574 
2575                 break;
2576             }
2577             /* Added for parameter test */
2578         case OMX_IndexParamCompBufferSupplier:
2579             {
2580                 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
2581                     (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
2582                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
2583 
2584                 bufferSupplierType->nSize = sizeof(bufferSupplierType);
2585                 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
2586                 if (0 == bufferSupplierType->nPortIndex)
2587                     bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2588                 else if (1 == bufferSupplierType->nPortIndex)
2589                     bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2590                 else
2591                     eRet = OMX_ErrorBadPortIndex;
2592 
2593 
2594                 break;
2595             }
2596         case OMX_IndexParamVideoAvc:
2597             {
2598                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
2599                         paramIndex);
2600                 break;
2601             }
2602         case OMX_IndexParamVideoH263:
2603             {
2604                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
2605                         paramIndex);
2606                 break;
2607             }
2608         case OMX_IndexParamVideoMpeg4:
2609             {
2610                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
2611                         paramIndex);
2612                 break;
2613             }
2614         case OMX_IndexParamVideoMpeg2:
2615             {
2616                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
2617                         paramIndex);
2618                 break;
2619             }
2620         case OMX_IndexParamVideoProfileLevelQuerySupported:
2621             {
2622                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
2623                 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
2624                     (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
2625                 eRet = get_supported_profile_level_for_1080p(profileLevelType);
2626                 break;
2627             }
2628 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
2629         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
2630             {
2631                 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
2632                 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
2633                 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
2634 
2635                     if (secure_mode) {
2636                         nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
2637                                 GRALLOC_USAGE_PRIVATE_UNCACHED);
2638                     } else {
2639 #ifdef _HEVC_USE_ADSP_HEAP_
2640                         nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2641 #else
2642                         nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2643 #endif
2644                         DEBUG_PRINT_HIGH("nativeBuffersUsage->nUsage %x", (unsigned int)nativeBuffersUsage->nUsage);
2645                     }
2646                 } else {
2647                     DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
2648                     eRet = OMX_ErrorBadParameter;
2649                 }
2650             }
2651             break;
2652 #endif
2653 
2654         default:
2655             {
2656                 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
2657                 eRet =OMX_ErrorUnsupportedIndex;
2658             }
2659 
2660     }
2661 
2662     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
2663             drv_ctx.video_resolution.frame_width,
2664             drv_ctx.video_resolution.frame_height,
2665             drv_ctx.video_resolution.stride,
2666             drv_ctx.video_resolution.scan_lines);
2667 
2668     return eRet;
2669 }
2670 
2671 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)2672 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
2673 {
2674     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
2675     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2676     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
2677 
2678     if ((params == NULL) ||
2679             (params->nativeBuffer == NULL) ||
2680             (params->nativeBuffer->handle == NULL) ||
2681             !m_enable_android_native_buffers)
2682         return OMX_ErrorBadParameter;
2683     m_use_android_native_buffers = OMX_TRUE;
2684     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
2685     private_handle_t *handle = (private_handle_t *)nBuf->handle;
2686     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
2687         OMX_U8 *buffer = NULL;
2688         if (!secure_mode) {
2689             buffer = (OMX_U8*)mmap(0, handle->size,
2690                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
2691             if (buffer == MAP_FAILED) {
2692                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
2693                 return OMX_ErrorInsufficientResources;
2694             }
2695         }
2696         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
2697     } else {
2698         eRet = OMX_ErrorBadParameter;
2699     }
2700     return eRet;
2701 }
2702 #endif
2703 /* ======================================================================
2704    FUNCTION
2705    omx_vdec::Setparameter
2706 
2707    DESCRIPTION
2708    OMX Set Parameter method implementation.
2709 
2710    PARAMETERS
2711    <TBD>.
2712 
2713    RETURN VALUE
2714    OMX Error None if successful.
2715 
2716    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)2717 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
2718         OMX_IN OMX_INDEXTYPE paramIndex,
2719         OMX_IN OMX_PTR        paramData)
2720 {
2721     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2722     int ret=0;
2723     struct v4l2_format fmt;
2724     if (m_state == OMX_StateInvalid) {
2725         DEBUG_PRINT_ERROR("Set Param in Invalid State");
2726         return OMX_ErrorInvalidState;
2727     }
2728     if (paramData == NULL) {
2729         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
2730         return OMX_ErrorBadParameter;
2731     }
2732     if ((m_state != OMX_StateLoaded) &&
2733             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
2734             (m_out_bEnabled == OMX_TRUE) &&
2735             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
2736             (m_inp_bEnabled == OMX_TRUE)) {
2737         DEBUG_PRINT_ERROR("Set Param in Invalid State");
2738         return OMX_ErrorIncorrectStateOperation;
2739     }
2740     switch ((unsigned long)paramIndex) {
2741         case OMX_IndexParamPortDefinition:
2742             {
2743                 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2744                 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2745                 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
2746                 //been called.
2747                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
2748                         (int)portDefn->format.video.nFrameHeight,
2749                         (int)portDefn->format.video.nFrameWidth);
2750                 if (OMX_DirOutput == portDefn->eDir) {
2751                     DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
2752                     m_display_id = portDefn->format.video.pNativeWindow;
2753                     unsigned int buffer_size;
2754                     if (!client_buffers.get_buffer_req(buffer_size)) {
2755                         DEBUG_PRINT_ERROR("Error in getting buffer requirements");
2756                         eRet = OMX_ErrorBadParameter;
2757                     } else {
2758                         if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
2759                                 portDefn->nBufferSize >=  drv_ctx.op_buf.buffer_size ) {
2760                             drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
2761                             drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
2762                             eRet = set_buffer_req(&drv_ctx.op_buf);
2763                             if (eRet == OMX_ErrorNone)
2764                                 m_port_def = *portDefn;
2765                         } else {
2766                             DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%lu: %lu)",
2767                                     drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size,
2768                                     portDefn->nBufferCountActual, portDefn->nBufferSize);
2769                             eRet = OMX_ErrorBadParameter;
2770                         }
2771                     }
2772                 } else if (OMX_DirInput == portDefn->eDir) {
2773                     if ((portDefn->format.video.xFramerate >> 16) > 0 &&
2774                             (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
2775                         // Frame rate only should be set if this is a "known value" or to
2776                         // activate ts prediction logic (arbitrary mode only) sending input
2777                         // timestamps with max value (LLONG_MAX).
2778                         DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %lu",
2779                                 portDefn->format.video.xFramerate >> 16);
2780                         Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
2781                                 drv_ctx.frame_rate.fps_denominator);
2782                         if (!drv_ctx.frame_rate.fps_numerator) {
2783                             DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
2784                             drv_ctx.frame_rate.fps_numerator = 30;
2785                         }
2786                         if (drv_ctx.frame_rate.fps_denominator)
2787                             drv_ctx.frame_rate.fps_numerator = (int)
2788                                 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
2789                         drv_ctx.frame_rate.fps_denominator = 1;
2790                         frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
2791                             drv_ctx.frame_rate.fps_numerator;
2792                         DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
2793                                 frm_int, drv_ctx.frame_rate.fps_numerator /
2794                                 (float)drv_ctx.frame_rate.fps_denominator);
2795                     }
2796                     DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
2797                     if (drv_ctx.video_resolution.frame_height !=
2798                             portDefn->format.video.nFrameHeight ||
2799                             drv_ctx.video_resolution.frame_width  !=
2800                             portDefn->format.video.nFrameWidth) {
2801                         DEBUG_PRINT_LOW("SetParam IP: WxH(%d x %d)",
2802                                 portDefn->format.video.nFrameWidth,
2803                                 portDefn->format.video.nFrameHeight);
2804                         if (portDefn->format.video.nFrameHeight != 0x0 &&
2805                                 portDefn->format.video.nFrameWidth != 0x0) {
2806                             update_resolution(portDefn->format.video.nFrameWidth,
2807                                     portDefn->format.video.nFrameHeight);
2808                             fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2809                             fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2810                             fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2811                             fmt.fmt.pix_mp.pixelformat = output_capability;
2812                             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);
2813                             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2814                             if (ret) {
2815                                 DEBUG_PRINT_ERROR("Set Resolution failed");
2816                                 eRet = OMX_ErrorUnsupportedSetting;
2817                             } else
2818                                 eRet = get_buffer_req(&drv_ctx.op_buf);
2819                         }
2820                     } else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
2821                             || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
2822                         vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
2823                         drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
2824                         drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
2825                             (~(buffer_prop->alignment - 1));
2826                         eRet = set_buffer_req(buffer_prop);
2827                     } else {
2828                         DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%lu: %lu)",
2829                                 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size,
2830                                 portDefn->nBufferCountActual, portDefn->nBufferSize);
2831                         eRet = OMX_ErrorBadParameter;
2832                     }
2833                 } else if (portDefn->eDir ==  OMX_DirMax) {
2834                     DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
2835                             (int)portDefn->nPortIndex);
2836                     eRet = OMX_ErrorBadPortIndex;
2837                 }
2838             }
2839             break;
2840         case OMX_IndexParamVideoPortFormat:
2841             {
2842                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2843                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2844                 int ret=0;
2845                 struct v4l2_format fmt;
2846                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d",
2847                         portFmt->eColorFormat);
2848 
2849                 if (1 == portFmt->nPortIndex) {
2850                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2851                     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2852                     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2853                     fmt.fmt.pix_mp.pixelformat = capture_capability;
2854                     enum vdec_output_fromat op_format;
2855                     if ((portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
2856                                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) ||
2857                             (portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar))
2858                         op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
2859                     else if (portFmt->eColorFormat ==
2860                             (OMX_COLOR_FORMATTYPE)
2861                             QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka)
2862                         op_format = VDEC_YUV_FORMAT_TILE_4x2;
2863                     else
2864                         eRet = OMX_ErrorBadParameter;
2865 
2866                     if (eRet == OMX_ErrorNone) {
2867                         drv_ctx.output_format = op_format;
2868                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2869                         if (ret) {
2870                             DEBUG_PRINT_ERROR("Set output format failed");
2871                             eRet = OMX_ErrorUnsupportedSetting;
2872                             /*TODO: How to handle this case */
2873                         } else {
2874                             eRet = get_buffer_req(&drv_ctx.op_buf);
2875                         }
2876                     }
2877                     if (eRet == OMX_ErrorNone) {
2878                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
2879                             DEBUG_PRINT_ERROR("Set color format failed");
2880                             eRet = OMX_ErrorBadParameter;
2881                         }
2882                     }
2883                 }
2884             }
2885             break;
2886 
2887         case OMX_QcomIndexPortDefn:
2888             {
2889                 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
2890                     (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
2891                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d",
2892                         portFmt->nFramePackingFormat);
2893 
2894                 /* Input port */
2895                 if (portFmt->nPortIndex == 0) {
2896                     if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
2897                         if (secure_mode) {
2898                             arbitrary_bytes = false;
2899                             DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session");
2900                             eRet = OMX_ErrorUnsupportedSetting;
2901                         } else {
2902                             arbitrary_bytes = true;
2903                         }
2904                     } else if (portFmt->nFramePackingFormat ==
2905                             OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
2906                         arbitrary_bytes = false;
2907                     } else {
2908                         DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %lu",
2909                                 portFmt->nFramePackingFormat);
2910                         eRet = OMX_ErrorUnsupportedSetting;
2911                     }
2912                 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
2913                     DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
2914                     if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
2915                                 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
2916                             portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
2917                         m_out_mem_region_smi = OMX_TRUE;
2918                         if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
2919                             DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
2920                             m_use_output_pmem = OMX_TRUE;
2921                         }
2922                     }
2923                 }
2924             }
2925             break;
2926 
2927         case OMX_IndexParamStandardComponentRole:
2928             {
2929                 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2930                 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2931                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
2932                         comp_role->cRole);
2933 
2934                 if ((m_state == OMX_StateLoaded)&&
2935                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
2936                     DEBUG_PRINT_LOW("Set Parameter called in valid state");
2937                 } else {
2938                     DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
2939                     return OMX_ErrorIncorrectStateOperation;
2940                 }
2941 
2942                 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2943                     if (!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2944                         strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2945                     } else {
2946                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2947                         eRet =OMX_ErrorUnsupportedSetting;
2948                     }
2949                 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2950                     if (!strncmp((char*)comp_role->cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2951                         strlcpy((char*)m_cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2952                     } else {
2953                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2954                         eRet =OMX_ErrorUnsupportedSetting;
2955                     }
2956                 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2957                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2958                         strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
2959                     } else {
2960                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2961                         eRet = OMX_ErrorUnsupportedSetting;
2962                     }
2963                 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
2964                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
2965                         strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2966                     } else {
2967                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2968                         eRet =OMX_ErrorUnsupportedSetting;
2969                     }
2970                 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2971                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2972                         strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
2973                     } else {
2974                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2975                         eRet = OMX_ErrorUnsupportedSetting;
2976                     }
2977                 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
2978                         (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
2979                         ) {
2980                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) {
2981                         strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2982                     } else {
2983                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2984                         eRet =OMX_ErrorUnsupportedSetting;
2985                     }
2986                 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
2987                         (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
2988                         ) {
2989                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) {
2990                         strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2991                     } else {
2992                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2993                         eRet =OMX_ErrorUnsupportedSetting;
2994                     }
2995                 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
2996                     if (!strncmp((const char*)comp_role->cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
2997                             (!strncmp((const char*)comp_role->cRole,"video_decoder.vpx",OMX_MAX_STRINGNAME_SIZE))) {
2998                         strlcpy((char*)m_cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2999                     } else {
3000                         DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3001                         eRet = OMX_ErrorUnsupportedSetting;
3002                     }
3003                 } else {
3004                     DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
3005                     eRet = OMX_ErrorInvalidComponentName;
3006                 }
3007                 break;
3008             }
3009 
3010         case OMX_IndexParamPriorityMgmt:
3011             {
3012                 if (m_state != OMX_StateLoaded) {
3013                     DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
3014                     return OMX_ErrorIncorrectStateOperation;
3015                 }
3016                 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
3017                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d",
3018                         priorityMgmtype->nGroupID);
3019 
3020                 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d",
3021                         priorityMgmtype->nGroupPriority);
3022 
3023                 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
3024                 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
3025 
3026                 break;
3027             }
3028 
3029         case OMX_IndexParamCompBufferSupplier:
3030             {
3031                 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3032                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
3033                         bufferSupplierType->eBufferSupplier);
3034                 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
3035                     m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
3036 
3037                 else
3038 
3039                     eRet = OMX_ErrorBadPortIndex;
3040 
3041                 break;
3042 
3043             }
3044         case OMX_IndexParamVideoAvc:
3045             {
3046                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
3047                         paramIndex);
3048                 break;
3049             }
3050         case OMX_IndexParamVideoH263:
3051             {
3052                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
3053                         paramIndex);
3054                 break;
3055             }
3056         case OMX_IndexParamVideoMpeg4:
3057             {
3058                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
3059                         paramIndex);
3060                 break;
3061             }
3062         case OMX_IndexParamVideoMpeg2:
3063             {
3064                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
3065                         paramIndex);
3066                 break;
3067             }
3068         case OMX_QcomIndexParamVideoDecoderPictureOrder:
3069             {
3070                 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
3071                     (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
3072                 struct v4l2_control control;
3073                 int pic_order,rc=0;
3074                 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
3075                         pictureOrder->eOutputPictureOrder);
3076                 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
3077                     pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
3078                 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
3079                     pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3080                     time_stamp_dts.set_timestamp_reorder_mode(false);
3081                 } else
3082                     eRet = OMX_ErrorBadParameter;
3083                 if (eRet == OMX_ErrorNone) {
3084                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3085                     control.value = pic_order;
3086                     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3087                     if (rc) {
3088                         DEBUG_PRINT_ERROR("Set picture order failed");
3089                         eRet = OMX_ErrorUnsupportedSetting;
3090                     }
3091                 }
3092                 break;
3093             }
3094         case OMX_QcomIndexParamConcealMBMapExtraData:
3095             if (!secure_mode)
3096                 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
3097                         ((QOMX_ENABLETYPE *)paramData)->bEnable);
3098             else {
3099                 DEBUG_PRINT_ERROR("secure mode setting not supported");
3100                 eRet = OMX_ErrorUnsupportedSetting;
3101             }
3102             break;
3103         case OMX_QcomIndexParamFrameInfoExtraData:
3104             {
3105                 if (!secure_mode)
3106                     eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
3107                             ((QOMX_ENABLETYPE *)paramData)->bEnable);
3108                 else {
3109                     DEBUG_PRINT_ERROR("secure mode setting not supported");
3110                     eRet = OMX_ErrorUnsupportedSetting;
3111                 }
3112                 break;
3113             }
3114         case OMX_QcomIndexParamInterlaceExtraData:
3115             if (!secure_mode)
3116                 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
3117                         ((QOMX_ENABLETYPE *)paramData)->bEnable);
3118             else {
3119                 DEBUG_PRINT_ERROR("secure mode setting not supported");
3120                 eRet = OMX_ErrorUnsupportedSetting;
3121             }
3122             break;
3123         case OMX_QcomIndexParamH264TimeInfo:
3124             if (!secure_mode)
3125                 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
3126                         ((QOMX_ENABLETYPE *)paramData)->bEnable);
3127             else {
3128                 DEBUG_PRINT_ERROR("secure mode setting not supported");
3129                 eRet = OMX_ErrorUnsupportedSetting;
3130             }
3131             break;
3132         case OMX_QcomIndexParamVideoDivx:
3133             {
3134                 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
3135             }
3136             break;
3137         case OMX_QcomIndexPlatformPvt:
3138             {
3139                 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
3140                 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
3141                 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3142                     DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
3143                     eRet = OMX_ErrorUnsupportedSetting;
3144                 } else {
3145                     m_out_pvt_entry_pmem = OMX_TRUE;
3146                     if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
3147                         DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
3148                         m_use_output_pmem = OMX_TRUE;
3149                     }
3150                 }
3151 
3152             }
3153             break;
3154         case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
3155             {
3156                 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
3157                 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
3158                 struct v4l2_control control;
3159                 int rc;
3160                 drv_ctx.idr_only_decoding = 1;
3161                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3162                 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3163                 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3164                 if (rc) {
3165                     DEBUG_PRINT_ERROR("Set picture order failed");
3166                     eRet = OMX_ErrorUnsupportedSetting;
3167                 } else {
3168                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
3169                     control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
3170                     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3171                     if (rc) {
3172                         DEBUG_PRINT_ERROR("Sync frame setting failed");
3173                         eRet = OMX_ErrorUnsupportedSetting;
3174                     }
3175                 }
3176             }
3177             break;
3178 
3179         case OMX_QcomIndexParamIndexExtraDataType:
3180             {
3181                 if (!secure_mode) {
3182                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
3183                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
3184                             (extradataIndexType->bEnabled == OMX_TRUE) &&
3185                             (extradataIndexType->nPortIndex == 1)) {
3186                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
3187                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
3188 
3189                     }
3190                 }
3191             }
3192             break;
3193         case OMX_QcomIndexParamEnableSmoothStreaming:
3194             {
3195                 struct v4l2_control control;
3196                 struct v4l2_format fmt;
3197                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3198                 control.value = 1;
3199                 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3200                 if (rc < 0) {
3201                     DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3202                     eRet = OMX_ErrorHardware;
3203                 }
3204             }
3205             break;
3206 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3207             /* Need to allow following two set_parameters even in Idle
3208              * state. This is ANDROID architecture which is not in sync
3209              * with openmax standard. */
3210         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
3211             {
3212                 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
3213                 if (enableNativeBuffers) {
3214                     m_enable_android_native_buffers = enableNativeBuffers->enable;
3215                 }
3216             }
3217             break;
3218         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
3219             {
3220                 eRet = use_android_native_buffer(hComp, paramData);
3221             }
3222             break;
3223 #endif
3224         case OMX_QcomIndexParamEnableTimeStampReorder:
3225             {
3226                 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
3227                 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
3228                     if (reorder->bEnable == OMX_TRUE) {
3229                         frm_int =0;
3230                         time_stamp_dts.set_timestamp_reorder_mode(true);
3231                     } else
3232                         time_stamp_dts.set_timestamp_reorder_mode(false);
3233                 } else {
3234                     time_stamp_dts.set_timestamp_reorder_mode(false);
3235                     if (reorder->bEnable == OMX_TRUE) {
3236                         eRet = OMX_ErrorUnsupportedSetting;
3237                     }
3238                 }
3239             }
3240             break;
3241         default:
3242             {
3243                 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
3244                 eRet = OMX_ErrorUnsupportedIndex;
3245             }
3246     }
3247     return eRet;
3248 }
3249 
3250 /* ======================================================================
3251    FUNCTION
3252    omx_vdec::GetConfig
3253 
3254    DESCRIPTION
3255    OMX Get Config Method implementation.
3256 
3257    PARAMETERS
3258    <TBD>.
3259 
3260    RETURN VALUE
3261    OMX Error None if successful.
3262 
3263    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)3264 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
3265         OMX_IN OMX_INDEXTYPE configIndex,
3266         OMX_INOUT OMX_PTR     configData)
3267 {
3268     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3269 
3270     if (m_state == OMX_StateInvalid) {
3271         DEBUG_PRINT_ERROR("Get Config in Invalid State");
3272         return OMX_ErrorInvalidState;
3273     }
3274 
3275     switch ((unsigned long)configIndex) {
3276         case OMX_QcomIndexConfigInterlaced:
3277             {
3278                 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
3279                     (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
3280                 if (configFmt->nPortIndex == 1) {
3281                     if (configFmt->nIndex == 0) {
3282                         configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
3283                     } else if (configFmt->nIndex == 1) {
3284                         configFmt->eInterlaceType =
3285                             OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
3286                     } else if (configFmt->nIndex == 2) {
3287                         configFmt->eInterlaceType =
3288                             OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
3289                     } else {
3290                         DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
3291                                 " NoMore Interlaced formats");
3292                         eRet = OMX_ErrorNoMore;
3293                     }
3294 
3295                 } else {
3296                     DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
3297                             (int)configFmt->nPortIndex);
3298                     eRet = OMX_ErrorBadPortIndex;
3299                 }
3300                 break;
3301             }
3302         case OMX_QcomIndexQueryNumberOfVideoDecInstance:
3303             {
3304                 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
3305                     (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
3306                 decoderinstances->nNumOfInstances = 16;
3307                 /*TODO: How to handle this case */
3308                 break;
3309             }
3310         case OMX_QcomIndexConfigVideoFramePackingArrangement:
3311             {
3312                 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
3313                     OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
3314                         (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
3315                     h264_parser->get_frame_pack_data(configFmt);
3316                 } else {
3317                     DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
3318                 }
3319                 break;
3320             }
3321         case OMX_IndexConfigCommonOutputCrop:
3322             {
3323                 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
3324                 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
3325                 break;
3326             }
3327         default:
3328             {
3329                 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
3330                 eRet = OMX_ErrorBadParameter;
3331             }
3332 
3333     }
3334 
3335     return eRet;
3336 }
3337 
3338 /* ======================================================================
3339    FUNCTION
3340    omx_vdec::SetConfig
3341 
3342    DESCRIPTION
3343    OMX Set Config method implementation
3344 
3345    PARAMETERS
3346    <TBD>.
3347 
3348    RETURN VALUE
3349    OMX Error None if successful.
3350    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)3351 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
3352         OMX_IN OMX_INDEXTYPE configIndex,
3353         OMX_IN OMX_PTR        configData)
3354 {
3355     if (m_state == OMX_StateInvalid) {
3356         DEBUG_PRINT_ERROR("Get Config in Invalid State");
3357         return OMX_ErrorInvalidState;
3358     }
3359 
3360     OMX_ERRORTYPE ret = OMX_ErrorNone;
3361     OMX_VIDEO_CONFIG_NALSIZE *pNal;
3362 
3363     DEBUG_PRINT_LOW("Set Config Called");
3364 
3365     if (m_state == OMX_StateExecuting) {
3366         DEBUG_PRINT_ERROR("set_config:Ignore in Exe state");
3367         return ret;
3368     }
3369 
3370     if (configIndex == (OMX_INDEXTYPE)OMX_IndexVendorVideoExtraData) {
3371         OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData;
3372         DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called");
3373         if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc")) {
3374             DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData AVC");
3375             OMX_U32 extra_size;
3376             // Parsing done here for the AVC atom is definitely not generic
3377             // Currently this piece of code is working, but certainly
3378             // not tested with all .mp4 files.
3379             // Incase of failure, we might need to revisit this
3380             // for a generic piece of code.
3381 
3382             // Retrieve size of NAL length field
3383             // byte #4 contains the size of NAL lenght field
3384             nal_length = (config->pData[4] & 0x03) + 1;
3385 
3386             extra_size = 0;
3387             if (nal_length > 2) {
3388                 /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
3389                 extra_size = (nal_length - 2) * 2;
3390             }
3391 
3392             // SPS starts from byte #6
3393             OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
3394             OMX_U8 *pDestBuf;
3395             m_vendor_config.nPortIndex = config->nPortIndex;
3396 
3397             // minus 6 --> SPS starts from byte #6
3398             // minus 1 --> picture param set byte to be ignored from avcatom
3399             m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size;
3400             m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize);
3401             OMX_U32 len;
3402             OMX_U8 index = 0;
3403             // case where SPS+PPS is sent as part of set_config
3404             pDestBuf = m_vendor_config.pData;
3405 
3406             DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]",
3407                     m_vendor_config.nPortIndex,
3408                     m_vendor_config.nDataSize,
3409                     m_vendor_config.pData);
3410             while (index < 2) {
3411                 uint8 *psize;
3412                 len = *pSrcBuf;
3413                 len = len << 8;
3414                 len |= *(pSrcBuf + 1);
3415                 psize = (uint8 *) & len;
3416                 memcpy(pDestBuf + nal_length, pSrcBuf + 2,len);
3417                 for (unsigned int i = 0; i < nal_length; i++) {
3418                     pDestBuf[i] = psize[nal_length - 1 - i];
3419                 }
3420                 //memcpy(pDestBuf,pSrcBuf,(len+2));
3421                 pDestBuf += len + nal_length;
3422                 pSrcBuf += len + 2;
3423                 index++;
3424                 pSrcBuf++;   // skip picture param set
3425                 len = 0;
3426             }
3427         } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") ||
3428                 !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) {
3429             m_vendor_config.nPortIndex = config->nPortIndex;
3430             m_vendor_config.nDataSize = config->nDataSize;
3431             m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize));
3432             memcpy(m_vendor_config.pData, config->pData,config->nDataSize);
3433         } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) {
3434             if (m_vendor_config.pData) {
3435                 free(m_vendor_config.pData);
3436                 m_vendor_config.pData = NULL;
3437                 m_vendor_config.nDataSize = 0;
3438             }
3439 
3440             if (((*((OMX_U32 *) config->pData)) &
3441                         VC1_SP_MP_START_CODE_MASK) ==
3442                     VC1_SP_MP_START_CODE) {
3443                 DEBUG_PRINT_LOW("set_config - VC1 simple/main profile");
3444                 m_vendor_config.nPortIndex = config->nPortIndex;
3445                 m_vendor_config.nDataSize = config->nDataSize;
3446                 m_vendor_config.pData =
3447                     (OMX_U8 *) malloc(config->nDataSize);
3448                 memcpy(m_vendor_config.pData, config->pData,
3449                         config->nDataSize);
3450                 m_vc1_profile = VC1_SP_MP_RCV;
3451             } else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) {
3452                 DEBUG_PRINT_LOW("set_config - VC1 Advance profile");
3453                 m_vendor_config.nPortIndex = config->nPortIndex;
3454                 m_vendor_config.nDataSize = config->nDataSize;
3455                 m_vendor_config.pData =
3456                     (OMX_U8 *) malloc((config->nDataSize));
3457                 memcpy(m_vendor_config.pData, config->pData,
3458                         config->nDataSize);
3459                 m_vc1_profile = VC1_AP;
3460             } else if ((config->nDataSize == VC1_STRUCT_C_LEN)) {
3461                 DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only");
3462                 m_vendor_config.nPortIndex = config->nPortIndex;
3463                 m_vendor_config.nDataSize  = config->nDataSize;
3464                 m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
3465                 memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
3466                 m_vc1_profile = VC1_SP_MP_RCV;
3467             } else {
3468                 DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile");
3469             }
3470         }
3471         return ret;
3472     } else if (configIndex == OMX_IndexConfigVideoNalSize) {
3473 
3474         pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
3475         nal_length = pNal->nNaluBytes;
3476         m_frame_parser.init_nal_length(nal_length);
3477         DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d",nal_length);
3478         return ret;
3479     }
3480 
3481     return OMX_ErrorNotImplemented;
3482 }
3483 
3484 /* ======================================================================
3485    FUNCTION
3486    omx_vdec::GetExtensionIndex
3487 
3488    DESCRIPTION
3489    OMX GetExtensionIndex method implementaion.  <TBD>
3490 
3491    PARAMETERS
3492    <TBD>.
3493 
3494    RETURN VALUE
3495    OMX Error None if everything successful.
3496 
3497    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)3498 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
3499         OMX_IN OMX_STRING      paramName,
3500         OMX_OUT OMX_INDEXTYPE* indexType)
3501 {
3502     if (m_state == OMX_StateInvalid) {
3503         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
3504         return OMX_ErrorInvalidState;
3505     } else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) {
3506         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
3507     } else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) {
3508         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
3509     }
3510 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3511     else if (!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
3512         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
3513     } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
3514         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
3515     } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
3516         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
3517         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
3518     } else if (!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
3519         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
3520     }
3521 #endif
3522     else {
3523         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
3524         return OMX_ErrorNotImplemented;
3525     }
3526     return OMX_ErrorNone;
3527 }
3528 
3529 /* ======================================================================
3530    FUNCTION
3531    omx_vdec::GetState
3532 
3533    DESCRIPTION
3534    Returns the state information back to the caller.<TBD>
3535 
3536    PARAMETERS
3537    <TBD>.
3538 
3539    RETURN VALUE
3540    Error None if everything is successful.
3541    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)3542 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
3543         OMX_OUT OMX_STATETYPE* state)
3544 {
3545     *state = m_state;
3546     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
3547     return OMX_ErrorNone;
3548 }
3549 
3550 /* ======================================================================
3551    FUNCTION
3552    omx_vdec::ComponentTunnelRequest
3553 
3554    DESCRIPTION
3555    OMX Component Tunnel Request method implementation. <TBD>
3556 
3557    PARAMETERS
3558    None.
3559 
3560    RETURN VALUE
3561    OMX Error None if everything successful.
3562 
3563    ========================================================================== */
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)3564 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE                hComp,
3565         OMX_IN OMX_U32                        port,
3566         OMX_IN OMX_HANDLETYPE        peerComponent,
3567         OMX_IN OMX_U32                    peerPort,
3568         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
3569 {
3570     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
3571     return OMX_ErrorNotImplemented;
3572 }
3573 
3574 /* ======================================================================
3575    FUNCTION
3576    omx_vdec::UseOutputBuffer
3577 
3578    DESCRIPTION
3579    Helper function for Use buffer in the input pin
3580 
3581    PARAMETERS
3582    None.
3583 
3584    RETURN VALUE
3585    true/false
3586 
3587    ========================================================================== */
allocate_extradata()3588 OMX_ERRORTYPE omx_vdec::allocate_extradata()
3589 {
3590 #ifdef USE_ION
3591     if (drv_ctx.extradata_info.buffer_size) {
3592         if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
3593             munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
3594             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3595             free_ion_memory(&drv_ctx.extradata_info.ion);
3596         }
3597         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
3598         DEBUG_PRINT_HIGH("allocate extradata memory size %d", drv_ctx.extradata_info.size);
3599         drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
3600                 drv_ctx.extradata_info.size, 4096,
3601                 &drv_ctx.extradata_info.ion.ion_alloc_data,
3602                 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
3603         if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
3604             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
3605             return OMX_ErrorInsufficientResources;
3606         }
3607         drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
3608                 drv_ctx.extradata_info.size,
3609                 PROT_READ|PROT_WRITE, MAP_SHARED,
3610                 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
3611         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
3612             DEBUG_PRINT_ERROR("Failed to map extradata memory");
3613             close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3614             free_ion_memory(&drv_ctx.extradata_info.ion);
3615             return OMX_ErrorInsufficientResources;
3616         }
3617         memset(drv_ctx.extradata_info.uaddr, 0, drv_ctx.extradata_info.size);
3618     }
3619 #endif
3620     return OMX_ErrorNone;
3621 }
3622 
free_extradata()3623 void omx_vdec::free_extradata()
3624 {
3625 #ifdef USE_ION
3626     if (drv_ctx.extradata_info.uaddr) {
3627         munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
3628         close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3629         free_ion_memory(&drv_ctx.extradata_info.ion);
3630     }
3631     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
3632 #endif
3633 }
3634 
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)3635 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
3636         OMX_IN OMX_HANDLETYPE            hComp,
3637         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3638         OMX_IN OMX_U32                   port,
3639         OMX_IN OMX_PTR                   appData,
3640         OMX_IN OMX_U32                   bytes,
3641         OMX_IN OMX_U8*                   buffer)
3642 {
3643     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3644     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
3645     unsigned                         i= 0; // Temporary counter
3646     struct vdec_setbuffer_cmd setbuffers;
3647     OMX_PTR privateAppData = NULL;
3648     private_handle_t *handle = NULL;
3649     OMX_U8 *buff = buffer;
3650     struct v4l2_buffer buf;
3651     struct v4l2_plane plane[VIDEO_MAX_PLANES];
3652     int extra_idx = 0;
3653 
3654     if (!m_out_mem_ptr) {
3655         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
3656         eRet = allocate_output_headers();
3657         if (eRet == OMX_ErrorNone)
3658             eRet = allocate_extradata();
3659     }
3660 
3661     if (eRet == OMX_ErrorNone) {
3662         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
3663             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
3664                 break;
3665             }
3666         }
3667     }
3668 
3669     if (i >= drv_ctx.op_buf.actualcount) {
3670         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
3671         eRet = OMX_ErrorInsufficientResources;
3672     }
3673 
3674     if (eRet == OMX_ErrorNone) {
3675 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
3676         if (m_enable_android_native_buffers) {
3677             if (m_use_android_native_buffers) {
3678                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
3679                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3680                 handle = (private_handle_t *)nBuf->handle;
3681                 privateAppData = params->pAppPrivate;
3682             } else {
3683                 handle = (private_handle_t *)buff;
3684                 privateAppData = appData;
3685             }
3686 
3687             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
3688                 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
3689                         " expected %u, got %lu",
3690                         drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size);
3691                 return OMX_ErrorBadParameter;
3692             }
3693 
3694             drv_ctx.op_buf.buffer_size = (OMX_U32)handle->size;
3695             if (!m_use_android_native_buffers) {
3696                 if (!secure_mode) {
3697                     buff =  (OMX_U8*)mmap(0, handle->size,
3698                             PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3699                     if (buff == MAP_FAILED) {
3700                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3701                         return OMX_ErrorInsufficientResources;
3702                     }
3703                 }
3704             }
3705 #if defined(_ANDROID_ICS_)
3706             native_buffer[i].nativehandle = handle;
3707             native_buffer[i].privatehandle = handle;
3708 #endif
3709             if (!handle) {
3710                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
3711                 return OMX_ErrorBadParameter;
3712             }
3713             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
3714             drv_ctx.ptr_outputbuffer[i].offset = 0;
3715             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3716             drv_ctx.ptr_outputbuffer[i].mmaped_size =
3717                 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3718         } else
3719 #endif
3720 
3721             if (!ouput_egl_buffers && !m_use_output_pmem) {
3722 #ifdef USE_ION
3723                 DEBUG_PRINT_HIGH("allocate output buffer memory size %d", drv_ctx.op_buf.buffer_size);
3724                 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
3725                         drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
3726                         &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
3727                         &drv_ctx.op_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0);
3728                 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
3729                     DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
3730                     return OMX_ErrorInsufficientResources;
3731                 }
3732                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3733                                                       drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
3734 #else
3735                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3736                                                       open (MEM_DEVICE,O_RDWR);
3737 
3738                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3739                     DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
3740                     return OMX_ErrorInsufficientResources;
3741                 }
3742 
3743                 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
3744                 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
3745                     drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3746                                                           open (MEM_DEVICE,O_RDWR);
3747                     if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3748                         DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
3749                         return OMX_ErrorInsufficientResources;
3750                     }
3751                 }
3752 
3753                 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
3754                             drv_ctx.op_buf.buffer_size,
3755                             drv_ctx.op_buf.alignment)) {
3756                     DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
3757                     close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3758                     return OMX_ErrorInsufficientResources;
3759                 }
3760 #endif
3761                 if (!secure_mode) {
3762                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
3763                         (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
3764                                 PROT_READ|PROT_WRITE, MAP_SHARED,
3765                                 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
3766                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
3767                         close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3768 #ifdef USE_ION
3769                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
3770 #endif
3771                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
3772                         return OMX_ErrorInsufficientResources;
3773                     }
3774                 }
3775                 drv_ctx.ptr_outputbuffer[i].offset = 0;
3776                 privateAppData = appData;
3777             } else {
3778 
3779                 DEBUG_PRINT_HIGH("Use_op_buf: out_pmem=%d",m_use_output_pmem);
3780                 if (!appData || !bytes ) {
3781                     if (!secure_mode && !buffer) {
3782                         DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
3783                         return OMX_ErrorBadParameter;
3784                     }
3785                 }
3786 
3787                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
3788                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
3789                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
3790                 if (!pmem_list->entryList || !pmem_list->entryList->entry ||
3791                         !pmem_list->nEntries ||
3792                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3793                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
3794                     return OMX_ErrorBadParameter;
3795                 }
3796                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
3797                     pmem_list->entryList->entry;
3798                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x",
3799                         pmem_info->pmem_fd);
3800                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
3801                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
3802                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3803                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
3804                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3805                 privateAppData = appData;
3806             }
3807         m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
3808         m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
3809 
3810         *bufferHdr = (m_out_mem_ptr + i );
3811         if (secure_mode)
3812             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
3813         //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
3814         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
3815                 sizeof (vdec_bufferpayload));
3816 
3817         DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
3818                 drv_ctx.ptr_outputbuffer[i].bufferaddr,
3819                 drv_ctx.ptr_outputbuffer[i].pmem_fd );
3820 
3821         buf.index = i;
3822         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3823         buf.memory = V4L2_MEMORY_USERPTR;
3824         plane[0].length = drv_ctx.op_buf.buffer_size;
3825         plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
3826             (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
3827         plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
3828         plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
3829         plane[0].data_offset = 0;
3830         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
3831         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
3832             plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
3833             plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
3834 #ifdef USE_ION
3835             plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
3836 #endif
3837             plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
3838             plane[extra_idx].data_offset = 0;
3839         } else if  (extra_idx >= VIDEO_MAX_PLANES) {
3840             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
3841             return OMX_ErrorBadParameter;
3842         }
3843         buf.m.planes = plane;
3844         buf.length = drv_ctx.num_planes;
3845 
3846         DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
3847 
3848         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
3849             DEBUG_PRINT_ERROR("Failed to prepare bufs");
3850             /*TODO: How to handle this case */
3851             return OMX_ErrorInsufficientResources;
3852         }
3853 
3854         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
3855             enum v4l2_buf_type buf_type;
3856             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3857             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
3858                 return OMX_ErrorInsufficientResources;
3859             } else {
3860                 streaming[CAPTURE_PORT] = true;
3861                 DEBUG_PRINT_LOW("STREAMON Successful");
3862             }
3863         }
3864 
3865         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
3866         if (m_enable_android_native_buffers) {
3867             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
3868             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
3869         } else {
3870             (*bufferHdr)->pBuffer = buff;
3871         }
3872         (*bufferHdr)->pAppPrivate = privateAppData;
3873         BITMASK_SET(&m_out_bm_count,i);
3874     }
3875     return eRet;
3876 }
3877 
3878 /* ======================================================================
3879    FUNCTION
3880    omx_vdec::use_input_heap_buffers
3881 
3882    DESCRIPTION
3883    OMX Use Buffer Heap allocation method implementation.
3884 
3885    PARAMETERS
3886    <TBD>.
3887 
3888    RETURN VALUE
3889    OMX Error None , if everything successful.
3890 
3891    ========================================================================== */
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)3892 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
3893         OMX_IN OMX_HANDLETYPE            hComp,
3894         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3895         OMX_IN OMX_U32                   port,
3896         OMX_IN OMX_PTR                   appData,
3897         OMX_IN OMX_U32                   bytes,
3898         OMX_IN OMX_U8*                   buffer)
3899 {
3900     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
3901     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3902     if (!m_inp_heap_ptr)
3903         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
3904             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
3905                     drv_ctx.ip_buf.actualcount);
3906     if (!m_phdr_pmem_ptr)
3907         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
3908             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
3909                     drv_ctx.ip_buf.actualcount);
3910     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
3911         DEBUG_PRINT_ERROR("Insufficent memory");
3912         eRet = OMX_ErrorInsufficientResources;
3913     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
3914         input_use_buffer = true;
3915         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
3916         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
3917         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
3918         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
3919         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
3920         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
3921         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
3922         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
3923         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
3924         if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt],
3925                     (unsigned)NULL, (unsigned)NULL)) {
3926             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
3927             return OMX_ErrorInsufficientResources;
3928         }
3929         m_in_alloc_cnt++;
3930     } else {
3931         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
3932         eRet = OMX_ErrorInsufficientResources;
3933     }
3934     return eRet;
3935 }
3936 
3937 /* ======================================================================
3938    FUNCTION
3939    omx_vdec::UseBuffer
3940 
3941    DESCRIPTION
3942    OMX Use Buffer method implementation.
3943 
3944    PARAMETERS
3945    <TBD>.
3946 
3947    RETURN VALUE
3948    OMX Error None , if everything successful.
3949 
3950    ========================================================================== */
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)3951 OMX_ERRORTYPE  omx_vdec::use_buffer(
3952         OMX_IN OMX_HANDLETYPE            hComp,
3953         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3954         OMX_IN OMX_U32                   port,
3955         OMX_IN OMX_PTR                   appData,
3956         OMX_IN OMX_U32                   bytes,
3957         OMX_IN OMX_U8*                   buffer)
3958 {
3959     OMX_ERRORTYPE error = OMX_ErrorNone;
3960     struct vdec_setbuffer_cmd setbuffers;
3961 
3962     if (bufferHdr == NULL || bytes == 0) {
3963         if (!secure_mode && buffer == NULL) {
3964             DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer);
3965             return OMX_ErrorBadParameter;
3966         }
3967     }
3968     if (m_state == OMX_StateInvalid) {
3969         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
3970         return OMX_ErrorInvalidState;
3971     }
3972     if (port == OMX_CORE_INPUT_PORT_INDEX)
3973         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
3974     else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
3975         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
3976     else {
3977         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
3978         error = OMX_ErrorBadPortIndex;
3979     }
3980     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error);
3981     if (error == OMX_ErrorNone) {
3982         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
3983             // Send the callback now
3984             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
3985             post_event(OMX_CommandStateSet,OMX_StateIdle,
3986                     OMX_COMPONENT_GENERATE_EVENT);
3987         }
3988         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
3989                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
3990             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
3991             post_event(OMX_CommandPortEnable,
3992                     OMX_CORE_INPUT_PORT_INDEX,
3993                     OMX_COMPONENT_GENERATE_EVENT);
3994         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
3995                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
3996             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3997             post_event(OMX_CommandPortEnable,
3998                     OMX_CORE_OUTPUT_PORT_INDEX,
3999                     OMX_COMPONENT_GENERATE_EVENT);
4000         }
4001     }
4002     return error;
4003 }
4004 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)4005 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
4006         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
4007 {
4008     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
4009         if (m_inp_heap_ptr[bufferindex].pBuffer)
4010             free(m_inp_heap_ptr[bufferindex].pBuffer);
4011         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
4012     }
4013     if (pmem_bufferHdr)
4014         free_input_buffer(pmem_bufferHdr);
4015     return OMX_ErrorNone;
4016 }
4017 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4018 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4019 {
4020     unsigned int index = 0;
4021     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
4022         return OMX_ErrorBadParameter;
4023     }
4024 
4025     index = bufferHdr - m_inp_mem_ptr;
4026     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
4027 
4028     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
4029         DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
4030         if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) {
4031             struct vdec_setbuffer_cmd setbuffers;
4032             setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
4033             memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
4034                     sizeof (vdec_bufferpayload));
4035             DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
4036                     drv_ctx.ptr_inputbuffer[index].pmem_fd);
4037             DEBUG_PRINT_LOW("unmap the input buffer size=%d  address = %d",
4038                     drv_ctx.ptr_inputbuffer[index].mmaped_size,
4039                     drv_ctx.ptr_inputbuffer[index].bufferaddr);
4040             munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
4041                     drv_ctx.ptr_inputbuffer[index].mmaped_size);
4042             close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
4043             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
4044             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
4045                 free(m_desc_buffer_ptr[index].buf_addr);
4046                 m_desc_buffer_ptr[index].buf_addr = NULL;
4047                 m_desc_buffer_ptr[index].desc_data_size = 0;
4048             }
4049 #ifdef USE_ION
4050             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
4051 #endif
4052         }
4053     }
4054 
4055     return OMX_ErrorNone;
4056 }
4057 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4058 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4059 {
4060     unsigned int index = 0;
4061 
4062     if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
4063         return OMX_ErrorBadParameter;
4064     }
4065 
4066     index = bufferHdr - m_out_mem_ptr;
4067     DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
4068 
4069     if (index < drv_ctx.op_buf.actualcount
4070             && drv_ctx.ptr_outputbuffer) {
4071         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %x", index,
4072                 drv_ctx.ptr_outputbuffer[index].bufferaddr);
4073 
4074         struct vdec_setbuffer_cmd setbuffers;
4075         setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
4076         memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
4077                 sizeof (vdec_bufferpayload));
4078 #ifdef _ANDROID_
4079         if (m_enable_android_native_buffers) {
4080             if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
4081                 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
4082                         drv_ctx.ptr_outputbuffer[index].mmaped_size);
4083             }
4084             drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
4085         } else {
4086 #endif
4087             if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
4088                 DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
4089                         drv_ctx.ptr_outputbuffer[0].pmem_fd);
4090                 DEBUG_PRINT_LOW("unmap the ouput buffer size=%d  address = %d",
4091                         drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
4092                         drv_ctx.ptr_outputbuffer[0].bufferaddr);
4093                 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
4094                         drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
4095                 close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
4096                 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
4097 #ifdef USE_ION
4098                 free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
4099 #endif
4100             }
4101 #ifdef _ANDROID_
4102         }
4103 #endif
4104         if (release_output_done()) {
4105             free_extradata();
4106         }
4107     }
4108 
4109     return OMX_ErrorNone;
4110 
4111 }
4112 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)4113 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
4114         OMX_BUFFERHEADERTYPE **bufferHdr,
4115         OMX_U32              port,
4116         OMX_PTR              appData,
4117         OMX_U32              bytes)
4118 {
4119     OMX_BUFFERHEADERTYPE *input = NULL;
4120     unsigned char *buf_addr = NULL;
4121     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4122     unsigned   i = 0;
4123 
4124     /* Sanity Check*/
4125     if (bufferHdr == NULL) {
4126         return OMX_ErrorBadParameter;
4127     }
4128 
4129     if (m_inp_heap_ptr == NULL) {
4130         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
4131                          calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4132                                  drv_ctx.ip_buf.actualcount);
4133         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
4134                           calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4135                                   drv_ctx.ip_buf.actualcount);
4136 
4137         if (m_inp_heap_ptr == NULL) {
4138             DEBUG_PRINT_ERROR("m_inp_heap_ptr Allocation failed ");
4139             return OMX_ErrorInsufficientResources;
4140         }
4141     }
4142 
4143     /*Find a Free index*/
4144     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
4145         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
4146             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
4147             break;
4148         }
4149     }
4150 
4151     if (i < drv_ctx.ip_buf.actualcount) {
4152         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
4153 
4154         if (buf_addr == NULL) {
4155             return OMX_ErrorInsufficientResources;
4156         }
4157 
4158         *bufferHdr = (m_inp_heap_ptr + i);
4159         input = *bufferHdr;
4160         BITMASK_SET(&m_heap_inp_bm_count,i);
4161 
4162         input->pBuffer           = (OMX_U8 *)buf_addr;
4163         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
4164         input->nVersion.nVersion = OMX_SPEC_VERSION;
4165         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
4166         input->pAppPrivate       = appData;
4167         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
4168         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
4169         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
4170         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
4171         /*Add the Buffers to freeq*/
4172         if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[i],
4173                     (unsigned)NULL, (unsigned)NULL)) {
4174             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
4175             return OMX_ErrorInsufficientResources;
4176         }
4177     } else {
4178         return OMX_ErrorBadParameter;
4179     }
4180 
4181     return eRet;
4182 
4183 }
4184 
4185 
4186 /* ======================================================================
4187    FUNCTION
4188    omx_vdec::AllocateInputBuffer
4189 
4190    DESCRIPTION
4191    Helper function for allocate buffer in the input pin
4192 
4193    PARAMETERS
4194    None.
4195 
4196    RETURN VALUE
4197    true/false
4198 
4199    ========================================================================== */
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)4200 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
4201         OMX_IN OMX_HANDLETYPE            hComp,
4202         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4203         OMX_IN OMX_U32                   port,
4204         OMX_IN OMX_PTR                   appData,
4205         OMX_IN OMX_U32                   bytes)
4206 {
4207 
4208     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4209     struct vdec_setbuffer_cmd setbuffers;
4210     OMX_BUFFERHEADERTYPE *input = NULL;
4211     unsigned   i = 0;
4212     unsigned char *buf_addr = NULL;
4213     int pmem_fd = -1;
4214 
4215     if (bytes != drv_ctx.ip_buf.buffer_size) {
4216         DEBUG_PRINT_LOW("Requested Size is wrong %d epected is %d",
4217                 bytes, drv_ctx.ip_buf.buffer_size);
4218         return OMX_ErrorBadParameter;
4219     }
4220 
4221     if (!m_inp_mem_ptr) {
4222         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
4223                 drv_ctx.ip_buf.actualcount,
4224                 drv_ctx.ip_buf.buffer_size);
4225 
4226         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4227                         calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4228 
4229         if (m_inp_mem_ptr == NULL) {
4230             return OMX_ErrorInsufficientResources;
4231         }
4232 
4233         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
4234                                   calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
4235 
4236         if (drv_ctx.ptr_inputbuffer == NULL) {
4237             return OMX_ErrorInsufficientResources;
4238         }
4239 #ifdef USE_ION
4240         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
4241                                   calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
4242 
4243         if (drv_ctx.ip_buf_ion_info == NULL) {
4244             return OMX_ErrorInsufficientResources;
4245         }
4246 #endif
4247 
4248         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
4249             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
4250 #ifdef USE_ION
4251             drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
4252 #endif
4253         }
4254     }
4255 
4256     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
4257         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
4258             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
4259             break;
4260         }
4261     }
4262 
4263     if (i < drv_ctx.ip_buf.actualcount) {
4264         struct v4l2_buffer buf;
4265         struct v4l2_plane plane;
4266         int rc;
4267 
4268 #ifdef USE_ION
4269         DEBUG_PRINT_HIGH("Allocate input Buffer size %d", drv_ctx.ip_buf.buffer_size);
4270         drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
4271                 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
4272                 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
4273                 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0);
4274         if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
4275             return OMX_ErrorInsufficientResources;
4276         }
4277         pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
4278 #else
4279         pmem_fd = open (MEM_DEVICE,O_RDWR);
4280 
4281         if (pmem_fd < 0) {
4282             DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
4283             return OMX_ErrorInsufficientResources;
4284         }
4285 
4286         if (pmem_fd == 0) {
4287             pmem_fd = open (MEM_DEVICE,O_RDWR);
4288 
4289             if (pmem_fd < 0) {
4290                 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
4291                 return OMX_ErrorInsufficientResources;
4292             }
4293         }
4294 
4295         if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
4296                     drv_ctx.ip_buf.alignment)) {
4297             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
4298             close(pmem_fd);
4299             return OMX_ErrorInsufficientResources;
4300         }
4301 #endif
4302         if (!secure_mode) {
4303             buf_addr = (unsigned char *)mmap(NULL,
4304                     drv_ctx.ip_buf.buffer_size,
4305                     PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
4306 
4307             if (buf_addr == MAP_FAILED) {
4308                 close(pmem_fd);
4309 #ifdef USE_ION
4310                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
4311 #endif
4312                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
4313                 return OMX_ErrorInsufficientResources;
4314             }
4315         }
4316         *bufferHdr = (m_inp_mem_ptr + i);
4317         if (secure_mode)
4318             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
4319         else
4320             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
4321         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
4322         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4323         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
4324         drv_ctx.ptr_inputbuffer [i].offset = 0;
4325 
4326 
4327         buf.index = i;
4328         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4329         buf.memory = V4L2_MEMORY_USERPTR;
4330         plane.bytesused = 0;
4331         plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
4332         plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
4333         plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
4334         plane.reserved[1] = 0;
4335         plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
4336         buf.m.planes = &plane;
4337         buf.length = 1;
4338 
4339         DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_inputbuffer[i]);
4340 
4341         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4342 
4343         if (rc) {
4344             DEBUG_PRINT_ERROR("Failed to prepare bufs");
4345             /*TODO: How to handle this case */
4346             return OMX_ErrorInsufficientResources;
4347         }
4348 
4349         input = *bufferHdr;
4350         BITMASK_SET(&m_inp_bm_count,i);
4351         DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
4352         if (secure_mode)
4353             input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd;
4354         else
4355             input->pBuffer           = (OMX_U8 *)buf_addr;
4356         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
4357         input->nVersion.nVersion = OMX_SPEC_VERSION;
4358         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
4359         input->pAppPrivate       = appData;
4360         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
4361         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
4362 
4363         if (drv_ctx.disable_dmx) {
4364             eRet = allocate_desc_buffer(i);
4365         }
4366     } else {
4367         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
4368         eRet = OMX_ErrorInsufficientResources;
4369     }
4370     return eRet;
4371 }
4372 
4373 
4374 /* ======================================================================
4375    FUNCTION
4376    omx_vdec::AllocateOutputBuffer
4377 
4378    DESCRIPTION
4379    Helper fn for AllocateBuffer in the output pin
4380 
4381    PARAMETERS
4382    <TBD>.
4383 
4384    RETURN VALUE
4385    OMX Error None if everything went well.
4386 
4387    ========================================================================== */
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)4388 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
4389         OMX_IN OMX_HANDLETYPE            hComp,
4390         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4391         OMX_IN OMX_U32                   port,
4392         OMX_IN OMX_PTR                   appData,
4393         OMX_IN OMX_U32                   bytes)
4394 {
4395     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4396     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
4397     unsigned                         i= 0; // Temporary counter
4398     struct vdec_setbuffer_cmd setbuffers;
4399     int extra_idx = 0;
4400 #ifdef USE_ION
4401     int ion_device_fd =-1;
4402     struct ion_allocation_data ion_alloc_data;
4403     struct ion_fd_data fd_ion_data;
4404 #endif
4405     if (!m_out_mem_ptr) {
4406         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%d)",
4407                 drv_ctx.op_buf.actualcount,
4408                 drv_ctx.op_buf.buffer_size);
4409         int nBufHdrSize        = 0;
4410         int nPlatformEntrySize = 0;
4411         int nPlatformListSize  = 0;
4412         int nPMEMInfoSize = 0;
4413         int pmem_fd = -1;
4414         unsigned char *pmem_baseaddress = NULL;
4415 
4416         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
4417         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
4418         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
4419 
4420         DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
4421                 drv_ctx.op_buf.actualcount);
4422         nBufHdrSize        = drv_ctx.op_buf.actualcount *
4423             sizeof(OMX_BUFFERHEADERTYPE);
4424 
4425         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
4426             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
4427         nPlatformListSize  = drv_ctx.op_buf.actualcount *
4428             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
4429         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
4430             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
4431 
4432         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize,
4433                 sizeof(OMX_BUFFERHEADERTYPE),
4434                 nPMEMInfoSize,
4435                 nPlatformListSize);
4436         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
4437                 drv_ctx.op_buf.actualcount);
4438 #ifdef USE_ION
4439         DEBUG_PRINT_HIGH("allocate outputBuffer size %d",drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount);
4440         ion_device_fd = alloc_map_ion_memory(
4441                 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
4442                 drv_ctx.op_buf.alignment,
4443                 &ion_alloc_data, &fd_ion_data, secure_mode ? ION_SECURE : 0);
4444         if (ion_device_fd < 0) {
4445             return OMX_ErrorInsufficientResources;
4446         }
4447         pmem_fd = fd_ion_data.fd;
4448 #else
4449         pmem_fd = open (MEM_DEVICE,O_RDWR);
4450 
4451         if (pmem_fd < 0) {
4452             DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
4453                     drv_ctx.op_buf.buffer_size);
4454             return OMX_ErrorInsufficientResources;
4455         }
4456 
4457         if (pmem_fd == 0) {
4458             pmem_fd = open (MEM_DEVICE,O_RDWR);
4459 
4460             if (pmem_fd < 0) {
4461                 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
4462                         drv_ctx.op_buf.buffer_size);
4463                 return OMX_ErrorInsufficientResources;
4464             }
4465         }
4466 
4467         if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
4468                     drv_ctx.op_buf.actualcount,
4469                     drv_ctx.op_buf.alignment)) {
4470             DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
4471             close(pmem_fd);
4472             return OMX_ErrorInsufficientResources;
4473         }
4474 #endif
4475         if (!secure_mode) {
4476             pmem_baseaddress = (unsigned char *)mmap(NULL,
4477                     (drv_ctx.op_buf.buffer_size *
4478                      drv_ctx.op_buf.actualcount),
4479                     PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
4480             if (pmem_baseaddress == MAP_FAILED) {
4481                 DEBUG_PRINT_ERROR("MMAP failed for Size %d",
4482                         drv_ctx.op_buf.buffer_size);
4483                 close(pmem_fd);
4484 #ifdef USE_ION
4485                 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
4486 #endif
4487                 return OMX_ErrorInsufficientResources;
4488             }
4489         }
4490         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
4491         // Alloc mem for platform specific info
4492         char *pPtr=NULL;
4493         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
4494                 nPMEMInfoSize,1);
4495         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
4496                                    calloc (sizeof(struct vdec_bufferpayload),
4497                                            drv_ctx.op_buf.actualcount);
4498         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
4499                                  calloc (sizeof (struct vdec_output_frameinfo),
4500                                          drv_ctx.op_buf.actualcount);
4501 #ifdef USE_ION
4502         drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
4503                                   calloc (sizeof(struct vdec_ion),
4504                                           drv_ctx.op_buf.actualcount);
4505 #endif
4506 
4507         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
4508                 && drv_ctx.ptr_respbuffer) {
4509             drv_ctx.ptr_outputbuffer[0].mmaped_size =
4510                 (drv_ctx.op_buf.buffer_size *
4511                  drv_ctx.op_buf.actualcount);
4512             bufHdr          =  m_out_mem_ptr;
4513             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
4514             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
4515                 (((char *) m_platform_list)  + nPlatformListSize);
4516             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4517                 (((char *) m_platform_entry) + nPlatformEntrySize);
4518             pPlatformList   = m_platform_list;
4519             pPlatformEntry  = m_platform_entry;
4520             pPMEMInfo       = m_pmem_info;
4521 
4522             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
4523 
4524             // Settting the entire storage nicely
4525             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
4526             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
4527             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
4528                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
4529                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
4530                 // Set the values when we determine the right HxW param
4531                 bufHdr->nAllocLen          = bytes;
4532                 bufHdr->nFilledLen         = 0;
4533                 bufHdr->pAppPrivate        = appData;
4534                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
4535                 // Platform specific PMEM Information
4536                 // Initialize the Platform Entry
4537                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
4538                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
4539                 pPlatformEntry->entry      = pPMEMInfo;
4540                 // Initialize the Platform List
4541                 pPlatformList->nEntries    = 1;
4542                 pPlatformList->entryList   = pPlatformEntry;
4543                 // Keep pBuffer NULL till vdec is opened
4544                 bufHdr->pBuffer            = NULL;
4545                 bufHdr->nOffset            = 0;
4546 
4547                 pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
4548                 pPMEMInfo->pmem_fd = 0;
4549                 bufHdr->pPlatformPrivate = pPlatformList;
4550 
4551                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
4552                 m_pmem_info[i].pmem_fd = pmem_fd;
4553 #ifdef USE_ION
4554                 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
4555                 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
4556                 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
4557 #endif
4558 
4559                 /*Create a mapping between buffers*/
4560                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
4561                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
4562                                                         &drv_ctx.ptr_outputbuffer[i];
4563                 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
4564                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
4565                     pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
4566 
4567                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %d address = %p",
4568                         pmem_fd, drv_ctx.ptr_outputbuffer[i].offset,
4569                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
4570                 // Move the buffer and buffer header pointers
4571                 bufHdr++;
4572                 pPMEMInfo++;
4573                 pPlatformEntry++;
4574                 pPlatformList++;
4575             }
4576         } else {
4577             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
4578                     m_out_mem_ptr, pPtr);
4579             if (m_out_mem_ptr) {
4580                 free(m_out_mem_ptr);
4581                 m_out_mem_ptr = NULL;
4582             }
4583             if (pPtr) {
4584                 free(pPtr);
4585                 pPtr = NULL;
4586             }
4587             if (drv_ctx.ptr_outputbuffer) {
4588                 free(drv_ctx.ptr_outputbuffer);
4589                 drv_ctx.ptr_outputbuffer = NULL;
4590             }
4591             if (drv_ctx.ptr_respbuffer) {
4592                 free(drv_ctx.ptr_respbuffer);
4593                 drv_ctx.ptr_respbuffer = NULL;
4594             }
4595 #ifdef USE_ION
4596             if (drv_ctx.op_buf_ion_info) {
4597                 DEBUG_PRINT_LOW("Free o/p ion context");
4598                 free(drv_ctx.op_buf_ion_info);
4599                 drv_ctx.op_buf_ion_info = NULL;
4600             }
4601 #endif
4602             eRet =  OMX_ErrorInsufficientResources;
4603         }
4604         if (eRet == OMX_ErrorNone)
4605             eRet = allocate_extradata();
4606     }
4607 
4608     for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
4609         if (BITMASK_ABSENT(&m_out_bm_count,i)) {
4610             DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
4611             break;
4612         }
4613     }
4614 
4615     if (eRet == OMX_ErrorNone) {
4616         if (i < drv_ctx.op_buf.actualcount) {
4617             struct v4l2_buffer buf;
4618             struct v4l2_plane plane[VIDEO_MAX_PLANES];
4619             int rc;
4620             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
4621 
4622             drv_ctx.ptr_outputbuffer[i].buffer_len =
4623                 drv_ctx.op_buf.buffer_size;
4624 
4625             *bufferHdr = (m_out_mem_ptr + i );
4626             if (secure_mode) {
4627                 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
4628             }
4629             drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
4630 
4631             buf.index = i;
4632             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4633             buf.memory = V4L2_MEMORY_USERPTR;
4634             plane[0].length = drv_ctx.op_buf.buffer_size;
4635             plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
4636                 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
4637 #ifdef USE_ION
4638             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
4639 #endif
4640             plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
4641             plane[0].data_offset = 0;
4642             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
4643             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4644                 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
4645                 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
4646 #ifdef USE_ION
4647                 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
4648 #endif
4649                 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
4650                 plane[extra_idx].data_offset = 0;
4651             } else if (extra_idx >= VIDEO_MAX_PLANES) {
4652                 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
4653                 return OMX_ErrorBadParameter;
4654             }
4655             buf.m.planes = plane;
4656             buf.length = drv_ctx.num_planes;
4657             DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
4658             rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4659             if (rc) {
4660                 /*TODO: How to handle this case */
4661                 return OMX_ErrorInsufficientResources;
4662             }
4663 
4664             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
4665                 enum v4l2_buf_type buf_type;
4666                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4667                 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
4668                 if (rc) {
4669                     return OMX_ErrorInsufficientResources;
4670                 } else {
4671                     streaming[CAPTURE_PORT] = true;
4672                     DEBUG_PRINT_LOW("STREAMON Successful");
4673                 }
4674             }
4675 
4676             (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
4677             (*bufferHdr)->pAppPrivate = appData;
4678             BITMASK_SET(&m_out_bm_count,i);
4679         } else {
4680             DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
4681             eRet = OMX_ErrorInsufficientResources;
4682         }
4683     }
4684 
4685     return eRet;
4686 }
4687 
4688 
4689 // AllocateBuffer  -- API Call
4690 /* ======================================================================
4691    FUNCTION
4692    omx_vdec::AllocateBuffer
4693 
4694    DESCRIPTION
4695    Returns zero if all the buffers released..
4696 
4697    PARAMETERS
4698    None.
4699 
4700    RETURN VALUE
4701    true/false
4702 
4703    ========================================================================== */
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)4704 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
4705         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4706         OMX_IN OMX_U32                        port,
4707         OMX_IN OMX_PTR                     appData,
4708         OMX_IN OMX_U32                       bytes)
4709 {
4710     unsigned i = 0;
4711     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
4712 
4713     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
4714     if (m_state == OMX_StateInvalid) {
4715         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
4716         return OMX_ErrorInvalidState;
4717     }
4718 
4719     if (port == OMX_CORE_INPUT_PORT_INDEX) {
4720         if (arbitrary_bytes) {
4721             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
4722         } else {
4723             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
4724         }
4725     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4726         eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
4727                 appData,bytes);
4728     } else {
4729         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
4730         eRet = OMX_ErrorBadPortIndex;
4731     }
4732     DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
4733     if (eRet == OMX_ErrorNone) {
4734         if (allocate_done()) {
4735             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
4736                 // Send the callback now
4737                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4738                 post_event(OMX_CommandStateSet,OMX_StateIdle,
4739                         OMX_COMPONENT_GENERATE_EVENT);
4740             }
4741         }
4742         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
4743             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
4744                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4745                 post_event(OMX_CommandPortEnable,
4746                         OMX_CORE_INPUT_PORT_INDEX,
4747                         OMX_COMPONENT_GENERATE_EVENT);
4748             }
4749         }
4750         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
4751             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
4752                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4753                 post_event(OMX_CommandPortEnable,
4754                         OMX_CORE_OUTPUT_PORT_INDEX,
4755                         OMX_COMPONENT_GENERATE_EVENT);
4756             }
4757         }
4758     }
4759     DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
4760     return eRet;
4761 }
4762 
4763 // Free Buffer - API call
4764 /* ======================================================================
4765    FUNCTION
4766    omx_vdec::FreeBuffer
4767 
4768    DESCRIPTION
4769 
4770    PARAMETERS
4771    None.
4772 
4773    RETURN VALUE
4774    true/false
4775 
4776    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4777 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
4778         OMX_IN OMX_U32                 port,
4779         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4780 {
4781     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4782     unsigned int nPortIndex;
4783     DEBUG_PRINT_LOW("In for decoder free_buffer");
4784 
4785     if (m_state == OMX_StateIdle &&
4786             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4787         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
4788     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
4789             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
4790         DEBUG_PRINT_LOW("Free Buffer while port %d disabled", port);
4791     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
4792                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
4793             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
4794              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
4795         DEBUG_PRINT_LOW("Free Buffer while port %d enable pending", port);
4796     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
4797         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
4798         post_event(OMX_EventError,
4799                 OMX_ErrorPortUnpopulated,
4800                 OMX_COMPONENT_GENERATE_EVENT);
4801 
4802         return OMX_ErrorIncorrectStateOperation;
4803     } else if (m_state != OMX_StateInvalid) {
4804         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
4805         post_event(OMX_EventError,
4806                 OMX_ErrorPortUnpopulated,
4807                 OMX_COMPONENT_GENERATE_EVENT);
4808     }
4809 
4810     if (port == OMX_CORE_INPUT_PORT_INDEX) {
4811         /*Check if arbitrary bytes*/
4812         if (!arbitrary_bytes && !input_use_buffer)
4813             nPortIndex = buffer - m_inp_mem_ptr;
4814         else
4815             nPortIndex = buffer - m_inp_heap_ptr;
4816 
4817         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
4818         if (nPortIndex < drv_ctx.ip_buf.actualcount) {
4819             // Clear the bit associated with it.
4820             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
4821             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
4822             if (input_use_buffer == true) {
4823 
4824                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
4825                 if (m_phdr_pmem_ptr)
4826                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
4827             } else {
4828                 if (arbitrary_bytes) {
4829                     if (m_phdr_pmem_ptr)
4830                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
4831                     else
4832                         free_input_buffer(nPortIndex,NULL);
4833                 } else
4834                     free_input_buffer(buffer);
4835             }
4836             m_inp_bPopulated = OMX_FALSE;
4837             /*Free the Buffer Header*/
4838             if (release_input_done()) {
4839                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
4840                 free_input_buffer_header();
4841             }
4842         } else {
4843             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
4844             eRet = OMX_ErrorBadPortIndex;
4845         }
4846 
4847         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
4848                 && release_input_done()) {
4849             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4850             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
4851             post_event(OMX_CommandPortDisable,
4852                     OMX_CORE_INPUT_PORT_INDEX,
4853                     OMX_COMPONENT_GENERATE_EVENT);
4854         }
4855     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4856         // check if the buffer is valid
4857         nPortIndex = buffer - client_buffers.get_il_buf_hdr();
4858         if (nPortIndex < drv_ctx.op_buf.actualcount) {
4859             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
4860             // Clear the bit associated with it.
4861             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
4862             m_out_bPopulated = OMX_FALSE;
4863             client_buffers.free_output_buffer (buffer);
4864 
4865             if (release_output_done()) {
4866                 free_output_buffer_header();
4867             }
4868         } else {
4869             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
4870             eRet = OMX_ErrorBadPortIndex;
4871         }
4872         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
4873                 && release_output_done()) {
4874             DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
4875 
4876             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4877             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
4878 #ifdef _ANDROID_ICS_
4879             if (m_enable_android_native_buffers) {
4880                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
4881                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
4882             }
4883 #endif
4884 
4885             post_event(OMX_CommandPortDisable,
4886                     OMX_CORE_OUTPUT_PORT_INDEX,
4887                     OMX_COMPONENT_GENERATE_EVENT);
4888         }
4889     } else {
4890         eRet = OMX_ErrorBadPortIndex;
4891     }
4892     if ((eRet == OMX_ErrorNone) &&
4893             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4894         if (release_done()) {
4895             // Send the callback now
4896             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
4897             post_event(OMX_CommandStateSet, OMX_StateLoaded,
4898                     OMX_COMPONENT_GENERATE_EVENT);
4899         }
4900     }
4901     return eRet;
4902 }
4903 
4904 
4905 /* ======================================================================
4906    FUNCTION
4907    omx_vdec::EmptyThisBuffer
4908 
4909    DESCRIPTION
4910    This routine is used to push the encoded video frames to
4911    the video decoder.
4912 
4913    PARAMETERS
4914    None.
4915 
4916    RETURN VALUE
4917    OMX Error None if everything went successful.
4918 
4919    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4920 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
4921         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4922 {
4923     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
4924     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
4925 
4926     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
4927         codec_config_flag = true;
4928         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
4929     }
4930     if (m_state == OMX_StateInvalid) {
4931         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
4932         return OMX_ErrorInvalidState;
4933     }
4934 
4935     if (buffer == NULL) {
4936         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
4937         return OMX_ErrorBadParameter;
4938     }
4939 
4940     if (!m_inp_bEnabled) {
4941         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
4942         return OMX_ErrorIncorrectStateOperation;
4943     }
4944 
4945     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4946         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %lu", buffer->nInputPortIndex);
4947         return OMX_ErrorBadPortIndex;
4948     }
4949 
4950 #ifdef _ANDROID_
4951     if (iDivXDrmDecrypt) {
4952         OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer);
4953         if (drmErr != OMX_ErrorNone) {
4954             // this error can be ignored
4955             DEBUG_PRINT_LOW("ERROR:iDivXDrmDecrypt->Decrypt %d", drmErr);
4956         }
4957     }
4958 #endif //_ANDROID_
4959     if (perf_flag) {
4960         if (!latency) {
4961             dec_time.stop();
4962             latency = dec_time.processing_time_us();
4963             dec_time.start();
4964         }
4965     }
4966 
4967     if (arbitrary_bytes) {
4968         nBufferIndex = buffer - m_inp_heap_ptr;
4969     } else {
4970         if (input_use_buffer == true) {
4971             nBufferIndex = buffer - m_inp_heap_ptr;
4972             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
4973             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
4974             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
4975             buffer = &m_inp_mem_ptr[nBufferIndex];
4976             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d",
4977                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen);
4978         } else {
4979             nBufferIndex = buffer - m_inp_mem_ptr;
4980         }
4981     }
4982 
4983     if (nBufferIndex > drv_ctx.ip_buf.actualcount ) {
4984         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
4985         return OMX_ErrorBadParameter;
4986     }
4987 
4988     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)",
4989             buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen);
4990     if (arbitrary_bytes) {
4991         post_event ((unsigned)hComp,(unsigned)buffer,
4992                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
4993     } else {
4994         if (!(client_extradata & OMX_TIMEINFO_EXTRADATA))
4995             set_frame_rate(buffer->nTimeStamp);
4996         post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
4997     }
4998     return OMX_ErrorNone;
4999 }
5000 
5001 /* ======================================================================
5002    FUNCTION
5003    omx_vdec::empty_this_buffer_proxy
5004 
5005    DESCRIPTION
5006    This routine is used to push the encoded video frames to
5007    the video decoder.
5008 
5009    PARAMETERS
5010    None.
5011 
5012    RETURN VALUE
5013    OMX Error None if everything went successful.
5014 
5015    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5016 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE         hComp,
5017         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5018 {
5019     int push_cnt = 0,i=0;
5020     unsigned nPortIndex = 0;
5021     OMX_ERRORTYPE ret = OMX_ErrorNone;
5022     struct vdec_input_frameinfo frameinfo;
5023     struct vdec_bufferpayload *temp_buffer;
5024     struct vdec_seqheader seq_header;
5025     bool port_setting_changed = true;
5026     bool not_coded_vop = false;
5027 
5028     /*Should we generate a Aync error event*/
5029     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
5030         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
5031         return OMX_ErrorBadParameter;
5032     }
5033 
5034     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
5035 
5036     if (nPortIndex > drv_ctx.ip_buf.actualcount) {
5037         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
5038                 nPortIndex);
5039         return OMX_ErrorBadParameter;
5040     }
5041 
5042     pending_input_buffers++;
5043 
5044     /* return zero length and not an EOS buffer */
5045     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
5046             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
5047         DEBUG_PRINT_HIGH("return zero legth buffer");
5048         post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5049                 OMX_COMPONENT_GENERATE_EBD);
5050         return OMX_ErrorNone;
5051     }
5052 
5053 
5054     if (codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX) {
5055         mp4StreamType psBits;
5056         psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset);
5057         psBits.numBytes = buffer->nFilledLen;
5058         mp4_headerparser.parseHeader(&psBits);
5059         not_coded_vop = mp4_headerparser.is_notcodec_vop(
5060                 (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5061         if (not_coded_vop) {
5062             DEBUG_PRINT_HIGH("Found Not coded vop len %lu frame number %u",
5063                     buffer->nFilledLen,frame_count);
5064             if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5065                 DEBUG_PRINT_HIGH("Eos and Not coded Vop set len to zero");
5066                 not_coded_vop = false;
5067                 buffer->nFilledLen = 0;
5068             }
5069         }
5070     }
5071 
5072     if (input_flush_progress == true
5073 
5074             || not_coded_vop
5075 
5076        ) {
5077         DEBUG_PRINT_LOW("Flush in progress return buffer ");
5078         post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5079                 OMX_COMPONENT_GENERATE_EBD);
5080         return OMX_ErrorNone;
5081     }
5082 
5083     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
5084 
5085     if ((temp_buffer -  drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount) {
5086         return OMX_ErrorBadParameter;
5087     }
5088 
5089     DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5090     /*for use buffer we need to memcpy the data*/
5091     temp_buffer->buffer_len = buffer->nFilledLen;
5092 
5093     if (input_use_buffer) {
5094         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
5095             if (arbitrary_bytes) {
5096                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5097             } else {
5098                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
5099                         buffer->nFilledLen);
5100             }
5101         } else {
5102             return OMX_ErrorBadParameter;
5103         }
5104 
5105     }
5106 
5107     frameinfo.bufferaddr = temp_buffer->bufferaddr;
5108     frameinfo.client_data = (void *) buffer;
5109     frameinfo.datalen = temp_buffer->buffer_len;
5110     frameinfo.flags = 0;
5111     frameinfo.offset = buffer->nOffset;
5112     frameinfo.pmem_fd = temp_buffer->pmem_fd;
5113     frameinfo.pmem_offset = temp_buffer->offset;
5114     frameinfo.timestamp = buffer->nTimeStamp;
5115     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
5116         DEBUG_PRINT_LOW("ETB: dmx enabled");
5117         if (m_demux_entries == 0) {
5118             extract_demux_addr_offsets(buffer);
5119         }
5120 
5121         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries);
5122         handle_demux_data(buffer);
5123         frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
5124         frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
5125     } else {
5126         frameinfo.desc_addr = NULL;
5127         frameinfo.desc_size = 0;
5128     }
5129     if (!arbitrary_bytes) {
5130         frameinfo.flags |= buffer->nFlags;
5131     }
5132 
5133 #ifdef _ANDROID_
5134     if (m_debug_timestamp) {
5135         if (arbitrary_bytes) {
5136             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5137             m_timestamp_list.insert_ts(buffer->nTimeStamp);
5138         } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
5139             DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5140             m_timestamp_list.insert_ts(buffer->nTimeStamp);
5141         }
5142     }
5143 #endif
5144 
5145 #ifdef INPUT_BUFFER_LOG
5146     if (inputBufferFile1) {
5147         fwrite((const char *)temp_buffer->bufferaddr,
5148                 temp_buffer->buffer_len,1,inputBufferFile1);
5149     }
5150 #endif
5151 
5152     if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
5153         frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5154         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5155     }
5156 
5157     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5158         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
5159         frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
5160         h264_scratch.nFilledLen = 0;
5161         nal_count = 0;
5162         look_ahead_nal = false;
5163         frame_count = 0;
5164         if (m_frame_parser.mutils)
5165             m_frame_parser.mutils->initialize_frame_checking_environment();
5166         m_frame_parser.flush();
5167         h264_last_au_ts = LLONG_MAX;
5168         h264_last_au_flags = 0;
5169         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
5170         m_demux_entries = 0;
5171     }
5172     struct v4l2_buffer buf;
5173     struct v4l2_plane plane;
5174     memset( (void *)&buf, 0, sizeof(buf));
5175     memset( (void *)&plane, 0, sizeof(plane));
5176     int rc;
5177     unsigned long  print_count;
5178     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5179         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
5180         DEBUG_PRINT_HIGH("INPUT EOS reached") ;
5181     }
5182     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5183     buf.index = nPortIndex;
5184     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5185     buf.memory = V4L2_MEMORY_USERPTR;
5186     plane.bytesused = temp_buffer->buffer_len;
5187     plane.length = drv_ctx.ip_buf.buffer_size;
5188     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
5189         (unsigned long)temp_buffer->offset;
5190     plane.reserved[0] = temp_buffer->pmem_fd;
5191     plane.reserved[1] = temp_buffer->offset;
5192     plane.data_offset = 0;
5193     buf.m.planes = &plane;
5194     buf.length = 1;
5195     if (frameinfo.timestamp >= LLONG_MAX) {
5196         buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
5197     }
5198     //assumption is that timestamp is in milliseconds
5199     buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
5200     buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
5201     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
5202 
5203     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5204     if (rc) {
5205         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
5206         return OMX_ErrorHardware;
5207     }
5208     codec_config_flag = false;
5209     DEBUG_PRINT_LOW("%s: codec_config cleared", __FUNCTION__);
5210 
5211     if (!streaming[OUTPUT_PORT]) {
5212         enum v4l2_buf_type buf_type;
5213         int ret,r;
5214 
5215         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5216         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
5217         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5218         if (!ret) {
5219             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
5220             streaming[OUTPUT_PORT] = true;
5221         } else {
5222             /*TODO: How to handle this case */
5223             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
5224             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
5225             post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5226                     OMX_COMPONENT_GENERATE_EBD);
5227             return OMX_ErrorBadParameter;
5228         }
5229     }
5230     DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)",
5231             frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen);
5232     time_stamp_dts.insert_timestamp(buffer);
5233 
5234     return ret;
5235 }
5236 
5237 /* ======================================================================
5238    FUNCTION
5239    omx_vdec::FillThisBuffer
5240 
5241    DESCRIPTION
5242    IL client uses this method to release the frame buffer
5243    after displaying them.
5244 
5245    PARAMETERS
5246    None.
5247 
5248    RETURN VALUE
5249    true/false
5250 
5251    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5252 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
5253         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5254 {
5255 
5256     if (m_state == OMX_StateInvalid) {
5257         DEBUG_PRINT_ERROR("FTB in Invalid State");
5258         return OMX_ErrorInvalidState;
5259     }
5260 
5261     if (!m_out_bEnabled) {
5262         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
5263         return OMX_ErrorIncorrectStateOperation;
5264     }
5265 
5266     if (buffer == NULL ||
5267             ((buffer - client_buffers.get_il_buf_hdr()) >= drv_ctx.op_buf.actualcount)) {
5268         return OMX_ErrorBadParameter;
5269     }
5270 
5271     if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
5272         DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %lu", buffer->nOutputPortIndex);
5273         return OMX_ErrorBadPortIndex;
5274     }
5275 
5276     DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5277     post_event((unsigned) hComp, (unsigned)buffer, m_fill_output_msg);
5278     return OMX_ErrorNone;
5279 }
5280 /* ======================================================================
5281    FUNCTION
5282    omx_vdec::fill_this_buffer_proxy
5283 
5284    DESCRIPTION
5285    IL client uses this method to release the frame buffer
5286    after displaying them.
5287 
5288    PARAMETERS
5289    None.
5290 
5291    RETURN VALUE
5292    true/false
5293 
5294    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)5295 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
5296         OMX_IN OMX_HANDLETYPE        hComp,
5297         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
5298 {
5299     OMX_ERRORTYPE nRet = OMX_ErrorNone;
5300     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
5301     unsigned nPortIndex = 0;
5302     struct vdec_fillbuffer_cmd fillbuffer;
5303     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
5304     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
5305 
5306     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
5307 
5308     if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount)
5309         return OMX_ErrorBadParameter;
5310 
5311     DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
5312             bufferAdd, bufferAdd->pBuffer);
5313     /*Return back the output buffer to client*/
5314     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
5315         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
5316         buffer->nFilledLen = 0;
5317         m_cb.FillBufferDone (hComp,m_app_data,buffer);
5318         return OMX_ErrorNone;
5319     }
5320     pending_output_buffers++;
5321     buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
5322     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
5323     if (ptr_respbuffer) {
5324         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
5325     }
5326 
5327     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
5328         DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
5329         buffer->nFilledLen = 0;
5330         m_cb.FillBufferDone (hComp,m_app_data,buffer);
5331         pending_output_buffers--;
5332         return OMX_ErrorBadParameter;
5333     }
5334 
5335     int rc = 0;
5336     struct v4l2_buffer buf;
5337     struct v4l2_plane plane[VIDEO_MAX_PLANES];
5338     memset( (void *)&buf, 0, sizeof(buf));
5339     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
5340     int extra_idx = 0;
5341 
5342     buf.index = nPortIndex;
5343     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5344     buf.memory = V4L2_MEMORY_USERPTR;
5345     plane[0].bytesused = buffer->nFilledLen;
5346     plane[0].length = drv_ctx.op_buf.buffer_size;
5347     plane[0].m.userptr =
5348         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
5349         (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
5350     plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
5351     plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
5352     plane[0].data_offset = 0;
5353     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5354     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5355         plane[extra_idx].bytesused = 0;
5356         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5357         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
5358 #ifdef USE_ION
5359         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5360 #endif
5361         plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
5362         plane[extra_idx].data_offset = 0;
5363     } else if (extra_idx >= VIDEO_MAX_PLANES) {
5364         DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx);
5365         return OMX_ErrorBadParameter;
5366     }
5367     buf.m.planes = plane;
5368     buf.length = drv_ctx.num_planes;
5369     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5370     if (rc) {
5371         /*TODO: How to handle this case */
5372         DEBUG_PRINT_ERROR("Failed to qbuf to driver");
5373     }
5374     return OMX_ErrorNone;
5375 }
5376 
5377 /* ======================================================================
5378    FUNCTION
5379    omx_vdec::SetCallbacks
5380 
5381    DESCRIPTION
5382    Set the callbacks.
5383 
5384    PARAMETERS
5385    None.
5386 
5387    RETURN VALUE
5388    OMX Error None if everything successful.
5389 
5390    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)5391 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
5392         OMX_IN OMX_CALLBACKTYPE* callbacks,
5393         OMX_IN OMX_PTR             appData)
5394 {
5395 
5396     m_cb       = *callbacks;
5397     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
5398             m_cb.EventHandler,m_cb.FillBufferDone);
5399     m_app_data =    appData;
5400     return OMX_ErrorNotImplemented;
5401 }
5402 
5403 /* ======================================================================
5404    FUNCTION
5405    omx_vdec::ComponentDeInit
5406 
5407    DESCRIPTION
5408    Destroys the component and release memory allocated to the heap.
5409 
5410    PARAMETERS
5411    <TBD>.
5412 
5413    RETURN VALUE
5414    OMX Error None if everything successful.
5415 
5416    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)5417 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
5418 {
5419 #ifdef _ANDROID_
5420     if (iDivXDrmDecrypt) {
5421         delete iDivXDrmDecrypt;
5422         iDivXDrmDecrypt=NULL;
5423     }
5424 #endif //_ANDROID_
5425 
5426     unsigned i = 0;
5427     if (OMX_StateLoaded != m_state) {
5428         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
5429                 m_state);
5430         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
5431     } else {
5432         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
5433     }
5434 
5435     /*Check if the output buffers have to be cleaned up*/
5436     if (m_out_mem_ptr) {
5437         DEBUG_PRINT_LOW("Freeing the Output Memory");
5438         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
5439             free_output_buffer (&m_out_mem_ptr[i]);
5440         }
5441 #ifdef _ANDROID_ICS_
5442         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5443 #endif
5444     }
5445 
5446     /*Check if the input buffers have to be cleaned up*/
5447     if (m_inp_mem_ptr || m_inp_heap_ptr) {
5448         DEBUG_PRINT_LOW("Freeing the Input Memory");
5449         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
5450             if (m_inp_mem_ptr)
5451                 free_input_buffer (i,&m_inp_mem_ptr[i]);
5452             else
5453                 free_input_buffer (i,NULL);
5454         }
5455     }
5456     free_input_buffer_header();
5457     free_output_buffer_header();
5458     if (h264_scratch.pBuffer) {
5459         free(h264_scratch.pBuffer);
5460         h264_scratch.pBuffer = NULL;
5461     }
5462 
5463     if (h264_parser) {
5464         delete h264_parser;
5465         h264_parser = NULL;
5466     }
5467 
5468     if (m_platform_list) {
5469         free(m_platform_list);
5470         m_platform_list = NULL;
5471     }
5472     if (m_vendor_config.pData) {
5473         free(m_vendor_config.pData);
5474         m_vendor_config.pData = NULL;
5475     }
5476 
5477     // Reset counters in mesg queues
5478     m_ftb_q.m_size=0;
5479     m_cmd_q.m_size=0;
5480     m_etb_q.m_size=0;
5481     m_ftb_q.m_read = m_ftb_q.m_write =0;
5482     m_cmd_q.m_read = m_cmd_q.m_write =0;
5483     m_etb_q.m_read = m_etb_q.m_write =0;
5484 #ifdef _ANDROID_
5485     if (m_debug_timestamp) {
5486         m_timestamp_list.reset_ts_list();
5487     }
5488 #endif
5489 
5490     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
5491     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
5492     // NULL);
5493     DEBUG_PRINT_HIGH("Close the driver instance");
5494 
5495 #ifdef INPUT_BUFFER_LOG
5496     fclose (inputBufferFile1);
5497 #endif
5498 #ifdef OUTPUT_BUFFER_LOG
5499     if (outputBufferFile1)
5500         fclose (outputBufferFile1);
5501 #endif
5502 #ifdef OUTPUT_EXTRADATA_LOG
5503     fclose (outputExtradataFile);
5504 #endif
5505     DEBUG_PRINT_HIGH("omx_vdec::component_deinit() complete");
5506     return OMX_ErrorNone;
5507 }
5508 
5509 /* ======================================================================
5510    FUNCTION
5511    omx_vdec::UseEGLImage
5512 
5513    DESCRIPTION
5514    OMX Use EGL Image method implementation <TBD>.
5515 
5516    PARAMETERS
5517    <TBD>.
5518 
5519    RETURN VALUE
5520    Not Implemented error.
5521 
5522    ========================================================================== */
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)5523 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE                hComp,
5524         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5525         OMX_IN OMX_U32                        port,
5526         OMX_IN OMX_PTR                     appData,
5527         OMX_IN void*                      eglImage)
5528 {
5529     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
5530     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
5531     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
5532 
5533 #ifdef USE_EGL_IMAGE_GPU
5534     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
5535     EGLint fd = -1, offset = 0,pmemPtr = 0;
5536 #else
5537     int fd = -1, offset = 0;
5538 #endif
5539     DEBUG_PRINT_HIGH("use EGL image support for decoder");
5540     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
5541         DEBUG_PRINT_ERROR("");
5542     }
5543 #ifdef USE_EGL_IMAGE_GPU
5544     if (m_display_id == NULL) {
5545         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
5546         return OMX_ErrorInsufficientResources;
5547     }
5548     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
5549         eglGetProcAddress("eglQueryImageKHR");
5550     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd);
5551     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset);
5552     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr);
5553 #else //with OMX test app
5554     struct temp_egl {
5555         int pmem_fd;
5556         int offset;
5557     };
5558     struct temp_egl *temp_egl_id = NULL;
5559     void * pmemPtr = (void *) eglImage;
5560     temp_egl_id = (struct temp_egl *)eglImage;
5561     if (temp_egl_id != NULL) {
5562         fd = temp_egl_id->pmem_fd;
5563         offset = temp_egl_id->offset;
5564     }
5565 #endif
5566     if (fd < 0) {
5567         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
5568         return OMX_ErrorInsufficientResources;
5569     }
5570     pmem_info.pmem_fd = (OMX_U32) fd;
5571     pmem_info.offset = (OMX_U32) offset;
5572     pmem_entry.entry = (void *) &pmem_info;
5573     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
5574     pmem_list.entryList = &pmem_entry;
5575     pmem_list.nEntries = 1;
5576     ouput_egl_buffers = true;
5577     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
5578                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
5579                 (OMX_U8 *)pmemPtr)) {
5580         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
5581         return OMX_ErrorInsufficientResources;
5582     }
5583     return OMX_ErrorNone;
5584 }
5585 
5586 /* ======================================================================
5587    FUNCTION
5588    omx_vdec::ComponentRoleEnum
5589 
5590    DESCRIPTION
5591    OMX Component Role Enum method implementation.
5592 
5593    PARAMETERS
5594    <TBD>.
5595 
5596    RETURN VALUE
5597    OMX Error None if everything is successful.
5598    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)5599 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
5600         OMX_OUT OMX_U8*        role,
5601         OMX_IN OMX_U32        index)
5602 {
5603     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5604 
5605     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
5606         if ((0 == index) && role) {
5607             strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
5608             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5609         } else {
5610             eRet = OMX_ErrorNoMore;
5611         }
5612     }
5613     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
5614         if ((0 == index) && role) {
5615             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
5616             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5617         } else {
5618             eRet = OMX_ErrorNoMore;
5619         }
5620     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
5621         if ((0 == index) && role) {
5622             strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
5623             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5624         } else {
5625             DEBUG_PRINT_LOW("No more roles");
5626             eRet = OMX_ErrorNoMore;
5627         }
5628     }
5629 
5630     else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
5631             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) ) {
5632         if ((0 == index) && role) {
5633             strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
5634             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5635         } else {
5636             DEBUG_PRINT_LOW("No more roles");
5637             eRet = OMX_ErrorNoMore;
5638         }
5639     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
5640         if ((0 == index) && role) {
5641             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
5642             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5643         } else {
5644             DEBUG_PRINT_LOW("No more roles");
5645             eRet = OMX_ErrorNoMore;
5646         }
5647     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
5648         if ((0 == index) && role) {
5649             strlcpy((char *)role, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
5650             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5651         } else {
5652             DEBUG_PRINT_LOW("No more roles");
5653             eRet = OMX_ErrorNoMore;
5654         }
5655     } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
5656             (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
5657             ) {
5658         if ((0 == index) && role) {
5659             strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
5660             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5661         } else {
5662             DEBUG_PRINT_LOW("No more roles");
5663             eRet = OMX_ErrorNoMore;
5664         }
5665     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
5666         if ((0 == index) && role) {
5667             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
5668             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5669         } else {
5670             DEBUG_PRINT_LOW("No more roles");
5671             eRet = OMX_ErrorNoMore;
5672         }
5673     } else {
5674         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
5675         eRet = OMX_ErrorInvalidComponentName;
5676     }
5677     return eRet;
5678 }
5679 
5680 
5681 
5682 
5683 /* ======================================================================
5684    FUNCTION
5685    omx_vdec::AllocateDone
5686 
5687    DESCRIPTION
5688    Checks if entire buffer pool is allocated by IL Client or not.
5689    Need this to move to IDLE state.
5690 
5691    PARAMETERS
5692    None.
5693 
5694    RETURN VALUE
5695    true/false.
5696 
5697    ========================================================================== */
allocate_done(void)5698 bool omx_vdec::allocate_done(void)
5699 {
5700     bool bRet = false;
5701     bool bRet_In = false;
5702     bool bRet_Out = false;
5703 
5704     bRet_In = allocate_input_done();
5705     bRet_Out = allocate_output_done();
5706 
5707     if (bRet_In && bRet_Out) {
5708         bRet = true;
5709     }
5710 
5711     return bRet;
5712 }
5713 /* ======================================================================
5714    FUNCTION
5715    omx_vdec::AllocateInputDone
5716 
5717    DESCRIPTION
5718    Checks if I/P buffer pool is allocated by IL Client or not.
5719 
5720    PARAMETERS
5721    None.
5722 
5723    RETURN VALUE
5724    true/false.
5725 
5726    ========================================================================== */
allocate_input_done(void)5727 bool omx_vdec::allocate_input_done(void)
5728 {
5729     bool bRet = false;
5730     unsigned i=0;
5731 
5732     if (m_inp_mem_ptr == NULL) {
5733         return bRet;
5734     }
5735     if (m_inp_mem_ptr ) {
5736         for (; i<drv_ctx.ip_buf.actualcount; i++) {
5737             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
5738                 break;
5739             }
5740         }
5741     }
5742     if (i == drv_ctx.ip_buf.actualcount) {
5743         bRet = true;
5744         DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
5745     }
5746     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
5747         m_inp_bPopulated = OMX_TRUE;
5748     }
5749     return bRet;
5750 }
5751 /* ======================================================================
5752    FUNCTION
5753    omx_vdec::AllocateOutputDone
5754 
5755    DESCRIPTION
5756    Checks if entire O/P buffer pool is allocated by IL Client or not.
5757 
5758    PARAMETERS
5759    None.
5760 
5761    RETURN VALUE
5762    true/false.
5763 
5764    ========================================================================== */
allocate_output_done(void)5765 bool omx_vdec::allocate_output_done(void)
5766 {
5767     bool bRet = false;
5768     unsigned j=0;
5769 
5770     if (m_out_mem_ptr == NULL) {
5771         return bRet;
5772     }
5773 
5774     if (m_out_mem_ptr) {
5775         for (; j < drv_ctx.op_buf.actualcount; j++) {
5776             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
5777                 break;
5778             }
5779         }
5780     }
5781 
5782     if (j == drv_ctx.op_buf.actualcount) {
5783         bRet = true;
5784         DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
5785         if (m_out_bEnabled)
5786             m_out_bPopulated = OMX_TRUE;
5787     }
5788 
5789     return bRet;
5790 }
5791 
5792 /* ======================================================================
5793    FUNCTION
5794    omx_vdec::ReleaseDone
5795 
5796    DESCRIPTION
5797    Checks if IL client has released all the buffers.
5798 
5799    PARAMETERS
5800    None.
5801 
5802    RETURN VALUE
5803    true/false
5804 
5805    ========================================================================== */
release_done(void)5806 bool omx_vdec::release_done(void)
5807 {
5808     bool bRet = false;
5809 
5810     if (release_input_done()) {
5811         if (release_output_done()) {
5812             bRet = true;
5813         }
5814     }
5815     return bRet;
5816 }
5817 
5818 
5819 /* ======================================================================
5820    FUNCTION
5821    omx_vdec::ReleaseOutputDone
5822 
5823    DESCRIPTION
5824    Checks if IL client has released all the buffers.
5825 
5826    PARAMETERS
5827    None.
5828 
5829    RETURN VALUE
5830    true/false
5831 
5832    ========================================================================== */
release_output_done(void)5833 bool omx_vdec::release_output_done(void)
5834 {
5835     bool bRet = false;
5836     unsigned i=0,j=0;
5837 
5838     DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_inp_mem_ptr);
5839     if (m_out_mem_ptr) {
5840         for (; j < drv_ctx.op_buf.actualcount ; j++) {
5841             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
5842                 break;
5843             }
5844         }
5845         if (j == drv_ctx.op_buf.actualcount) {
5846             m_out_bm_count = 0;
5847             bRet = true;
5848         }
5849     } else {
5850         m_out_bm_count = 0;
5851         bRet = true;
5852     }
5853     return bRet;
5854 }
5855 /* ======================================================================
5856    FUNCTION
5857    omx_vdec::ReleaseInputDone
5858 
5859    DESCRIPTION
5860    Checks if IL client has released all the buffers.
5861 
5862    PARAMETERS
5863    None.
5864 
5865    RETURN VALUE
5866    true/false
5867 
5868    ========================================================================== */
release_input_done(void)5869 bool omx_vdec::release_input_done(void)
5870 {
5871     bool bRet = false;
5872     unsigned i=0,j=0;
5873 
5874     DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
5875     if (m_inp_mem_ptr) {
5876         for (; j<drv_ctx.ip_buf.actualcount; j++) {
5877             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
5878                 break;
5879             }
5880         }
5881         if (j==drv_ctx.ip_buf.actualcount) {
5882             bRet = true;
5883         }
5884     } else {
5885         bRet = true;
5886     }
5887     return bRet;
5888 }
5889 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)5890 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
5891         OMX_BUFFERHEADERTYPE * buffer)
5892 {
5893     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
5894     if (!buffer || (buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount) {
5895         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
5896         return OMX_ErrorBadParameter;
5897     } else if (output_flush_progress) {
5898         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
5899         buffer->nFilledLen = 0;
5900         buffer->nTimeStamp = 0;
5901         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
5902         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5903         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
5904     }
5905 
5906     DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
5907             buffer, buffer->pBuffer);
5908     pending_output_buffers --;
5909 
5910     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5911         DEBUG_PRINT_HIGH("Output EOS has been reached");
5912         if (!output_flush_progress)
5913             post_event((unsigned)NULL, (unsigned)NULL,
5914                     OMX_COMPONENT_GENERATE_EOS_DONE);
5915 
5916         if (psource_frame) {
5917             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
5918             psource_frame = NULL;
5919         }
5920         if (pdest_frame) {
5921             pdest_frame->nFilledLen = 0;
5922             m_input_free_q.insert_entry((unsigned) pdest_frame,(unsigned)NULL,
5923                     (unsigned)NULL);
5924             pdest_frame = NULL;
5925         }
5926     }
5927 
5928     DEBUG_PRINT_LOW("In fill Buffer done call address %p ",buffer);
5929 #ifdef OUTPUT_BUFFER_LOG
5930     if (outputBufferFile1 && buffer->nFilledLen) {
5931         int buf_index = buffer - m_out_mem_ptr;
5932         int stride = drv_ctx.video_resolution.stride;
5933         int scanlines = drv_ctx.video_resolution.scan_lines;
5934         char *temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
5935         int i;
5936         int bytes_written = 0;
5937         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
5938             bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, outputBufferFile1);
5939             temp += stride;
5940         }
5941         temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
5942         int stride_c = stride;
5943         for (i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
5944             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, outputBufferFile1);
5945             temp += stride_c;
5946         }
5947     }
5948 #endif
5949 
5950     /* For use buffer we need to copy the data */
5951     if (!output_flush_progress) {
5952         time_stamp_dts.get_next_timestamp(buffer,
5953                 (drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
5954                 ?true:false);
5955         if (m_debug_timestamp) {
5956             {
5957                 OMX_TICKS expected_ts = 0;
5958                 m_timestamp_list.pop_min_ts(expected_ts);
5959                 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
5960                         buffer->nTimeStamp, expected_ts);
5961 
5962                 if (buffer->nTimeStamp != expected_ts) {
5963                     DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
5964                 }
5965             }
5966         }
5967     }
5968     if (m_cb.FillBufferDone) {
5969         if (buffer->nFilledLen > 0) {
5970             handle_extradata(buffer);
5971             if (client_extradata & OMX_TIMEINFO_EXTRADATA)
5972                 // Keep min timestamp interval to handle corrupted bit stream scenario
5973                 set_frame_rate(buffer->nTimeStamp);
5974             else if (arbitrary_bytes)
5975                 adjust_timestamp(buffer->nTimeStamp);
5976             if (perf_flag) {
5977                 if (!proc_frms) {
5978                     dec_time.stop();
5979                     latency = dec_time.processing_time_us() - latency;
5980                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
5981                     dec_time.start();
5982                     fps_metrics.start();
5983                 }
5984                 proc_frms++;
5985                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5986                     OMX_U64 proc_time = 0;
5987                     fps_metrics.stop();
5988                     proc_time = fps_metrics.processing_time_us();
5989                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)",
5990                             proc_frms, (float)proc_time / 1e6,
5991                             (float)(1e6 * proc_frms) / proc_time);
5992                     proc_frms = 0;
5993                 }
5994             }
5995 
5996 #ifdef OUTPUT_EXTRADATA_LOG
5997             if (outputExtradataFile) {
5998 
5999                 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
6000                 p_extra = (OMX_OTHER_EXTRADATATYPE *)
6001                     ((unsigned)(buffer->pBuffer + buffer->nOffset +
6002                         buffer->nFilledLen + 3)&(~3));
6003                 while (p_extra &&
6004                         (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) ) {
6005                     DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType);
6006                     fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
6007                     if (p_extra->eType == OMX_ExtraDataNone) {
6008                         break;
6009                     }
6010                     p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
6011                 }
6012             }
6013 #endif
6014         }
6015         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
6016             prev_ts = LLONG_MAX;
6017             rst_prev_ts = true;
6018         }
6019 
6020         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6021             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
6022              buffer->pPlatformPrivate)->entryList->entry;
6023         DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd);
6024         OMX_BUFFERHEADERTYPE *il_buffer;
6025         il_buffer = client_buffers.get_il_buf_hdr(buffer);
6026         if (il_buffer)
6027             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
6028         else {
6029             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
6030             return OMX_ErrorBadParameter;
6031         }
6032         DEBUG_PRINT_LOW("After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd);
6033     } else {
6034         return OMX_ErrorBadParameter;
6035     }
6036 
6037     return OMX_ErrorNone;
6038 }
6039 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6040 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
6041         OMX_BUFFERHEADERTYPE* buffer)
6042 {
6043 
6044     if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount)) {
6045         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
6046         return OMX_ErrorBadParameter;
6047     }
6048 
6049     DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
6050             buffer, buffer->pBuffer);
6051     pending_input_buffers--;
6052 
6053     if (arbitrary_bytes) {
6054         if (pdest_frame == NULL && input_flush_progress == false) {
6055             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
6056             pdest_frame = buffer;
6057             buffer->nFilledLen = 0;
6058             buffer->nTimeStamp = LLONG_MAX;
6059             push_input_buffer (hComp);
6060         } else {
6061             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
6062             buffer->nFilledLen = 0;
6063             if (!m_input_free_q.insert_entry((unsigned)buffer,
6064                         (unsigned)NULL, (unsigned)NULL)) {
6065                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
6066             }
6067         }
6068     } else if (m_cb.EmptyBufferDone) {
6069         buffer->nFilledLen = 0;
6070         if (input_use_buffer == true) {
6071             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
6072         }
6073         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
6074     }
6075     return OMX_ErrorNone;
6076 }
6077 
async_message_process(void * context,void * message)6078 int omx_vdec::async_message_process (void *context, void* message)
6079 {
6080     omx_vdec* omx = NULL;
6081     struct vdec_msginfo *vdec_msg = NULL;
6082     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
6083     struct v4l2_buffer *v4l2_buf_ptr = NULL;
6084     struct vdec_output_frameinfo *output_respbuf = NULL;
6085     int rc=1;
6086     if (context == NULL || message == NULL) {
6087         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
6088         return -1;
6089     }
6090     vdec_msg = (struct vdec_msginfo *)message;
6091 
6092     omx = reinterpret_cast<omx_vdec*>(context);
6093 
6094     switch (vdec_msg->msgcode) {
6095 
6096         case VDEC_MSG_EVT_HW_ERROR:
6097             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6098                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6099             break;
6100 
6101         case VDEC_MSG_RESP_START_DONE:
6102             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6103                     OMX_COMPONENT_GENERATE_START_DONE);
6104             break;
6105 
6106         case VDEC_MSG_RESP_STOP_DONE:
6107             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6108                     OMX_COMPONENT_GENERATE_STOP_DONE);
6109             break;
6110 
6111         case VDEC_MSG_RESP_RESUME_DONE:
6112             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6113                     OMX_COMPONENT_GENERATE_RESUME_DONE);
6114             break;
6115 
6116         case VDEC_MSG_RESP_PAUSE_DONE:
6117             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6118                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
6119             break;
6120 
6121         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
6122             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6123                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
6124             break;
6125         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
6126             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6127                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
6128             break;
6129         case VDEC_MSG_RESP_INPUT_FLUSHED:
6130         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
6131 
6132             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
6133                vdec_msg->msgdata.input_frame_clientdata; */
6134 
6135             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
6136             omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index;
6137             if (omxhdr == NULL ||
6138                     ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) ) {
6139                 omxhdr = NULL;
6140                 vdec_msg->status_code = VDEC_S_EFATAL;
6141             }
6142 
6143             omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
6144                     OMX_COMPONENT_GENERATE_EBD);
6145             break;
6146         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
6147             int64_t *timestamp;
6148             timestamp = (int64_t *) malloc(sizeof(int64_t));
6149             if (timestamp) {
6150                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
6151                 omx->post_event ((unsigned int)timestamp, vdec_msg->status_code,
6152                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
6153                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
6154                         vdec_msg->msgdata.output_frame.time_stamp);
6155             }
6156             break;
6157         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
6158         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
6159 
6160             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
6161             omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index;
6162             DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)",
6163                     omxhdr, vdec_msg->msgdata.output_frame.time_stamp,
6164                     vdec_msg->msgdata.output_frame.pic_type);
6165 
6166             if (omxhdr && omxhdr->pOutputPortPrivate &&
6167                     ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) &&
6168                     (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
6169                       - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount)) {
6170                 if ( vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
6171                     omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
6172                     omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
6173                     omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
6174                     omxhdr->nFlags = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nFlags;
6175 
6176                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
6177                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
6178                         //rc = -1;
6179                     }
6180                     if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
6181                         omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6182                     }
6183                     vdec_msg->msgdata.output_frame.bufferaddr =
6184                         omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
6185                     if (omxhdr->nFilledLen && (((unsigned)omx->rectangle.nLeft !=
6186                                     vdec_msg->msgdata.output_frame.framesize.left)
6187                                 || ((unsigned)omx->rectangle.nTop != vdec_msg->msgdata.output_frame.framesize.top)
6188                                 || (omx->rectangle.nWidth != vdec_msg->msgdata.output_frame.framesize.right)
6189                                 || (omx->rectangle.nHeight != vdec_msg->msgdata.output_frame.framesize.bottom))) {
6190                         omx->rectangle.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
6191                         omx->rectangle.nTop = vdec_msg->msgdata.output_frame.framesize.top;
6192                         omx->rectangle.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
6193                         omx->rectangle.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
6194                         DEBUG_PRINT_HIGH("Crop information has changed");
6195                         omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexConfigCommonOutputCrop,
6196                                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6197                     }
6198                     output_respbuf = (struct vdec_output_frameinfo *)\
6199                                      omxhdr->pOutputPortPrivate;
6200                     output_respbuf->len = vdec_msg->msgdata.output_frame.len;
6201                     output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
6202                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
6203                         output_respbuf->pic_type = PICTURE_TYPE_I;
6204                     }
6205                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
6206                         output_respbuf->pic_type = PICTURE_TYPE_P;
6207                     }
6208                     if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
6209                         output_respbuf->pic_type = PICTURE_TYPE_B;
6210                     }
6211 
6212                     if (omx->output_use_buffer)
6213                         memcpy ( omxhdr->pBuffer, (void *)
6214                                 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
6215                                  (unsigned long)vdec_msg->msgdata.output_frame.offset),
6216                                 vdec_msg->msgdata.output_frame.len);
6217                 } else
6218                     omxhdr->nFilledLen = 0;
6219                 omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code,
6220                         OMX_COMPONENT_GENERATE_FBD);
6221             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS)
6222                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
6223                         OMX_COMPONENT_GENERATE_EOS_DONE);
6224             else
6225                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
6226                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6227             break;
6228         case VDEC_MSG_EVT_CONFIG_CHANGED:
6229             DEBUG_PRINT_HIGH("Port settings changed");
6230             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
6231                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6232             break;
6233         case VDEC_MSG_EVT_INFO_CONFIG_CHANGED:
6234             {
6235                 DEBUG_PRINT_HIGH("Port settings changed info");
6236                 // get_buffer_req and populate port defn structure
6237                 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6238                 struct v4l2_format fmt;
6239                 int ret;
6240                 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6241                 ret = ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
6242                 omx->update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
6243                 omx->drv_ctx.video_resolution.stride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
6244                 omx->drv_ctx.video_resolution.scan_lines = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
6245                 omx->m_port_def.nPortIndex = 1;
6246                 eRet = omx->update_portdef(&(omx->m_port_def));
6247                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6248                         OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG);
6249                 break;
6250             }
6251         default:
6252             break;
6253     }
6254     return rc;
6255 }
6256 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6257 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
6258         OMX_HANDLETYPE hComp,
6259         OMX_BUFFERHEADERTYPE *buffer
6260         )
6261 {
6262     unsigned address,p2,id;
6263     DEBUG_PRINT_LOW("Empty this arbitrary");
6264 
6265     if (buffer == NULL) {
6266         return OMX_ErrorBadParameter;
6267     }
6268     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6269     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %d, timestamp %u",
6270             buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp);
6271 
6272     /* return zero length and not an EOS buffer */
6273     /* return buffer if input flush in progress */
6274     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
6275                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
6276         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
6277         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
6278         return OMX_ErrorNone;
6279     }
6280 
6281     if (psource_frame == NULL) {
6282         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp);
6283         psource_frame = buffer;
6284         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
6285         push_input_buffer (hComp);
6286     } else {
6287         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
6288         if (!m_input_pending_q.insert_entry((unsigned)buffer, (unsigned)NULL,
6289                     (unsigned)NULL)) {
6290             return OMX_ErrorBadParameter;
6291         }
6292     }
6293 
6294 
6295     return OMX_ErrorNone;
6296 }
6297 
push_input_buffer(OMX_HANDLETYPE hComp)6298 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
6299 {
6300     unsigned address,p2,id;
6301     OMX_ERRORTYPE ret = OMX_ErrorNone;
6302 
6303     if (pdest_frame == NULL || psource_frame == NULL) {
6304         /*Check if we have a destination buffer*/
6305         if (pdest_frame == NULL) {
6306             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
6307             if (m_input_free_q.m_size) {
6308                 m_input_free_q.pop_entry(&address,&p2,&id);
6309                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
6310                 pdest_frame->nFilledLen = 0;
6311                 pdest_frame->nTimeStamp = LLONG_MAX;
6312                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
6313             }
6314         }
6315 
6316         /*Check if we have a destination buffer*/
6317         if (psource_frame == NULL) {
6318             DEBUG_PRINT_LOW("Get a source buffer from the queue");
6319             if (m_input_pending_q.m_size) {
6320                 m_input_pending_q.pop_entry(&address,&p2,&id);
6321                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
6322                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame,
6323                         psource_frame->nTimeStamp);
6324                 DEBUG_PRINT_LOW("Next source Buffer flag %d length %d",
6325                         psource_frame->nFlags,psource_frame->nFilledLen);
6326 
6327             }
6328         }
6329 
6330     }
6331 
6332     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
6333         switch (codec_type_parse) {
6334             case CODEC_TYPE_MPEG4:
6335             case CODEC_TYPE_H263:
6336             case CODEC_TYPE_MPEG2:
6337                 ret =  push_input_sc_codec(hComp);
6338                 break;
6339             case CODEC_TYPE_H264:
6340                 ret = push_input_h264(hComp);
6341                 break;
6342             case CODEC_TYPE_HEVC:
6343                 ret = push_input_hevc(hComp);
6344                 break;
6345             case CODEC_TYPE_VC1:
6346                 ret = push_input_vc1(hComp);
6347                 break;
6348             default:
6349                 break;
6350         }
6351         if (ret != OMX_ErrorNone) {
6352             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
6353             omx_report_error ();
6354             break;
6355         }
6356     }
6357 
6358     return ret;
6359 }
6360 
push_input_sc_codec(OMX_HANDLETYPE hComp)6361 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
6362 {
6363     OMX_U32 partial_frame = 1;
6364     OMX_BOOL generate_ebd = OMX_TRUE;
6365     unsigned address,p2,id;
6366 
6367     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %d",
6368             psource_frame,psource_frame->nTimeStamp);
6369     if (m_frame_parser.parse_sc_frame(psource_frame,
6370                 pdest_frame,&partial_frame) == -1) {
6371         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6372         return OMX_ErrorBadParameter;
6373     }
6374 
6375     if (partial_frame == 0) {
6376         DEBUG_PRINT_LOW("Frame size %d source %p frame count %d",
6377                 pdest_frame->nFilledLen,psource_frame,frame_count);
6378 
6379 
6380         DEBUG_PRINT_LOW("TimeStamp updated %d",pdest_frame->nTimeStamp);
6381         /*First Parsed buffer will have only header Hence skip*/
6382         if (frame_count == 0) {
6383             DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
6384 
6385             if (codec_type_parse == CODEC_TYPE_MPEG4 ||
6386                     codec_type_parse == CODEC_TYPE_DIVX) {
6387                 mp4StreamType psBits;
6388                 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
6389                 psBits.numBytes = pdest_frame->nFilledLen;
6390                 mp4_headerparser.parseHeader(&psBits);
6391             }
6392 
6393             frame_count++;
6394         } else {
6395             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6396             if (pdest_frame->nFilledLen) {
6397                 /*Push the frame to the Decoder*/
6398                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6399                     return OMX_ErrorBadParameter;
6400                 }
6401                 frame_count++;
6402                 pdest_frame = NULL;
6403 
6404                 if (m_input_free_q.m_size) {
6405                     m_input_free_q.pop_entry(&address,&p2,&id);
6406                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6407                     pdest_frame->nFilledLen = 0;
6408                 }
6409             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
6410                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
6411                 m_input_free_q.insert_entry((unsigned) pdest_frame, (unsigned)NULL,
6412                         (unsigned)NULL);
6413                 pdest_frame = NULL;
6414             }
6415         }
6416     } else {
6417         DEBUG_PRINT_LOW("Not a Complete Frame %d",pdest_frame->nFilledLen);
6418         /*Check if Destination Buffer is full*/
6419         if (pdest_frame->nAllocLen ==
6420                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
6421             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
6422             return OMX_ErrorStreamCorrupt;
6423         }
6424     }
6425 
6426     if (psource_frame->nFilledLen == 0) {
6427         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6428             if (pdest_frame) {
6429                 pdest_frame->nFlags |= psource_frame->nFlags;
6430                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x",
6431                         pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6432                 DEBUG_PRINT_LOW("Found a frame size = %d number = %d",
6433                         pdest_frame->nFilledLen,frame_count++);
6434                 /*Push the frame to the Decoder*/
6435                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6436                     return OMX_ErrorBadParameter;
6437                 }
6438                 frame_count++;
6439                 pdest_frame = NULL;
6440             } else {
6441                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
6442                 generate_ebd = OMX_FALSE;
6443             }
6444         }
6445         if (generate_ebd) {
6446             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
6447             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6448             psource_frame = NULL;
6449 
6450             if (m_input_pending_q.m_size) {
6451                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
6452                 m_input_pending_q.pop_entry(&address,&p2,&id);
6453                 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6454                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame,
6455                         psource_frame->nTimeStamp);
6456                 DEBUG_PRINT_LOW("Next source Buffer flag %d length %d",
6457                         psource_frame->nFlags,psource_frame->nFilledLen);
6458             }
6459         }
6460     }
6461     return OMX_ErrorNone;
6462 }
6463 
push_input_h264(OMX_HANDLETYPE hComp)6464 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
6465 {
6466     OMX_U32 partial_frame = 1;
6467     unsigned address,p2,id;
6468     OMX_BOOL isNewFrame = OMX_FALSE;
6469     OMX_BOOL generate_ebd = OMX_TRUE;
6470 
6471     if (h264_scratch.pBuffer == NULL) {
6472         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
6473         return OMX_ErrorBadParameter;
6474     }
6475     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %d "
6476             "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal);
6477     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
6478     if (h264_scratch.nFilledLen && look_ahead_nal) {
6479         look_ahead_nal = false;
6480         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6481                 h264_scratch.nFilledLen) {
6482             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6483                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
6484             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6485             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
6486             h264_scratch.nFilledLen = 0;
6487         } else {
6488             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
6489             return OMX_ErrorBadParameter;
6490         }
6491     }
6492     if (nal_length == 0) {
6493         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
6494         if (m_frame_parser.parse_sc_frame(psource_frame,
6495                     &h264_scratch,&partial_frame) == -1) {
6496             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6497             return OMX_ErrorBadParameter;
6498         }
6499     } else {
6500         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
6501         if (m_frame_parser.parse_h264_nallength(psource_frame,
6502                     &h264_scratch,&partial_frame) == -1) {
6503             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
6504             return OMX_ErrorBadParameter;
6505         }
6506     }
6507 
6508     if (partial_frame == 0) {
6509         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
6510             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
6511             nal_count++;
6512             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
6513             h264_scratch.nFlags = psource_frame->nFlags;
6514         } else {
6515             DEBUG_PRINT_LOW("Parsed New NAL Length = %d",h264_scratch.nFilledLen);
6516             if (h264_scratch.nFilledLen) {
6517                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
6518                         NALU_TYPE_SPS);
6519 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6520                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
6521                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6522                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
6523                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6524                     // If timeinfo is present frame info from SEI is already processed
6525                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6526                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
6527 #endif
6528                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
6529                 nal_count++;
6530                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
6531                     pdest_frame->nTimeStamp = h264_last_au_ts;
6532                     pdest_frame->nFlags = h264_last_au_flags;
6533 #ifdef PANSCAN_HDLR
6534                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6535                         h264_parser->update_panscan_data(h264_last_au_ts);
6536 #endif
6537                 }
6538                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
6539                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
6540                     h264_last_au_ts = h264_scratch.nTimeStamp;
6541                     h264_last_au_flags = h264_scratch.nFlags;
6542 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6543                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
6544                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
6545                         if (!VALID_TS(h264_last_au_ts))
6546                             h264_last_au_ts = ts_in_sei;
6547                     }
6548 #endif
6549                 } else
6550                     h264_last_au_ts = LLONG_MAX;
6551             }
6552 
6553             if (!isNewFrame) {
6554                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6555                         h264_scratch.nFilledLen) {
6556                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %d",
6557                             h264_scratch.nFilledLen);
6558                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6559                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
6560                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6561                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
6562                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6563                     h264_scratch.nFilledLen = 0;
6564                 } else {
6565                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
6566                     return OMX_ErrorBadParameter;
6567                 }
6568             } else {
6569                 look_ahead_nal = true;
6570                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x",
6571                         pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6572                 DEBUG_PRINT_LOW("Found a frame size = %d number = %d",
6573                         pdest_frame->nFilledLen,frame_count++);
6574 
6575                 if (pdest_frame->nFilledLen == 0) {
6576                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
6577                     look_ahead_nal = false;
6578                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6579                             h264_scratch.nFilledLen) {
6580                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6581                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6582                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6583                         h264_scratch.nFilledLen = 0;
6584                     } else {
6585                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
6586                         return OMX_ErrorBadParameter;
6587                     }
6588                 } else {
6589                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
6590                         DEBUG_PRINT_LOW("Reset the EOS Flag");
6591                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6592                     }
6593                     /*Push the frame to the Decoder*/
6594                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6595                         return OMX_ErrorBadParameter;
6596                     }
6597                     //frame_count++;
6598                     pdest_frame = NULL;
6599                     if (m_input_free_q.m_size) {
6600                         m_input_free_q.pop_entry(&address,&p2,&id);
6601                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6602                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
6603                         pdest_frame->nFilledLen = 0;
6604                         pdest_frame->nFlags = 0;
6605                         pdest_frame->nTimeStamp = LLONG_MAX;
6606                     }
6607                 }
6608             }
6609         }
6610     } else {
6611         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
6612         /*Check if Destination Buffer is full*/
6613         if (h264_scratch.nAllocLen ==
6614                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
6615             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
6616             return OMX_ErrorStreamCorrupt;
6617         }
6618     }
6619 
6620     if (!psource_frame->nFilledLen) {
6621         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
6622 
6623         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6624             if (pdest_frame) {
6625                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
6626                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6627                         h264_scratch.nFilledLen) {
6628                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6629                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
6630                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6631                     h264_scratch.nFilledLen = 0;
6632                 } else {
6633                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
6634                     return OMX_ErrorBadParameter;
6635                 }
6636                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
6637                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
6638 
6639                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%d TimeStamp = %x",
6640                         pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6641                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
6642 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6643                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
6644                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
6645                     if (!VALID_TS(pdest_frame->nTimeStamp))
6646                         pdest_frame->nTimeStamp = ts_in_sei;
6647                 }
6648 #endif
6649                 /*Push the frame to the Decoder*/
6650                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6651                     return OMX_ErrorBadParameter;
6652                 }
6653                 frame_count++;
6654                 pdest_frame = NULL;
6655             } else {
6656                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %d",
6657                         pdest_frame,h264_scratch.nFilledLen);
6658                 generate_ebd = OMX_FALSE;
6659             }
6660         }
6661     }
6662     if (generate_ebd && !psource_frame->nFilledLen) {
6663         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6664         psource_frame = NULL;
6665         if (m_input_pending_q.m_size) {
6666             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
6667             m_input_pending_q.pop_entry(&address,&p2,&id);
6668             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6669             DEBUG_PRINT_LOW("Next source Buffer flag %d src length %d",
6670                     psource_frame->nFlags,psource_frame->nFilledLen);
6671         }
6672     }
6673     return OMX_ErrorNone;
6674 }
6675 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)6676 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
6677 {
6678     OMX_ERRORTYPE rc = OMX_ErrorNone;
6679     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
6680         memcpy ((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
6681         if (pDst->nTimeStamp == LLONG_MAX) {
6682             pDst->nTimeStamp = pSrc->nTimeStamp;
6683             DEBUG_PRINT_LOW("Assign Dst nTimeStamp=%lld", pDst->nTimeStamp);
6684         }
6685         pDst->nFilledLen += pSrc->nFilledLen;
6686         pSrc->nFilledLen = 0;
6687     } else {
6688         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
6689         rc = OMX_ErrorBadParameter;
6690     }
6691     return rc;
6692 }
6693 
push_input_hevc(OMX_HANDLETYPE hComp)6694 OMX_ERRORTYPE omx_vdec::push_input_hevc (OMX_HANDLETYPE hComp)
6695 {
6696     OMX_U32 partial_frame = 1;
6697     unsigned address,p2,id;
6698     OMX_BOOL isNewFrame = OMX_FALSE;
6699     OMX_BOOL generate_ebd = OMX_TRUE;
6700     OMX_ERRORTYPE rc = OMX_ErrorNone;
6701 
6702     if (h264_scratch.pBuffer == NULL) {
6703         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
6704         return OMX_ErrorBadParameter;
6705     }
6706 
6707 
6708     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %d has look_ahead_nal %d pdest_frame nFilledLen %d nTimeStamp %lld",
6709             h264_scratch.nFilledLen, look_ahead_nal, pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
6710 
6711     if (h264_scratch.nFilledLen && look_ahead_nal) {
6712         look_ahead_nal = false;
6713 
6714         // copy the lookahead buffer in the scratch
6715         rc = copy_buffer(pdest_frame, &h264_scratch);
6716         if (rc != OMX_ErrorNone) {
6717             return rc;
6718         }
6719     }
6720     if (nal_length == 0) {
6721         if (m_frame_parser.parse_sc_frame(psource_frame,
6722                     &h264_scratch,&partial_frame) == -1) {
6723             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6724             return OMX_ErrorBadParameter;
6725         }
6726     } else {
6727         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
6728         if (m_frame_parser.parse_h264_nallength(psource_frame,
6729                     &h264_scratch,&partial_frame) == -1) {
6730             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
6731             return OMX_ErrorBadParameter;
6732         }
6733     }
6734 
6735     if (partial_frame == 0) {
6736         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
6737             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
6738             nal_count++;
6739             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
6740             h264_scratch.nFlags = psource_frame->nFlags;
6741         } else {
6742             DEBUG_PRINT_LOW("Parsed New NAL Length = %d",h264_scratch.nFilledLen);
6743             if (h264_scratch.nFilledLen) {
6744                 mHEVCutils.isNewFrame(&h264_scratch, 0, isNewFrame);
6745                 nal_count++;
6746             }
6747 
6748             if (!isNewFrame) {
6749                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %d nTimestamp %lld, pdest_frame nFilledLen %d nTimestamp %lld",
6750                         h264_scratch.nFilledLen, h264_scratch.nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
6751                 rc = copy_buffer(pdest_frame, &h264_scratch);
6752                 if ( rc != OMX_ErrorNone) {
6753                     return rc;
6754                 }
6755             } else {
6756                 look_ahead_nal = true;
6757                 if (pdest_frame->nFilledLen == 0) {
6758                     look_ahead_nal = false;
6759                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
6760                     rc = copy_buffer(pdest_frame, &h264_scratch);
6761                     if ( rc != OMX_ErrorNone ) {
6762                         return OMX_ErrorBadParameter;
6763                     }
6764                 } else {
6765                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
6766                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6767                     }
6768 
6769                     DEBUG_PRINT_LOW("FrameDetecetd # %d pdest_frame nFilledLen %d nTimeStamp %lld, look_ahead_nal in h264_scratch nFilledLen %d nTimeStamp %lld",
6770                             frame_count++, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
6771                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6772                         return OMX_ErrorBadParameter;
6773                     }
6774                     pdest_frame = NULL;
6775                     if (m_input_free_q.m_size) {
6776                         m_input_free_q.pop_entry(&address,&p2,&id);
6777                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6778                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p",pdest_frame);
6779                         pdest_frame->nFilledLen = 0;
6780                         pdest_frame->nFlags = 0;
6781                         pdest_frame->nTimeStamp = LLONG_MAX;
6782                     }
6783                 }
6784             }
6785         }
6786     } else {
6787         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %d nTimeStamp %lld, pdest_frame nFilledLen %d nTimeStamp %lld, h264_scratch nFilledLen %d nTimeStamp %lld",
6788                 psource_frame->nFilledLen, psource_frame->nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
6789 
6790         /*Check if Destination Buffer is full*/
6791         if (h264_scratch.nAllocLen ==
6792                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
6793             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
6794             return OMX_ErrorStreamCorrupt;
6795         }
6796     }
6797 
6798     if (!psource_frame->nFilledLen) {
6799         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
6800 
6801         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6802             if (pdest_frame) {
6803                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
6804                 rc = copy_buffer(pdest_frame, &h264_scratch);
6805                 if ( rc != OMX_ErrorNone ) {
6806                     return rc;
6807                 }
6808                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
6809                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
6810 
6811                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%d TimeStamp = %lld",
6812                         frame_count, pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6813 
6814                 /*Push the frame to the Decoder*/
6815                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6816                     return OMX_ErrorBadParameter;
6817                 }
6818                 frame_count++;
6819                 pdest_frame = NULL;
6820             } else {
6821                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %d",
6822                         pdest_frame,h264_scratch.nFilledLen);
6823                 generate_ebd = OMX_FALSE;
6824             }
6825         }
6826     }
6827     if (generate_ebd && !psource_frame->nFilledLen) {
6828         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6829         psource_frame = NULL;
6830         if (m_input_pending_q.m_size) {
6831             m_input_pending_q.pop_entry(&address,&p2,&id);
6832             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6833             DEBUG_PRINT_LOW("Next source Buffer flag %d nFilledLen %d, nTimeStamp %lld",
6834                     psource_frame->nFlags,psource_frame->nFilledLen, psource_frame->nTimeStamp);
6835         }
6836     }
6837     return OMX_ErrorNone;
6838 }
6839 
push_input_vc1(OMX_HANDLETYPE hComp)6840 OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
6841 {
6842     OMX_U8 *buf, *pdest;
6843     OMX_U32 partial_frame = 1;
6844     OMX_U32 buf_len, dest_len;
6845 
6846     if (first_frame == 0) {
6847         first_frame = 1;
6848         DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
6849         if (!m_vendor_config.pData) {
6850             DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
6851             buf = psource_frame->pBuffer;
6852             buf_len = psource_frame->nFilledLen;
6853 
6854             if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
6855                     VC1_SP_MP_START_CODE) {
6856                 m_vc1_profile = VC1_SP_MP_RCV;
6857             } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
6858                 m_vc1_profile = VC1_AP;
6859             } else {
6860                 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
6861                 return OMX_ErrorStreamCorrupt;
6862             }
6863         } else {
6864             pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
6865                 pdest_frame->nOffset;
6866             dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
6867                     pdest_frame->nOffset);
6868 
6869             if (dest_len < m_vendor_config.nDataSize) {
6870                 DEBUG_PRINT_ERROR("Destination buffer full");
6871                 return OMX_ErrorBadParameter;
6872             } else {
6873                 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
6874                 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
6875             }
6876         }
6877     }
6878 
6879     switch (m_vc1_profile) {
6880         case VC1_AP:
6881             DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
6882             if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
6883                 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
6884                 return OMX_ErrorBadParameter;
6885             }
6886             break;
6887 
6888         case VC1_SP_MP_RCV:
6889         default:
6890             DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
6891             return OMX_ErrorBadParameter;
6892     }
6893     return OMX_ErrorNone;
6894 }
6895 
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)6896 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
6897         OMX_U32 alignment)
6898 {
6899     struct pmem_allocation allocation;
6900     allocation.size = buffer_size;
6901     allocation.align = clip2(alignment);
6902     if (allocation.align < 4096) {
6903         allocation.align = 4096;
6904     }
6905     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
6906         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
6907                 allocation.align, allocation.size);
6908         return false;
6909     }
6910     return true;
6911 }
6912 #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)6913 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
6914         OMX_U32 alignment, struct ion_allocation_data *alloc_data,
6915         struct ion_fd_data *fd_data, int flag)
6916 {
6917     int fd = -EINVAL;
6918     int rc = -EINVAL;
6919     int ion_dev_flag;
6920     struct vdec_ion ion_buf_info;
6921     if (!alloc_data || buffer_size <= 0 || !fd_data) {
6922         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
6923         return -EINVAL;
6924     }
6925     ion_dev_flag = O_RDONLY;
6926     fd = open (MEM_DEVICE, ion_dev_flag);
6927     if (fd < 0) {
6928         DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
6929         return fd;
6930     }
6931     alloc_data->flags = 0;
6932     if (!secure_mode && (flag & ION_FLAG_CACHED)) {
6933         alloc_data->flags |= ION_FLAG_CACHED;
6934     }
6935     alloc_data->len = buffer_size;
6936     alloc_data->align = clip2(alignment);
6937     if (alloc_data->align < 4096) {
6938         alloc_data->align = 4096;
6939     }
6940     if ((secure_mode) && (flag & ION_SECURE))
6941         alloc_data->flags |= ION_SECURE;
6942 
6943 #ifdef _HEVC_USE_ADSP_HEAP_
6944     alloc_data->ION_HEAP_MASK = ION_HEAP(ION_ADSP_HEAP_ID);
6945 #else
6946     alloc_data->ION_HEAP_MASK = ION_HEAP(ION_IOMMU_HEAP_ID);
6947 #endif
6948     if (secure_mode) {
6949         alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID);
6950     }
6951     rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
6952     if (rc || !alloc_data->handle) {
6953         DEBUG_PRINT_ERROR("ION ALLOC memory failed ");
6954         alloc_data->handle = NULL;
6955         close(fd);
6956         fd = -ENOMEM;
6957         return fd;
6958     }
6959     fd_data->handle = alloc_data->handle;
6960     rc = ioctl(fd,ION_IOC_MAP,fd_data);
6961     if (rc) {
6962         DEBUG_PRINT_ERROR("ION MAP failed ");
6963         ion_buf_info.ion_alloc_data = *alloc_data;
6964         ion_buf_info.ion_device_fd = fd;
6965         ion_buf_info.fd_ion_data = *fd_data;
6966         free_ion_memory(&ion_buf_info);
6967         fd_data->fd =-1;
6968         fd = -ENOMEM;
6969     }
6970 
6971     return fd;
6972 }
6973 
free_ion_memory(struct vdec_ion * buf_ion_info)6974 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
6975 {
6976 
6977     if (!buf_ion_info) {
6978         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
6979         return;
6980     }
6981     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
6982                 &buf_ion_info->ion_alloc_data.handle)) {
6983         DEBUG_PRINT_ERROR("ION: free failed" );
6984     }
6985     close(buf_ion_info->ion_device_fd);
6986     buf_ion_info->ion_device_fd = -1;
6987     buf_ion_info->ion_alloc_data.handle = NULL;
6988     buf_ion_info->fd_ion_data.fd = -1;
6989 }
6990 #endif
free_output_buffer_header()6991 void omx_vdec::free_output_buffer_header()
6992 {
6993     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
6994     output_use_buffer = false;
6995     ouput_egl_buffers = false;
6996 
6997     if (m_out_mem_ptr) {
6998         free (m_out_mem_ptr);
6999         m_out_mem_ptr = NULL;
7000     }
7001 
7002     if (m_platform_list) {
7003         free(m_platform_list);
7004         m_platform_list = NULL;
7005     }
7006 
7007     if (drv_ctx.ptr_respbuffer) {
7008         free (drv_ctx.ptr_respbuffer);
7009         drv_ctx.ptr_respbuffer = NULL;
7010     }
7011     if (drv_ctx.ptr_outputbuffer) {
7012         free (drv_ctx.ptr_outputbuffer);
7013         drv_ctx.ptr_outputbuffer = NULL;
7014     }
7015 #ifdef USE_ION
7016     if (drv_ctx.op_buf_ion_info) {
7017         DEBUG_PRINT_LOW("Free o/p ion context");
7018         free(drv_ctx.op_buf_ion_info);
7019         drv_ctx.op_buf_ion_info = NULL;
7020     }
7021 #endif
7022 }
7023 
free_input_buffer_header()7024 void omx_vdec::free_input_buffer_header()
7025 {
7026     input_use_buffer = false;
7027     if (arbitrary_bytes) {
7028         if (m_frame_parser.mutils) {
7029             DEBUG_PRINT_LOW("Free utils parser");
7030             delete (m_frame_parser.mutils);
7031             m_frame_parser.mutils = NULL;
7032         }
7033 
7034         if (m_inp_heap_ptr) {
7035             DEBUG_PRINT_LOW("Free input Heap Pointer");
7036             free (m_inp_heap_ptr);
7037             m_inp_heap_ptr = NULL;
7038         }
7039 
7040         if (m_phdr_pmem_ptr) {
7041             DEBUG_PRINT_LOW("Free input pmem header Pointer");
7042             free (m_phdr_pmem_ptr);
7043             m_phdr_pmem_ptr = NULL;
7044         }
7045     }
7046     if (m_inp_mem_ptr) {
7047         DEBUG_PRINT_LOW("Free input pmem Pointer area");
7048         free (m_inp_mem_ptr);
7049         m_inp_mem_ptr = NULL;
7050     }
7051     if (drv_ctx.ptr_inputbuffer) {
7052         DEBUG_PRINT_LOW("Free Driver Context pointer");
7053         free (drv_ctx.ptr_inputbuffer);
7054         drv_ctx.ptr_inputbuffer = NULL;
7055     }
7056 #ifdef USE_ION
7057     if (drv_ctx.ip_buf_ion_info) {
7058         DEBUG_PRINT_LOW("Free ion context");
7059         free(drv_ctx.ip_buf_ion_info);
7060         drv_ctx.ip_buf_ion_info = NULL;
7061     }
7062 #endif
7063 }
7064 
stream_off(OMX_U32 port)7065 int omx_vdec::stream_off(OMX_U32 port)
7066 {
7067     enum v4l2_buf_type btype;
7068     int rc = 0;
7069     enum v4l2_ports v4l2_port = OUTPUT_PORT;
7070 
7071     if (port == OMX_CORE_INPUT_PORT_INDEX) {
7072         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7073         v4l2_port = OUTPUT_PORT;
7074     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7075         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7076         v4l2_port = CAPTURE_PORT;
7077     } else if (port == OMX_ALL) {
7078         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
7079         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
7080 
7081         if (!rc_input)
7082             return rc_input;
7083         else
7084             return rc_output;
7085     }
7086 
7087     if (!streaming[v4l2_port]) {
7088         // already streamed off, warn and move on
7089         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
7090                 " which is already streamed off", v4l2_port);
7091         return 0;
7092     }
7093 
7094     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
7095 
7096     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
7097     if (rc) {
7098         /*TODO: How to handle this case */
7099         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
7100     } else {
7101         streaming[v4l2_port] = false;
7102     }
7103 
7104     return rc;
7105 }
7106 
get_buffer_req(vdec_allocatorproperty * buffer_prop)7107 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
7108 {
7109     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7110     struct v4l2_requestbuffers bufreq;
7111     unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
7112     struct v4l2_format fmt;
7113     int ret = 0;
7114 
7115     bufreq.memory = V4L2_MEMORY_USERPTR;
7116     bufreq.count = 1;
7117     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7118         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7119         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7120         fmt.fmt.pix_mp.pixelformat = output_capability;
7121     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7122         bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7123         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7124         fmt.fmt.pix_mp.pixelformat = capture_capability;
7125     } else {
7126         eRet = OMX_ErrorBadParameter;
7127     }
7128     if (eRet==OMX_ErrorNone) {
7129         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7130     }
7131     if (ret) {
7132         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7133         /*TODO: How to handle this case */
7134         eRet = OMX_ErrorInsufficientResources;
7135         return eRet;
7136     } else {
7137         buffer_prop->actualcount = bufreq.count;
7138         buffer_prop->mincount = bufreq.count;
7139         DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
7140     }
7141     DEBUG_PRINT_HIGH("GetBufReq: ActCnt(%d) Size(%d), BufType(%d)",
7142             buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type);
7143 
7144     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7145     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7146 
7147     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7148 
7149     update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
7150     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
7151         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
7152     DEBUG_PRINT_HIGH("Buffer Size (plane[0].sizeimage) = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
7153 
7154     if (ret) {
7155         /*TODO: How to handle this case */
7156         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7157         eRet = OMX_ErrorInsufficientResources;
7158     } else {
7159         int extra_idx = 0;
7160         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
7161         buf_size = buffer_prop->buffer_size;
7162         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7163         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7164             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
7165         } else if (extra_idx >= VIDEO_MAX_PLANES) {
7166             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
7167             return OMX_ErrorBadParameter;
7168         }
7169         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
7170             DEBUG_PRINT_HIGH("Frame info extra data enabled!");
7171             client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
7172         }
7173         if (client_extradata & OMX_INTERLACE_EXTRADATA) {
7174             client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE;
7175         }
7176         if (client_extradata & OMX_PORTDEF_EXTRADATA) {
7177             client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE;
7178             DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d",
7179                     client_extra_data_size);
7180         }
7181         if (client_extra_data_size) {
7182             client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
7183             buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
7184         }
7185         drv_ctx.extradata_info.size = buffer_prop->actualcount * extra_data_size;
7186         drv_ctx.extradata_info.count = buffer_prop->actualcount;
7187         drv_ctx.extradata_info.buffer_size = extra_data_size;
7188         buf_size += client_extra_data_size;
7189         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7190         DEBUG_PRINT_HIGH("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d) BufType(%d)",
7191                 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size, buffer_prop->buffer_type);
7192         if (in_reconfig) // BufReq will be set to driver when port is disabled
7193             buffer_prop->buffer_size = buf_size;
7194         else if (buf_size != buffer_prop->buffer_size) {
7195             buffer_prop->buffer_size = buf_size;
7196             eRet = set_buffer_req(buffer_prop);
7197         }
7198     }
7199     DEBUG_PRINT_HIGH("GetBufReq OUT: ActCnt(%d) Size(%d), BufType(%d)",
7200             buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type);
7201     return eRet;
7202 }
7203 
set_buffer_req(vdec_allocatorproperty * buffer_prop)7204 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
7205 {
7206     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7207     unsigned buf_size = 0;
7208     struct v4l2_format fmt;
7209     struct v4l2_requestbuffers bufreq;
7210     int ret;
7211     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)",
7212             buffer_prop->actualcount, buffer_prop->buffer_size);
7213     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7214     if (buf_size != buffer_prop->buffer_size) {
7215         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
7216                 buffer_prop->buffer_size, buf_size);
7217         eRet = OMX_ErrorBadParameter;
7218     } else {
7219         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7220         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7221 
7222         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7223             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7224             fmt.fmt.pix_mp.pixelformat = output_capability;
7225         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7226             fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7227             fmt.fmt.pix_mp.pixelformat = capture_capability;
7228         } else {
7229             eRet = OMX_ErrorBadParameter;
7230         }
7231 
7232         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
7233         if (ret) {
7234             /*TODO: How to handle this case */
7235             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
7236             eRet = OMX_ErrorInsufficientResources;
7237         }
7238 
7239         bufreq.memory = V4L2_MEMORY_USERPTR;
7240         bufreq.count = buffer_prop->actualcount;
7241         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7242             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7243         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7244             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7245         } else {
7246             eRet = OMX_ErrorBadParameter;
7247         }
7248 
7249         if (eRet==OMX_ErrorNone) {
7250             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7251         }
7252 
7253         if (ret) {
7254             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
7255             /*TODO: How to handle this case */
7256             eRet = OMX_ErrorInsufficientResources;
7257         } else if (bufreq.count < buffer_prop->actualcount) {
7258             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
7259                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
7260                     buffer_prop->actualcount, bufreq.count);
7261             eRet = OMX_ErrorInsufficientResources;
7262         } else {
7263             if (!client_buffers.update_buffer_req()) {
7264                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
7265                 eRet = OMX_ErrorInsufficientResources;
7266             }
7267         }
7268     }
7269     if (!eRet && buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7270         // need to update extradata buffers also
7271         drv_ctx.extradata_info.size = buffer_prop->actualcount * drv_ctx.extradata_info.buffer_size;
7272         drv_ctx.extradata_info.count = buffer_prop->actualcount;
7273     }
7274     return eRet;
7275 }
7276 
update_picture_resolution()7277 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
7278 {
7279     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7280     return eRet;
7281 }
7282 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)7283 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
7284 {
7285     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7286     if (!portDefn) {
7287         return OMX_ErrorBadParameter;
7288     }
7289     DEBUG_PRINT_LOW("omx_vdec::update_portdef");
7290     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
7291     portDefn->nSize = sizeof(portDefn);
7292     portDefn->eDomain    = OMX_PortDomainVideo;
7293     if (drv_ctx.frame_rate.fps_denominator > 0)
7294         portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator /
7295             drv_ctx.frame_rate.fps_denominator;
7296     else {
7297         DEBUG_PRINT_ERROR("Error: Divide by zero");
7298         return OMX_ErrorBadParameter;
7299     }
7300     if (0 == portDefn->nPortIndex) {
7301         portDefn->eDir =  OMX_DirInput;
7302         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
7303         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
7304         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
7305         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
7306         portDefn->format.video.eCompressionFormat = eCompressionFormat;
7307         portDefn->bEnabled   = m_inp_bEnabled;
7308         portDefn->bPopulated = m_inp_bPopulated;
7309     } else if (1 == portDefn->nPortIndex) {
7310         unsigned int buf_size = 0;
7311         if (!client_buffers.update_buffer_req()) {
7312             DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
7313             return OMX_ErrorHardware;
7314         }
7315         if (!client_buffers.get_buffer_req(buf_size)) {
7316             DEBUG_PRINT_ERROR("update buffer requirements");
7317             return OMX_ErrorHardware;
7318         }
7319         portDefn->nBufferSize = buf_size;
7320         portDefn->eDir =  OMX_DirOutput;
7321         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
7322         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
7323         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7324         portDefn->bEnabled   = m_out_bEnabled;
7325         portDefn->bPopulated = m_out_bPopulated;
7326         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
7327             DEBUG_PRINT_ERROR("Error in getting color format");
7328             return OMX_ErrorHardware;
7329         }
7330     } else {
7331         portDefn->eDir = OMX_DirMax;
7332         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
7333                 (int)portDefn->nPortIndex);
7334         eRet = OMX_ErrorBadPortIndex;
7335     }
7336     portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
7337     portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
7338     portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
7339     portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
7340     DEBUG_PRINT_HIGH("update_portdef Width = %lu Height = %lu Stride = %ld"
7341             " SliceHeight = %lu", portDefn->format.video.nFrameWidth,
7342             portDefn->format.video.nFrameHeight,
7343             portDefn->format.video.nStride,
7344             portDefn->format.video.nSliceHeight);
7345     return eRet;
7346 
7347 }
7348 
allocate_output_headers()7349 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
7350 {
7351     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7352     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
7353     unsigned i= 0;
7354 
7355     if (!m_out_mem_ptr) {
7356         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
7357         int nBufHdrSize        = 0;
7358         int nPlatformEntrySize = 0;
7359         int nPlatformListSize  = 0;
7360         int nPMEMInfoSize = 0;
7361         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
7362         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
7363         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
7364 
7365         DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
7366                 drv_ctx.op_buf.actualcount);
7367         nBufHdrSize        = drv_ctx.op_buf.actualcount *
7368             sizeof(OMX_BUFFERHEADERTYPE);
7369 
7370         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
7371             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
7372         nPlatformListSize  = drv_ctx.op_buf.actualcount *
7373             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
7374         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
7375             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
7376 
7377         DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize,
7378                 sizeof(OMX_BUFFERHEADERTYPE),
7379                 nPMEMInfoSize,
7380                 nPlatformListSize);
7381         DEBUG_PRINT_LOW("PE %d bmSize %d",nPlatformEntrySize,
7382                 m_out_bm_count);
7383         m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
7384         // Alloc mem for platform specific info
7385         char *pPtr=NULL;
7386         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7387                 nPMEMInfoSize,1);
7388         drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
7389                                    calloc (sizeof(struct vdec_bufferpayload),
7390                                            drv_ctx.op_buf.actualcount);
7391         drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
7392                                  calloc (sizeof (struct vdec_output_frameinfo),
7393                                          drv_ctx.op_buf.actualcount);
7394 #ifdef USE_ION
7395         drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
7396                                   calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
7397 #endif
7398 
7399         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
7400                 && drv_ctx.ptr_respbuffer) {
7401             bufHdr          =  m_out_mem_ptr;
7402             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7403             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7404                 (((char *) m_platform_list)  + nPlatformListSize);
7405             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7406                 (((char *) m_platform_entry) + nPlatformEntrySize);
7407             pPlatformList   = m_platform_list;
7408             pPlatformEntry  = m_platform_entry;
7409             pPMEMInfo       = m_pmem_info;
7410 
7411             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
7412 
7413             // Settting the entire storage nicely
7414             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
7415                     m_out_mem_ptr,pPlatformEntry);
7416             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
7417             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
7418                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
7419                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
7420                 // Set the values when we determine the right HxW param
7421                 bufHdr->nAllocLen          = 0;
7422                 bufHdr->nFilledLen         = 0;
7423                 bufHdr->pAppPrivate        = NULL;
7424                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
7425                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7426                 pPlatformEntry->entry      = pPMEMInfo;
7427                 // Initialize the Platform List
7428                 pPlatformList->nEntries    = 1;
7429                 pPlatformList->entryList   = pPlatformEntry;
7430                 // Keep pBuffer NULL till vdec is opened
7431                 bufHdr->pBuffer            = NULL;
7432                 pPMEMInfo->offset          =  0;
7433                 pPMEMInfo->pmem_fd = 0;
7434                 bufHdr->pPlatformPrivate = pPlatformList;
7435                 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
7436 #ifdef USE_ION
7437                 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
7438 #endif
7439                 /*Create a mapping between buffers*/
7440                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7441                 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
7442                                                         &drv_ctx.ptr_outputbuffer[i];
7443                 // Move the buffer and buffer header pointers
7444                 bufHdr++;
7445                 pPMEMInfo++;
7446                 pPlatformEntry++;
7447                 pPlatformList++;
7448             }
7449         } else {
7450             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7451                     m_out_mem_ptr, pPtr);
7452             if (m_out_mem_ptr) {
7453                 free(m_out_mem_ptr);
7454                 m_out_mem_ptr = NULL;
7455             }
7456             if (pPtr) {
7457                 free(pPtr);
7458                 pPtr = NULL;
7459             }
7460             if (drv_ctx.ptr_outputbuffer) {
7461                 free(drv_ctx.ptr_outputbuffer);
7462                 drv_ctx.ptr_outputbuffer = NULL;
7463             }
7464             if (drv_ctx.ptr_respbuffer) {
7465                 free(drv_ctx.ptr_respbuffer);
7466                 drv_ctx.ptr_respbuffer = NULL;
7467             }
7468 #ifdef USE_ION
7469             if (drv_ctx.op_buf_ion_info) {
7470                 DEBUG_PRINT_LOW("Free o/p ion context");
7471                 free(drv_ctx.op_buf_ion_info);
7472                 drv_ctx.op_buf_ion_info = NULL;
7473             }
7474 #endif
7475             eRet =  OMX_ErrorInsufficientResources;
7476         }
7477     } else {
7478         eRet =  OMX_ErrorInsufficientResources;
7479     }
7480     return eRet;
7481 }
7482 
complete_pending_buffer_done_cbs()7483 void omx_vdec::complete_pending_buffer_done_cbs()
7484 {
7485     unsigned p1;
7486     unsigned p2;
7487     unsigned ident;
7488     omx_cmd_queue tmp_q, pending_bd_q;
7489     pthread_mutex_lock(&m_lock);
7490     // pop all pending GENERATE FDB from ftb queue
7491     while (m_ftb_q.m_size) {
7492         m_ftb_q.pop_entry(&p1,&p2,&ident);
7493         if (ident == OMX_COMPONENT_GENERATE_FBD) {
7494             pending_bd_q.insert_entry(p1,p2,ident);
7495         } else {
7496             tmp_q.insert_entry(p1,p2,ident);
7497         }
7498     }
7499     //return all non GENERATE FDB to ftb queue
7500     while (tmp_q.m_size) {
7501         tmp_q.pop_entry(&p1,&p2,&ident);
7502         m_ftb_q.insert_entry(p1,p2,ident);
7503     }
7504     // pop all pending GENERATE EDB from etb queue
7505     while (m_etb_q.m_size) {
7506         m_etb_q.pop_entry(&p1,&p2,&ident);
7507         if (ident == OMX_COMPONENT_GENERATE_EBD) {
7508             pending_bd_q.insert_entry(p1,p2,ident);
7509         } else {
7510             tmp_q.insert_entry(p1,p2,ident);
7511         }
7512     }
7513     //return all non GENERATE FDB to etb queue
7514     while (tmp_q.m_size) {
7515         tmp_q.pop_entry(&p1,&p2,&ident);
7516         m_etb_q.insert_entry(p1,p2,ident);
7517     }
7518     pthread_mutex_unlock(&m_lock);
7519     // process all pending buffer dones
7520     while (pending_bd_q.m_size) {
7521         pending_bd_q.pop_entry(&p1,&p2,&ident);
7522         switch (ident) {
7523             case OMX_COMPONENT_GENERATE_EBD:
7524                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
7525                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
7526                     omx_report_error ();
7527                 }
7528                 break;
7529 
7530             case OMX_COMPONENT_GENERATE_FBD:
7531                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
7532                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
7533                     omx_report_error ();
7534                 }
7535                 break;
7536         }
7537     }
7538 }
7539 
set_frame_rate(OMX_S64 act_timestamp)7540 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
7541 {
7542     OMX_U32 new_frame_interval = 0;
7543     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
7544             && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000)) {
7545         new_frame_interval = (act_timestamp > prev_ts)?
7546             act_timestamp - prev_ts :
7547             prev_ts - act_timestamp;
7548         if (new_frame_interval < frm_int || frm_int == 0) {
7549             frm_int = new_frame_interval;
7550             if (frm_int) {
7551                 drv_ctx.frame_rate.fps_numerator = 1e6;
7552                 drv_ctx.frame_rate.fps_denominator = frm_int;
7553                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
7554                         frm_int, drv_ctx.frame_rate.fps_numerator /
7555                         (float)drv_ctx.frame_rate.fps_denominator);
7556             }
7557         }
7558     }
7559     prev_ts = act_timestamp;
7560 }
7561 
adjust_timestamp(OMX_S64 & act_timestamp)7562 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
7563 {
7564     if (rst_prev_ts && VALID_TS(act_timestamp)) {
7565         prev_ts = act_timestamp;
7566         rst_prev_ts = false;
7567     } else if (VALID_TS(prev_ts)) {
7568         bool codec_cond = (drv_ctx.timestamp_adjust)?
7569             (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)?
7570                                            (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)):
7571             (!VALID_TS(act_timestamp) || act_timestamp == prev_ts);
7572         if (frm_int > 0 && codec_cond) {
7573             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
7574             act_timestamp = prev_ts + frm_int;
7575             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
7576             prev_ts = act_timestamp;
7577         } else
7578             set_frame_rate(act_timestamp);
7579     } else if (frm_int > 0)          // In this case the frame rate was set along
7580     {                               // with the port definition, start ts with 0
7581         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
7582         rst_prev_ts = true;
7583     }
7584 }
7585 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)7586 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
7587 {
7588     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
7589     OMX_U32 num_conceal_MB = 0;
7590     OMX_U32 frame_rate = 0;
7591     int consumed_len = 0;
7592     OMX_U32 num_MB_in_frame;
7593     OMX_U32 recovery_sei_flags = 1;
7594     int buf_index = p_buf_hdr - m_out_mem_ptr;
7595     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
7596     OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
7597         p_buf_hdr->nOffset;
7598     if (!drv_ctx.extradata_info.uaddr) {
7599         return;
7600     }
7601     p_extra = (OMX_OTHER_EXTRADATATYPE *)
7602         ((unsigned)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
7603     char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
7604     if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))
7605         p_extra = NULL;
7606     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
7607     if (data) {
7608         while ((consumed_len < drv_ctx.extradata_info.buffer_size)
7609                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
7610             if ((consumed_len + data->nSize) > drv_ctx.extradata_info.buffer_size) {
7611                 DEBUG_PRINT_LOW("Invalid extra data size");
7612                 break;
7613             }
7614             switch ((unsigned long)data->eType) {
7615                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
7616                     struct msm_vidc_interlace_payload *payload;
7617                     payload = (struct msm_vidc_interlace_payload *)data->data;
7618                     if (payload->format != MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
7619                         int enable = 1;
7620                         OMX_U32 mbaff = 0;
7621                         mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
7622                         if ((payload->format == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE)  && !mbaff)
7623                             drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
7624                         else
7625                             drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
7626                         if (m_enable_android_native_buffers)
7627                             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
7628                                     PP_PARAM_INTERLACED, (void*)&enable);
7629                     }
7630                     if (!secure_mode && (client_extradata & OMX_INTERLACE_EXTRADATA)) {
7631                         append_interlace_extradata(p_extra, payload->format);
7632                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7633                     }
7634                     break;
7635                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
7636                     struct msm_vidc_framerate_payload *frame_rate_payload;
7637                     frame_rate_payload = (struct msm_vidc_framerate_payload *)data->data;
7638                     frame_rate = frame_rate_payload->frame_rate;
7639                     break;
7640                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
7641                     struct msm_vidc_ts_payload *time_stamp_payload;
7642                     time_stamp_payload = (struct msm_vidc_ts_payload *)data->data;
7643                     p_buf_hdr->nTimeStamp = time_stamp_payload->timestamp_lo;
7644                     p_buf_hdr->nTimeStamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
7645                     break;
7646                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
7647                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
7648                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)data->data;
7649                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
7650                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
7651                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
7652                     break;
7653                 case MSM_VIDC_EXTRADATA_ASPECT_RATIO:
7654                     struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
7655                     aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)data->data;
7656                     ((struct vdec_output_frameinfo *)
7657                      p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
7658                     ((struct vdec_output_frameinfo *)
7659                      p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
7660                     break;
7661                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
7662                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
7663                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)data->data;
7664                     recovery_sei_flags = recovery_sei_payload->flags;
7665                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
7666                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
7667                         DEBUG_PRINT_HIGH("Extradata: OMX_BUFFERFLAG_DATACORRUPT Received");
7668                     }
7669                     break;
7670                 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
7671                     panscan_payload = (struct msm_vidc_panscan_window_payload *)data->data;
7672                     break;
7673                 default:
7674                     goto unrecognized_extradata;
7675             }
7676             consumed_len += data->nSize;
7677             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
7678         }
7679         if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
7680             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
7681             append_frame_info_extradata(p_extra,
7682                     num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
7683                     panscan_payload,&((struct vdec_output_frameinfo *)
7684                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
7685         }
7686     }
7687 unrecognized_extradata:
7688     if (!secure_mode && client_extradata)
7689         append_terminator_extradata(p_extra);
7690     return;
7691 }
7692 
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)7693 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
7694         bool is_internal, bool enable)
7695 {
7696     OMX_ERRORTYPE ret = OMX_ErrorNone;
7697     struct v4l2_control control;
7698     if (m_state != OMX_StateLoaded) {
7699         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
7700         return OMX_ErrorIncorrectStateOperation;
7701     }
7702     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%lu] requested[%lu] enable[%d], is_internal: %d",
7703             client_extradata, requested_extradata, enable, is_internal);
7704 
7705     if (!is_internal) {
7706         if (enable)
7707             client_extradata |= requested_extradata;
7708         else
7709             client_extradata = client_extradata & ~requested_extradata;
7710     }
7711 
7712     if (enable) {
7713         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
7714             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7715             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
7716             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7717                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
7718                         " Quality of interlaced clips might be impacted.");
7719             }
7720         } else if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
7721             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7722             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
7723             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7724                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
7725             }
7726             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7727             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
7728             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7729                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
7730             }
7731             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7732             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
7733             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7734                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
7735             }
7736             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7737             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
7738             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7739                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
7740             }
7741             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7742             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
7743             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7744                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
7745             }
7746         } else if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
7747             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7748             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
7749             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7750                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
7751             }
7752         }
7753     }
7754     ret = get_buffer_req(&drv_ctx.op_buf);
7755     return ret;
7756 }
7757 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)7758 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7759 {
7760     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
7761     OMX_U8 *data_ptr = extra->data, data = 0;
7762     while (byte_count < extra->nDataSize) {
7763         data = *data_ptr;
7764         while (data) {
7765             num_MB += (data&0x01);
7766             data >>= 1;
7767         }
7768         data_ptr++;
7769         byte_count++;
7770     }
7771     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
7772             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
7773     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
7774 }
7775 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)7776 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7777 {
7778     if (!m_debug_extradata)
7779         return;
7780 
7781     DEBUG_PRINT_HIGH(
7782             "============== Extra Data ==============\n"
7783             "           Size: %lu \n"
7784             "        Version: %lu \n"
7785             "      PortIndex: %lu \n"
7786             "           Type: %x \n"
7787             "       DataSize: %lu",
7788             extra->nSize, extra->nVersion.nVersion,
7789             extra->nPortIndex, extra->eType, extra->nDataSize);
7790 
7791     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
7792         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data;
7793         DEBUG_PRINT_HIGH(
7794                 "------ Interlace Format ------\n"
7795                 "                Size: %lu \n"
7796                 "             Version: %lu \n"
7797                 "           PortIndex: %lu \n"
7798                 " Is Interlace Format: %d \n"
7799                 "   Interlace Formats: %lu \n"
7800                 "=========== End of Interlace ===========",
7801                 intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex,
7802                 intfmt->bInterlaceFormat, intfmt->nInterlaceFormats);
7803     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
7804         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
7805 
7806         DEBUG_PRINT_HIGH(
7807                 "-------- Frame Format --------\n"
7808                 "             Picture Type: %d \n"
7809                 "           Interlace Type: %d \n"
7810                 " Pan Scan Total Frame Num: %lu \n"
7811                 "   Concealed Macro Blocks: %lu \n"
7812                 "               frame rate: %lu \n"
7813                 "           Aspect Ratio X: %lu \n"
7814                 "           Aspect Ratio Y: %lu",
7815                 fminfo->ePicType,
7816                 fminfo->interlaceType,
7817                 fminfo->panScan.numWindows,
7818                 fminfo->nConcealedMacroblocks,
7819                 fminfo->nFrameRate,
7820                 fminfo->aspectRatio.aspectRatioX,
7821                 fminfo->aspectRatio.aspectRatioY);
7822 
7823         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
7824             DEBUG_PRINT_HIGH(
7825                     "------------------------------\n"
7826                     "     Pan Scan Frame Num: %lu \n"
7827                     "            Rectangle x: %ld \n"
7828                     "            Rectangle y: %ld \n"
7829                     "           Rectangle dx: %ld \n"
7830                     "           Rectangle dy: %ld",
7831                     i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y,
7832                     fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy);
7833         }
7834 
7835         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
7836     } else if (extra->eType == OMX_ExtraDataNone) {
7837         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
7838     } else {
7839         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
7840     }
7841 }
7842 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)7843 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
7844         OMX_U32 interlaced_format_type)
7845 {
7846     OMX_STREAMINTERLACEFORMAT *interlace_format;
7847     OMX_U32 mbaff = 0;
7848     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
7849         return;
7850     }
7851     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
7852     extra->nVersion.nVersion = OMX_SPEC_VERSION;
7853     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7854     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
7855     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
7856     interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data;
7857     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
7858     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
7859     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7860     mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
7861     if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE)  && !mbaff) {
7862         interlace_format->bInterlaceFormat = OMX_FALSE;
7863         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
7864         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
7865     } else {
7866         interlace_format->bInterlaceFormat = OMX_TRUE;
7867         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
7868         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
7869     }
7870     print_debug_extradata(extra);
7871 }
7872 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)7873 void omx_vdec::fill_aspect_ratio_info(
7874         struct vdec_aspectratioinfo *aspect_ratio_info,
7875         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
7876 {
7877     m_extradata = frame_info;
7878     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
7879     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
7880     DEBUG_PRINT_LOW("aspectRatioX %d aspectRatioX %d", m_extradata->aspectRatio.aspectRatioX,
7881             m_extradata->aspectRatio.aspectRatioY);
7882 }
7883 
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 picture_type,OMX_U32 frame_rate,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)7884 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
7885         OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
7886         struct msm_vidc_panscan_window_payload *panscan_payload,
7887         struct vdec_aspectratioinfo *aspect_ratio_info)
7888 {
7889     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
7890     struct msm_vidc_panscan_window *panscan_window;
7891     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
7892         return;
7893     }
7894     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
7895     extra->nVersion.nVersion = OMX_SPEC_VERSION;
7896     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7897     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
7898     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
7899     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
7900     switch (picture_type) {
7901         case PICTURE_TYPE_I:
7902             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
7903             break;
7904         case PICTURE_TYPE_P:
7905             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
7906             break;
7907         case PICTURE_TYPE_B:
7908             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
7909             break;
7910         default:
7911             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
7912     }
7913     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
7914         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
7915     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
7916         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
7917     else
7918         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
7919     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
7920     frame_info->nConcealedMacroblocks = num_conceal_mb;
7921     frame_info->nFrameRate = frame_rate;
7922     frame_info->panScan.numWindows = 0;
7923     if (panscan_payload) {
7924         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
7925         panscan_window = &panscan_payload->wnd[0];
7926         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
7927             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
7928             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
7929             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
7930             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
7931             panscan_window++;
7932         }
7933     }
7934     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
7935     print_debug_extradata(extra);
7936 }
7937 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)7938 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7939 {
7940     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
7941     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
7942     extra->nVersion.nVersion = OMX_SPEC_VERSION;
7943     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7944     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
7945     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
7946     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data;
7947     *portDefn = m_port_def;
7948     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u"
7949             "sliceheight = %u",portDefn->format.video.nFrameHeight,
7950             portDefn->format.video.nFrameWidth,
7951             portDefn->format.video.nStride,
7952             portDefn->format.video.nSliceHeight);
7953 }
7954 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)7955 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7956 {
7957     if (!client_extradata) {
7958         return;
7959     }
7960     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
7961     extra->nVersion.nVersion = OMX_SPEC_VERSION;
7962     extra->eType = OMX_ExtraDataNone;
7963     extra->nDataSize = 0;
7964     extra->data[0] = 0;
7965 
7966     print_debug_extradata(extra);
7967 }
7968 
allocate_desc_buffer(OMX_U32 index)7969 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
7970 {
7971     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7972     if (index >= drv_ctx.ip_buf.actualcount) {
7973         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
7974         return OMX_ErrorInsufficientResources;
7975     }
7976     if (m_desc_buffer_ptr == NULL) {
7977         m_desc_buffer_ptr = (desc_buffer_hdr*) \
7978                             calloc( (sizeof(desc_buffer_hdr)),
7979                                     drv_ctx.ip_buf.actualcount);
7980         if (m_desc_buffer_ptr == NULL) {
7981             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
7982             return OMX_ErrorInsufficientResources;
7983         }
7984     }
7985 
7986     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
7987     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
7988         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
7989         return OMX_ErrorInsufficientResources;
7990     }
7991 
7992     return eRet;
7993 }
7994 
insert_demux_addr_offset(OMX_U32 address_offset)7995 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
7996 {
7997     DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries);
7998     if (m_demux_entries < 8192) {
7999         m_demux_offsets[m_demux_entries++] = address_offset;
8000     }
8001     return;
8002 }
8003 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)8004 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
8005 {
8006     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
8007     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
8008     OMX_U32 index = 0;
8009 
8010     m_demux_entries = 0;
8011 
8012     while (index < bytes_to_parse) {
8013         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8014                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
8015                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8016                  (buf[index+2] == 0x01)) ) {
8017             //Found start code, insert address offset
8018             insert_demux_addr_offset(index);
8019             if (buf[index+2] == 0x01) // 3 byte start code
8020                 index += 3;
8021             else                      //4 byte start code
8022                 index += 4;
8023         } else
8024             index++;
8025     }
8026     DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries);
8027     return;
8028 }
8029 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)8030 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
8031 {
8032     //fix this, handle 3 byte start code, vc1 terminator entry
8033     OMX_U8 *p_demux_data = NULL;
8034     OMX_U32 desc_data = 0;
8035     OMX_U32 start_addr = 0;
8036     OMX_U32 nal_size = 0;
8037     OMX_U32 suffix_byte = 0;
8038     OMX_U32 demux_index = 0;
8039     OMX_U32 buffer_index = 0;
8040 
8041     if (m_desc_buffer_ptr == NULL) {
8042         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
8043         return OMX_ErrorBadParameter;
8044     }
8045 
8046     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
8047     if (buffer_index > drv_ctx.ip_buf.actualcount) {
8048         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%lu)", buffer_index);
8049         return OMX_ErrorBadParameter;
8050     }
8051 
8052     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
8053 
8054     if ( ((OMX_U8*)p_demux_data == NULL) ||
8055             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
8056         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
8057         return OMX_ErrorBadParameter;
8058     } else {
8059         for (; demux_index < m_demux_entries; demux_index++) {
8060             desc_data = 0;
8061             start_addr = m_demux_offsets[demux_index];
8062             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
8063                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
8064             } else {
8065                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
8066             }
8067             if (demux_index < (m_demux_entries - 1)) {
8068                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
8069             } else {
8070                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
8071             }
8072             DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)",
8073                     start_addr,
8074                     suffix_byte,
8075                     nal_size,
8076                     demux_index);
8077             desc_data = (start_addr >> 3) << 1;
8078             desc_data |= (start_addr & 7) << 21;
8079             desc_data |= suffix_byte << 24;
8080 
8081             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8082             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
8083             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8084             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8085 
8086             p_demux_data += 16;
8087         }
8088         if (codec_type_parse == CODEC_TYPE_VC1) {
8089             DEBUG_PRINT_LOW("VC1 terminator entry");
8090             desc_data = 0;
8091             desc_data = 0x82 << 24;
8092             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8093             memset(p_demux_data + 4, 0, sizeof(OMX_U32));
8094             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8095             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8096             p_demux_data += 16;
8097             m_demux_entries++;
8098         }
8099         //Add zero word to indicate end of descriptors
8100         memset(p_demux_data, 0, sizeof(OMX_U32));
8101 
8102         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
8103         DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size);
8104     }
8105     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
8106     m_demux_entries = 0;
8107     DEBUG_PRINT_LOW("Demux table complete!");
8108     return OMX_ErrorNone;
8109 }
8110 
createDivxDrmContext()8111 OMX_ERRORTYPE omx_vdec::createDivxDrmContext()
8112 {
8113     OMX_ERRORTYPE err = OMX_ErrorNone;
8114     iDivXDrmDecrypt = DivXDrmDecrypt::Create();
8115     if (iDivXDrmDecrypt) {
8116         OMX_ERRORTYPE err = iDivXDrmDecrypt->Init();
8117         if (err!=OMX_ErrorNone) {
8118             DEBUG_PRINT_ERROR("ERROR :iDivXDrmDecrypt->Init %d", err);
8119             delete iDivXDrmDecrypt;
8120             iDivXDrmDecrypt = NULL;
8121         }
8122     } else {
8123         DEBUG_PRINT_ERROR("Unable to Create DIVX DRM");
8124         err = OMX_ErrorUndefined;
8125     }
8126     return err;
8127 }
8128 
allocate_color_convert_buf()8129 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
8130 {
8131     enabled = false;
8132     omx = NULL;
8133     init_members();
8134     ColorFormat = OMX_COLOR_FormatMax;
8135 }
8136 
set_vdec_client(void * client)8137 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
8138 {
8139     omx = reinterpret_cast<omx_vdec*>(client);
8140 }
8141 
init_members()8142 void omx_vdec::allocate_color_convert_buf::init_members()
8143 {
8144     allocated_count = 0;
8145     buffer_size_req = 0;
8146     buffer_alignment_req = 0;
8147     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
8148     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
8149     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
8150     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
8151 #ifdef USE_ION
8152     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
8153 #endif
8154     for (int i = 0; i < MAX_COUNT; i++)
8155         pmem_fd[i] = -1;
8156 }
8157 
~allocate_color_convert_buf()8158 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
8159 {
8160     c2d.destroy();
8161 }
8162 
update_buffer_req()8163 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
8164 {
8165     bool status = true;
8166     unsigned int src_size = 0, destination_size = 0;
8167     OMX_COLOR_FORMATTYPE drv_color_format;
8168     if (!omx) {
8169         DEBUG_PRINT_ERROR("Invalid client in color convert");
8170         return false;
8171     }
8172     if (!enabled) {
8173         DEBUG_PRINT_HIGH("No color conversion required");
8174         return status;
8175     }
8176     pthread_mutex_lock(&omx->c_lock);
8177     if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
8178             ColorFormat != OMX_COLOR_FormatYUV420Planar) {
8179         DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
8180         status = false;
8181         goto fail_update_buf_req;
8182     }
8183     c2d.close();
8184     status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
8185             omx->drv_ctx.video_resolution.frame_width,
8186             NV12_128m,YCbCr420P);
8187     if (status) {
8188         status = c2d.get_buffer_size(C2D_INPUT,src_size);
8189         if (status)
8190             status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
8191     }
8192     if (status) {
8193         if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
8194                 !destination_size) {
8195             DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
8196                     "driver size %d destination size %d",
8197                     src_size,omx->drv_ctx.op_buf.buffer_size,destination_size);
8198             status = false;
8199             c2d.close();
8200             buffer_size_req = 0;
8201         } else {
8202             buffer_size_req = destination_size;
8203             if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
8204                 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
8205             if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
8206                 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
8207         }
8208     }
8209 fail_update_buf_req:
8210     pthread_mutex_unlock(&omx->c_lock);
8211     return status;
8212 }
8213 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)8214 bool omx_vdec::allocate_color_convert_buf::set_color_format(
8215         OMX_COLOR_FORMATTYPE dest_color_format)
8216 {
8217     bool status = true;
8218     OMX_COLOR_FORMATTYPE drv_color_format;
8219     if (!omx) {
8220         DEBUG_PRINT_ERROR("Invalid client in color convert");
8221         return false;
8222     }
8223     pthread_mutex_lock(&omx->c_lock);
8224     if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
8225         drv_color_format = (OMX_COLOR_FORMATTYPE)
8226             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
8227     else {
8228         DEBUG_PRINT_ERROR("Incorrect color format");
8229         status = false;
8230     }
8231     if (status && (drv_color_format != dest_color_format)) {
8232         DEBUG_PRINT_LOW("Enabling C2D");
8233         if (dest_color_format != OMX_COLOR_FormatYUV420Planar) {
8234             DEBUG_PRINT_ERROR("Unsupported color format for c2d");
8235             status = false;
8236         } else {
8237             ColorFormat = OMX_COLOR_FormatYUV420Planar;
8238             if (enabled)
8239                 c2d.destroy();
8240             enabled = false;
8241             if (!c2d.init()) {
8242                 DEBUG_PRINT_ERROR("open failed for c2d");
8243                 status = false;
8244             } else
8245                 enabled = true;
8246         }
8247     } else {
8248         if (enabled)
8249             c2d.destroy();
8250         enabled = false;
8251     }
8252     pthread_mutex_unlock(&omx->c_lock);
8253     return status;
8254 }
8255 
get_il_buf_hdr()8256 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
8257 {
8258     if (!omx) {
8259         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8260         return NULL;
8261     }
8262     if (!enabled)
8263         return omx->m_out_mem_ptr;
8264     return m_out_mem_ptr_client;
8265 }
8266 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)8267     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
8268 (OMX_BUFFERHEADERTYPE *bufadd)
8269 {
8270     if (!omx) {
8271         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8272         return NULL;
8273     }
8274     if (!enabled)
8275         return bufadd;
8276 
8277     unsigned index = 0;
8278     index = bufadd - omx->m_out_mem_ptr;
8279     if (index < omx->drv_ctx.op_buf.actualcount) {
8280         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
8281         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
8282         bool status;
8283         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
8284             pthread_mutex_lock(&omx->c_lock);
8285             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
8286                     omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer,pmem_fd[index],
8287                     pmem_baseaddress[index], pmem_baseaddress[index]);
8288             pthread_mutex_unlock(&omx->c_lock);
8289             m_out_mem_ptr_client[index].nFilledLen = buffer_size_req;
8290             if (!status) {
8291                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
8292                 m_out_mem_ptr_client[index].nFilledLen = 0;
8293                 return &m_out_mem_ptr_client[index];
8294             }
8295         } else
8296             m_out_mem_ptr_client[index].nFilledLen = 0;
8297         return &m_out_mem_ptr_client[index];
8298     }
8299     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
8300     return NULL;
8301 }
8302 
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)8303     OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
8304 (OMX_BUFFERHEADERTYPE *bufadd)
8305 {
8306     if (!omx) {
8307         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8308         return NULL;
8309     }
8310     if (!enabled)
8311         return bufadd;
8312     unsigned index = 0;
8313     index = bufadd - m_out_mem_ptr_client;
8314     if (index < omx->drv_ctx.op_buf.actualcount) {
8315         return &omx->m_out_mem_ptr[index];
8316     }
8317     DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
8318     return NULL;
8319 }
get_buffer_req(unsigned int & buffer_size)8320     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
8321 (unsigned int &buffer_size)
8322 {
8323     bool status = true;
8324     pthread_mutex_lock(&omx->c_lock);
8325     if (!enabled)
8326         buffer_size = omx->drv_ctx.op_buf.buffer_size;
8327     else {
8328         if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
8329             DEBUG_PRINT_ERROR("Get buffer size failed");
8330             status = false;
8331             goto fail_get_buffer_size;
8332         }
8333     }
8334     if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
8335         buffer_size = omx->drv_ctx.op_buf.buffer_size;
8336     if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
8337         buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
8338 fail_get_buffer_size:
8339     pthread_mutex_unlock(&omx->c_lock);
8340     return status;
8341 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)8342 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
8343         OMX_BUFFERHEADERTYPE *bufhdr)
8344 {
8345     unsigned int index = 0;
8346 
8347     if (!enabled)
8348         return omx->free_output_buffer(bufhdr);
8349     if (enabled && omx->is_component_secure())
8350         return OMX_ErrorNone;
8351     if (!allocated_count || !bufhdr) {
8352         DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
8353         return OMX_ErrorBadParameter;
8354     }
8355     index = bufhdr - m_out_mem_ptr_client;
8356     if (index >= omx->drv_ctx.op_buf.actualcount) {
8357         DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
8358         return OMX_ErrorBadParameter;
8359     }
8360     if (pmem_fd[index] > 0) {
8361         munmap(pmem_baseaddress[index], buffer_size_req);
8362         close(pmem_fd[index]);
8363     }
8364     pmem_fd[index] = -1;
8365 #ifdef USE_ION
8366     omx->free_ion_memory(&op_buf_ion_info[index]);
8367 #endif
8368     m_heap_ptr[index].video_heap_ptr = NULL;
8369     if (allocated_count > 0)
8370         allocated_count--;
8371     else
8372         allocated_count = 0;
8373     if (!allocated_count) {
8374         pthread_mutex_lock(&omx->c_lock);
8375         c2d.close();
8376         init_members();
8377         pthread_mutex_unlock(&omx->c_lock);
8378     }
8379     return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
8380 }
8381 
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)8382 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
8383         OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
8384 {
8385     OMX_ERRORTYPE eRet = OMX_ErrorNone;
8386     if (!enabled) {
8387         eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
8388         return eRet;
8389     }
8390     if (enabled && omx->is_component_secure()) {
8391         DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
8392                 omx->is_component_secure());
8393         return OMX_ErrorUnsupportedSetting;
8394     }
8395     if (!bufferHdr || bytes > buffer_size_req) {
8396         DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
8397         DEBUG_PRINT_ERROR("color_convert buffer_size_req %d bytes %lu",
8398                 buffer_size_req,bytes);
8399         return OMX_ErrorBadParameter;
8400     }
8401     if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
8402         DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
8403         return OMX_ErrorInsufficientResources;
8404     }
8405     OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
8406     eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
8407             port,appData,omx->drv_ctx.op_buf.buffer_size);
8408     if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
8409         DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
8410         return eRet;
8411     }
8412     if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
8413             omx->drv_ctx.op_buf.actualcount) {
8414         DEBUG_PRINT_ERROR("Invalid header index %d",
8415                 (temp_bufferHdr - omx->m_out_mem_ptr));
8416         return OMX_ErrorUndefined;
8417     }
8418     unsigned int i = allocated_count;
8419 #ifdef USE_ION
8420     op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
8421             buffer_size_req,buffer_alignment_req,
8422             &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
8423             0);
8424     pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
8425     if (op_buf_ion_info[i].ion_device_fd < 0) {
8426         DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
8427         return OMX_ErrorInsufficientResources;
8428     }
8429     pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
8430             PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
8431 
8432     if (pmem_baseaddress[i] == MAP_FAILED) {
8433         DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
8434         close(pmem_fd[i]);
8435         omx->free_ion_memory(&op_buf_ion_info[i]);
8436         return OMX_ErrorInsufficientResources;
8437     }
8438     m_heap_ptr[i].video_heap_ptr = new VideoHeap (
8439             op_buf_ion_info[i].ion_device_fd,buffer_size_req,
8440             pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
8441 #endif
8442     m_pmem_info_client[i].pmem_fd = (OMX_U32)m_heap_ptr[i].video_heap_ptr.get();
8443     m_pmem_info_client[i].offset = 0;
8444     m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
8445     m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8446     m_platform_list_client[i].nEntries = 1;
8447     m_platform_list_client[i].entryList = &m_platform_entry_client[i];
8448     m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
8449     m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
8450     m_out_mem_ptr_client[i].nFilledLen = 0;
8451     m_out_mem_ptr_client[i].nFlags = 0;
8452     m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8453     m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
8454     m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
8455     m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
8456     m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
8457     m_out_mem_ptr_client[i].pAppPrivate = appData;
8458     *bufferHdr = &m_out_mem_ptr_client[i];
8459     DEBUG_PRINT_ERROR("IL client buffer header %p", *bufferHdr);
8460     allocated_count++;
8461     return eRet;
8462 }
8463 
is_component_secure()8464 bool omx_vdec::is_component_secure()
8465 {
8466     return secure_mode;
8467 }
8468 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)8469 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
8470 {
8471     bool status = true;
8472     if (!enabled) {
8473         if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
8474             dest_color_format =  (OMX_COLOR_FORMATTYPE)
8475                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
8476         else
8477             status = false;
8478     } else {
8479         if (ColorFormat != OMX_COLOR_FormatYUV420Planar) {
8480             status = false;
8481         } else
8482             dest_color_format = OMX_COLOR_FormatYUV420Planar;
8483     }
8484     return status;
8485 }
8486