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