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