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