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