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