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