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