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