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