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