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