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