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