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