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