1/*--------------------------------------------------------------------------
2Copyright (c) 2010 - 2017, 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#if !defined(_ANDROID_) || defined(SYS_IOCTL)
59#include <sys/ioctl.h>
60#include <sys/mman.h>
61#endif
62
63#ifdef _ANDROID_
64#include <cutils/properties.h>
65#undef USE_EGL_IMAGE_GPU
66
67#ifdef _QUERY_DISP_RES_
68#include "display_config.h"
69#endif
70#endif
71
72#ifdef _USE_GLIB_
73#include <glib.h>
74#define strlcpy g_strlcpy
75#endif
76
77#include <qdMetaData.h>
78#include <gralloc_priv.h>
79
80#ifdef ANDROID_JELLYBEAN_MR2
81#include "QComOMXMetadata.h"
82#endif
83
84#ifdef USE_EGL_IMAGE_GPU
85#include <EGL/egl.h>
86#include <EGL/eglQCOM.h>
87#define EGL_BUFFER_HANDLE 0x4F00
88#define EGL_BUFFER_OFFSET 0x4F01
89#endif
90
91#define BUFFER_LOG_LOC "/data/misc/media"
92
93#ifdef OUTPUT_EXTRADATA_LOG
94FILE *outputExtradataFile;
95char output_extradata_filename [] = "/data/misc/media/extradata";
96#endif
97
98#define DEFAULT_FPS 30
99#define MAX_SUPPORTED_FPS 240
100#define DEFAULT_WIDTH_ALIGNMENT 128
101#define DEFAULT_HEIGHT_ALIGNMENT 32
102
103#define VC1_SP_MP_START_CODE        0xC5000000
104#define VC1_SP_MP_START_CODE_MASK   0xFF000000
105#define VC1_AP_SEQ_START_CODE       0x0F010000
106#define VC1_STRUCT_C_PROFILE_MASK   0xF0
107#define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
108#define VC1_SIMPLE_PROFILE          0
109#define VC1_MAIN_PROFILE            1
110#define VC1_ADVANCE_PROFILE         3
111#define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
112#define VC1_SIMPLE_PROFILE_MED_LEVEL  2
113#define VC1_STRUCT_C_LEN            4
114#define VC1_STRUCT_C_POS            8
115#define VC1_STRUCT_A_POS            12
116#define VC1_STRUCT_B_POS            24
117#define VC1_SEQ_LAYER_SIZE          36
118#define POLL_TIMEOUT 0x7fffffff
119
120#define MEM_DEVICE "/dev/ion"
121
122#ifdef _ANDROID_
123extern "C" {
124#include<utils/Log.h>
125}
126#endif//_ANDROID_
127
128#define SZ_4K 0x1000
129#define SZ_1M 0x100000
130
131#define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
132#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
133#define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
134#define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
135
136#define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
137                           | OMX_DISPLAY_INFO_EXTRADATA | OMX_HDR_COLOR_INFO_EXTRADATA)
138#define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
139
140#ifndef ION_FLAG_CP_BITSTREAM
141#define ION_FLAG_CP_BITSTREAM 0
142#endif
143
144#ifndef ION_FLAG_CP_PIXEL
145#define ION_FLAG_CP_PIXEL 0
146#endif
147
148#ifdef MASTER_SIDE_CP
149#define MEM_HEAP_ID ION_SECURE_HEAP_ID
150#define SECURE_ALIGN SZ_4K
151#define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
152#define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
153#else //SLAVE_SIDE_CP
154#define MEM_HEAP_ID ION_CP_MM_HEAP_ID
155#define SECURE_ALIGN SZ_1M
156#define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
157#define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
158#endif
159
160#define LUMINANCE_DIV_FACTOR 10000.0
161
162#define MIN(x,y) (((x) < (y)) ? (x) : (y))
163#define MAX(x,y) (((x) > (y)) ? (x) : (y))
164
165static OMX_U32 maxSmoothStreamingWidth = 1920;
166static OMX_U32 maxSmoothStreamingHeight = 1088;
167
168void* async_message_thread (void *input)
169{
170    OMX_BUFFERHEADERTYPE *buffer;
171    struct v4l2_plane plane[VIDEO_MAX_PLANES];
172    struct pollfd pfds[2];
173    struct v4l2_buffer v4l2_buf;
174    memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
175    struct v4l2_event dqevent;
176    omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
177    pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
178    pfds[1].events = POLLIN | POLLERR;
179    pfds[0].fd = omx->drv_ctx.video_driver_fd;
180    pfds[1].fd = omx->m_poll_efd;
181    int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
182    DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
183    prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
184    while (!omx->async_thread_force_stop) {
185        rc = poll(pfds, 2, POLL_TIMEOUT);
186        if (!rc) {
187            DEBUG_PRINT_ERROR("Poll timedout");
188            break;
189        } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
190            DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
191            break;
192        }
193        if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
194            DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
195            break;
196        }
197        if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
198            struct vdec_msginfo vdec_msg;
199            memset(&vdec_msg, 0, sizeof(vdec_msg));
200            v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
201            v4l2_buf.memory = V4L2_MEMORY_USERPTR;
202            v4l2_buf.length = omx->drv_ctx.num_planes;
203            v4l2_buf.m.planes = plane;
204            while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
205                vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
206                vdec_msg.status_code=VDEC_S_SUCCESS;
207                vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
208                vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
209                vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
210                vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
211                    (uint64_t)v4l2_buf.timestamp.tv_usec;
212
213                if (omx->async_message_process(input,&vdec_msg) < 0) {
214                    DEBUG_PRINT_HIGH("async_message_thread Exited");
215                    break;
216                }
217            }
218        }
219        if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
220            struct vdec_msginfo vdec_msg;
221            v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
222            v4l2_buf.memory = V4L2_MEMORY_USERPTR;
223            v4l2_buf.length = 1;
224            v4l2_buf.m.planes = plane;
225            while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
226                vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
227                vdec_msg.status_code=VDEC_S_SUCCESS;
228                vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
229                if (omx->async_message_process(input,&vdec_msg) < 0) {
230                    DEBUG_PRINT_HIGH("async_message_thread Exited");
231                    break;
232                }
233            }
234        }
235        if (pfds[0].revents & POLLPRI) {
236            rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
237            if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
238                struct vdec_msginfo vdec_msg;
239                unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
240
241                vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
242                vdec_msg.status_code=VDEC_S_SUCCESS;
243                vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
244                vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
245                DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
246                if(ptr[2] & V4L2_EVENT_BITDEPTH_FLAG) {
247                    omx->dpb_bit_depth = ptr[3];
248                    DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", ptr[3]);
249                }
250                if(ptr[2] & V4L2_EVENT_PICSTRUCT_FLAG) {
251                    omx->m_progressive = ptr[4];
252                    DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct change - %d", ptr[4]);
253                }
254                if(ptr[2] & V4L2_EVENT_COLOUR_SPACE_FLAG) {
255                    if (ptr[5] == MSM_VIDC_BT2020) {
256                        omx->m_color_space = omx_vdec::BT2020;
257                    } else {
258                        omx->m_color_space = omx_vdec::EXCEPT_BT2020;
259                    }
260                    DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace change - %d", omx->m_color_space);
261                }
262                if (omx->async_message_process(input,&vdec_msg) < 0) {
263                    DEBUG_PRINT_HIGH("async_message_thread Exited");
264                    break;
265                }
266            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
267                struct vdec_msginfo vdec_msg;
268                uint32_t flush_type = *(uint32_t *)dqevent.u.data;
269                // Old driver doesn't send flushType information.
270                // To make this backward compatible fallback to old approach
271                // if the flush_type is not present.
272                vdec_msg.status_code=VDEC_S_SUCCESS;
273                if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
274                    vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
275                    DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
276                    if (omx->async_message_process(input,&vdec_msg) < 0) {
277                        DEBUG_PRINT_HIGH("async_message_thread Exited");
278                        break;
279                    }
280                }
281
282                if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
283                    vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
284                    DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
285                    if (omx->async_message_process(input,&vdec_msg) < 0) {
286                        DEBUG_PRINT_HIGH("async_message_thread Exited");
287                        break;
288                    }
289                }
290            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
291                struct vdec_msginfo vdec_msg;
292                vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
293                vdec_msg.status_code=VDEC_S_SUCCESS;
294                DEBUG_PRINT_ERROR("HW Overload received");
295                if (omx->async_message_process(input,&vdec_msg) < 0) {
296                    DEBUG_PRINT_HIGH("async_message_thread Exited");
297                    break;
298                }
299            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
300                struct vdec_msginfo vdec_msg;
301                vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
302                vdec_msg.status_code=VDEC_S_SUCCESS;
303                DEBUG_PRINT_ERROR("HW Unsupported received");
304                if (omx->async_message_process(input,&vdec_msg) < 0) {
305                    DEBUG_PRINT_HIGH("async_message_thread Exited");
306                    break;
307                }
308            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
309                struct vdec_msginfo vdec_msg;
310                vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
311                vdec_msg.status_code = VDEC_S_SUCCESS;
312                DEBUG_PRINT_HIGH("SYS Error Recieved");
313                if (omx->async_message_process(input,&vdec_msg) < 0) {
314                    DEBUG_PRINT_HIGH("async_message_thread Exited");
315                    break;
316                }
317            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
318                unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
319
320                DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
321            } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
322                unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
323                struct vdec_msginfo vdec_msg;
324
325                DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
326
327                v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
328                v4l2_buf.memory = V4L2_MEMORY_USERPTR;
329                v4l2_buf.length = omx->drv_ctx.num_planes;
330                v4l2_buf.m.planes = plane;
331                v4l2_buf.index = ptr[5];
332                v4l2_buf.flags = 0;
333
334                vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
335                vdec_msg.status_code = VDEC_S_SUCCESS;
336                vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
337                vdec_msg.msgdata.output_frame.len = 0;
338                vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
339                vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
340                    (uint64_t)ptr[4];
341                if (omx->async_message_process(input,&vdec_msg) < 0) {
342                    DEBUG_PRINT_HIGH("async_message_thread Exitedn");
343                    break;
344                }
345            } else {
346                DEBUG_PRINT_HIGH("VIDC Some Event recieved");
347                continue;
348            }
349        }
350    }
351    DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
352    return NULL;
353}
354
355void* message_thread_dec(void *input)
356{
357    omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
358    unsigned char id;
359    int n;
360
361    fd_set readFds;
362    int res = 0;
363    struct timeval tv;
364
365    DEBUG_PRINT_HIGH("omx_vdec: message thread start");
366    prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
367    while (!omx->message_thread_stop) {
368
369        tv.tv_sec = 2;
370        tv.tv_usec = 0;
371
372        FD_ZERO(&readFds);
373        FD_SET(omx->m_pipe_in, &readFds);
374
375        res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
376        if (res < 0) {
377            DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
378            continue;
379        } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
380            continue;
381        }
382
383        n = read(omx->m_pipe_in, &id, 1);
384
385        if (0 == n) {
386            break;
387        }
388
389        if (1 == n) {
390            omx->process_event_cb(omx, id);
391        }
392
393        if ((n < 0) && (errno != EINTR)) {
394            DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
395            break;
396        }
397    }
398    DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
399    return 0;
400}
401
402void post_message(omx_vdec *omx, unsigned char id)
403{
404    int ret_value;
405    DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
406    ret_value = write(omx->m_pipe_out, &id, 1);
407    if (ret_value <= 0) {
408        DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
409    } else {
410        DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
411    }
412}
413
414// omx_cmd_queue destructor
415omx_vdec::omx_cmd_queue::~omx_cmd_queue()
416{
417    // Nothing to do
418}
419
420// omx cmd queue constructor
421omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
422{
423    memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
424}
425
426// omx cmd queue insert
427bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
428{
429    bool ret = true;
430    if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
431        m_q[m_write].id       = id;
432        m_q[m_write].param1   = p1;
433        m_q[m_write].param2   = p2;
434        m_write++;
435        m_size ++;
436        if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
437            m_write = 0;
438        }
439    } else {
440        ret = false;
441        DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
442    }
443    return ret;
444}
445
446// omx cmd queue pop
447bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
448{
449    bool ret = true;
450    if (m_size > 0) {
451        *id = m_q[m_read].id;
452        *p1 = m_q[m_read].param1;
453        *p2 = m_q[m_read].param2;
454        // Move the read pointer ahead
455        ++m_read;
456        --m_size;
457        if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
458            m_read = 0;
459        }
460    } else {
461        ret = false;
462    }
463    return ret;
464}
465
466// Retrieve the first mesg type in the queue
467unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
468{
469    return m_q[m_read].id;
470}
471
472#ifdef _ANDROID_
473omx_vdec::ts_arr_list::ts_arr_list()
474{
475    //initialize timestamps array
476    memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
477}
478omx_vdec::ts_arr_list::~ts_arr_list()
479{
480    //free m_ts_arr_list?
481}
482
483bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
484{
485    bool ret = true;
486    bool duplicate_ts = false;
487    int idx = 0;
488
489    //insert at the first available empty location
490    for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
491        if (!m_ts_arr_list[idx].valid) {
492            //found invalid or empty entry, save timestamp
493            m_ts_arr_list[idx].valid = true;
494            m_ts_arr_list[idx].timestamp = ts;
495            DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
496                    ts, idx);
497            break;
498        }
499    }
500
501    if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
502        DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
503        ret = false;
504    }
505    return ret;
506}
507
508bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
509{
510    bool ret = true;
511    int min_idx = -1;
512    OMX_TICKS min_ts = 0;
513    int idx = 0;
514
515    for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
516
517        if (m_ts_arr_list[idx].valid) {
518            //found valid entry, save index
519            if (min_idx < 0) {
520                //first valid entry
521                min_ts = m_ts_arr_list[idx].timestamp;
522                min_idx = idx;
523            } else if (m_ts_arr_list[idx].timestamp < min_ts) {
524                min_ts = m_ts_arr_list[idx].timestamp;
525                min_idx = idx;
526            }
527        }
528
529    }
530
531    if (min_idx < 0) {
532        //no valid entries found
533        DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
534        ts = 0;
535        ret = false;
536    } else {
537        ts = m_ts_arr_list[min_idx].timestamp;
538        m_ts_arr_list[min_idx].valid = false;
539        DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
540                ts, min_idx);
541    }
542
543    return ret;
544
545}
546
547
548bool omx_vdec::ts_arr_list::reset_ts_list()
549{
550    bool ret = true;
551    int idx = 0;
552
553    DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
554    for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
555        m_ts_arr_list[idx].valid = false;
556    }
557    return ret;
558}
559#endif
560
561// factory function executed by the core to create instances
562void *get_omx_component_factory_fn(void)
563{
564    return (new omx_vdec);
565}
566
567#ifdef _ANDROID_
568#ifdef USE_ION
569VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
570        ion_user_handle_t handle, int ionMapfd)
571{
572    (void) devicefd;
573    (void) size;
574    (void) base;
575    (void) handle;
576    (void) ionMapfd;
577    //    ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
578}
579#else
580VideoHeap::VideoHeap(int fd, size_t size, void* base)
581{
582    // dup file descriptor, map once, use pmem
583    init(dup(fd), base, size, 0 , MEM_DEVICE);
584}
585#endif
586#endif // _ANDROID_
587
588bool is_platform_tp10capture_supported()
589{
590    char platform_name[PROPERTY_VALUE_MAX] = {0};
591    property_get("ro.board.platform", platform_name, "0");
592    if (!strncmp(platform_name, "msm8998", 7)) {
593        DEBUG_PRINT_HIGH("TP10 on capture port is supported");
594        return true;
595    }
596    DEBUG_PRINT_HIGH("TP10 on capture port is not supported");
597    return false;
598}
599
600/* ======================================================================
601   FUNCTION
602   omx_vdec::omx_vdec
603
604   DESCRIPTION
605   Constructor
606
607   PARAMETERS
608   None
609
610   RETURN VALUE
611   None.
612   ========================================================================== */
613omx_vdec::omx_vdec(): m_error_propogated(false),
614    m_state(OMX_StateInvalid),
615    m_app_data(NULL),
616    m_inp_mem_ptr(NULL),
617    m_out_mem_ptr(NULL),
618    input_flush_progress (false),
619    output_flush_progress (false),
620    input_use_buffer (false),
621    output_use_buffer (false),
622    ouput_egl_buffers(false),
623    m_use_output_pmem(OMX_FALSE),
624    m_out_mem_region_smi(OMX_FALSE),
625    m_out_pvt_entry_pmem(OMX_FALSE),
626    pending_input_buffers(0),
627    pending_output_buffers(0),
628    m_out_bm_count(0),
629    m_inp_bm_count(0),
630    m_inp_bPopulated(OMX_FALSE),
631    m_out_bPopulated(OMX_FALSE),
632    m_flags(0),
633#ifdef _ANDROID_
634    m_heap_ptr(NULL),
635#endif
636    m_inp_bEnabled(OMX_TRUE),
637    m_out_bEnabled(OMX_TRUE),
638    m_in_alloc_cnt(0),
639    m_platform_list(NULL),
640    m_platform_entry(NULL),
641    m_pmem_info(NULL),
642    h264_parser(NULL),
643    arbitrary_bytes (true),
644    psource_frame (NULL),
645    pdest_frame (NULL),
646    m_inp_heap_ptr (NULL),
647    m_phdr_pmem_ptr(NULL),
648    m_heap_inp_bm_count (0),
649    codec_type_parse ((codec_type)0),
650    first_frame_meta (true),
651    frame_count (0),
652    nal_count (0),
653    nal_length(0),
654    look_ahead_nal (false),
655    first_frame(0),
656    first_buffer(NULL),
657    first_frame_size (0),
658    m_device_file_ptr(NULL),
659    m_vc1_profile((vc1_profile_type)0),
660    h264_last_au_ts(LLONG_MAX),
661    h264_last_au_flags(0),
662    m_disp_hor_size(0),
663    m_disp_vert_size(0),
664    prev_ts(LLONG_MAX),
665    prev_ts_actual(LLONG_MAX),
666    rst_prev_ts(true),
667    frm_int(0),
668    m_fps_received(0),
669    m_fps_prev(0),
670    m_drc_enable(0),
671    in_reconfig(false),
672    m_display_id(NULL),
673    client_extradata(0),
674    m_reject_avc_1080p_mp (0),
675#ifdef _ANDROID_
676    m_enable_android_native_buffers(OMX_FALSE),
677    m_use_android_native_buffers(OMX_FALSE),
678#endif
679    m_desc_buffer_ptr(NULL),
680    secure_mode(false),
681    allocate_native_handle(false),
682    m_other_extradata(NULL),
683    m_profile(0),
684    m_need_turbo(0),
685    client_set_fps(false),
686    stereo_output_mode(HAL_NO_3D),
687    m_last_rendered_TS(-1),
688    m_queued_codec_config_count(0),
689    current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
690    secure_scaling_to_non_secure_opb(false),
691    m_force_compressed_for_dpb(true),
692    m_is_display_session(false)
693{
694    m_pipe_in = -1;
695    m_pipe_out = -1;
696    m_poll_efd = -1;
697    drv_ctx.video_driver_fd = -1;
698    drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
699    /* Assumption is that , to begin with , we have all the frames with decoder */
700    DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
701    memset(&m_debug,0,sizeof(m_debug));
702#ifdef _ANDROID_
703    char property_value[PROPERTY_VALUE_MAX] = {0};
704    property_get("vidc.debug.level", property_value, "1");
705    debug_level = strtoul(property_value, NULL, 16);
706    property_value[0] = '\0';
707
708    DEBUG_PRINT_HIGH("In OMX vdec Constructor");
709
710    property_get("vidc.dec.debug.perf", property_value, "0");
711    perf_flag = atoi(property_value);
712    if (perf_flag) {
713        DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
714        dec_time.start();
715    }
716    proc_frms = latency = 0;
717    prev_n_filled_len = 0;
718    property_value[0] = '\0';
719    property_get("vidc.dec.debug.ts", property_value, "0");
720    m_debug_timestamp = atoi(property_value);
721    DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
722    if (m_debug_timestamp) {
723        time_stamp_dts.set_timestamp_reorder_mode(true);
724        time_stamp_dts.enable_debug_print(true);
725    }
726
727    property_value[0] = '\0';
728    property_get("vidc.dec.debug.concealedmb", property_value, "0");
729    m_debug_concealedmb = atoi(property_value);
730    DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
731
732    property_value[0] = '\0';
733    property_get("vidc.dec.profile.check", property_value, "0");
734    m_reject_avc_1080p_mp = atoi(property_value);
735    DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
736
737    property_value[0] = '\0';
738    property_get("vidc.dec.log.in", property_value, "0");
739    m_debug.in_buffer_log = atoi(property_value);
740
741    property_value[0] = '\0';
742    property_get("vidc.dec.log.out", property_value, "0");
743    m_debug.out_buffer_log = atoi(property_value);
744    snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
745
746    property_value[0] = '\0';
747    property_get("vidc.dec.meta.log.out", property_value, "0");
748    m_debug.out_meta_buffer_log = atoi(property_value);
749    snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
750
751    property_value[0] = '\0';
752    property_get("vidc.log.loc", property_value, "");
753    if (*property_value)
754        strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
755
756    property_value[0] = '\0';
757    property_get("vidc.dec.120fps.enabled", property_value, "0");
758
759    //if this feature is not enabled then reset this value -ve
760    if(atoi(property_value)) {
761        DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
762        m_last_rendered_TS = 0;
763    }
764
765    property_value[0] = '\0';
766    property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
767    m_disable_dynamic_buf_mode = atoi(property_value);
768    DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
769
770    property_value[0] = '\0';
771    property_get("vidc.dec.drc.enable", property_value, "0");
772    if (atoi(property_value)) {
773        m_drc_enable = true;
774        DEBUG_PRINT_HIGH("DRC enabled");
775    }
776
777#ifdef _UBWC_
778    property_value[0] = '\0';
779    property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
780    m_disable_ubwc_mode = atoi(property_value);
781    DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
782#else
783    m_disable_ubwc_mode = true;
784#endif
785#endif
786    memset(&m_cmp,0,sizeof(m_cmp));
787    memset(&m_cb,0,sizeof(m_cb));
788    memset (&drv_ctx,0,sizeof(drv_ctx));
789    memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
790    memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
791    memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
792    memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
793    memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
794    memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
795    memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
796    memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
797    memset(&m_color_mdata, 0, sizeof(ColorMetaData));
798    m_demux_entries = 0;
799    msg_thread_id = 0;
800    async_thread_id = 0;
801    msg_thread_created = false;
802    async_thread_created = false;
803    async_thread_force_stop = false;
804    message_thread_stop = false;
805#ifdef _ANDROID_ICS_
806    memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
807#endif
808    memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
809
810    /* invalidate m_frame_pack_arrangement */
811    memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
812    m_frame_pack_arrangement.cancel_flag = 1;
813
814    drv_ctx.timestamp_adjust = false;
815    m_vendor_config.pData = NULL;
816    pthread_mutex_init(&m_lock, NULL);
817    pthread_mutex_init(&c_lock, NULL);
818    pthread_mutex_init(&buf_lock, NULL);
819    sem_init(&m_cmd_lock,0,0);
820    sem_init(&m_safe_flush, 0, 0);
821    streaming[CAPTURE_PORT] =
822        streaming[OUTPUT_PORT] = false;
823#ifdef _ANDROID_
824    char extradata_value[PROPERTY_VALUE_MAX] = {0};
825    property_get("vidc.dec.debug.extradata", extradata_value, "0");
826    m_debug_extradata = atoi(extradata_value);
827    DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
828#endif
829    m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
830    client_buffers.set_vdec_client(this);
831    dynamic_buf_mode = false;
832    out_dynamic_list = NULL;
833    is_down_scalar_enabled = false;
834    m_enable_downscalar = 0;
835    m_downscalar_width = 0;
836    m_downscalar_height = 0;
837    m_force_down_scalar = 0;
838    m_reconfig_height = 0;
839    m_reconfig_width = 0;
840    m_smoothstreaming_mode = false;
841    m_smoothstreaming_width = 0;
842    m_smoothstreaming_height = 0;
843    is_q6_platform = false;
844    m_perf_control.send_hint_to_mpctl(true);
845    m_input_pass_buffer_fd = false;
846    memset(&m_extradata_info, 0, sizeof(m_extradata_info));
847    m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
848    m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
849    m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
850    m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
851    m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
852
853    m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
854    m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
855    m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
856    m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
857    m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
858    m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
859
860    m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
861    m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
862    m_change_client_hdr_info = false;
863    pthread_mutex_init(&m_hdr_info_client_lock, NULL);
864
865    char dither_value[PROPERTY_VALUE_MAX] = {0};
866    property_get("vidc.dec.dither", dither_value, "0");
867    if ((atoi(dither_value) > DITHER_ALL_COLORSPACE) ||
868        (atoi(dither_value) < DITHER_DISABLE)) {
869        m_dither_config = DITHER_ALL_COLORSPACE;
870    } else {
871        m_dither_config = is_platform_tp10capture_supported() ? (dither_type)atoi(dither_value) : DITHER_ALL_COLORSPACE;
872    }
873
874    DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
875    m_color_space = EXCEPT_BT2020;
876}
877
878static const int event_type[] = {
879    V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
880    V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
881    V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
882    V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
883    V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
884    V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
885    V4L2_EVENT_MSM_VIDC_SYS_ERROR,
886    V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
887    V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
888};
889
890static OMX_ERRORTYPE subscribe_to_events(int fd)
891{
892    OMX_ERRORTYPE eRet = OMX_ErrorNone;
893    struct v4l2_event_subscription sub;
894    int array_sz = sizeof(event_type)/sizeof(int);
895    int i,rc;
896    if (fd < 0) {
897        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
898        return OMX_ErrorBadParameter;
899    }
900
901    for (i = 0; i < array_sz; ++i) {
902        memset(&sub, 0, sizeof(sub));
903        sub.type = event_type[i];
904        rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
905        if (rc) {
906            DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
907            break;
908        }
909    }
910    if (i < array_sz) {
911        for (--i; i >=0 ; i--) {
912            memset(&sub, 0, sizeof(sub));
913            sub.type = event_type[i];
914            rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
915            if (rc)
916                DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
917        }
918        eRet = OMX_ErrorNotImplemented;
919    }
920    return eRet;
921}
922
923
924static OMX_ERRORTYPE unsubscribe_to_events(int fd)
925{
926    OMX_ERRORTYPE eRet = OMX_ErrorNone;
927    struct v4l2_event_subscription sub;
928    int array_sz = sizeof(event_type)/sizeof(int);
929    int i,rc;
930    if (fd < 0) {
931        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
932        return OMX_ErrorBadParameter;
933    }
934
935    for (i = 0; i < array_sz; ++i) {
936        memset(&sub, 0, sizeof(sub));
937        sub.type = event_type[i];
938        rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
939        if (rc) {
940            DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
941            break;
942        }
943    }
944    return eRet;
945}
946
947/* ======================================================================
948   FUNCTION
949   omx_vdec::~omx_vdec
950
951   DESCRIPTION
952   Destructor
953
954   PARAMETERS
955   None
956
957   RETURN VALUE
958   None.
959   ========================================================================== */
960omx_vdec::~omx_vdec()
961{
962    m_pmem_info = NULL;
963    DEBUG_PRINT_HIGH("In OMX vdec Destructor");
964    if (msg_thread_created) {
965        DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
966        message_thread_stop = true;
967        post_message(this, OMX_COMPONENT_CLOSE_MSG);
968        DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
969        pthread_join(msg_thread_id,NULL);
970    }
971    close(m_pipe_in);
972    close(m_pipe_out);
973    m_pipe_in = -1;
974    m_pipe_out = -1;
975    DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
976    if(eventfd_write(m_poll_efd, 1)) {
977         DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
978         async_thread_force_stop = true;
979    }
980
981    if (async_thread_created)
982        pthread_join(async_thread_id,NULL);
983    unsubscribe_to_events(drv_ctx.video_driver_fd);
984    close(m_poll_efd);
985    close(drv_ctx.video_driver_fd);
986    pthread_mutex_destroy(&m_lock);
987    pthread_mutex_destroy(&c_lock);
988    pthread_mutex_destroy(&buf_lock);
989    sem_destroy(&m_cmd_lock);
990    pthread_mutex_destroy(&m_hdr_info_client_lock);
991    if (perf_flag) {
992        DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
993        dec_time.end();
994    }
995    DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
996    m_perf_control.send_hint_to_mpctl(false);
997}
998
999int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
1000{
1001    struct v4l2_requestbuffers bufreq;
1002    int rc = 0;
1003    if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
1004        bufreq.memory = V4L2_MEMORY_USERPTR;
1005        bufreq.count = 0;
1006        bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1007        rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
1008    } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
1009        bufreq.memory = V4L2_MEMORY_USERPTR;
1010        bufreq.count = 0;
1011        bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1012        rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
1013    }
1014    return rc;
1015}
1016
1017OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
1018{
1019    int rc = 0;
1020    struct v4l2_ext_control ctrl[2];
1021    struct v4l2_ext_controls controls;
1022
1023    DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
1024         is_split_mode ? "split" : "combined",
1025         dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
1026         dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
1027         dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
1028         "unknown",
1029         capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
1030         capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
1031         capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC ? "nv12_10bit_ubwc":
1032         "unknown");
1033
1034    ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1035    if (is_split_mode) {
1036        ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1037    } else {
1038        ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1039    }
1040
1041    ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
1042    ctrl[1].value = dpb_color_format;
1043
1044    controls.count = 2;
1045    controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1046    controls.controls = ctrl;
1047
1048    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1049    if (rc) {
1050        DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1051        return OMX_ErrorUnsupportedSetting;
1052    }
1053    return OMX_ErrorNone;
1054}
1055
1056
1057OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt)
1058{
1059    OMX_ERRORTYPE eRet = OMX_ErrorNone;
1060    struct v4l2_format fmt;
1061    int rc = 0;
1062    bool cpu_access = (capture_capability != V4L2_PIX_FMT_NV12_UBWC) &&
1063        capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC;
1064    bool tp10_enable = !cpu_access &&
1065        dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10;
1066    bool dither_enable = true;
1067
1068    switch (m_dither_config) {
1069    case DITHER_DISABLE:
1070        dither_enable = false;
1071        break;
1072    case DITHER_COLORSPACE_EXCEPTBT2020:
1073        dither_enable = (m_color_space == EXCEPT_BT2020);
1074        break;
1075    case DITHER_ALL_COLORSPACE:
1076        dither_enable = true;
1077        break;
1078    default:
1079        DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1080    }
1081
1082    if (tp10_enable && !dither_enable) {
1083        drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1084        capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1085
1086        memset(&fmt, 0x0, sizeof(struct v4l2_format));
1087        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1088        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1089        if (rc) {
1090            DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1091            return OMX_ErrorUnsupportedSetting;
1092        }
1093        fmt.fmt.pix_mp.pixelformat = capture_capability;
1094        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1095        if (rc) {
1096            DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1097            return OMX_ErrorUnsupportedSetting;
1098        }
1099
1100    }
1101
1102
1103    if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1104        !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1105        DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1106        return eRet;
1107    }
1108
1109
1110    if (cpu_access) {
1111        if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1112            /* Disabled split mode for VP9. In split mode the DPB buffers are part of the internal
1113             * scratch buffers and the driver does not does the reference buffer management for
1114             * scratch buffers. In case of VP9 with spatial scalability, when a sequence changed
1115             * event is received with the new resolution, and when a flush is sent by the driver, it
1116             * releases all the references of internal scratch buffers. However as per the VP9
1117             * spatial scalability, even after the flush, the buffers which have not yet received
1118             * release reference event should not be unmapped and freed. Currently in driver,
1119             * reference buffer management of the internal scratch buffer is not implemented
1120             * and hence the DPB buffers get unmapped. For other codecs it does not matter
1121             * as with the new SPS/PPS, the DPB is flushed.
1122             */
1123            bool is_not_vp9 = eCompressionFormat != OMX_VIDEO_CodingVP9;
1124            bool eligible_for_split_dpb_ubwc =
1125               m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE &&     //@ Due to Venus limitation for Interlaced, Split mode enabled only for Progressive.
1126               is_not_vp9                                       &&     //@ Split mode disabled for VP9.
1127               !drv_ctx.idr_only_decoding                       &&     //@ Split mode disabled for Thumbnail usecase.
1128               !m_disable_split_mode;                                  //@ Set prop to disable split mode
1129
1130            //Since opb is linear, dpb should also be linear.
1131            if (split_opb_dpb_with_same_color_fmt) {
1132                eligible_for_split_dpb_ubwc = false;
1133            }
1134
1135            if (eligible_for_split_dpb_ubwc) {
1136                //split DPB-OPB
1137                //DPB -> UBWC , OPB -> Linear
1138                eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1139            } else if (split_opb_dpb_with_same_color_fmt) {
1140                        //DPB -> Linear, OPB -> Linear
1141                        eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1142            } else {
1143                        //DPB-OPB combined linear
1144                        eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1145           }
1146        } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1147            //split DPB-OPB
1148            //DPB -> UBWC, OPB -> Linear
1149            eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1150        }
1151    } else { //no cpu access
1152        if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1153            if (split_opb_dpb_with_same_color_fmt) {
1154                //split DPB-OPB
1155                //DPB -> UBWC, OPB -> UBWC
1156                eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1157            } else {
1158                //DPB-OPB combined UBWC
1159                eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1160            }
1161        } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1162            if (dither_enable) {
1163                //split DPB-OPB
1164                //DPB -> TP10UBWC, OPB -> UBWC
1165                eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1166            } else {
1167                //combined DPB-OPB
1168                //DPB -> TP10UBWC, OPB -> TP10UBWC
1169                eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1170            }
1171        }
1172    }
1173    if (eRet) {
1174        DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1175    }
1176
1177
1178
1179    return eRet;
1180}
1181
1182int omx_vdec::enable_downscalar()
1183{
1184    int rc = 0;
1185    struct v4l2_control control;
1186    struct v4l2_format fmt;
1187
1188    if (is_down_scalar_enabled) {
1189        DEBUG_PRINT_LOW("%s: already enabled", __func__);
1190        return 0;
1191    }
1192
1193    DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1194    rc = decide_dpb_buffer_mode(true);
1195    if (rc) {
1196        DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1197        return rc;
1198    }
1199    is_down_scalar_enabled = true;
1200
1201    memset(&control, 0x0, sizeof(struct v4l2_control));
1202    control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1203    control.value = 1;
1204    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1205    if (rc) {
1206        DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1207        return rc;
1208    }
1209
1210    return 0;
1211}
1212
1213int omx_vdec::disable_downscalar()
1214{
1215    int rc = 0;
1216    struct v4l2_control control;
1217
1218    if (!is_down_scalar_enabled) {
1219        DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1220        return 0;
1221    }
1222
1223    rc = decide_dpb_buffer_mode(false);
1224    if (rc < 0) {
1225        DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1226        return rc;
1227    }
1228    is_down_scalar_enabled = false;
1229
1230    return rc;
1231}
1232
1233int omx_vdec::decide_downscalar()
1234{
1235    int rc = 0;
1236    struct v4l2_format fmt;
1237    enum color_fmts color_format;
1238    OMX_U32 width, height;
1239    OMX_BOOL isPortraitVideo = OMX_FALSE;
1240
1241    if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1242        rc = disable_downscalar();
1243        if (rc) {
1244            DEBUG_PRINT_ERROR("Disable downscalar failed!");
1245            return rc;
1246        }
1247        return 0;
1248    }
1249
1250    if  (!m_enable_downscalar) {
1251        DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1252        return 0;
1253    }
1254
1255#ifdef _QUERY_DISP_RES_
1256    memset(&fmt, 0x0, sizeof(struct v4l2_format));
1257    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1258    fmt.fmt.pix_mp.pixelformat = capture_capability;
1259    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1260    if (rc < 0) {
1261       DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1262       return rc;
1263    }
1264    isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
1265    if (!m_downscalar_width || !m_downscalar_height) {
1266        qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
1267        int prim_config, ext_config, virt_config;
1268
1269        prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
1270        dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
1271        DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d  dpa.yres=%d   dpa.xdpi = %f  dpa.ydpi = %f ",
1272            __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
1273
1274        ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
1275        dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
1276        DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d  dsa.yres = %d   dsa.xdpi = %f  dsa.ydpi = %f ",
1277            __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
1278
1279        virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
1280        dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
1281        DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d  dva.yres = %d   dva.xdpi = %f  dva.ydpi = %f ",
1282            __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
1283
1284        /* Below logic takes care of following conditions:
1285         *   1. Choose display resolution as maximum resolution of all the connected
1286         *      displays (secondary, primary, virtual), so that we do not downscale
1287         *      unnecessarily which might be supported on one of the display losing quality.
1288         *   2. Displays connected might be in landscape or portrait mode, so the xres might
1289         *      be smaller or greater than the yres. So we first take the max of the two
1290         *      in width and min of two in height and then rotate it if below point is true.
1291         *   3. Video might also be in portrait mode, so invert the downscalar width and
1292         *      height for such cases.
1293         */
1294        if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
1295            m_downscalar_width = MAX(dsa.xres, dsa.yres);
1296            m_downscalar_height = MIN(dsa.xres, dsa.yres);
1297        } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
1298            m_downscalar_width = MAX(dva.xres, dva.yres);
1299            m_downscalar_height = MIN(dva.xres, dva.yres);
1300
1301        } else {
1302            m_downscalar_width = MAX(dpa.xres, dpa.yres);
1303            m_downscalar_height = MIN(dpa.xres, dpa.yres);
1304        }
1305        if (isPortraitVideo) {
1306            // Swap width and height
1307            m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1308            m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
1309            m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1310        }
1311    }
1312    m_downscalar_width = ALIGN(m_downscalar_width, 128);
1313    m_downscalar_height = ALIGN(m_downscalar_height, 32);
1314#endif
1315
1316    if (!m_downscalar_width || !m_downscalar_height) {
1317        DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
1318        return 0;
1319    }
1320
1321    if (m_force_down_scalar) {
1322        DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1323        return 0;
1324    }
1325
1326    memset(&fmt, 0x0, sizeof(struct v4l2_format));
1327    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1328    fmt.fmt.pix_mp.pixelformat = capture_capability;
1329    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1330    if (rc < 0) {
1331       DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1332       return rc;
1333    }
1334
1335    height = fmt.fmt.pix_mp.height;
1336    width = fmt.fmt.pix_mp.width;
1337
1338    DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
1339        fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
1340
1341    if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
1342         m_is_display_session) {
1343        rc = enable_downscalar();
1344        if (rc < 0) {
1345            DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1346            return rc;
1347        }
1348
1349        width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1350                            fmt.fmt.pix_mp.width : m_downscalar_width;
1351        height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1352                            fmt.fmt.pix_mp.height : m_downscalar_height;
1353        switch (capture_capability) {
1354            case V4L2_PIX_FMT_NV12:
1355                color_format = COLOR_FMT_NV12;
1356                break;
1357            case V4L2_PIX_FMT_NV12_UBWC:
1358                color_format = COLOR_FMT_NV12_UBWC;
1359                break;
1360            case V4L2_PIX_FMT_NV12_TP10_UBWC:
1361                color_format = COLOR_FMT_NV12_BPP10_UBWC;
1362                break;
1363            default:
1364                DEBUG_PRINT_ERROR("Color format not recognized\n");
1365                rc = OMX_ErrorUndefined;
1366                return rc;
1367        }
1368    } else {
1369
1370        rc = disable_downscalar();
1371        if (rc < 0) {
1372            DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1373            return rc;
1374        }
1375    }
1376
1377    memset(&fmt, 0x0, sizeof(struct v4l2_format));
1378    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1379    fmt.fmt.pix_mp.height = height;
1380    fmt.fmt.pix_mp.width = width;
1381    fmt.fmt.pix_mp.pixelformat = capture_capability;
1382    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1383    if (rc) {
1384        DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1385        return rc;
1386    }
1387
1388    rc = get_buffer_req(&drv_ctx.op_buf);
1389    if (rc) {
1390        DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1391        return rc;
1392    }
1393
1394    return rc;
1395}
1396
1397/* ======================================================================
1398   FUNCTION
1399   omx_vdec::OMXCntrlProcessMsgCb
1400
1401   DESCRIPTION
1402   IL Client callbacks are generated through this routine. The decoder
1403   provides the thread context for this routine.
1404
1405   PARAMETERS
1406   ctxt -- Context information related to the self.
1407   id   -- Event identifier. This could be any of the following:
1408   1. Command completion event
1409   2. Buffer done callback event
1410   3. Frame done callback event
1411
1412   RETURN VALUE
1413   None.
1414
1415   ========================================================================== */
1416void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1417{
1418    unsigned long p1; // Parameter - 1
1419    unsigned long p2; // Parameter - 2
1420    unsigned long ident;
1421    unsigned qsize=0; // qsize
1422    omx_vdec *pThis = (omx_vdec *) ctxt;
1423
1424    if (!pThis) {
1425        DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1426                __func__);
1427        return;
1428    }
1429
1430    // Protect the shared queue data structure
1431    do {
1432        /*Read the message id's from the queue*/
1433        pthread_mutex_lock(&pThis->m_lock);
1434        qsize = pThis->m_cmd_q.m_size;
1435        if (qsize) {
1436            pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1437        }
1438
1439        if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1440            qsize = pThis->m_ftb_q.m_size;
1441            if (qsize) {
1442                pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1443            }
1444        }
1445
1446        if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1447            qsize = pThis->m_etb_q.m_size;
1448            if (qsize) {
1449                pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1450            }
1451        }
1452        pthread_mutex_unlock(&pThis->m_lock);
1453
1454        /*process message if we have one*/
1455        if (qsize > 0) {
1456            id = ident;
1457            switch (id) {
1458                case OMX_COMPONENT_GENERATE_EVENT:
1459                    if (pThis->m_cb.EventHandler) {
1460                        switch (p1) {
1461                            case OMX_CommandStateSet:
1462                                pThis->m_state = (OMX_STATETYPE) p2;
1463                                DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1464                                        pThis->m_state);
1465                                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1466                                        OMX_EventCmdComplete, p1, p2, NULL);
1467                                break;
1468
1469                            case OMX_EventError:
1470                                if (p2 == OMX_StateInvalid) {
1471                                    DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1472                                    pThis->m_state = (OMX_STATETYPE) p2;
1473                                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1474                                            OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1475                                } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1476                                    pThis->omx_report_error();
1477                                } else {
1478                                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1479                                            OMX_EventError, p2, (OMX_U32)NULL, NULL );
1480                                }
1481                                break;
1482
1483                            case OMX_CommandPortDisable:
1484                                DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1485                                if (BITMASK_PRESENT(&pThis->m_flags,
1486                                            OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1487                                    BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1488                                    break;
1489                                }
1490                                if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1491                                    OMX_ERRORTYPE eRet = OMX_ErrorNone;
1492                                    pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1493                                    if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1494                                        DEBUG_PRINT_HIGH("Failed to release output buffers");
1495                                    OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1496                                    if (eRet !=  OMX_ErrorNone) {
1497                                        DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1498                                        pThis->omx_report_error();
1499                                        break;
1500                                    }
1501                                }
1502                                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1503                                        OMX_EventCmdComplete, p1, p2, NULL );
1504                                break;
1505                            case OMX_CommandPortEnable:
1506                                DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1507                                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1508                                        OMX_EventCmdComplete, p1, p2, NULL );
1509                                pThis->in_reconfig = false;
1510                                break;
1511
1512                            default:
1513                                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1514                                        OMX_EventCmdComplete, p1, p2, NULL );
1515                                break;
1516
1517                        }
1518                    } else {
1519                        DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1520                    }
1521                    break;
1522                case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1523                    if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1524                                (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1525                        DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1526                        pThis->omx_report_error ();
1527                    }
1528                    break;
1529                case OMX_COMPONENT_GENERATE_ETB: {
1530                        OMX_ERRORTYPE iret;
1531                        iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1532                        if (iret == OMX_ErrorInsufficientResources) {
1533                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1534                            pThis->omx_report_hw_overload ();
1535                        } else if (iret != OMX_ErrorNone) {
1536                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1537                            pThis->omx_report_error ();
1538                        }
1539                    }
1540                    break;
1541
1542                case OMX_COMPONENT_GENERATE_FTB:
1543                    if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1544                                (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1545                        DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1546                        pThis->omx_report_error ();
1547                    }
1548                    break;
1549
1550                case OMX_COMPONENT_GENERATE_COMMAND:
1551                    pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1552                            (OMX_U32)p2,(OMX_PTR)NULL);
1553                    break;
1554
1555                case OMX_COMPONENT_GENERATE_EBD:
1556
1557                    if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1558                        DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1559                        pThis->omx_report_error ();
1560                    } else {
1561                        if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1562                            pThis->time_stamp_dts.remove_time_stamp(
1563                                    ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1564                                    (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1565                                    ?true:false);
1566                        }
1567
1568                        if ( pThis->empty_buffer_done(&pThis->m_cmp,
1569                                    (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1570                            DEBUG_PRINT_ERROR("empty_buffer_done failure");
1571                            pThis->omx_report_error ();
1572                        }
1573                    }
1574                    break;
1575                case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1576                                            int64_t *timestamp = (int64_t *)(intptr_t)p1;
1577                                            if (p1) {
1578                                                pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1579                                                        (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1580                                                        ?true:false);
1581                                                free(timestamp);
1582                                            }
1583                                        }
1584                                        break;
1585                case OMX_COMPONENT_GENERATE_FBD:
1586                                        if (p2 != VDEC_S_SUCCESS) {
1587                                            DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1588                                            pThis->omx_report_error ();
1589                                        } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1590                                                    (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1591                                            DEBUG_PRINT_ERROR("fill_buffer_done failure");
1592                                            pThis->omx_report_error ();
1593                                        }
1594                                        break;
1595
1596                case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1597                                        DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1598                                        if (!pThis->input_flush_progress) {
1599                                            DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1600                                        } else {
1601                                            pThis->execute_input_flush();
1602                                            if (pThis->m_cb.EventHandler) {
1603                                                if (p2 != VDEC_S_SUCCESS) {
1604                                                    DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1605                                                    pThis->omx_report_error ();
1606                                                } else {
1607                                                    /*Check if we need generate event for Flush done*/
1608                                                    if (BITMASK_PRESENT(&pThis->m_flags,
1609                                                                OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
1610                                                        BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
1611                                                        DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
1612                                                        pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1613                                                                OMX_EventCmdComplete,OMX_CommandFlush,
1614                                                                OMX_CORE_INPUT_PORT_INDEX,NULL );
1615                                                    }
1616                                                    if (BITMASK_PRESENT(&pThis->m_flags,
1617                                                                OMX_COMPONENT_IDLE_PENDING)) {
1618                                                        if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1619                                                            DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1620                                                            pThis->omx_report_error ();
1621                                                        } else {
1622                                                            pThis->streaming[OUTPUT_PORT] = false;
1623                                                        }
1624                                                        if (!pThis->output_flush_progress) {
1625                                                            DEBUG_PRINT_LOW("Input flush done hence issue stop");
1626                                                            pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1627                                                                    OMX_COMPONENT_GENERATE_STOP_DONE);
1628                                                        }
1629                                                    }
1630                                                }
1631                                            } else {
1632                                                DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1633                                            }
1634                                        }
1635                                        break;
1636
1637                case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1638                                        DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1639                                        if (!pThis->output_flush_progress) {
1640                                            DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1641                                        } else {
1642                                            pThis->execute_output_flush();
1643                                            if (pThis->m_cb.EventHandler) {
1644                                                if (p2 != VDEC_S_SUCCESS) {
1645                                                    DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1646                                                    pThis->omx_report_error ();
1647                                                } else {
1648                                                    /*Check if we need generate event for Flush done*/
1649                                                    if (BITMASK_PRESENT(&pThis->m_flags,
1650                                                                OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
1651                                                        DEBUG_PRINT_LOW("Notify Output Flush done");
1652                                                        BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1653                                                        pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1654                                                                OMX_EventCmdComplete,OMX_CommandFlush,
1655                                                                OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1656                                                    }
1657                                                    if (BITMASK_PRESENT(&pThis->m_flags,
1658                                                                OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1659                                                        DEBUG_PRINT_LOW("Internal flush complete");
1660                                                        BITMASK_CLEAR (&pThis->m_flags,
1661                                                                OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1662                                                        if (BITMASK_PRESENT(&pThis->m_flags,
1663                                                                    OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1664                                                            pThis->post_event(OMX_CommandPortDisable,
1665                                                                    OMX_CORE_OUTPUT_PORT_INDEX,
1666                                                                    OMX_COMPONENT_GENERATE_EVENT);
1667                                                            BITMASK_CLEAR (&pThis->m_flags,
1668                                                                    OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1669                                                            BITMASK_CLEAR (&pThis->m_flags,
1670                                                                    OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1671
1672                                                        }
1673                                                    }
1674
1675                                                    if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1676                                                        if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1677                                                            DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1678                                                            pThis->omx_report_error ();
1679                                                            break;
1680                                                        }
1681                                                        pThis->streaming[CAPTURE_PORT] = false;
1682                                                        if (!pThis->input_flush_progress) {
1683                                                            DEBUG_PRINT_LOW("Output flush done hence issue stop");
1684                                                            pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1685                                                                    OMX_COMPONENT_GENERATE_STOP_DONE);
1686                                                        }
1687                                                    }
1688                                                }
1689                                            } else {
1690                                                DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1691                                            }
1692                                        }
1693                                        break;
1694
1695                case OMX_COMPONENT_GENERATE_START_DONE:
1696                                        DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1697
1698                                        if (pThis->m_cb.EventHandler) {
1699                                            if (p2 != VDEC_S_SUCCESS) {
1700                                                DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1701                                                pThis->omx_report_error ();
1702                                            } else {
1703                                                DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1704                                                if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1705                                                    DEBUG_PRINT_LOW("Move to executing");
1706                                                    // Send the callback now
1707                                                    BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1708                                                    pThis->m_state = OMX_StateExecuting;
1709                                                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1710                                                            OMX_EventCmdComplete,OMX_CommandStateSet,
1711                                                            OMX_StateExecuting, NULL);
1712                                                } else if (BITMASK_PRESENT(&pThis->m_flags,
1713                                                            OMX_COMPONENT_PAUSE_PENDING)) {
1714                                                    if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1715                                                          VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1716                                                        DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1717                                                        pThis->omx_report_error ();
1718                                                    }
1719                                                }
1720                                            }
1721                                        } else {
1722                                            DEBUG_PRINT_LOW("Event Handler callback is NULL");
1723                                        }
1724                                        break;
1725
1726                case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1727                                        DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1728                                        if (pThis->m_cb.EventHandler) {
1729                                            if (p2 != VDEC_S_SUCCESS) {
1730                                                DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1731                                                pThis->omx_report_error ();
1732                                            } else {
1733                                                pThis->complete_pending_buffer_done_cbs();
1734                                                if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1735                                                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1736                                                    //Send the callback now
1737                                                    BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1738                                                    pThis->m_state = OMX_StatePause;
1739                                                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1740                                                            OMX_EventCmdComplete,OMX_CommandStateSet,
1741                                                            OMX_StatePause, NULL);
1742                                                }
1743                                            }
1744                                        } else {
1745                                            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1746                                        }
1747
1748                                        break;
1749
1750                case OMX_COMPONENT_GENERATE_RESUME_DONE:
1751                                        DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1752                                        if (pThis->m_cb.EventHandler) {
1753                                            if (p2 != VDEC_S_SUCCESS) {
1754                                                DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1755                                                pThis->omx_report_error ();
1756                                            } else {
1757                                                if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1758                                                    DEBUG_PRINT_LOW("Moving the decoder to execute state");
1759                                                    // Send the callback now
1760                                                    BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1761                                                    pThis->m_state = OMX_StateExecuting;
1762                                                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1763                                                            OMX_EventCmdComplete,OMX_CommandStateSet,
1764                                                            OMX_StateExecuting,NULL);
1765                                                }
1766                                            }
1767                                        } else {
1768                                            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1769                                        }
1770
1771                                        break;
1772
1773                case OMX_COMPONENT_GENERATE_STOP_DONE:
1774                                        DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1775                                        if (pThis->m_cb.EventHandler) {
1776                                            if (p2 != VDEC_S_SUCCESS) {
1777                                                DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1778                                                pThis->omx_report_error ();
1779                                            } else {
1780                                                pThis->complete_pending_buffer_done_cbs();
1781                                                if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1782                                                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1783                                                    // Send the callback now
1784                                                    BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1785                                                    pThis->m_state = OMX_StateIdle;
1786                                                    DEBUG_PRINT_LOW("Move to Idle State");
1787                                                    pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1788                                                            OMX_EventCmdComplete,OMX_CommandStateSet,
1789                                                            OMX_StateIdle,NULL);
1790                                                }
1791                                            }
1792                                        } else {
1793                                            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1794                                        }
1795
1796                                        break;
1797
1798                case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1799                                        if (p2 == OMX_IndexParamPortDefinition) {
1800                                            DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1801                                            pThis->in_reconfig = true;
1802                                            pThis->m_need_turbo &= ~TURBO_MODE_HIGH_FPS;
1803                                        }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1804                                            DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1805
1806                                            /* Check if resolution is changed in smooth streaming mode */
1807                                            if (pThis->m_smoothstreaming_mode &&
1808                                                (pThis->framesize.nWidth !=
1809                                                    pThis->drv_ctx.video_resolution.frame_width) ||
1810                                                (pThis->framesize.nHeight !=
1811                                                    pThis->drv_ctx.video_resolution.frame_height)) {
1812
1813                                                DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1814                                                        pThis->framesize.nWidth,
1815                                                        pThis->framesize.nHeight,
1816                                                        pThis->drv_ctx.video_resolution.frame_width,
1817                                                        pThis->drv_ctx.video_resolution.frame_height);
1818
1819                                                /* Update new resolution */
1820                                                pThis->framesize.nWidth =
1821                                                       pThis->drv_ctx.video_resolution.frame_width;
1822                                                pThis->framesize.nHeight =
1823                                                       pThis->drv_ctx.video_resolution.frame_height;
1824
1825                                                /* Update C2D with new resolution */
1826                                                if (!pThis->client_buffers.update_buffer_req()) {
1827                                                    DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1828                                                }
1829                                            }
1830
1831                                            /* Update new crop information */
1832                                            pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1833                                            pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1834                                            pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1835                                            pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1836
1837                                            /* Validate the new crop information */
1838                                            if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1839                                                pThis->drv_ctx.video_resolution.frame_width) {
1840
1841                                                DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1842                                                        pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1843                                                        pThis->drv_ctx.video_resolution.frame_width);
1844                                                pThis->rectangle.nLeft = 0;
1845
1846                                                if (pThis->rectangle.nWidth >
1847                                                    pThis->drv_ctx.video_resolution.frame_width) {
1848
1849                                                    DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1850                                                            pThis->rectangle.nWidth,
1851                                                            pThis->drv_ctx.video_resolution.frame_width);
1852                                                    pThis->rectangle.nWidth =
1853                                                        pThis->drv_ctx.video_resolution.frame_width;
1854                                                }
1855                                            }
1856                                            if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1857                                                pThis->drv_ctx.video_resolution.frame_height) {
1858
1859                                                DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1860                                                    pThis->rectangle.nTop, pThis->rectangle.nHeight,
1861                                                    pThis->drv_ctx.video_resolution.frame_height);
1862                                                pThis->rectangle.nTop = 0;
1863
1864                                                if (pThis->rectangle.nHeight >
1865                                                    pThis->drv_ctx.video_resolution.frame_height) {
1866
1867                                                    DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1868                                                        pThis->rectangle.nHeight,
1869                                                        pThis->drv_ctx.video_resolution.frame_height);
1870                                                    pThis->rectangle.nHeight =
1871                                                        pThis->drv_ctx.video_resolution.frame_height;
1872                                                }
1873                                            }
1874                                            DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1875                                                    pThis->rectangle.nLeft, pThis->rectangle.nTop,
1876                                                    pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1877                                        } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1878                                            DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1879                                        } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1880                                            DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1881                                        } else {
1882                                            DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1883                                            break;
1884                                        }
1885                                        if (pThis->m_debug.outfile) {
1886                                            fclose(pThis->m_debug.outfile);
1887                                            pThis->m_debug.outfile = NULL;
1888                                        }
1889                                        if (pThis->m_debug.out_ymeta_file) {
1890                                            fclose(pThis->m_debug.out_ymeta_file);
1891                                            pThis->m_debug.out_ymeta_file = NULL;
1892                                        }
1893                                        if (pThis->m_debug.out_uvmeta_file) {
1894                                            fclose(pThis->m_debug.out_uvmeta_file);
1895                                            pThis->m_debug.out_uvmeta_file = NULL;
1896                                        }
1897
1898                                        if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1899                                            pThis->prefetchNewBuffers();
1900                                        }
1901
1902                                        if (pThis->m_cb.EventHandler) {
1903                                            uint32_t frame_data[4];
1904                                            frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1905                                                pThis->m_reconfig_height : pThis->rectangle.nHeight;
1906                                            frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1907                                                pThis->m_reconfig_width : pThis->rectangle.nWidth;
1908
1909                                            frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ?
1910                                                frame_data[0] : pThis->drv_ctx.video_resolution.frame_height;
1911
1912                                            frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ?
1913                                                frame_data[1] : pThis->drv_ctx.video_resolution.frame_width;
1914
1915                                            pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1916                                                    OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1917                                        } else {
1918                                            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1919                                        }
1920                                        break;
1921
1922                case OMX_COMPONENT_GENERATE_EOS_DONE:
1923                                        DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1924                                        if (pThis->m_cb.EventHandler) {
1925                                            pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1926                                                    OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1927                                        } else {
1928                                            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1929                                        }
1930                                        pThis->prev_ts = LLONG_MAX;
1931                                        pThis->rst_prev_ts = true;
1932                                        break;
1933
1934                case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1935                                        DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1936                                        pThis->omx_report_error();
1937                                        break;
1938
1939                case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1940                                        DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1941                                        pThis->omx_report_unsupported_setting();
1942                                        break;
1943
1944                case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1945                                        DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1946                                        pThis->omx_report_hw_overload();
1947                                        break;
1948
1949                default:
1950                                        break;
1951            }
1952        }
1953        pthread_mutex_lock(&pThis->m_lock);
1954        qsize = pThis->m_cmd_q.m_size;
1955        if (pThis->m_state != OMX_StatePause)
1956            qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1957        pthread_mutex_unlock(&pThis->m_lock);
1958    } while (qsize>0);
1959
1960}
1961
1962int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1963{
1964    int format_changed = 0;
1965    if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1966            (width != (int)drv_ctx.video_resolution.frame_width)) {
1967        DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1968                width, drv_ctx.video_resolution.frame_width,
1969                height,drv_ctx.video_resolution.frame_height);
1970        format_changed = 1;
1971    }
1972    drv_ctx.video_resolution.frame_height = height;
1973    drv_ctx.video_resolution.frame_width = width;
1974    drv_ctx.video_resolution.scan_lines = scan_lines;
1975    drv_ctx.video_resolution.stride = stride;
1976
1977    if (!is_down_scalar_enabled) {
1978        rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
1979        rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
1980        rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
1981        rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
1982    }
1983    return format_changed;
1984}
1985
1986OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1987{
1988    if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1989                OMX_MAX_STRINGNAME_SIZE) &&
1990            (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1991        m_decoder_capability.max_width = 1280;
1992        m_decoder_capability.max_height = 720;
1993        DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1994    }
1995
1996    if ((drv_ctx.video_resolution.frame_width *
1997                drv_ctx.video_resolution.frame_height >
1998                m_decoder_capability.max_width *
1999                m_decoder_capability.max_height) ||
2000            (drv_ctx.video_resolution.frame_width*
2001             drv_ctx.video_resolution.frame_height <
2002             m_decoder_capability.min_width *
2003             m_decoder_capability.min_height)) {
2004        DEBUG_PRINT_ERROR(
2005                "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
2006                drv_ctx.video_resolution.frame_width,
2007                drv_ctx.video_resolution.frame_height,
2008                m_decoder_capability.min_width,
2009                m_decoder_capability.min_height,
2010                m_decoder_capability.max_width,
2011                m_decoder_capability.max_height);
2012        return OMX_ErrorUnsupportedSetting;
2013    }
2014    DEBUG_PRINT_HIGH("video session supported");
2015    return OMX_ErrorNone;
2016}
2017
2018int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
2019{
2020    if (m_debug.in_buffer_log && !m_debug.infile) {
2021        if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
2022           snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
2023                   m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2024        } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
2025                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
2026                        drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2027        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
2028                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
2029                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2030        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
2031                    !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2032                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
2033                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2034        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2035                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
2036                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2037        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
2038                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2039                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2040        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
2041                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2042                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2043        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
2044                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2045                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2046        } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2047                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2048                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2049        } else {
2050               snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
2051                        m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2052        }
2053        m_debug.infile = fopen (m_debug.infile_name, "ab");
2054        if (!m_debug.infile) {
2055            DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
2056            m_debug.infile_name[0] = '\0';
2057            return -1;
2058        }
2059        if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2060                !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2061            struct ivf_file_header {
2062                OMX_U8 signature[4]; //='DKIF';
2063                OMX_U8 version         ; //= 0;
2064                OMX_U8 headersize      ; //= 32;
2065                OMX_U32 FourCC;
2066                OMX_U8 width;
2067                OMX_U8 height;
2068                OMX_U32 rate;
2069                OMX_U32 scale;
2070                OMX_U32 length;
2071                OMX_U8 unused[4];
2072            } file_header;
2073
2074            memset((void *)&file_header,0,sizeof(file_header));
2075            file_header.signature[0] = 'D';
2076            file_header.signature[1] = 'K';
2077            file_header.signature[2] = 'I';
2078            file_header.signature[3] = 'F';
2079            file_header.version = 0;
2080            file_header.headersize = 32;
2081            switch (drv_ctx.decoder_format) {
2082                case VDEC_CODECTYPE_VP8:
2083                    file_header.FourCC = 0x30385056;
2084                    break;
2085                case VDEC_CODECTYPE_VP9:
2086                    file_header.FourCC = 0x30395056;
2087                    break;
2088                default:
2089                    DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
2090                    break;
2091            }
2092            fwrite((const char *)&file_header,
2093                    sizeof(file_header),1,m_debug.infile);
2094         }
2095    }
2096    if (m_debug.infile && buffer_addr && buffer_len) {
2097        if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2098                !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2099            struct vpx_ivf_frame_header {
2100                OMX_U32 framesize;
2101                OMX_U32 timestamp_lo;
2102                OMX_U32 timestamp_hi;
2103            } vpx_frame_header;
2104            vpx_frame_header.framesize = buffer_len;
2105            /* Currently FW doesn't use timestamp values */
2106            vpx_frame_header.timestamp_lo = 0;
2107            vpx_frame_header.timestamp_hi = 0;
2108            fwrite((const char *)&vpx_frame_header,
2109                    sizeof(vpx_frame_header),1,m_debug.infile);
2110        }
2111        fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
2112    }
2113    return 0;
2114}
2115
2116int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2117    int buf_index = 0;
2118    char *temp = NULL;
2119
2120    if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2121        return 0;
2122
2123    if (m_debug.out_buffer_log && !m_debug.outfile) {
2124        snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
2125                m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2126        m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2127        if (!m_debug.outfile) {
2128            DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2129            m_debug.outfile_name[0] = '\0';
2130            return -1;
2131        }
2132    }
2133
2134    if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2135        snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2136                m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2137        snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2138                m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2139        m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2140        m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2141        if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2142            DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2143            m_debug.out_ymetafile_name[0] = '\0';
2144            m_debug.out_uvmetafile_name[0] = '\0';
2145            return -1;
2146        }
2147    }
2148
2149    buf_index = buffer - m_out_mem_ptr;
2150    temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2151
2152    if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2153            drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2154        DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2155            drv_ctx.video_resolution.frame_width,
2156            drv_ctx.video_resolution.frame_height);
2157
2158        if (m_debug.outfile)
2159            fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2160
2161        if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2162            unsigned int width = 0, height = 0;
2163            unsigned int y_plane, y_meta_plane;
2164            int y_stride = 0, y_sclines = 0;
2165            int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2166            int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2167            int i;
2168            int bytes_written = 0;
2169
2170            width = drv_ctx.video_resolution.frame_width;
2171            height = drv_ctx.video_resolution.frame_height;
2172            y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2173            y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2174            y_stride = VENUS_Y_STRIDE(color_fmt, width);
2175            y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2176            uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2177            uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2178
2179            y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2180            y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2181
2182            temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2183            for (i = 0; i < y_meta_scanlines; i++) {
2184                 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2185                 temp += y_meta_stride;
2186            }
2187
2188            temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
2189            for(i = 0; i < uv_meta_scanlines; i++) {
2190                bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2191                temp += uv_meta_stride;
2192            }
2193        }
2194    } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2195        int stride = drv_ctx.video_resolution.stride;
2196        int scanlines = drv_ctx.video_resolution.scan_lines;
2197        if (m_smoothstreaming_mode) {
2198            stride = drv_ctx.video_resolution.frame_width;
2199            scanlines = drv_ctx.video_resolution.frame_height;
2200            stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2201            scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2202        }
2203        unsigned i;
2204        DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2205            drv_ctx.video_resolution.frame_width,
2206            drv_ctx.video_resolution.frame_height, stride, scanlines);
2207        int bytes_written = 0;
2208        for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2209             bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2210             temp += stride;
2211        }
2212        temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
2213        int stride_c = stride;
2214        for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2215            bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2216            temp += stride_c;
2217        }
2218    }
2219    return 0;
2220}
2221
2222/* ======================================================================
2223   FUNCTION
2224   omx_vdec::ComponentInit
2225
2226   DESCRIPTION
2227   Initialize the component.
2228
2229   PARAMETERS
2230   ctxt -- Context information related to the self.
2231   id   -- Event identifier. This could be any of the following:
2232   1. Command completion event
2233   2. Buffer done callback event
2234   3. Frame done callback event
2235
2236   RETURN VALUE
2237   None.
2238
2239   ========================================================================== */
2240OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2241{
2242
2243    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2244    struct v4l2_fmtdesc fdesc;
2245    struct v4l2_format fmt;
2246    struct v4l2_requestbuffers bufreq;
2247    struct v4l2_control control;
2248    struct v4l2_frmsizeenum frmsize;
2249    unsigned int   alignment = 0,buffer_size = 0;
2250    int fds[2];
2251    int r,ret=0;
2252    bool codec_ambiguous = false;
2253    OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2254    char property_value[PROPERTY_VALUE_MAX] = {0};
2255    FILE *soc_file = NULL;
2256    char buffer[10];
2257
2258#ifdef _ANDROID_
2259    char platform_name[PROPERTY_VALUE_MAX];
2260    property_get("ro.board.platform", platform_name, "0");
2261    if (!strncmp(platform_name, "msm8610", 7)) {
2262        device_name = (OMX_STRING)"/dev/video/q6_dec";
2263        is_q6_platform = true;
2264        maxSmoothStreamingWidth = 1280;
2265        maxSmoothStreamingHeight = 720;
2266    }
2267#endif
2268
2269    is_thulium_v1 = false;
2270    soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2271    if (soc_file) {
2272        fread(buffer, 1, 4, soc_file);
2273        fclose(soc_file);
2274        if (atoi(buffer) == 246) {
2275            soc_file = fopen("/sys/devices/soc0/revision", "r");
2276            if (soc_file) {
2277                fread(buffer, 1, 4, soc_file);
2278                fclose(soc_file);
2279                if (atoi(buffer) == 1) {
2280                    is_thulium_v1 = true;
2281                    DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2282                }
2283            }
2284        }
2285    }
2286
2287#ifdef _ANDROID_
2288    /*
2289     * turn off frame parsing for Android by default.
2290     * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2291     */
2292    arbitrary_bytes = false;
2293    property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2294    if (atoi(property_value)) {
2295        DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2296        arbitrary_bytes = true;
2297    }
2298#endif
2299
2300    if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2301                OMX_MAX_STRINGNAME_SIZE)) {
2302        secure_mode = true;
2303        arbitrary_bytes = false;
2304        role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2305    } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2306                OMX_MAX_STRINGNAME_SIZE)) {
2307        secure_mode = true;
2308        arbitrary_bytes = false;
2309        role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2310    } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2311                OMX_MAX_STRINGNAME_SIZE)) {
2312        secure_mode = true;
2313        arbitrary_bytes = false;
2314        role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2315    } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2316                OMX_MAX_STRINGNAME_SIZE)) {
2317        secure_mode = true;
2318        arbitrary_bytes = false;
2319        role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2320    } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2321                OMX_MAX_STRINGNAME_SIZE)) {
2322        secure_mode = true;
2323        arbitrary_bytes = false;
2324        role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2325    } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2326                OMX_MAX_STRINGNAME_SIZE)) {
2327        secure_mode = true;
2328        arbitrary_bytes = false;
2329        role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2330    } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2331                OMX_MAX_STRINGNAME_SIZE)) {
2332        secure_mode = true;
2333        arbitrary_bytes = false;
2334        role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2335    }
2336    else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure",
2337                OMX_MAX_STRINGNAME_SIZE)) {
2338        secure_mode = true;
2339        arbitrary_bytes = false;
2340        role = (OMX_STRING)"OMX.qcom.video.decoder.vp8";
2341    }
2342
2343    drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2344
2345    DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2346
2347    if (drv_ctx.video_driver_fd < 0) {
2348        DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2349        return OMX_ErrorInsufficientResources;
2350    }
2351    drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2352    drv_ctx.frame_rate.fps_denominator = 1;
2353    operating_frame_rate = DEFAULT_FPS;
2354    m_poll_efd = eventfd(0, 0);
2355    if (m_poll_efd < 0) {
2356        DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2357        return OMX_ErrorInsufficientResources;
2358    }
2359    ret = subscribe_to_events(drv_ctx.video_driver_fd);
2360    if (!ret) {
2361        async_thread_created = true;
2362        ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2363    }
2364    if (ret) {
2365        DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2366        async_thread_created = false;
2367        return OMX_ErrorInsufficientResources;
2368    }
2369
2370#ifdef OUTPUT_EXTRADATA_LOG
2371    outputExtradataFile = fopen (output_extradata_filename, "ab");
2372#endif
2373
2374    // Copy the role information which provides the decoder kind
2375    strlcpy(drv_ctx.kind,role,128);
2376
2377    if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2378                OMX_MAX_STRINGNAME_SIZE)) {
2379        strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2380                OMX_MAX_STRINGNAME_SIZE);
2381        drv_ctx.timestamp_adjust = true;
2382        drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2383        eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2384        output_capability=V4L2_PIX_FMT_MPEG4;
2385        /*Initialize Start Code for MPEG4*/
2386        codec_type_parse = CODEC_TYPE_MPEG4;
2387        m_frame_parser.init_start_codes(codec_type_parse);
2388    } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2389                OMX_MAX_STRINGNAME_SIZE)) {
2390        strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2391                OMX_MAX_STRINGNAME_SIZE);
2392        drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2393        output_capability = V4L2_PIX_FMT_MPEG2;
2394        eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2395        /*Initialize Start Code for MPEG2*/
2396        codec_type_parse = CODEC_TYPE_MPEG2;
2397        m_frame_parser.init_start_codes(codec_type_parse);
2398    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2399                OMX_MAX_STRINGNAME_SIZE)) {
2400        strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2401        DEBUG_PRINT_LOW("H263 Decoder selected");
2402        drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2403        eCompressionFormat = OMX_VIDEO_CodingH263;
2404        output_capability = V4L2_PIX_FMT_H263;
2405        codec_type_parse = CODEC_TYPE_H263;
2406        m_frame_parser.init_start_codes(codec_type_parse);
2407    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2408                OMX_MAX_STRINGNAME_SIZE)) {
2409        strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2410        DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2411        drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2412        output_capability = V4L2_PIX_FMT_DIVX_311;
2413        eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2414        codec_type_parse = CODEC_TYPE_DIVX;
2415        m_frame_parser.init_start_codes(codec_type_parse);
2416
2417    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2418                OMX_MAX_STRINGNAME_SIZE)) {
2419        strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2420        DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2421        drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2422        output_capability = V4L2_PIX_FMT_DIVX;
2423        eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2424        codec_type_parse = CODEC_TYPE_DIVX;
2425        codec_ambiguous = true;
2426        m_frame_parser.init_start_codes(codec_type_parse);
2427
2428    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2429                OMX_MAX_STRINGNAME_SIZE)) {
2430        strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2431        DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2432        drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2433        output_capability = V4L2_PIX_FMT_DIVX;
2434        eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2435        codec_type_parse = CODEC_TYPE_DIVX;
2436        codec_ambiguous = true;
2437        m_frame_parser.init_start_codes(codec_type_parse);
2438
2439    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2440                OMX_MAX_STRINGNAME_SIZE)) {
2441        strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2442        drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2443        output_capability=V4L2_PIX_FMT_H264;
2444        eCompressionFormat = OMX_VIDEO_CodingAVC;
2445        codec_type_parse = CODEC_TYPE_H264;
2446        m_frame_parser.init_start_codes(codec_type_parse);
2447        m_frame_parser.init_nal_length(nal_length);
2448        if (is_thulium_v1) {
2449            arbitrary_bytes = true;
2450            DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2451        }
2452    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2453                OMX_MAX_STRINGNAME_SIZE)) {
2454        strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2455        drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2456        output_capability = V4L2_PIX_FMT_H264_MVC;
2457        eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2458        codec_type_parse = CODEC_TYPE_H264;
2459        m_frame_parser.init_start_codes(codec_type_parse);
2460        m_frame_parser.init_nal_length(nal_length);
2461    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2462                OMX_MAX_STRINGNAME_SIZE)) {
2463        strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2464        drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2465        output_capability = V4L2_PIX_FMT_HEVC;
2466        eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2467        codec_type_parse = CODEC_TYPE_HEVC;
2468        m_frame_parser.init_start_codes(codec_type_parse);
2469        m_frame_parser.init_nal_length(nal_length);
2470    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2471                OMX_MAX_STRINGNAME_SIZE)) {
2472        strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2473        drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2474        eCompressionFormat = OMX_VIDEO_CodingWMV;
2475        codec_type_parse = CODEC_TYPE_VC1;
2476        output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2477        m_frame_parser.init_start_codes(codec_type_parse);
2478    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2479                OMX_MAX_STRINGNAME_SIZE)) {
2480        strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2481        drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2482        eCompressionFormat = OMX_VIDEO_CodingWMV;
2483        codec_type_parse = CODEC_TYPE_VC1;
2484        output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2485        m_frame_parser.init_start_codes(codec_type_parse);
2486    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2487                OMX_MAX_STRINGNAME_SIZE)) {
2488        strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2489        drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2490        output_capability = V4L2_PIX_FMT_VP8;
2491        eCompressionFormat = OMX_VIDEO_CodingVP8;
2492        codec_type_parse = CODEC_TYPE_VP8;
2493        arbitrary_bytes = false;
2494    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2495                OMX_MAX_STRINGNAME_SIZE)) {
2496        strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2497        drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2498        output_capability = V4L2_PIX_FMT_VP9;
2499        eCompressionFormat = OMX_VIDEO_CodingVP9;
2500        codec_type_parse = CODEC_TYPE_VP9;
2501        arbitrary_bytes = false;
2502    } else {
2503        DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2504        eRet = OMX_ErrorInvalidComponentName;
2505    }
2506
2507    if (eRet == OMX_ErrorNone) {
2508        OMX_COLOR_FORMATTYPE dest_color_format;
2509        if (m_disable_ubwc_mode) {
2510            drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2511        } else {
2512            drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2513        }
2514        if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2515            dest_color_format = (OMX_COLOR_FORMATTYPE)
2516                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2517        else
2518            dest_color_format = (OMX_COLOR_FORMATTYPE)
2519                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2520        if (!client_buffers.set_color_format(dest_color_format)) {
2521            DEBUG_PRINT_ERROR("Setting color format failed");
2522            eRet = OMX_ErrorInsufficientResources;
2523        }
2524
2525        dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2526        m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2527
2528        if (m_disable_ubwc_mode) {
2529            capture_capability = V4L2_PIX_FMT_NV12;
2530        } else {
2531            capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2532        }
2533
2534        struct v4l2_capability cap;
2535        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2536        if (ret) {
2537            DEBUG_PRINT_ERROR("Failed to query capabilities");
2538            /*TODO: How to handle this case */
2539        } else {
2540            DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2541                " version = %d, capabilities = %x", cap.driver, cap.card,
2542                cap.bus_info, cap.version, cap.capabilities);
2543        }
2544        ret=0;
2545        fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2546        fdesc.index=0;
2547        while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2548            DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2549                    fdesc.pixelformat, fdesc.flags);
2550            fdesc.index++;
2551        }
2552        fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2553        fdesc.index=0;
2554        while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2555
2556            DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2557                    fdesc.pixelformat, fdesc.flags);
2558            fdesc.index++;
2559        }
2560        m_extradata_info.output_crop_rect.nLeft = 0;
2561        m_extradata_info.output_crop_rect.nTop = 0;
2562        m_extradata_info.output_crop_rect.nWidth = 320;
2563        m_extradata_info.output_crop_rect.nHeight = 240;
2564        update_resolution(320, 240, 320, 240);
2565
2566        fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2567        fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2568        fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2569        fmt.fmt.pix_mp.pixelformat = output_capability;
2570        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2571        if (ret) {
2572            /*TODO: How to handle this case */
2573            DEBUG_PRINT_ERROR("Failed to set format on output port");
2574            return OMX_ErrorInsufficientResources;
2575        }
2576        DEBUG_PRINT_HIGH("Set Format was successful");
2577        if (codec_ambiguous) {
2578            if (output_capability == V4L2_PIX_FMT_DIVX) {
2579                struct v4l2_control divx_ctrl;
2580
2581                if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2582                    divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2583                } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2584                    divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2585                } else {
2586                    divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2587                }
2588
2589                divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2590                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2591                if (ret) {
2592                    DEBUG_PRINT_ERROR("Failed to set divx version");
2593                }
2594            } else {
2595                DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2596            }
2597        }
2598
2599        property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2600        m_conceal_color= atoi(property_value);
2601        DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2602        control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2603        control.value = m_conceal_color;
2604        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2605        if (ret) {
2606            DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2607        }
2608
2609        //Get the hardware capabilities
2610        memset((void *)&frmsize,0,sizeof(frmsize));
2611        frmsize.index = 0;
2612        frmsize.pixel_format = output_capability;
2613        ret = ioctl(drv_ctx.video_driver_fd,
2614                VIDIOC_ENUM_FRAMESIZES, &frmsize);
2615        if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2616            DEBUG_PRINT_ERROR("Failed to get framesizes");
2617            return OMX_ErrorHardware;
2618        }
2619
2620        if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2621            m_decoder_capability.min_width = frmsize.stepwise.min_width;
2622            m_decoder_capability.max_width = frmsize.stepwise.max_width;
2623            m_decoder_capability.min_height = frmsize.stepwise.min_height;
2624            m_decoder_capability.max_height = frmsize.stepwise.max_height;
2625        }
2626
2627        memset(&fmt, 0x0, sizeof(struct v4l2_format));
2628        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2629        fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2630        fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2631        fmt.fmt.pix_mp.pixelformat = capture_capability;
2632        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2633        if (ret) {
2634            /*TODO: How to handle this case */
2635            DEBUG_PRINT_ERROR("Failed to set format on capture port");
2636        }
2637        memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2638        framesize.nWidth = drv_ctx.video_resolution.frame_width;
2639        framesize.nHeight = drv_ctx.video_resolution.frame_height;
2640
2641        memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2642        rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2643        rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2644
2645        DEBUG_PRINT_HIGH("Set Format was successful");
2646        if (secure_mode) {
2647            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2648            control.value = 1;
2649            DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2650            ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2651            if (ret) {
2652                DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2653                return OMX_ErrorInsufficientResources;
2654            }
2655        }
2656        if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2657            control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2658            control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2659            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2660            if (ret) {
2661                DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2662                return OMX_ErrorInsufficientResources;
2663            }
2664        }
2665
2666        if (is_thulium_v1) {
2667            eRet = enable_smoothstreaming();
2668            if (eRet != OMX_ErrorNone) {
2669               DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2670               return eRet;
2671            }
2672        }
2673
2674        /*Get the Buffer requirements for input and output ports*/
2675        drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2676        drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2677
2678        if (secure_mode) {
2679            drv_ctx.op_buf.alignment = SECURE_ALIGN;
2680            drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2681        } else {
2682            drv_ctx.op_buf.alignment = SZ_4K;
2683            drv_ctx.ip_buf.alignment = SZ_4K;
2684        }
2685
2686        drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2687        drv_ctx.extradata = 0;
2688        drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2689        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2690        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2691        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2692        drv_ctx.idr_only_decoding = 0;
2693
2694#ifdef _ANDROID_
2695        property_get("vidc.dec.enable.downscalar",property_value,"0");
2696        if (atoi(property_value)) {
2697            m_enable_downscalar =  atoi(property_value);
2698            property_get("vidc.dec.downscalar_width",property_value,"0");
2699            if (atoi(property_value)) {
2700                m_downscalar_width = atoi(property_value);
2701            }
2702            property_get("vidc.dec.downscalar_height",property_value,"0");
2703            if (atoi(property_value)) {
2704                m_downscalar_height = atoi(property_value);
2705            }
2706
2707            if (m_downscalar_width < m_decoder_capability.min_width ||
2708                m_downscalar_height < m_decoder_capability.min_height) {
2709                m_downscalar_width = 0;
2710                m_downscalar_height = 0;
2711            }
2712
2713            DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2714                m_downscalar_width, m_downscalar_height);
2715        }
2716        property_get("vidc.disable.split.mode",property_value,"0");
2717        m_disable_split_mode = atoi(property_value);
2718        DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");
2719#endif
2720        m_state = OMX_StateLoaded;
2721#ifdef DEFAULT_EXTRADATA
2722        enable_extradata(DEFAULT_EXTRADATA, true, true);
2723#endif
2724        eRet = get_buffer_req(&drv_ctx.ip_buf);
2725        DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2726        get_buffer_req(&drv_ctx.op_buf);
2727        if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2728                drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2729                drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2730                    h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2731                    h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2732                    h264_scratch.nFilledLen = 0;
2733                    h264_scratch.nOffset = 0;
2734
2735                    if (h264_scratch.pBuffer == NULL) {
2736                        DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2737                        return OMX_ErrorInsufficientResources;
2738                    }
2739        }
2740        if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2741            drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2742            if (m_frame_parser.mutils == NULL) {
2743                m_frame_parser.mutils = new H264_Utils();
2744                if (m_frame_parser.mutils == NULL) {
2745                    DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2746                    eRet = OMX_ErrorInsufficientResources;
2747                } else {
2748                    m_frame_parser.mutils->initialize_frame_checking_environment();
2749                    m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2750                }
2751            }
2752
2753            h264_parser = new h264_stream_parser();
2754            if (!h264_parser) {
2755                DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2756                eRet = OMX_ErrorInsufficientResources;
2757            }
2758        }
2759
2760        if (pipe(fds)) {
2761            DEBUG_PRINT_ERROR("pipe creation failed");
2762            eRet = OMX_ErrorInsufficientResources;
2763        } else {
2764            m_pipe_in = fds[0];
2765            m_pipe_out = fds[1];
2766            msg_thread_created = true;
2767            r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2768
2769            if (r < 0) {
2770                DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2771                msg_thread_created = false;
2772                eRet = OMX_ErrorInsufficientResources;
2773            }
2774        }
2775    }
2776
2777    if (eRet != OMX_ErrorNone) {
2778        DEBUG_PRINT_ERROR("Component Init Failed");
2779    } else {
2780        DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2781                drv_ctx.video_driver_fd);
2782    }
2783    //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2784    return eRet;
2785}
2786
2787/* ======================================================================
2788   FUNCTION
2789   omx_vdec::GetComponentVersion
2790
2791   DESCRIPTION
2792   Returns the component version.
2793
2794   PARAMETERS
2795   TBD.
2796
2797   RETURN VALUE
2798   OMX_ErrorNone.
2799
2800   ========================================================================== */
2801OMX_ERRORTYPE  omx_vdec::get_component_version
2802(
2803 OMX_IN OMX_HANDLETYPE hComp,
2804 OMX_OUT OMX_STRING componentName,
2805 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2806 OMX_OUT OMX_VERSIONTYPE* specVersion,
2807 OMX_OUT OMX_UUIDTYPE* componentUUID
2808 )
2809{
2810    (void) hComp;
2811    (void) componentName;
2812    (void) componentVersion;
2813    (void) componentUUID;
2814    if (m_state == OMX_StateInvalid) {
2815        DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2816        return OMX_ErrorInvalidState;
2817    }
2818    /* TBD -- Return the proper version */
2819    if (specVersion) {
2820        specVersion->nVersion = OMX_SPEC_VERSION;
2821    }
2822    return OMX_ErrorNone;
2823}
2824/* ======================================================================
2825   FUNCTION
2826   omx_vdec::SendCommand
2827
2828   DESCRIPTION
2829   Returns zero if all the buffers released..
2830
2831   PARAMETERS
2832   None.
2833
2834   RETURN VALUE
2835   true/false
2836
2837   ========================================================================== */
2838OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2839        OMX_IN OMX_COMMANDTYPE cmd,
2840        OMX_IN OMX_U32 param1,
2841        OMX_IN OMX_PTR cmdData
2842        )
2843{
2844    (void) hComp;
2845    (void) cmdData;
2846    DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2847    if (m_state == OMX_StateInvalid) {
2848        DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2849        return OMX_ErrorInvalidState;
2850    }
2851    if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2852            && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2853        DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2854                "to invalid port: %u", (unsigned int)param1);
2855        return OMX_ErrorBadPortIndex;
2856    }
2857
2858    post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2859    sem_wait(&m_cmd_lock);
2860    DEBUG_PRINT_LOW("send_command: Command Processed");
2861    return OMX_ErrorNone;
2862}
2863
2864/* ======================================================================
2865   FUNCTION
2866   omx_vdec::SendCommand
2867
2868   DESCRIPTION
2869   Returns zero if all the buffers released..
2870
2871   PARAMETERS
2872   None.
2873
2874   RETURN VALUE
2875   true/false
2876
2877   ========================================================================== */
2878OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2879        OMX_IN OMX_COMMANDTYPE cmd,
2880        OMX_IN OMX_U32 param1,
2881        OMX_IN OMX_PTR cmdData
2882        )
2883{
2884    (void) hComp;
2885    (void) cmdData;
2886    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2887    OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2888    int bFlag = 1,sem_posted = 0,ret=0;
2889
2890    DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2891    DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2892            m_state, eState);
2893
2894    if (cmd == OMX_CommandStateSet) {
2895        DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2896        DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2897        /***************************/
2898        /* Current State is Loaded */
2899        /***************************/
2900        if (m_state == OMX_StateLoaded) {
2901            if (eState == OMX_StateIdle) {
2902                //if all buffers are allocated or all ports disabled
2903                if (allocate_done() ||
2904                        (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2905                    DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2906                } else {
2907                    DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2908                    BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2909                    // Skip the event notification
2910                    bFlag = 0;
2911                }
2912            }
2913            /* Requesting transition from Loaded to Loaded */
2914            else if (eState == OMX_StateLoaded) {
2915                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2916                post_event(OMX_EventError,OMX_ErrorSameState,\
2917                        OMX_COMPONENT_GENERATE_EVENT);
2918                eRet = OMX_ErrorSameState;
2919            }
2920            /* Requesting transition from Loaded to WaitForResources */
2921            else if (eState == OMX_StateWaitForResources) {
2922                /* Since error is None , we will post an event
2923                   at the end of this function definition */
2924                DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2925            }
2926            /* Requesting transition from Loaded to Executing */
2927            else if (eState == OMX_StateExecuting) {
2928                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2929                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2930                        OMX_COMPONENT_GENERATE_EVENT);
2931                eRet = OMX_ErrorIncorrectStateTransition;
2932            }
2933            /* Requesting transition from Loaded to Pause */
2934            else if (eState == OMX_StatePause) {
2935                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2936                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2937                        OMX_COMPONENT_GENERATE_EVENT);
2938                eRet = OMX_ErrorIncorrectStateTransition;
2939            }
2940            /* Requesting transition from Loaded to Invalid */
2941            else if (eState == OMX_StateInvalid) {
2942                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2943                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2944                eRet = OMX_ErrorInvalidState;
2945            } else {
2946                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2947                        eState);
2948                eRet = OMX_ErrorBadParameter;
2949            }
2950        }
2951
2952        /***************************/
2953        /* Current State is IDLE */
2954        /***************************/
2955        else if (m_state == OMX_StateIdle) {
2956            if (eState == OMX_StateLoaded) {
2957                if (release_done()) {
2958                    /*
2959                     * Since error is None , we will post an event at the end
2960                     * of this function definition
2961                     * Reset buffer requirements here to ensure setting buffer requirement
2962                     * when component move to executing state from loaded state via Idle.
2963                     */
2964                    drv_ctx.op_buf.buffer_size = 0;
2965                    drv_ctx.op_buf.actualcount = 0;
2966                    DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2967                } else {
2968                    DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2969                    BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2970                    // Skip the event notification
2971                    bFlag = 0;
2972                }
2973            }
2974            /* Requesting transition from Idle to Executing */
2975            else if (eState == OMX_StateExecuting) {
2976                DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2977                //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2978                bFlag = 1;
2979                DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2980                m_state=OMX_StateExecuting;
2981                DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2982            }
2983            /* Requesting transition from Idle to Idle */
2984            else if (eState == OMX_StateIdle) {
2985                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2986                post_event(OMX_EventError,OMX_ErrorSameState,\
2987                        OMX_COMPONENT_GENERATE_EVENT);
2988                eRet = OMX_ErrorSameState;
2989            }
2990            /* Requesting transition from Idle to WaitForResources */
2991            else if (eState == OMX_StateWaitForResources) {
2992                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2993                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2994                        OMX_COMPONENT_GENERATE_EVENT);
2995                eRet = OMX_ErrorIncorrectStateTransition;
2996            }
2997            /* Requesting transition from Idle to Pause */
2998            else if (eState == OMX_StatePause) {
2999                /*To pause the Video core we need to start the driver*/
3000                if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
3001                      NULL) < */0) {
3002                    DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
3003                    omx_report_error ();
3004                    eRet = OMX_ErrorHardware;
3005                } else {
3006                    BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
3007                    DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
3008                    bFlag = 0;
3009                }
3010            }
3011            /* Requesting transition from Idle to Invalid */
3012            else if (eState == OMX_StateInvalid) {
3013                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
3014                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3015                eRet = OMX_ErrorInvalidState;
3016            } else {
3017                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
3018                eRet = OMX_ErrorBadParameter;
3019            }
3020        }
3021
3022        /******************************/
3023        /* Current State is Executing */
3024        /******************************/
3025        else if (m_state == OMX_StateExecuting) {
3026            DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
3027            /* Requesting transition from Executing to Idle */
3028            if (eState == OMX_StateIdle) {
3029                /* Since error is None , we will post an event
3030                   at the end of this function definition
3031                 */
3032                DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
3033                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3034                if (!sem_posted) {
3035                    sem_posted = 1;
3036                    sem_post (&m_cmd_lock);
3037                    execute_omx_flush(OMX_ALL);
3038                }
3039                bFlag = 0;
3040            }
3041            /* Requesting transition from Executing to Paused */
3042            else if (eState == OMX_StatePause) {
3043                DEBUG_PRINT_LOW("PAUSE Command Issued");
3044                m_state = OMX_StatePause;
3045                bFlag = 1;
3046            }
3047            /* Requesting transition from Executing to Loaded */
3048            else if (eState == OMX_StateLoaded) {
3049                DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
3050                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3051                        OMX_COMPONENT_GENERATE_EVENT);
3052                eRet = OMX_ErrorIncorrectStateTransition;
3053            }
3054            /* Requesting transition from Executing to WaitForResources */
3055            else if (eState == OMX_StateWaitForResources) {
3056                DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
3057                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3058                        OMX_COMPONENT_GENERATE_EVENT);
3059                eRet = OMX_ErrorIncorrectStateTransition;
3060            }
3061            /* Requesting transition from Executing to Executing */
3062            else if (eState == OMX_StateExecuting) {
3063                DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
3064                post_event(OMX_EventError,OMX_ErrorSameState,\
3065                        OMX_COMPONENT_GENERATE_EVENT);
3066                eRet = OMX_ErrorSameState;
3067            }
3068            /* Requesting transition from Executing to Invalid */
3069            else if (eState == OMX_StateInvalid) {
3070                DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
3071                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3072                eRet = OMX_ErrorInvalidState;
3073            } else {
3074                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
3075                eRet = OMX_ErrorBadParameter;
3076            }
3077        }
3078        /***************************/
3079        /* Current State is Pause  */
3080        /***************************/
3081        else if (m_state == OMX_StatePause) {
3082            /* Requesting transition from Pause to Executing */
3083            if (eState == OMX_StateExecuting) {
3084                DEBUG_PRINT_LOW("Pause --> Executing");
3085                m_state = OMX_StateExecuting;
3086                bFlag = 1;
3087            }
3088            /* Requesting transition from Pause to Idle */
3089            else if (eState == OMX_StateIdle) {
3090                /* Since error is None , we will post an event
3091                   at the end of this function definition */
3092                DEBUG_PRINT_LOW("Pause --> Idle");
3093                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3094                if (!sem_posted) {
3095                    sem_posted = 1;
3096                    sem_post (&m_cmd_lock);
3097                    execute_omx_flush(OMX_ALL);
3098                }
3099                bFlag = 0;
3100            }
3101            /* Requesting transition from Pause to loaded */
3102            else if (eState == OMX_StateLoaded) {
3103                DEBUG_PRINT_ERROR("Pause --> loaded");
3104                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3105                        OMX_COMPONENT_GENERATE_EVENT);
3106                eRet = OMX_ErrorIncorrectStateTransition;
3107            }
3108            /* Requesting transition from Pause to WaitForResources */
3109            else if (eState == OMX_StateWaitForResources) {
3110                DEBUG_PRINT_ERROR("Pause --> WaitForResources");
3111                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3112                        OMX_COMPONENT_GENERATE_EVENT);
3113                eRet = OMX_ErrorIncorrectStateTransition;
3114            }
3115            /* Requesting transition from Pause to Pause */
3116            else if (eState == OMX_StatePause) {
3117                DEBUG_PRINT_ERROR("Pause --> Pause");
3118                post_event(OMX_EventError,OMX_ErrorSameState,\
3119                        OMX_COMPONENT_GENERATE_EVENT);
3120                eRet = OMX_ErrorSameState;
3121            }
3122            /* Requesting transition from Pause to Invalid */
3123            else if (eState == OMX_StateInvalid) {
3124                DEBUG_PRINT_ERROR("Pause --> Invalid");
3125                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3126                eRet = OMX_ErrorInvalidState;
3127            } else {
3128                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
3129                eRet = OMX_ErrorBadParameter;
3130            }
3131        }
3132        /***************************/
3133        /* Current State is WaitForResources  */
3134        /***************************/
3135        else if (m_state == OMX_StateWaitForResources) {
3136            /* Requesting transition from WaitForResources to Loaded */
3137            if (eState == OMX_StateLoaded) {
3138                /* Since error is None , we will post an event
3139                   at the end of this function definition */
3140                DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
3141            }
3142            /* Requesting transition from WaitForResources to WaitForResources */
3143            else if (eState == OMX_StateWaitForResources) {
3144                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
3145                post_event(OMX_EventError,OMX_ErrorSameState,
3146                        OMX_COMPONENT_GENERATE_EVENT);
3147                eRet = OMX_ErrorSameState;
3148            }
3149            /* Requesting transition from WaitForResources to Executing */
3150            else if (eState == OMX_StateExecuting) {
3151                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
3152                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3153                        OMX_COMPONENT_GENERATE_EVENT);
3154                eRet = OMX_ErrorIncorrectStateTransition;
3155            }
3156            /* Requesting transition from WaitForResources to Pause */
3157            else if (eState == OMX_StatePause) {
3158                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
3159                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3160                        OMX_COMPONENT_GENERATE_EVENT);
3161                eRet = OMX_ErrorIncorrectStateTransition;
3162            }
3163            /* Requesting transition from WaitForResources to Invalid */
3164            else if (eState == OMX_StateInvalid) {
3165                DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
3166                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3167                eRet = OMX_ErrorInvalidState;
3168            }
3169            /* Requesting transition from WaitForResources to Loaded -
3170               is NOT tested by Khronos TS */
3171
3172        } else {
3173            DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
3174            eRet = OMX_ErrorBadParameter;
3175        }
3176    }
3177    /********************************/
3178    /* Current State is Invalid */
3179    /*******************************/
3180    else if (m_state == OMX_StateInvalid) {
3181        /* State Transition from Inavlid to any state */
3182        if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
3183                    || OMX_StateIdle || OMX_StateExecuting
3184                    || OMX_StatePause || OMX_StateInvalid)) {
3185            DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
3186            post_event(OMX_EventError,OMX_ErrorInvalidState,\
3187                    OMX_COMPONENT_GENERATE_EVENT);
3188            eRet = OMX_ErrorInvalidState;
3189        }
3190    } else if (cmd == OMX_CommandFlush) {
3191        DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
3192                "with param1: %u", (unsigned int)param1);
3193#ifdef _MSM8974_
3194        send_codec_config();
3195#endif
3196        if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3197                    param1 == OMX_ALL)) {
3198            if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3199               struct timespec ts;
3200
3201               clock_gettime(CLOCK_REALTIME, &ts);
3202               ts.tv_sec += 2;
3203               DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3204                       m_queued_codec_config_count);
3205               BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3206               if (sem_timedwait(&m_safe_flush, &ts)) {
3207                   DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3208               }
3209               BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3210            }
3211        }
3212
3213        if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3214            BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3215        }
3216        if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3217            BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3218        }
3219        if (!sem_posted) {
3220            sem_posted = 1;
3221            DEBUG_PRINT_LOW("Set the Semaphore");
3222            sem_post (&m_cmd_lock);
3223            execute_omx_flush(param1);
3224        }
3225        bFlag = 0;
3226    } else if ( cmd == OMX_CommandPortEnable) {
3227        DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3228                "with param1: %u", (unsigned int)param1);
3229        if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3230            m_inp_bEnabled = OMX_TRUE;
3231
3232            if ( (m_state == OMX_StateLoaded &&
3233                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3234                    || allocate_input_done()) {
3235                post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3236                        OMX_COMPONENT_GENERATE_EVENT);
3237            } else {
3238                DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3239                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3240                // Skip the event notification
3241                bFlag = 0;
3242            }
3243        }
3244        if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3245            DEBUG_PRINT_LOW("Enable output Port command recieved");
3246            m_out_bEnabled = OMX_TRUE;
3247
3248            if ( (m_state == OMX_StateLoaded &&
3249                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3250                    || (allocate_output_done())) {
3251                post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3252                        OMX_COMPONENT_GENERATE_EVENT);
3253
3254            } else {
3255                DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3256                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3257                // Skip the event notification
3258                bFlag = 0;
3259                /* enable/disable downscaling if required */
3260                ret = decide_downscalar();
3261                if (ret) {
3262                    DEBUG_PRINT_LOW("decide_downscalar failed\n");
3263                }
3264            }
3265        }
3266    } else if (cmd == OMX_CommandPortDisable) {
3267        DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3268                "with param1: %u", (unsigned int)param1);
3269        if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3270            codec_config_flag = false;
3271            m_inp_bEnabled = OMX_FALSE;
3272            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3273                    && release_input_done()) {
3274                post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3275                        OMX_COMPONENT_GENERATE_EVENT);
3276            } else {
3277                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3278                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3279                    if (!sem_posted) {
3280                        sem_posted = 1;
3281                        sem_post (&m_cmd_lock);
3282                    }
3283                    execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3284                }
3285
3286                // Skip the event notification
3287                bFlag = 0;
3288            }
3289        }
3290        if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3291            m_out_bEnabled = OMX_FALSE;
3292            DEBUG_PRINT_LOW("Disable output Port command recieved");
3293            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3294                    && release_output_done()) {
3295                post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3296                        OMX_COMPONENT_GENERATE_EVENT);
3297            } else {
3298                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3299                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3300                    if (!sem_posted) {
3301                        sem_posted = 1;
3302                        sem_post (&m_cmd_lock);
3303                    }
3304                    BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3305                    execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3306                }
3307                // Skip the event notification
3308                bFlag = 0;
3309
3310            }
3311        }
3312    } else {
3313        DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3314        eRet = OMX_ErrorNotImplemented;
3315    }
3316    if (eRet == OMX_ErrorNone && bFlag) {
3317        post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3318    }
3319    if (!sem_posted) {
3320        sem_post(&m_cmd_lock);
3321    }
3322
3323    return eRet;
3324}
3325
3326/* ======================================================================
3327   FUNCTION
3328   omx_vdec::ExecuteOmxFlush
3329
3330   DESCRIPTION
3331   Executes the OMX flush.
3332
3333   PARAMETERS
3334   flushtype - input flush(1)/output flush(0)/ both.
3335
3336   RETURN VALUE
3337   true/false
3338
3339   ========================================================================== */
3340bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3341{
3342    bool bRet = false;
3343    struct v4l2_plane plane;
3344    struct v4l2_buffer v4l2_buf;
3345    struct v4l2_decoder_cmd dec;
3346    DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3347    memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3348    dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3349
3350    DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3351
3352    if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3353        output_flush_progress = true;
3354        dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3355    } else {
3356        /* XXX: The driver/hardware does not support flushing of individual ports
3357         * in all states. So we pretty much need to flush both ports internally,
3358         * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3359         * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3360         * we automatically omit sending the FLUSH done for the "opposite" port. */
3361        input_flush_progress = true;
3362        output_flush_progress = true;
3363        dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3364        request_perf_level(VIDC_TURBO);
3365    }
3366
3367    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3368        DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3369        bRet = false;
3370    }
3371
3372    return bRet;
3373}
3374/*=========================================================================
3375FUNCTION : execute_output_flush
3376
3377DESCRIPTION
3378Executes the OMX flush at OUTPUT PORT.
3379
3380PARAMETERS
3381None.
3382
3383RETURN VALUE
3384true/false
3385==========================================================================*/
3386bool omx_vdec::execute_output_flush()
3387{
3388    unsigned long p1 = 0; // Parameter - 1
3389    unsigned long p2 = 0; // Parameter - 2
3390    unsigned long ident = 0;
3391    bool bRet = true;
3392
3393    /*Generate FBD for all Buffers in the FTBq*/
3394    pthread_mutex_lock(&m_lock);
3395    DEBUG_PRINT_LOW("Initiate Output Flush");
3396
3397    //reset last render TS
3398    if(m_last_rendered_TS > 0) {
3399        m_last_rendered_TS = 0;
3400    }
3401
3402    while (m_ftb_q.m_size) {
3403        DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3404                m_ftb_q.m_size,pending_output_buffers);
3405        m_ftb_q.pop_entry(&p1,&p2,&ident);
3406        DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3407        if (ident == m_fill_output_msg ) {
3408            m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3409        } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3410            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3411        }
3412    }
3413    pthread_mutex_unlock(&m_lock);
3414    output_flush_progress = false;
3415
3416    if (arbitrary_bytes) {
3417        prev_ts = LLONG_MAX;
3418        rst_prev_ts = true;
3419    }
3420    DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3421    return bRet;
3422}
3423/*=========================================================================
3424FUNCTION : execute_input_flush
3425
3426DESCRIPTION
3427Executes the OMX flush at INPUT PORT.
3428
3429PARAMETERS
3430None.
3431
3432RETURN VALUE
3433true/false
3434==========================================================================*/
3435bool omx_vdec::execute_input_flush()
3436{
3437    unsigned       i =0;
3438    unsigned long p1 = 0; // Parameter - 1
3439    unsigned long p2 = 0; // Parameter - 2
3440    unsigned long ident = 0;
3441    bool bRet = true;
3442
3443    /*Generate EBD for all Buffers in the ETBq*/
3444    DEBUG_PRINT_LOW("Initiate Input Flush");
3445
3446    pthread_mutex_lock(&m_lock);
3447    DEBUG_PRINT_LOW("Check if the Queue is empty");
3448    while (m_etb_q.m_size) {
3449        m_etb_q.pop_entry(&p1,&p2,&ident);
3450
3451        if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3452            DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3453            m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3454        } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3455            pending_input_buffers++;
3456            VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3457            DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3458                    (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3459            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3460        } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3461            DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3462                    (OMX_BUFFERHEADERTYPE *)p1);
3463            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3464        }
3465    }
3466    time_stamp_dts.flush_timestamp();
3467    /*Check if Heap Buffers are to be flushed*/
3468    if (arbitrary_bytes && !(codec_config_flag)) {
3469        DEBUG_PRINT_LOW("Reset all the variables before flusing");
3470        h264_scratch.nFilledLen = 0;
3471        nal_count = 0;
3472        look_ahead_nal = false;
3473        frame_count = 0;
3474        h264_last_au_ts = LLONG_MAX;
3475        h264_last_au_flags = 0;
3476        memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3477        m_demux_entries = 0;
3478        DEBUG_PRINT_LOW("Initialize parser");
3479        if (m_frame_parser.mutils) {
3480            m_frame_parser.mutils->initialize_frame_checking_environment();
3481        }
3482
3483        while (m_input_pending_q.m_size) {
3484            m_input_pending_q.pop_entry(&p1,&p2,&ident);
3485            m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3486        }
3487
3488        if (psource_frame) {
3489            m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3490            psource_frame = NULL;
3491        }
3492
3493        if (pdest_frame) {
3494            pdest_frame->nFilledLen = 0;
3495            m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3496                    (unsigned int)NULL);
3497            pdest_frame = NULL;
3498        }
3499        m_frame_parser.flush();
3500    } else if (codec_config_flag) {
3501        DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3502                "is not sent to the driver yet");
3503    }
3504    pthread_mutex_unlock(&m_lock);
3505    input_flush_progress = false;
3506    if (!arbitrary_bytes) {
3507        prev_ts = LLONG_MAX;
3508        rst_prev_ts = true;
3509    }
3510#ifdef _ANDROID_
3511    if (m_debug_timestamp) {
3512        m_timestamp_list.reset_ts_list();
3513    }
3514#endif
3515    DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3516    return bRet;
3517}
3518
3519
3520/* ======================================================================
3521   FUNCTION
3522   omx_vdec::SendCommandEvent
3523
3524   DESCRIPTION
3525   Send the event to decoder pipe.  This is needed to generate the callbacks
3526   in decoder thread context.
3527
3528   PARAMETERS
3529   None.
3530
3531   RETURN VALUE
3532   true/false
3533
3534   ========================================================================== */
3535bool omx_vdec::post_event(unsigned long p1,
3536        unsigned long p2,
3537        unsigned long id)
3538{
3539    bool bRet = false;
3540
3541    /* Just drop messages typically generated by hardware (w/o client request),
3542     * if we've reported an error to client. */
3543    if (m_error_propogated) {
3544        switch (id) {
3545            case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3546            case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3547                DEBUG_PRINT_ERROR("Dropping message %lx "
3548                        "since client expected to be in error state", id);
3549                return false;
3550            default:
3551                /* whatever */
3552                break;
3553        }
3554    }
3555
3556    pthread_mutex_lock(&m_lock);
3557
3558    if (id == m_fill_output_msg ||
3559            id == OMX_COMPONENT_GENERATE_FBD ||
3560            id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3561            id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3562        m_ftb_q.insert_entry(p1,p2,id);
3563    } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3564            id == OMX_COMPONENT_GENERATE_EBD ||
3565            id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3566            id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3567        m_etb_q.insert_entry(p1,p2,id);
3568    } else {
3569        m_cmd_q.insert_entry(p1,p2,id);
3570    }
3571
3572    bRet = true;
3573    DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3574    post_message(this, id);
3575
3576    pthread_mutex_unlock(&m_lock);
3577
3578    return bRet;
3579}
3580
3581OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3582{
3583    OMX_ERRORTYPE eRet = OMX_ErrorNone;
3584    if (!profileLevelType)
3585        return OMX_ErrorBadParameter;
3586
3587    if (profileLevelType->nPortIndex == 0) {
3588        if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3589            profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
3590            if (profileLevelType->nProfileIndex == 0) {
3591                profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3592            } else if (profileLevelType->nProfileIndex == 1) {
3593                profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3594            } else if (profileLevelType->nProfileIndex == 2) {
3595                profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3596            } else if (profileLevelType->nProfileIndex == 3) {
3597                profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
3598            } else if (profileLevelType->nProfileIndex == 4) {
3599                profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
3600            } else {
3601                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3602                        (unsigned int)profileLevelType->nProfileIndex);
3603                eRet = OMX_ErrorNoMore;
3604            }
3605        } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3606            if (profileLevelType->nProfileIndex == 0) {
3607                profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3608                profileLevelType->eLevel   = QOMX_VIDEO_MVCLevel51;
3609            } else {
3610                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3611                                (unsigned int)profileLevelType->nProfileIndex);
3612                eRet = OMX_ErrorNoMore;
3613            }
3614        } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3615            if (profileLevelType->nProfileIndex == 0) {
3616                profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3617                profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3618            } else if (profileLevelType->nProfileIndex == 1) {
3619                profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3620                profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3621            } else if (profileLevelType->nProfileIndex == 2) {
3622                profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
3623                profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
3624            } else {
3625                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3626                        (unsigned int)profileLevelType->nProfileIndex);
3627                eRet = OMX_ErrorNoMore;
3628            }
3629        } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3630            if (profileLevelType->nProfileIndex == 0) {
3631                profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3632                profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
3633            } else {
3634                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3635                                (unsigned int)profileLevelType->nProfileIndex);
3636                eRet = OMX_ErrorNoMore;
3637            }
3638        } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3639            if (profileLevelType->nProfileIndex == 0) {
3640                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3641                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3642            } else if (profileLevelType->nProfileIndex == 1) {
3643                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3644                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
3645            } else {
3646                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3647                                (unsigned int)profileLevelType->nProfileIndex);
3648                eRet = OMX_ErrorNoMore;
3649            }
3650        } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3651                !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3652            eRet = OMX_ErrorNoMore;
3653        } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3654            if (profileLevelType->nProfileIndex == 0) {
3655                profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3656                profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3657            } else if (profileLevelType->nProfileIndex == 1) {
3658                profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3659                profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
3660            } else {
3661                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3662                                (unsigned int)profileLevelType->nProfileIndex);
3663                eRet = OMX_ErrorNoMore;
3664            }
3665        } else {
3666            DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3667            eRet = OMX_ErrorNoMore;
3668        }
3669    } else {
3670        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3671                          (unsigned int)profileLevelType->nPortIndex);
3672        eRet = OMX_ErrorBadPortIndex;
3673    }
3674    return eRet;
3675}
3676
3677/* ======================================================================
3678   FUNCTION
3679   omx_vdec::GetParameter
3680
3681   DESCRIPTION
3682   OMX Get Parameter method implementation
3683
3684   PARAMETERS
3685   <TBD>.
3686
3687   RETURN VALUE
3688   Error None if successful.
3689
3690   ========================================================================== */
3691OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3692        OMX_IN OMX_INDEXTYPE paramIndex,
3693        OMX_INOUT OMX_PTR     paramData)
3694{
3695    (void) hComp;
3696    OMX_ERRORTYPE eRet = OMX_ErrorNone;
3697
3698    DEBUG_PRINT_LOW("get_parameter:");
3699    if (m_state == OMX_StateInvalid) {
3700        DEBUG_PRINT_ERROR("Get Param in Invalid State");
3701        return OMX_ErrorInvalidState;
3702    }
3703    if (paramData == NULL) {
3704        DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3705        return OMX_ErrorBadParameter;
3706    }
3707    switch ((unsigned long)paramIndex) {
3708        case OMX_IndexParamPortDefinition: {
3709                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3710                               OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3711                                   (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3712                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3713                               decide_dpb_buffer_mode(is_down_scalar_enabled);
3714                               eRet = update_portdef(portDefn);
3715                               if (eRet == OMX_ErrorNone)
3716                                   m_port_def = *portDefn;
3717                               break;
3718                           }
3719        case OMX_IndexParamVideoInit: {
3720                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3721                              OMX_PORT_PARAM_TYPE *portParamType =
3722                                  (OMX_PORT_PARAM_TYPE *) paramData;
3723                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3724
3725                              portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3726                              portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3727                              portParamType->nPorts           = 2;
3728                              portParamType->nStartPortNumber = 0;
3729                              break;
3730                          }
3731        case OMX_IndexParamVideoPortFormat: {
3732                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3733                                OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3734                                    (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3735                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3736
3737                                portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3738                                portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3739
3740                                if (0 == portFmt->nPortIndex) {
3741                                    if (0 == portFmt->nIndex) {
3742                                        portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3743                                        portFmt->eCompressionFormat = eCompressionFormat;
3744                                    } else {
3745                                        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3746                                                " NoMore compression formats");
3747                                        eRet =  OMX_ErrorNoMore;
3748                                    }
3749                                } else if (1 == portFmt->nPortIndex) {
3750                                    portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3751
3752                                    // Distinguish non-surface mode from normal playback use-case based on
3753                                    // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3754                                    // For non-android, use the default list
3755                                    // Also use default format-list if FLEXIBLE YUV is supported,
3756                                    // as the client negotiates the standard color-format if it needs to
3757                                    bool useNonSurfaceMode = false;
3758#if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3759                                    useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3760#endif
3761                                    if (is_thulium_v1) {
3762                                        portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3763                                    } else {
3764                                        portFmt->eColorFormat = useNonSurfaceMode ?
3765                                            getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3766                                            getPreferredColorFormatDefaultMode(portFmt->nIndex);
3767                                    }
3768
3769                                    if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3770                                        eRet = OMX_ErrorNoMore;
3771                                        DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3772                                                " NoMore Color formats");
3773                                    }
3774                                    DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3775                                } else {
3776                                    DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3777                                            (int)portFmt->nPortIndex);
3778                                    eRet = OMX_ErrorBadPortIndex;
3779                                }
3780                                break;
3781                            }
3782                            /*Component should support this port definition*/
3783        case OMX_IndexParamAudioInit: {
3784                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3785                              OMX_PORT_PARAM_TYPE *audioPortParamType =
3786                                  (OMX_PORT_PARAM_TYPE *) paramData;
3787                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3788                              audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3789                              audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3790                              audioPortParamType->nPorts           = 0;
3791                              audioPortParamType->nStartPortNumber = 0;
3792                              break;
3793                          }
3794                          /*Component should support this port definition*/
3795        case OMX_IndexParamImageInit: {
3796                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3797                              OMX_PORT_PARAM_TYPE *imagePortParamType =
3798                                  (OMX_PORT_PARAM_TYPE *) paramData;
3799                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3800                              imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3801                              imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3802                              imagePortParamType->nPorts           = 0;
3803                              imagePortParamType->nStartPortNumber = 0;
3804                              break;
3805
3806                          }
3807                          /*Component should support this port definition*/
3808        case OMX_IndexParamOtherInit: {
3809                              DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3810                                      paramIndex);
3811                              eRet =OMX_ErrorUnsupportedIndex;
3812                              break;
3813                          }
3814        case OMX_IndexParamStandardComponentRole: {
3815                                  VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3816                                  OMX_PARAM_COMPONENTROLETYPE *comp_role;
3817                                  comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3818                                  comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3819                                  comp_role->nSize = sizeof(*comp_role);
3820
3821                                  DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3822                                          paramIndex);
3823                                  strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3824                                          OMX_MAX_STRINGNAME_SIZE);
3825                                  break;
3826                              }
3827                              /* Added for parameter test */
3828        case OMX_IndexParamPriorityMgmt: {
3829                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3830                             OMX_PRIORITYMGMTTYPE *priorityMgmType =
3831                                 (OMX_PRIORITYMGMTTYPE *) paramData;
3832                             DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3833                             priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3834                             priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3835
3836                             break;
3837                         }
3838                         /* Added for parameter test */
3839        case OMX_IndexParamCompBufferSupplier: {
3840                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3841                                   OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3842                                       (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3843                                   DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3844
3845                                   bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3846                                   bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3847                                   if (0 == bufferSupplierType->nPortIndex)
3848                                       bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3849                                   else if (1 == bufferSupplierType->nPortIndex)
3850                                       bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3851                                   else
3852                                       eRet = OMX_ErrorBadPortIndex;
3853
3854
3855                                   break;
3856                               }
3857        case OMX_IndexParamVideoAvc: {
3858                             DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3859                                     paramIndex);
3860                             break;
3861                         }
3862        case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3863                             DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3864                                     paramIndex);
3865                             break;
3866                         }
3867        case OMX_IndexParamVideoH263: {
3868                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3869                                      paramIndex);
3870                              break;
3871                          }
3872        case OMX_IndexParamVideoMpeg4: {
3873                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3874                                       paramIndex);
3875                               break;
3876                           }
3877        case OMX_IndexParamVideoMpeg2: {
3878                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3879                                       paramIndex);
3880                               break;
3881                           }
3882        case OMX_IndexParamVideoProfileLevelQuerySupported: {
3883                                        VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3884                                        DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3885                                        OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3886                                            (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3887                                        eRet = get_supported_profile_level(profileLevelType);
3888                                        break;
3889                                    }
3890#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3891        case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3892                                        VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3893                                        DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3894                                        GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3895                                        if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3896
3897                                            if (secure_mode && !secure_scaling_to_non_secure_opb) {
3898                                                nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3899                                                        GRALLOC_USAGE_PRIVATE_UNCACHED);
3900                                            } else {
3901                                                nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3902                                            }
3903                                        } else {
3904                                            DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3905                                            eRet = OMX_ErrorBadParameter;
3906                                        }
3907                                    }
3908                                    break;
3909#endif
3910
3911#ifdef FLEXYUV_SUPPORTED
3912        case OMX_QcomIndexFlexibleYUVDescription: {
3913                DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3914                VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3915                eRet = describeColorFormat(paramData);
3916                break;
3917            }
3918#endif
3919        case OMX_IndexParamVideoProfileLevelCurrent: {
3920             VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3921             OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3922             struct v4l2_control profile_control, level_control;
3923
3924             switch (drv_ctx.decoder_format) {
3925                 case VDEC_CODECTYPE_H264:
3926                     profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3927                     level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3928                     break;
3929                 default:
3930                     DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3931                     eRet = OMX_ErrorNotImplemented;
3932                     break;
3933             }
3934
3935             if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3936                switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3937                    case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3938                    case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3939                        pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3940                        break;
3941                    case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3942                        pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3943                        break;
3944                    case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3945                        pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3946                        break;
3947                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3948                        pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3949                        break;
3950                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3951                        pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3952                        break;
3953                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3954                        pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3955                        break;
3956                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3957                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3958                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3959                    case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3960                    case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3961                    case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3962                    case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3963                    case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3964                    case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3965                    case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3966                    case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3967                        eRet = OMX_ErrorUnsupportedIndex;
3968                        break;
3969                }
3970             } else {
3971                 eRet = OMX_ErrorUnsupportedIndex;
3972             }
3973
3974
3975             if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3976                switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3977                    case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3978                        pParam->eLevel = OMX_VIDEO_AVCLevel1;
3979                        break;
3980                    case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3981                        pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3982                        break;
3983                    case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3984                        pParam->eLevel = OMX_VIDEO_AVCLevel11;
3985                        break;
3986                    case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3987                        pParam->eLevel = OMX_VIDEO_AVCLevel12;
3988                        break;
3989                    case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3990                        pParam->eLevel = OMX_VIDEO_AVCLevel13;
3991                        break;
3992                    case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3993                        pParam->eLevel = OMX_VIDEO_AVCLevel2;
3994                        break;
3995                    case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3996                        pParam->eLevel = OMX_VIDEO_AVCLevel21;
3997                        break;
3998                    case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3999                        pParam->eLevel = OMX_VIDEO_AVCLevel22;
4000                        break;
4001                    case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4002                        pParam->eLevel = OMX_VIDEO_AVCLevel3;
4003                        break;
4004                    case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4005                        pParam->eLevel = OMX_VIDEO_AVCLevel31;
4006                        break;
4007                    case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4008                        pParam->eLevel = OMX_VIDEO_AVCLevel32;
4009                        break;
4010                    case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4011                        pParam->eLevel = OMX_VIDEO_AVCLevel4;
4012                        break;
4013                    case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4014                        pParam->eLevel = OMX_VIDEO_AVCLevel41;
4015                        break;
4016                    case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4017                        pParam->eLevel = OMX_VIDEO_AVCLevel42;
4018                        break;
4019                    case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4020                        pParam->eLevel = OMX_VIDEO_AVCLevel5;
4021                        break;
4022                    case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4023                        pParam->eLevel = OMX_VIDEO_AVCLevel51;
4024                        break;
4025                    case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4026                        pParam->eLevel = OMX_VIDEO_AVCLevel52;
4027                        break;
4028                }
4029             } else {
4030                 eRet = OMX_ErrorUnsupportedIndex;
4031             }
4032
4033             break;
4034
4035         }
4036        case OMX_QTIIndexParamVideoClientExtradata:
4037        {
4038            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CLIENT_EXTRADATATYPE);
4039            DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
4040            QOMX_VIDEO_CLIENT_EXTRADATATYPE *pParam =
4041                (QOMX_VIDEO_CLIENT_EXTRADATATYPE *)paramData;
4042            pParam->nExtradataSize = VENUS_EXTRADATA_SIZE(4096, 2160);
4043            pParam->nExtradataAllocSize = pParam->nExtradataSize * MAX_NUM_INPUT_OUTPUT_BUFFERS;
4044            eRet = OMX_ErrorNone;
4045            break;
4046        }
4047        case OMX_QTIIndexParamDitherControl:
4048        {
4049            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4050            DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
4051            QOMX_VIDEO_DITHER_CONTROL *pParam =
4052                (QOMX_VIDEO_DITHER_CONTROL *) paramData;
4053            pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
4054            eRet = OMX_ErrorNone;
4055            break;
4056        }
4057        default: {
4058                 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
4059                 eRet =OMX_ErrorUnsupportedIndex;
4060             }
4061
4062    }
4063
4064    DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
4065            drv_ctx.video_resolution.frame_width,
4066            drv_ctx.video_resolution.frame_height,
4067            drv_ctx.video_resolution.stride,
4068            drv_ctx.video_resolution.scan_lines);
4069
4070    return eRet;
4071}
4072
4073#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4074OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
4075{
4076    DEBUG_PRINT_LOW("Inside use_android_native_buffer");
4077    OMX_ERRORTYPE eRet = OMX_ErrorNone;
4078    UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
4079
4080    if ((params == NULL) ||
4081            (params->nativeBuffer == NULL) ||
4082            (params->nativeBuffer->handle == NULL) ||
4083            !m_enable_android_native_buffers)
4084        return OMX_ErrorBadParameter;
4085    m_use_android_native_buffers = OMX_TRUE;
4086    sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4087    private_handle_t *handle = (private_handle_t *)nBuf->handle;
4088    if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
4089        OMX_U8 *buffer = NULL;
4090        if (!secure_mode) {
4091            buffer = (OMX_U8*)mmap(0, handle->size,
4092                    PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4093            if (buffer == MAP_FAILED) {
4094                DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4095                return OMX_ErrorInsufficientResources;
4096            }
4097        }
4098        eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
4099    } else {
4100        eRet = OMX_ErrorBadParameter;
4101    }
4102    return eRet;
4103}
4104#endif
4105
4106OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
4107    struct v4l2_control control;
4108    struct v4l2_format fmt;
4109    control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
4110    control.value = 1;
4111    int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4112    if (rc < 0) {
4113        DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
4114        return OMX_ErrorHardware;
4115    }
4116    m_smoothstreaming_mode = true;
4117    return OMX_ErrorNone;
4118}
4119
4120/* ======================================================================
4121   FUNCTION
4122   omx_vdec::Setparameter
4123
4124   DESCRIPTION
4125   OMX Set Parameter method implementation.
4126
4127   PARAMETERS
4128   <TBD>.
4129
4130   RETURN VALUE
4131   OMX Error None if successful.
4132
4133   ========================================================================== */
4134OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
4135        OMX_IN OMX_INDEXTYPE paramIndex,
4136        OMX_IN OMX_PTR        paramData)
4137{
4138    OMX_ERRORTYPE eRet = OMX_ErrorNone;
4139    int ret=0;
4140    struct v4l2_format fmt;
4141#ifdef _ANDROID_
4142    char property_value[PROPERTY_VALUE_MAX] = {0};
4143#endif
4144    if (m_state == OMX_StateInvalid) {
4145        DEBUG_PRINT_ERROR("Set Param in Invalid State");
4146        return OMX_ErrorInvalidState;
4147    }
4148    if (paramData == NULL) {
4149        DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4150        return OMX_ErrorBadParameter;
4151    }
4152    if ((m_state != OMX_StateLoaded) &&
4153            BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4154            (m_out_bEnabled == OMX_TRUE) &&
4155            BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4156            (m_inp_bEnabled == OMX_TRUE)) {
4157        DEBUG_PRINT_ERROR("Set Param in Invalid State");
4158        return OMX_ErrorIncorrectStateOperation;
4159    }
4160    switch ((unsigned long)paramIndex) {
4161        case OMX_IndexParamPortDefinition: {
4162                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4163                               OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4164                               portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4165                               //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4166                               //been called.
4167                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
4168                                       (int)portDefn->format.video.nFrameHeight,
4169                                       (int)portDefn->format.video.nFrameWidth);
4170
4171                               if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4172                                   DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4173                                                          portDefn->nBufferCountActual);
4174                                   eRet = OMX_ErrorBadParameter;
4175                                   break;
4176                               }
4177                               if (OMX_DirOutput == portDefn->eDir) {
4178                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4179                                   bool port_format_changed = false;
4180                                   m_display_id = portDefn->format.video.pNativeWindow;
4181                                   unsigned int buffer_size;
4182                                   /* update output port resolution with client supplied dimensions
4183                                      in case scaling is enabled, else it follows input resolution set
4184                                   */
4185                                   decide_dpb_buffer_mode(is_down_scalar_enabled);
4186                                   if (is_down_scalar_enabled) {
4187                                       DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4188                                               (unsigned int)portDefn->format.video.nFrameWidth,
4189                                               (unsigned int)portDefn->format.video.nFrameHeight);
4190                                       if (portDefn->format.video.nFrameHeight != 0x0 &&
4191                                               portDefn->format.video.nFrameWidth != 0x0) {
4192                                           memset(&fmt, 0x0, sizeof(struct v4l2_format));
4193                                           fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4194                                           fmt.fmt.pix_mp.pixelformat = capture_capability;
4195                                           ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4196                                           if (ret) {
4197                                               DEBUG_PRINT_ERROR("Get Resolution failed");
4198                                               eRet = OMX_ErrorHardware;
4199                                               break;
4200                                           }
4201                                           if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4202                                               (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4203                                                   port_format_changed = true;
4204                                           }
4205
4206                                           /* set crop info */
4207                                           rectangle.nLeft = 0;
4208                                           rectangle.nTop = 0;
4209                                           rectangle.nWidth = portDefn->format.video.nFrameWidth;
4210                                           rectangle.nHeight = portDefn->format.video.nFrameHeight;
4211
4212                                           m_extradata_info.output_crop_rect.nLeft = 0;
4213                                           m_extradata_info.output_crop_rect.nTop = 0;
4214                                           m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4215                                           m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4216
4217                                           eRet = is_video_session_supported();
4218                                           if (eRet)
4219                                               break;
4220                                           memset(&fmt, 0x0, sizeof(struct v4l2_format));
4221                                           fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4222                                           fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4223                                           fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4224                                           fmt.fmt.pix_mp.pixelformat = capture_capability;
4225                                           DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4226                                               fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4227                                           ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4228                                           if (ret) {
4229                                               DEBUG_PRINT_ERROR("Set Resolution failed");
4230                                               eRet = OMX_ErrorUnsupportedSetting;
4231                                           } else
4232                                               eRet = get_buffer_req(&drv_ctx.op_buf);
4233                                       }
4234
4235                                       if (eRet) {
4236                                           break;
4237                                       }
4238
4239                                       if (secure_mode) {
4240                                           struct v4l2_control control;
4241                                           control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
4242                                           if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4243                                               DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
4244                                               eRet = OMX_ErrorHardware;
4245                                           } else {
4246                                               /* This is a workaround for a bug in fw which uses stride
4247                                                * and slice instead of width and height to check against
4248                                                * the threshold.
4249                                                */
4250                                               OMX_U32 stride, slice;
4251                                               if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
4252                                                   stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
4253                                                   slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
4254                                               } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
4255                                                   stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
4256                                                   slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
4257                                               } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
4258                                                   stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameWidth);
4259                                                   slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameHeight);
4260                                               } else {
4261                                                   stride = portDefn->format.video.nFrameWidth;
4262                                                   slice = portDefn->format.video.nFrameHeight;
4263                                               }
4264
4265                                               DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
4266                                               DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
4267
4268                                               if (stride * slice <= (OMX_U32)control.value) {
4269                                                   secure_scaling_to_non_secure_opb = true;
4270                                                   DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
4271                                                   control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
4272                                                   control.value = 1;
4273                                                   if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4274                                                       DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4275                                                       eRet = OMX_ErrorUnsupportedSetting;
4276                                                   }
4277                                               }
4278                                           }
4279                                       }
4280                                   }
4281
4282                                   if (eRet) {
4283                                       break;
4284                                   }
4285
4286                                   if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4287                                       DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4288                                               portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4289                                       eRet = OMX_ErrorBadParameter;
4290                                   } else if (!client_buffers.get_buffer_req(buffer_size)) {
4291                                       DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4292                                       eRet = OMX_ErrorBadParameter;
4293                                   } else if (!port_format_changed) {
4294
4295                                       // Buffer count can change only when port is unallocated
4296                                       if (m_out_mem_ptr &&
4297                                                (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4298                                                portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4299
4300                                           DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4301                                           eRet = OMX_ErrorInvalidState;
4302                                           break;
4303                                       }
4304
4305                                       // route updating of buffer requirements via c2d proxy.
4306                                       // Based on whether c2d is enabled, requirements will be handed
4307                                       // to the vidc driver appropriately
4308                                       eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4309                                                portDefn->nBufferCountActual);
4310                                       if (eRet == OMX_ErrorNone) {
4311                                           m_port_def = *portDefn;
4312                                       } else {
4313                                           DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4314                                                   drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4315                                                   (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4316                                           eRet = OMX_ErrorBadParameter;
4317                                       }
4318                                   }
4319                               } else if (OMX_DirInput == portDefn->eDir) {
4320                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4321                                   bool port_format_changed = false;
4322                                   if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4323                                           (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4324                                       // Frame rate only should be set if this is a "known value" or to
4325                                       // activate ts prediction logic (arbitrary mode only) sending input
4326                                       // timestamps with max value (LLONG_MAX).
4327                                       m_fps_received = portDefn->format.video.xFramerate;
4328                                       DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4329                                               (unsigned int)portDefn->format.video.xFramerate >> 16);
4330                                       Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4331                                               drv_ctx.frame_rate.fps_denominator);
4332                                       if (!drv_ctx.frame_rate.fps_numerator) {
4333                                           DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4334                                           drv_ctx.frame_rate.fps_numerator = 30;
4335                                       }
4336                                       if (drv_ctx.frame_rate.fps_denominator)
4337                                           drv_ctx.frame_rate.fps_numerator = (int)
4338                                               drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4339                                       drv_ctx.frame_rate.fps_denominator = 1;
4340                                       frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4341                                           drv_ctx.frame_rate.fps_numerator;
4342                                       DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4343                                               (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4344                                               (float)drv_ctx.frame_rate.fps_denominator);
4345
4346                                       struct v4l2_outputparm oparm;
4347                                       /*XXX: we're providing timing info as seconds per frame rather than frames
4348                                        * per second.*/
4349                                       oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4350                                       oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4351
4352                                       struct v4l2_streamparm sparm;
4353                                       sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4354                                       sparm.parm.output = oparm;
4355                                       if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4356                                           DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4357                                           eRet = OMX_ErrorHardware;
4358                                           break;
4359                                       }
4360                                       m_perf_control.request_cores(frm_int);
4361                                   }
4362
4363                                   if (drv_ctx.video_resolution.frame_height !=
4364                                           portDefn->format.video.nFrameHeight ||
4365                                           drv_ctx.video_resolution.frame_width  !=
4366                                           portDefn->format.video.nFrameWidth) {
4367                                       DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4368                                               (unsigned int)portDefn->format.video.nFrameWidth,
4369                                               (unsigned int)portDefn->format.video.nFrameHeight);
4370                                       port_format_changed = true;
4371                                       OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4372                                       OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4373                                       if (frameHeight != 0x0 && frameWidth != 0x0) {
4374                                           if (m_smoothstreaming_mode &&
4375                                                   ((frameWidth * frameHeight) <
4376                                                   (m_smoothstreaming_width * m_smoothstreaming_height))) {
4377                                               frameWidth = m_smoothstreaming_width;
4378                                               frameHeight = m_smoothstreaming_height;
4379                                               DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4380                                                       "for adaptive-playback/smooth-streaming",
4381                                                       (unsigned int)frameWidth, (unsigned int)frameHeight);
4382                                           }
4383
4384                                           m_extradata_info.output_crop_rect.nLeft = 0;
4385                                           m_extradata_info.output_crop_rect.nTop = 0;
4386                                           m_extradata_info.output_crop_rect.nWidth = frameWidth;
4387                                           m_extradata_info.output_crop_rect.nHeight = frameHeight;
4388
4389                                           update_resolution(frameWidth, frameHeight,
4390                                                   frameWidth, frameHeight);
4391                                           eRet = is_video_session_supported();
4392                                           if (eRet)
4393                                               break;
4394                                           if (is_down_scalar_enabled) {
4395                                               memset(&fmt, 0x0, sizeof(struct v4l2_format));
4396                                               fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4397                                               fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4398                                               fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4399                                               fmt.fmt.pix_mp.pixelformat = output_capability;
4400                                               DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4401                                                   fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4402                                               ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4403                                           } else {
4404                                               memset(&fmt, 0x0, sizeof(struct v4l2_format));
4405                                               fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4406                                               fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4407                                               fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4408                                               fmt.fmt.pix_mp.pixelformat = output_capability;
4409                                               DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4410                                                   fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4411                                               ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4412                                               fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4413                                               fmt.fmt.pix_mp.pixelformat = capture_capability;
4414                                               ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4415                                           }
4416                                           if (ret) {
4417                                               DEBUG_PRINT_ERROR("Set Resolution failed");
4418                                               eRet = OMX_ErrorUnsupportedSetting;
4419                                           } else {
4420                                               if (!is_down_scalar_enabled)
4421                                                   eRet = get_buffer_req(&drv_ctx.op_buf);
4422                                           }
4423                                       }
4424                                   }
4425                                   if (m_custom_buffersize.input_buffersize
4426                                        && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4427                                       DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4428                                               m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4429                                       eRet = OMX_ErrorBadParameter;
4430                                       break;
4431                                   }
4432                                   if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4433                                       DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4434                                               portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4435                                       eRet = OMX_ErrorBadParameter;
4436                                       break;
4437                                   }
4438                                   // Buffer count can change only when port is unallocated
4439                                   if (m_inp_mem_ptr &&
4440                                            (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4441                                            portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4442                                       DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4443                                       eRet = OMX_ErrorInvalidState;
4444                                       break;
4445                                   }
4446
4447                                   if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4448                                           || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4449                                       port_format_changed = true;
4450                                       vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4451                                       drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4452                                       drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4453                                           (~(buffer_prop->alignment - 1));
4454                                       eRet = set_buffer_req(buffer_prop);
4455                                   }
4456                                   if (false == port_format_changed) {
4457                                       DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4458                                               drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4459                                               (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4460                                       eRet = OMX_ErrorBadParameter;
4461                                   }
4462                               } else if (portDefn->eDir ==  OMX_DirMax) {
4463                                   DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4464                                           (int)portDefn->nPortIndex);
4465                                   eRet = OMX_ErrorBadPortIndex;
4466                               }
4467                           }
4468                           break;
4469        case OMX_IndexParamVideoPortFormat: {
4470                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4471                                OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4472                                    (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4473                                int ret=0;
4474                                struct v4l2_format fmt;
4475                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4476                                        portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4477
4478                                memset(&fmt, 0x0, sizeof(struct v4l2_format));
4479                                if (1 == portFmt->nPortIndex) {
4480                                    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4481                                    ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4482                                    if (ret < 0) {
4483                                        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4484                                        return OMX_ErrorBadParameter;
4485                                    }
4486                                    enum vdec_output_fromat op_format;
4487                                    if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4488                                            QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4489                                            portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4490                                            QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4491                                            portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4492                                            portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4493                                        op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4494                                    } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4495                                            QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4496                                        op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4497                                    } else
4498                                        eRet = OMX_ErrorBadParameter;
4499
4500                                    if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4501                                            QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4502                                        fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4503                                    } else {
4504                                        fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4505                                    }
4506
4507                                    if (eRet == OMX_ErrorNone) {
4508                                        drv_ctx.output_format = op_format;
4509                                        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4510                                        if (ret) {
4511                                            DEBUG_PRINT_ERROR("Set output format failed");
4512                                            eRet = OMX_ErrorUnsupportedSetting;
4513                                            /*TODO: How to handle this case */
4514                                        } else {
4515                                            eRet = get_buffer_req(&drv_ctx.op_buf);
4516                                        }
4517                                    }
4518                                    if (eRet == OMX_ErrorNone) {
4519                                        if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4520                                            DEBUG_PRINT_ERROR("Set color format failed");
4521                                            eRet = OMX_ErrorBadParameter;
4522                                        }
4523                                    }
4524                                }
4525                            }
4526                            break;
4527
4528        case OMX_QcomIndexPortDefn: {
4529                            VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4530                            OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4531                                (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4532                            DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4533                                    (unsigned int)portFmt->nFramePackingFormat);
4534
4535                            /* Input port */
4536                            if (portFmt->nPortIndex == 0) {
4537                                // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4538                                //   - headers are allocated and
4539                                //   - headers-indices are derived
4540                                // Avoid changing arbitrary_bytes when the port is already allocated
4541                                if (m_inp_mem_ptr) {
4542                                    DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4543                                    return OMX_ErrorUnsupportedSetting;
4544                                }
4545                                if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4546                                    if (secure_mode || m_input_pass_buffer_fd) {
4547                                        arbitrary_bytes = false;
4548                                        DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4549                                        eRet = OMX_ErrorUnsupportedSetting;
4550                                    } else {
4551                                        arbitrary_bytes = true;
4552                                    }
4553                                } else if (portFmt->nFramePackingFormat ==
4554                                        OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4555                                    arbitrary_bytes = false;
4556#ifdef _ANDROID_
4557                                    property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4558                                    if (atoi(property_value)) {
4559                                        DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4560                                        arbitrary_bytes = true;
4561                                    }
4562#endif
4563                                } else {
4564                                    DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4565                                            (unsigned int)portFmt->nFramePackingFormat);
4566                                    eRet = OMX_ErrorUnsupportedSetting;
4567                                }
4568                            } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4569                                DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4570                                if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4571                                            portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4572                                        portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4573                                    m_out_mem_region_smi = OMX_TRUE;
4574                                    if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4575                                        DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4576                                        m_use_output_pmem = OMX_TRUE;
4577                                    }
4578                                }
4579                            }
4580                        }
4581                        if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4582                                    OMX_MAX_STRINGNAME_SIZE)) {
4583                            arbitrary_bytes = true;
4584                            DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4585                        }
4586                        break;
4587
4588        case OMX_IndexParamStandardComponentRole: {
4589                                  VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4590                                  OMX_PARAM_COMPONENTROLETYPE *comp_role;
4591                                  comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4592                                  DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4593                                          comp_role->cRole);
4594
4595                                  if ((m_state == OMX_StateLoaded)&&
4596                                          !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4597                                      DEBUG_PRINT_LOW("Set Parameter called in valid state");
4598                                  } else {
4599                                      DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4600                                      return OMX_ErrorIncorrectStateOperation;
4601                                  }
4602
4603                                  if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4604                                      if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4605                                          strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4606                                      } else {
4607                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4608                                          eRet =OMX_ErrorUnsupportedSetting;
4609                                      }
4610                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4611                                      if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4612                                          strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4613                                      } else {
4614                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4615                                          eRet = OMX_ErrorUnsupportedSetting;
4616                                      }
4617                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4618                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4619                                          strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4620                                      } else {
4621                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4622                                          eRet = OMX_ErrorUnsupportedSetting;
4623                                      }
4624                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4625                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4626                                          strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4627                                      } else {
4628                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4629                                          eRet =OMX_ErrorUnsupportedSetting;
4630                                      }
4631                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4632                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4633                                          strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4634                                      } else {
4635                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4636                                          eRet = OMX_ErrorUnsupportedSetting;
4637                                      }
4638                                  } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4639                                          (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4640                                          (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4641                                        ) {
4642                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4643                                          strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4644                                      } else {
4645                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4646                                          eRet =OMX_ErrorUnsupportedSetting;
4647                                      }
4648                                  } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4649                                          (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4650                                        ) {
4651                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4652                                          strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4653                                      } else {
4654                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4655                                          eRet =OMX_ErrorUnsupportedSetting;
4656                                      }
4657                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4658                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4659                                              !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4660                                          strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4661                                      } else {
4662                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4663                                          eRet = OMX_ErrorUnsupportedSetting;
4664                                      }
4665                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4666                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4667                                              !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4668                                          strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4669                                      } else {
4670                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4671                                          eRet = OMX_ErrorUnsupportedSetting;
4672                                      }
4673                                  } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4674                                      if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4675                                          strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4676                                      } else {
4677                                          DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4678                                          eRet = OMX_ErrorUnsupportedSetting;
4679                                      }
4680                                  } else {
4681                                      DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4682                                      eRet = OMX_ErrorInvalidComponentName;
4683                                  }
4684                                  break;
4685                              }
4686
4687        case OMX_IndexParamPriorityMgmt: {
4688                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4689                             if (m_state != OMX_StateLoaded) {
4690                                 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4691                                 return OMX_ErrorIncorrectStateOperation;
4692                             }
4693                             OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4694                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4695                                     (unsigned int)priorityMgmtype->nGroupID);
4696
4697                             DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4698                                     (unsigned int)priorityMgmtype->nGroupPriority);
4699
4700                             m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4701                             m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4702
4703                             break;
4704                         }
4705
4706        case OMX_IndexParamCompBufferSupplier: {
4707                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4708                                   OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4709                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4710                                           bufferSupplierType->eBufferSupplier);
4711                                   if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4712                                       m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4713
4714                                   else
4715
4716                                       eRet = OMX_ErrorBadPortIndex;
4717
4718                                   break;
4719
4720                               }
4721        case OMX_IndexParamVideoAvc: {
4722                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4723                                     paramIndex);
4724                             break;
4725                         }
4726        case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4727                            DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4728                                     paramIndex);
4729                             break;
4730                        }
4731        case OMX_IndexParamVideoH263: {
4732                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4733                                      paramIndex);
4734                              break;
4735                          }
4736        case OMX_IndexParamVideoMpeg4: {
4737                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4738                                       paramIndex);
4739                               break;
4740                           }
4741        case OMX_IndexParamVideoMpeg2: {
4742                               DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4743                                       paramIndex);
4744                               break;
4745                           }
4746        case OMX_QTIIndexParamLowLatencyMode: {
4747                               struct v4l2_control control;
4748                               int rc = 0;
4749                               QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam =
4750                                   (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData;
4751                               if (pParam->bLowLatencyMode) {
4752                                   DEBUG_PRINT_HIGH("Enabling DECODE order");
4753                                   time_stamp_dts.set_timestamp_reorder_mode(false);
4754                                   control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4755                                   control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4756                                   rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4757                                   if (rc) {
4758                                       DEBUG_PRINT_ERROR("Set picture order failed");
4759                                       eRet = OMX_ErrorUnsupportedSetting;
4760                                   }
4761                               }
4762                               break;
4763                           }
4764        case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4765                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4766                                     QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4767                                         (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4768                                     struct v4l2_control control;
4769                                     int pic_order,rc=0;
4770                                     DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4771                                             pictureOrder->eOutputPictureOrder);
4772                                     if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4773                                         pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4774                                     } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4775                                         pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4776                                         time_stamp_dts.set_timestamp_reorder_mode(false);
4777                                     } else
4778                                         eRet = OMX_ErrorBadParameter;
4779                                     if (eRet == OMX_ErrorNone) {
4780                                         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4781                                         control.value = pic_order;
4782                                         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4783                                         if (rc) {
4784                                             DEBUG_PRINT_ERROR("Set picture order failed");
4785                                             eRet = OMX_ErrorUnsupportedSetting;
4786                                         }
4787                                     }
4788                                     break;
4789                                 }
4790        case OMX_QcomIndexParamConcealMBMapExtraData:
4791                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4792                               eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4793                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4794                               break;
4795        case OMX_QcomIndexParamFrameInfoExtraData:
4796                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4797                               eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4798                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4799                               break;
4800        case OMX_ExtraDataFrameDimension:
4801                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4802                               eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4803                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4804                               break;
4805        case OMX_QcomIndexParamInterlaceExtraData:
4806                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4807                               eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4808                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4809                               break;
4810        case OMX_QcomIndexParamH264TimeInfo:
4811                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4812                               eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4813                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4814                               break;
4815        case OMX_QcomIndexParamVideoFramePackingExtradata:
4816                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4817                               eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4818                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4819                               break;
4820        case OMX_QcomIndexParamVideoQPExtraData:
4821                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4822                               eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4823                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4824                               break;
4825        case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4826                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4827                               eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4828                                       ((QOMX_ENABLETYPE *)paramData)->bEnable);
4829                               break;
4830        case OMX_QcomIndexEnableExtnUserData:
4831                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4832                                eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4833                                    ((QOMX_ENABLETYPE *)paramData)->bEnable);
4834                                break;
4835        case OMX_QTIIndexParamVQZipSEIExtraData:
4836                               VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4837                                eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4838                                    ((QOMX_ENABLETYPE *)paramData)->bEnable);
4839                                break;
4840        case OMX_QcomIndexParamVideoDivx: {
4841                              QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4842                          }
4843                          break;
4844        case OMX_QcomIndexPlatformPvt: {
4845                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4846                               DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4847                               OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4848                               if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4849                                   DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4850                                   eRet = OMX_ErrorUnsupportedSetting;
4851                               } else {
4852                                   m_out_pvt_entry_pmem = OMX_TRUE;
4853                                   if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4854                                       DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4855                                       m_use_output_pmem = OMX_TRUE;
4856                                   }
4857                               }
4858
4859                           }
4860                           break;
4861        case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4862                                       DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4863                                       DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4864                                       struct v4l2_control control;
4865                                       int rc;
4866                                       drv_ctx.idr_only_decoding = 1;
4867                                       control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4868                                       control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4869                                       rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4870                                       if (rc) {
4871                                           DEBUG_PRINT_ERROR("Set picture order failed");
4872                                           eRet = OMX_ErrorUnsupportedSetting;
4873                                       } else {
4874                                           control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4875                                           control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4876                                           rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4877                                           if (rc) {
4878                                               DEBUG_PRINT_ERROR("Sync frame setting failed");
4879                                               eRet = OMX_ErrorUnsupportedSetting;
4880                                           }
4881                                           /*Setting sync frame decoding on driver might change buffer
4882                                            * requirements so update them here*/
4883                                           if (get_buffer_req(&drv_ctx.ip_buf)) {
4884                                               DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4885                                               eRet = OMX_ErrorUnsupportedSetting;
4886                                           }
4887                                           if (get_buffer_req(&drv_ctx.op_buf)) {
4888                                               DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4889                                               eRet = OMX_ErrorUnsupportedSetting;
4890                                           }
4891                                       }
4892                                   }
4893                                   break;
4894
4895        case OMX_QcomIndexParamIndexExtraDataType: {
4896                                    VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4897                                    QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4898                                    if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4899                                            (extradataIndexType->bEnabled == OMX_TRUE) &&
4900                                            (extradataIndexType->nPortIndex == 1)) {
4901                                        DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4902                                        eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4903
4904                                    }
4905                                }
4906                                break;
4907        case OMX_QcomIndexParamEnableSmoothStreaming: {
4908#ifndef SMOOTH_STREAMING_DISABLED
4909                                      eRet = enable_smoothstreaming();
4910#else
4911                                      eRet = OMX_ErrorUnsupportedSetting;
4912#endif
4913                                  }
4914                                  break;
4915#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4916                                  /* Need to allow following two set_parameters even in Idle
4917                                   * state. This is ANDROID architecture which is not in sync
4918                                   * with openmax standard. */
4919        case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4920                                           VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4921                                           EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4922                                           if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4923                                                DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4924                                                eRet = OMX_ErrorUnsupportedSetting;
4925                                                break;
4926                                           } else if (m_out_mem_ptr) {
4927                                                DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4928                                                eRet = OMX_ErrorInvalidState;
4929                                                break;
4930                                           }
4931                                           if (enableNativeBuffers) {
4932                                               m_enable_android_native_buffers = enableNativeBuffers->enable;
4933                                           }
4934#if !defined(FLEXYUV_SUPPORTED)
4935                                           if (m_enable_android_native_buffers) {
4936                                               // Use the most-preferred-native-color-format as surface-mode is hinted here
4937                                               if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4938                                                   DEBUG_PRINT_ERROR("Failed to set native color format!");
4939                                                   eRet = OMX_ErrorUnsupportedSetting;
4940                                               }
4941                                           }
4942#endif
4943                                       }
4944                                       break;
4945        case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4946                                       VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4947                                       eRet = use_android_native_buffer(hComp, paramData);
4948                                   }
4949                                   break;
4950#if ALLOCATE_OUTPUT_NATIVEHANDLE
4951        case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4952
4953                AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4954                VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4955
4956                if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4957                    DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
4958                    eRet = OMX_ErrorUnsupportedSetting;
4959                    break;
4960                } else if (m_inp_mem_ptr) {
4961                    DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4962                    eRet = OMX_ErrorInvalidState;
4963                    break;
4964                }
4965
4966                if (allocateNativeHandleParams != NULL) {
4967                    allocate_native_handle = allocateNativeHandleParams->enable;
4968                }
4969            }
4970            break;
4971#endif //ALLOCATE_OUTPUT_NATIVEHANDLE
4972#endif
4973        case OMX_QcomIndexParamEnableTimeStampReorder: {
4974                                       VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4975                                       QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4976                                       if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4977                                           if (reorder->bEnable == OMX_TRUE) {
4978                                               frm_int =0;
4979                                               time_stamp_dts.set_timestamp_reorder_mode(true);
4980                                           } else
4981                                               time_stamp_dts.set_timestamp_reorder_mode(false);
4982                                       } else {
4983                                           time_stamp_dts.set_timestamp_reorder_mode(false);
4984                                           if (reorder->bEnable == OMX_TRUE) {
4985                                               eRet = OMX_ErrorUnsupportedSetting;
4986                                           }
4987                                       }
4988                                   }
4989                                   break;
4990        case OMX_IndexParamVideoProfileLevelCurrent: {
4991                                     VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4992                                     OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4993                                         (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4994                                     if (pParam) {
4995                                         m_profile_lvl.eProfile = pParam->eProfile;
4996                                         m_profile_lvl.eLevel = pParam->eLevel;
4997                                     }
4998                                     break;
4999
5000                                 }
5001        case OMX_QcomIndexParamVideoMetaBufferMode:
5002        {
5003            VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
5004            StoreMetaDataInBuffersParams *metabuffer =
5005                (StoreMetaDataInBuffersParams *)paramData;
5006            if (!metabuffer) {
5007                DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
5008                eRet = OMX_ErrorBadParameter;
5009                break;
5010            }
5011            if (m_disable_dynamic_buf_mode) {
5012                DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
5013                eRet = OMX_ErrorUnsupportedSetting;
5014                break;
5015            }
5016            if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5017
5018                    if (m_out_mem_ptr) {
5019                        DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
5020                        eRet = OMX_ErrorInvalidState;
5021                        break;
5022                    }
5023                    //set property dynamic buffer mode to driver.
5024                    struct v4l2_control control;
5025                    struct v4l2_format fmt;
5026                    control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
5027                    if (metabuffer->bStoreMetaData == true) {
5028                        control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
5029                    } else {
5030                        control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
5031                    }
5032                    int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
5033                    if (!rc) {
5034                        DEBUG_PRINT_HIGH("%s buffer mode",
5035                           (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
5036                               dynamic_buf_mode = metabuffer->bStoreMetaData;
5037                    } else {
5038                        DEBUG_PRINT_ERROR("Failed to %s buffer mode",
5039                           (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
5040                        eRet = OMX_ErrorUnsupportedSetting;
5041                    }
5042                } else {
5043                    DEBUG_PRINT_ERROR(
5044                       "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
5045                       (unsigned int)metabuffer->nPortIndex);
5046                    eRet = OMX_ErrorUnsupportedSetting;
5047                }
5048                break;
5049        }
5050        case OMX_QcomIndexParamVideoDownScalar:
5051        {
5052            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
5053            QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
5054            struct v4l2_control control;
5055            int rc;
5056            DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
5057
5058            if (pParam && pParam->bEnable) {
5059                rc = enable_downscalar();
5060                if (rc < 0) {
5061                    DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
5062                    return OMX_ErrorUnsupportedSetting;
5063                }
5064                m_force_down_scalar = pParam->bEnable;
5065            } else {
5066                rc = disable_downscalar();
5067                if (rc < 0) {
5068                    DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
5069                    return OMX_ErrorUnsupportedSetting;
5070                }
5071                m_force_down_scalar = pParam->bEnable;
5072            }
5073            break;
5074        }
5075#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5076        case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
5077        {
5078            VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
5079            DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
5080            PrepareForAdaptivePlaybackParams* pParams =
5081                    (PrepareForAdaptivePlaybackParams *) paramData;
5082            if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5083                if (!pParams->bEnable) {
5084                    return OMX_ErrorNone;
5085                }
5086                if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
5087                        || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
5088                    DEBUG_PRINT_ERROR(
5089                            "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
5090                             (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
5091                             (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
5092                    eRet = OMX_ErrorBadParameter;
5093                } else {
5094                    eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
5095                }
5096            } else {
5097                DEBUG_PRINT_ERROR(
5098                        "Prepare for adaptive playback supported only on output port");
5099                eRet = OMX_ErrorBadParameter;
5100            }
5101            break;
5102        }
5103
5104        case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
5105        {
5106            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5107            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
5108            m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5109            if (m_disable_dynamic_buf_mode) {
5110                DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
5111            }
5112            break;
5113        }
5114#endif
5115        case OMX_QcomIndexParamVideoCustomBufferSize:
5116        {
5117            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
5118            DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
5119            QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
5120            if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5121                struct v4l2_control control;
5122                control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
5123                control.value = pParam->nBufferSize;
5124                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5125                    DEBUG_PRINT_ERROR("Failed to set input buffer size");
5126                    eRet = OMX_ErrorUnsupportedSetting;
5127                } else {
5128                    eRet = get_buffer_req(&drv_ctx.ip_buf);
5129                    if (eRet == OMX_ErrorNone) {
5130                        m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
5131                        DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
5132                            m_custom_buffersize.input_buffersize);
5133                    } else {
5134                        DEBUG_PRINT_ERROR("Failed to get buffer requirement");
5135                    }
5136                }
5137            } else {
5138                DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
5139                eRet = OMX_ErrorBadParameter;
5140            }
5141            break;
5142        }
5143        case OMX_QTIIndexParamVQZIPSEIType:
5144        {
5145            VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
5146            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
5147            OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
5148                (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
5149                DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
5150
5151            eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
5152                ((QOMX_ENABLETYPE *)paramData)->bEnable);
5153            if (eRet != OMX_ErrorNone) {
5154                DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
5155                eRet = OMX_ErrorBadParameter;
5156                client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5157                break;
5158            }
5159            eRet = enable_extradata(OMX_QP_EXTRADATA, false,
5160                    ((QOMX_ENABLETYPE *)paramData)->bEnable);
5161            if (eRet != OMX_ErrorNone) {
5162                DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
5163                eRet = OMX_ErrorBadParameter;
5164                client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5165                client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5166                break;
5167            }
5168            eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
5169                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
5170            if (eRet != OMX_ErrorNone) {
5171                DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
5172                eRet = OMX_ErrorBadParameter;
5173                client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5174                client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5175                client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
5176            }
5177            break;
5178        }
5179        case OMX_QTIIndexParamPassInputBufferFd:
5180        {
5181            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5182            if (arbitrary_bytes) {
5183                DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
5184                eRet = OMX_ErrorUnsupportedSetting;
5185                break;
5186            }
5187
5188            m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5189            if (m_input_pass_buffer_fd)
5190                DEBUG_PRINT_LOW("Enable passing input buffer FD");
5191            break;
5192        }
5193        case OMX_QTIIndexParamForceCompressedForDPB:
5194        {
5195            VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
5196            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
5197            OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
5198                (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
5199            if (m_disable_ubwc_mode) {
5200                DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
5201                eRet = OMX_ErrorUnsupportedSetting;
5202                break;
5203            }
5204            if (!paramData) {
5205               DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
5206               eRet = OMX_ErrorBadParameter;
5207               break;
5208            }
5209
5210            m_force_compressed_for_dpb = pParam->bEnable;
5211            break;
5212        }
5213        case OMX_QTIIndexParamForceUnCompressedForOPB:
5214        {
5215            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
5216            OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
5217                (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
5218            if (!paramData) {
5219                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
5220                eRet = OMX_ErrorBadParameter;
5221                break;
5222            }
5223            m_disable_ubwc_mode = pParam->bEnable;
5224            DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
5225            break;
5226        }
5227        case OMX_QTIIndexParamVideoClientExtradata:
5228        {
5229            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CLIENT_EXTRADATATYPE);
5230            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
5231            QOMX_VIDEO_CLIENT_EXTRADATATYPE *pParam =
5232                (QOMX_VIDEO_CLIENT_EXTRADATATYPE *)paramData;
5233            OMX_U32 extradata_size = VENUS_EXTRADATA_SIZE(4096, 2160);
5234            if (pParam->nExtradataSize < extradata_size ||
5235                pParam->nExtradataAllocSize < (extradata_size * MAX_NUM_INPUT_OUTPUT_BUFFERS) ||
5236                pParam->nExtradataAllocSize < (pParam->nExtradataSize * MAX_NUM_INPUT_OUTPUT_BUFFERS)) {
5237                DEBUG_PRINT_ERROR("set_parameter: Incorrect buffer size for client extradata");
5238                eRet = OMX_ErrorBadParameter;
5239                break;
5240            }
5241            if (!m_client_extradata_info.set_extradata_info(dup(pParam->nFd),
5242                pParam->nExtradataAllocSize, pParam->nExtradataSize)) {
5243                DEBUG_PRINT_ERROR("set_parameter: Setting client extradata failed.");
5244                eRet = OMX_ErrorBadParameter;
5245                break;
5246            }
5247            break;
5248        }
5249        case OMX_QTIIndexParamDitherControl:
5250        {
5251            VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
5252            DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
5253            QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
5254            DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
5255            if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
5256                ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
5257                DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
5258                eRet = OMX_ErrorBadParameter;
5259                break;
5260            }
5261            m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
5262            DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
5263            break;
5264        }
5265        default: {
5266                 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
5267                 eRet = OMX_ErrorUnsupportedIndex;
5268             }
5269    }
5270    if (eRet != OMX_ErrorNone)
5271        DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
5272    return eRet;
5273}
5274
5275/* ======================================================================
5276   FUNCTION
5277   omx_vdec::GetConfig
5278
5279   DESCRIPTION
5280   OMX Get Config Method implementation.
5281
5282   PARAMETERS
5283   <TBD>.
5284
5285   RETURN VALUE
5286   OMX Error None if successful.
5287
5288   ========================================================================== */
5289OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
5290        OMX_IN OMX_INDEXTYPE configIndex,
5291        OMX_INOUT OMX_PTR     configData)
5292{
5293    (void) hComp;
5294    OMX_ERRORTYPE eRet = OMX_ErrorNone;
5295
5296    if (m_state == OMX_StateInvalid) {
5297        DEBUG_PRINT_ERROR("Get Config in Invalid State");
5298        return OMX_ErrorInvalidState;
5299    }
5300
5301    switch ((unsigned long)configIndex) {
5302        case OMX_QcomIndexConfigInterlaced: {
5303                                VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
5304                                OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
5305                                    (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
5306                                if (configFmt->nPortIndex == 1) {
5307                                    if (configFmt->nIndex == 0) {
5308                                        configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
5309                                    } else if (configFmt->nIndex == 1) {
5310                                        configFmt->eInterlaceType =
5311                                            OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
5312                                    } else if (configFmt->nIndex == 2) {
5313                                        configFmt->eInterlaceType =
5314                                            OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
5315                                    } else {
5316                                        DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
5317                                                " NoMore Interlaced formats");
5318                                        eRet = OMX_ErrorNoMore;
5319                                    }
5320
5321                                } else {
5322                                    DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
5323                                            (int)configFmt->nPortIndex);
5324                                    eRet = OMX_ErrorBadPortIndex;
5325                                }
5326                                break;
5327                            }
5328        case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5329                                     VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5330                                     QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5331                                         (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5332                                     decoderinstances->nNumOfInstances = 16;
5333                                     /*TODO: How to handle this case */
5334                                     break;
5335                                 }
5336        case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5337                                          if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5338                                              VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5339                                              OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5340                                                  (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5341                                              memcpy(configFmt, &m_frame_pack_arrangement,
5342                                                  sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5343                                          } else {
5344                                              DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5345                                          }
5346                                          break;
5347                                      }
5348        case OMX_IndexConfigCommonOutputCrop: {
5349                                  VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5350                                  OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5351                                  memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5352                                  DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5353                                        rectangle.nLeft, rectangle.nTop,
5354                                        rectangle.nWidth, rectangle.nHeight);
5355                                  break;
5356                              }
5357        case OMX_QcomIndexConfigPerfLevel: {
5358                VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
5359                struct v4l2_control control;
5360                OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5361                        (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5362
5363                control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5364                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
5365                    DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
5366                    eRet = OMX_ErrorHardware;
5367                }
5368
5369                if (eRet == OMX_ErrorNone) {
5370                    switch (control.value) {
5371                        case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
5372                            perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
5373                            break;
5374                        default:
5375                            DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
5376                            /* Fall through */
5377                        case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
5378                            perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
5379                            break;
5380                    }
5381                }
5382
5383                break;
5384        }
5385        case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5386            VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5387            QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5388            struct v4l2_control control;
5389
5390            if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5391                DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5392                eRet = OMX_ErrorNotImplemented;
5393                break;
5394            }
5395
5396            control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5397            if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5398                coding->bCabac = (OMX_BOOL)
5399                    (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5400                /* We can't query driver at the moment for the cabac mode, so
5401                 * just use 0xff...f as a place holder for future improvement */
5402                coding->nCabacInitIdc = ~0;
5403            } else {
5404                eRet = OMX_ErrorUnsupportedIndex;
5405            }
5406
5407            break;
5408        }
5409        case OMX_QTIIndexConfigDescribeColorAspects:
5410        {
5411            VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5412            DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5413
5414            print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5415            print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5416
5417            if (params->bRequestingDataSpace) {
5418                DEBUG_PRINT_ERROR("Does not handle dataspace request");
5419                return OMX_ErrorUnsupportedSetting;
5420            }
5421            if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) {
5422                DEBUG_PRINT_LOW("Updating Client's color aspects with internal");
5423                memcpy(&(m_client_color_space.sAspects),
5424                        &(m_internal_color_space.sAspects), sizeof(ColorAspects));
5425                m_internal_color_space.bDataSpaceChanged = OMX_FALSE;
5426            }
5427            memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects));
5428
5429            break;
5430        }
5431        case OMX_QTIIndexConfigDescribeHDRColorInfo:
5432        {
5433            VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5434            DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5435            auto_lock lock(m_hdr_info_client_lock);
5436
5437            print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5438            print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5439
5440            if (m_change_client_hdr_info) {
5441                DEBUG_PRINT_LOW("Updating Client's HDR Info with internal");
5442                memcpy(&m_client_hdr_info.sInfo,
5443                       &m_internal_hdr_info.sInfo, sizeof(HDRStaticInfo));
5444                m_change_client_hdr_info = false;
5445            }
5446
5447            memcpy(&(params->sInfo), &(m_client_hdr_info.sInfo), sizeof(HDRStaticInfo));
5448
5449            break;
5450        }
5451        default:
5452        {
5453            DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5454            eRet = OMX_ErrorBadParameter;
5455        }
5456
5457    }
5458
5459    return eRet;
5460}
5461
5462/* ======================================================================
5463   FUNCTION
5464   omx_vdec::SetConfig
5465
5466   DESCRIPTION
5467   OMX Set Config method implementation
5468
5469   PARAMETERS
5470   <TBD>.
5471
5472   RETURN VALUE
5473   OMX Error None if successful.
5474   ========================================================================== */
5475OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5476        OMX_IN OMX_INDEXTYPE configIndex,
5477        OMX_IN OMX_PTR        configData)
5478{
5479    (void) hComp;
5480    if (m_state == OMX_StateInvalid) {
5481        DEBUG_PRINT_ERROR("Get Config in Invalid State");
5482        return OMX_ErrorInvalidState;
5483    }
5484
5485    OMX_ERRORTYPE ret = OMX_ErrorNone;
5486    OMX_VIDEO_CONFIG_NALSIZE *pNal;
5487
5488    DEBUG_PRINT_LOW("Set Config Called");
5489
5490    if (configIndex == OMX_IndexConfigVideoNalSize) {
5491        struct v4l2_control temp;
5492        temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5493
5494        VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5495        pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5496        switch (pNal->nNaluBytes) {
5497            case 0:
5498                temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5499                break;
5500            case 2:
5501                temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5502                break;
5503            case 4:
5504                temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5505                break;
5506            default:
5507                return OMX_ErrorUnsupportedSetting;
5508        }
5509
5510        if (!arbitrary_bytes) {
5511            /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5512             * with start code, so only need to notify driver in frame by frame mode */
5513            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5514                DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5515                return OMX_ErrorHardware;
5516            }
5517        }
5518
5519        nal_length = pNal->nNaluBytes;
5520        m_frame_parser.init_nal_length(nal_length);
5521
5522        DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5523        return ret;
5524    } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5525        OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5526        DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5527
5528        if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5529            if (config->bEnabled) {
5530                if ((config->nFps >> 16) > 0 &&
5531                        (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5532                    m_fps_received = config->nFps;
5533                    DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5534                            (unsigned int)config->nFps >> 16);
5535                    Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5536                            drv_ctx.frame_rate.fps_denominator);
5537
5538                    if (!drv_ctx.frame_rate.fps_numerator) {
5539                        DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5540                        drv_ctx.frame_rate.fps_numerator = 30;
5541                    }
5542
5543                    if (drv_ctx.frame_rate.fps_denominator) {
5544                        drv_ctx.frame_rate.fps_numerator = (int)
5545                            drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5546                    }
5547
5548                    drv_ctx.frame_rate.fps_denominator = 1;
5549                    frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5550                        drv_ctx.frame_rate.fps_numerator;
5551
5552                    struct v4l2_outputparm oparm;
5553                    /*XXX: we're providing timing info as seconds per frame rather than frames
5554                     * per second.*/
5555                    oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5556                    oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5557
5558                    struct v4l2_streamparm sparm;
5559                    sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5560                    sparm.parm.output = oparm;
5561                    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5562                        DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5563                                performance might be affected");
5564                        ret = OMX_ErrorHardware;
5565                    }
5566                    client_set_fps = true;
5567                } else {
5568                    DEBUG_PRINT_ERROR("Frame rate not supported.");
5569                    ret = OMX_ErrorUnsupportedSetting;
5570                }
5571            } else {
5572                DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5573                client_set_fps = false;
5574            }
5575        } else {
5576            DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5577                    (int)config->nPortIndex);
5578            ret = OMX_ErrorBadPortIndex;
5579        }
5580
5581        return ret;
5582    } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5583        OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5584            (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5585        struct v4l2_control control;
5586
5587        DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5588        control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5589
5590        switch (perf->ePerfLevel) {
5591            case OMX_QCOM_PerfLevelNominal:
5592                control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5593                m_need_turbo &= ~TURBO_MODE_CLIENT_REQUESTED;
5594                break;
5595            case OMX_QCOM_PerfLevelTurbo:
5596                control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5597                m_need_turbo |= TURBO_MODE_CLIENT_REQUESTED;
5598                break;
5599            default:
5600                ret = OMX_ErrorUnsupportedSetting;
5601                break;
5602        }
5603
5604        if (ret == OMX_ErrorNone) {
5605            ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5606                OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5607        }
5608
5609        return ret;
5610    } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5611        OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5612            (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5613        struct v4l2_control control;
5614        DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5615        control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5616
5617        switch (config->eDecodeType) {
5618            case OMX_QCOM_PictypeDecode_I:
5619                control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5620                break;
5621            case OMX_QCOM_PictypeDecode_IPB:
5622            default:
5623                control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5624                break;
5625        }
5626
5627        ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5628                OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5629        if (ret)
5630            DEBUG_PRINT_ERROR("Failed to set picture type decode");
5631
5632        return ret;
5633    } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5634        OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5635        DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5636
5637        struct v4l2_control control;
5638
5639        control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5640        if (priority->nU32 == 0)
5641            control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5642        else
5643            control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5644
5645        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5646            DEBUG_PRINT_ERROR("Failed to set Priority");
5647            ret = OMX_ErrorUnsupportedSetting;
5648        }
5649        return ret;
5650    } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5651        OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5652        DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5653
5654        struct v4l2_control control;
5655
5656        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5657        control.value = rate->nU32;
5658
5659        operating_frame_rate = rate->nU32 >> 16;
5660
5661        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5662            ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5663                    OMX_ErrorUnsupportedSetting;
5664            DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5665                    rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5666        }
5667        return ret;
5668
5669    } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5670        VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5671        DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5672        if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5673            enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5674        }
5675
5676        print_debug_color_aspects(&(params->sAspects), "Set Config");
5677        memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5678        return ret;
5679    } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5680        VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5681        DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5682        if (!DEFAULT_EXTRADATA & OMX_HDR_COLOR_INFO_EXTRADATA) {
5683            ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, true, true);
5684            if (ret != OMX_ErrorNone) {
5685                DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5686                return ret;
5687            }
5688        }
5689
5690        print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5691        memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5692        return ret;
5693    }
5694
5695    return OMX_ErrorNotImplemented;
5696}
5697
5698#define extn_equals(param, extn) (!strcmp(param, extn))
5699
5700/* ======================================================================
5701   FUNCTION
5702   omx_vdec::GetExtensionIndex
5703
5704   DESCRIPTION
5705   OMX GetExtensionIndex method implementaion.  <TBD>
5706
5707   PARAMETERS
5708   <TBD>.
5709
5710   RETURN VALUE
5711   OMX Error None if everything successful.
5712
5713   ========================================================================== */
5714OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5715        OMX_IN OMX_STRING      paramName,
5716        OMX_OUT OMX_INDEXTYPE* indexType)
5717{
5718    (void) hComp;
5719    if (m_state == OMX_StateInvalid) {
5720        DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5721        return OMX_ErrorInvalidState;
5722    } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5723        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5724    } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5725        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5726    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5727        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5728    } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5729        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5730    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5731        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5732    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5733        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5734    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5735        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5736    }
5737#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5738    else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5739        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5740    } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5741        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5742    } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5743        DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5744        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5745    } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5746        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5747    }
5748#if ALLOCATE_OUTPUT_NATIVEHANDLE
5749    else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5750        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5751    }
5752#endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5753#endif
5754    else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5755        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5756    }
5757#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5758    else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5759        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5760    } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5761        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5762    }
5763#endif
5764#ifdef FLEXYUV_SUPPORTED
5765    else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5766        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5767    }
5768#endif
5769    else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5770        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5771    } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5772        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5773    } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5774        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5775    } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5776        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5777    } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5778        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5779    } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5780        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5781    } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5782        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5783    } else {
5784        DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5785        return OMX_ErrorNotImplemented;
5786    }
5787    return OMX_ErrorNone;
5788}
5789
5790/* ======================================================================
5791   FUNCTION
5792   omx_vdec::GetState
5793
5794   DESCRIPTION
5795   Returns the state information back to the caller.<TBD>
5796
5797   PARAMETERS
5798   <TBD>.
5799
5800   RETURN VALUE
5801   Error None if everything is successful.
5802   ========================================================================== */
5803OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5804        OMX_OUT OMX_STATETYPE* state)
5805{
5806    (void) hComp;
5807    *state = m_state;
5808    DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5809    return OMX_ErrorNone;
5810}
5811
5812/* ======================================================================
5813   FUNCTION
5814   omx_vdec::ComponentTunnelRequest
5815
5816   DESCRIPTION
5817   OMX Component Tunnel Request method implementation. <TBD>
5818
5819   PARAMETERS
5820   None.
5821
5822   RETURN VALUE
5823   OMX Error None if everything successful.
5824
5825   ========================================================================== */
5826OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5827        OMX_IN OMX_U32                        port,
5828        OMX_IN OMX_HANDLETYPE        peerComponent,
5829        OMX_IN OMX_U32                    peerPort,
5830        OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5831{
5832    (void) hComp;
5833    (void) port;
5834    (void) peerComponent;
5835    (void) peerPort;
5836    (void) tunnelSetup;
5837    DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5838    return OMX_ErrorNotImplemented;
5839}
5840
5841/* ======================================================================
5842   FUNCTION
5843   omx_vdec::UseOutputBuffer
5844
5845   DESCRIPTION
5846   Helper function for Use buffer in the input pin
5847
5848   PARAMETERS
5849   None.
5850
5851   RETURN VALUE
5852   true/false
5853
5854   ========================================================================== */
5855OMX_ERRORTYPE omx_vdec::allocate_extradata()
5856{
5857#ifdef USE_ION
5858    if (drv_ctx.extradata_info.buffer_size) {
5859        if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5860            munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5861            close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5862            free_ion_memory(&drv_ctx.extradata_info.ion);
5863        }
5864        drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5865        drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5866                drv_ctx.extradata_info.size, 4096,
5867                &drv_ctx.extradata_info.ion.ion_alloc_data,
5868                &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5869        if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5870            DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5871            return OMX_ErrorInsufficientResources;
5872        }
5873        drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5874                drv_ctx.extradata_info.size,
5875                PROT_READ|PROT_WRITE, MAP_SHARED,
5876                drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5877        if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5878            DEBUG_PRINT_ERROR("Failed to map extradata memory");
5879            close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5880            free_ion_memory(&drv_ctx.extradata_info.ion);
5881            return OMX_ErrorInsufficientResources;
5882        }
5883    }
5884#endif
5885    if (!m_other_extradata) {
5886        m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5887        if (!m_other_extradata) {
5888            DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5889            return OMX_ErrorInsufficientResources;
5890        }
5891    }
5892    return OMX_ErrorNone;
5893}
5894
5895void omx_vdec::free_extradata()
5896{
5897#ifdef USE_ION
5898    if (drv_ctx.extradata_info.uaddr) {
5899        munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5900        close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5901        free_ion_memory(&drv_ctx.extradata_info.ion);
5902    }
5903#endif
5904    if (m_other_extradata) {
5905        free(m_other_extradata);
5906        m_other_extradata = NULL;
5907    }
5908}
5909
5910OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5911        OMX_IN OMX_HANDLETYPE            hComp,
5912        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5913        OMX_IN OMX_U32                   port,
5914        OMX_IN OMX_PTR                   appData,
5915        OMX_IN OMX_U32                   bytes,
5916        OMX_IN OMX_U8*                   buffer)
5917{
5918    OMX_ERRORTYPE eRet = OMX_ErrorNone;
5919    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5920    unsigned                         i= 0; // Temporary counter
5921    struct vdec_setbuffer_cmd setbuffers;
5922    OMX_PTR privateAppData = NULL;
5923    private_handle_t *handle = NULL;
5924    OMX_U8 *buff = buffer;
5925    struct v4l2_buffer buf;
5926    struct v4l2_plane plane[VIDEO_MAX_PLANES];
5927    int extra_idx = 0;
5928    (void) hComp;
5929    (void) port;
5930
5931    if (!m_out_mem_ptr) {
5932        DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5933        eRet = allocate_output_headers();
5934        if (eRet == OMX_ErrorNone)
5935            eRet = allocate_extradata();
5936    }
5937
5938    if (eRet == OMX_ErrorNone) {
5939        for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5940            if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5941                break;
5942            }
5943        }
5944    }
5945
5946    if (i >= drv_ctx.op_buf.actualcount) {
5947        DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5948        eRet = OMX_ErrorInsufficientResources;
5949    }
5950
5951    if (eRet != OMX_ErrorNone)
5952       return eRet;
5953
5954    if (dynamic_buf_mode) {
5955        *bufferHdr = (m_out_mem_ptr + i );
5956        (*bufferHdr)->pBuffer = NULL;
5957        if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5958            enum v4l2_buf_type buf_type;
5959            int rr = 0;
5960            buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5961            if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5962                DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5963                return OMX_ErrorInsufficientResources;
5964            } else {
5965                streaming[CAPTURE_PORT] = true;
5966                DEBUG_PRINT_LOW("STREAMON Successful");
5967            }
5968
5969            DEBUG_PRINT_HIGH("Enabling Turbo mode");
5970            request_perf_level(VIDC_TURBO);
5971        }
5972        BITMASK_SET(&m_out_bm_count,i);
5973        (*bufferHdr)->pAppPrivate = appData;
5974        (*bufferHdr)->pBuffer = buffer;
5975        (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5976        return eRet;
5977    }
5978
5979    if (eRet == OMX_ErrorNone) {
5980#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5981        if (m_enable_android_native_buffers) {
5982            if (m_use_android_native_buffers) {
5983                UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5984                sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5985                handle = (private_handle_t *)nBuf->handle;
5986                privateAppData = params->pAppPrivate;
5987            } else {
5988                handle = (private_handle_t *)buff;
5989                privateAppData = appData;
5990            }
5991            if (!handle) {
5992                DEBUG_PRINT_ERROR("handle is invalid");
5993                return OMX_ErrorBadParameter;
5994            }
5995
5996            if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5997                if (secure_mode && secure_scaling_to_non_secure_opb) {
5998                    DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5999                        (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6000                } else {
6001                    DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
6002                            " expected %u, got %u",
6003                            (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6004                    return OMX_ErrorBadParameter;
6005                }
6006            }
6007
6008            drv_ctx.op_buf.buffer_size = handle->size;
6009
6010            if (!m_use_android_native_buffers) {
6011                if (!secure_mode) {
6012                    buff =  (OMX_U8*)mmap(0, handle->size,
6013                            PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
6014                    if (buff == MAP_FAILED) {
6015                        DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
6016                        return OMX_ErrorInsufficientResources;
6017                    }
6018                }
6019            }
6020#if defined(_ANDROID_ICS_)
6021            native_buffer[i].nativehandle = handle;
6022            native_buffer[i].privatehandle = handle;
6023#endif
6024            if (!handle) {
6025                DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
6026                return OMX_ErrorBadParameter;
6027            }
6028            drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
6029            drv_ctx.ptr_outputbuffer[i].offset = 0;
6030            drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6031            drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6032            drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
6033        } else
6034#endif
6035
6036            if (!ouput_egl_buffers && !m_use_output_pmem) {
6037#ifdef USE_ION
6038                drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6039                        drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
6040                        &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
6041                        &drv_ctx.op_buf_ion_info[i].fd_ion_data,
6042                        secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
6043                if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
6044                    DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
6045                    return OMX_ErrorInsufficientResources;
6046                }
6047                drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6048                                      drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6049#else
6050                drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6051                                      open (MEM_DEVICE,O_RDWR);
6052
6053                if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6054                    DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6055                    return OMX_ErrorInsufficientResources;
6056                }
6057
6058                /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
6059                if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
6060                    drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6061                                          open (MEM_DEVICE,O_RDWR);
6062                    if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6063                        DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6064                        return OMX_ErrorInsufficientResources;
6065                    }
6066                }
6067
6068                if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
6069                            drv_ctx.op_buf.buffer_size,
6070                            drv_ctx.op_buf.alignment)) {
6071                    DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6072                    close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6073                    return OMX_ErrorInsufficientResources;
6074                }
6075#endif
6076                if (!secure_mode) {
6077                    drv_ctx.ptr_outputbuffer[i].bufferaddr =
6078                        (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
6079                                PROT_READ|PROT_WRITE, MAP_SHARED,
6080                                drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
6081                    if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
6082                        close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6083#ifdef USE_ION
6084                        free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6085#endif
6086                        DEBUG_PRINT_ERROR("Unable to mmap output buffer");
6087                        return OMX_ErrorInsufficientResources;
6088                    }
6089                }
6090                drv_ctx.ptr_outputbuffer[i].offset = 0;
6091                privateAppData = appData;
6092            } else {
6093
6094                DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
6095                if (!appData || !bytes ) {
6096                    if (!secure_mode && !buffer) {
6097                        DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
6098                        return OMX_ErrorBadParameter;
6099                    }
6100                }
6101
6102                OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
6103                OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
6104                pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
6105                if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
6106                        !pmem_list->nEntries ||
6107                        pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
6108                    DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
6109                    return OMX_ErrorBadParameter;
6110                }
6111                pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6112                    pmem_list->entryList->entry;
6113                DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
6114                        pmem_info->pmem_fd);
6115                drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
6116                drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
6117                drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6118                drv_ctx.ptr_outputbuffer[i].mmaped_size =
6119                    drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6120                privateAppData = appData;
6121            }
6122        m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6123        m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6124        m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6125        m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6126        m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6127
6128        *bufferHdr = (m_out_mem_ptr + i );
6129        if (secure_mode)
6130            drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6131        //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6132        memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
6133                sizeof (vdec_bufferpayload));
6134
6135        DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
6136                drv_ctx.ptr_outputbuffer[i].bufferaddr,
6137                drv_ctx.ptr_outputbuffer[i].pmem_fd );
6138
6139        buf.index = i;
6140        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6141        buf.memory = V4L2_MEMORY_USERPTR;
6142        plane[0].length = drv_ctx.op_buf.buffer_size;
6143        plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6144            (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6145        plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6146        plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6147        plane[0].data_offset = 0;
6148        extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6149        if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6150            plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6151            plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6152#ifdef USE_ION
6153            plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6154#endif
6155            plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6156            plane[extra_idx].data_offset = 0;
6157        } else if  (extra_idx >= VIDEO_MAX_PLANES) {
6158            DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
6159            return OMX_ErrorBadParameter;
6160        }
6161        buf.m.planes = plane;
6162        buf.length = drv_ctx.num_planes;
6163
6164        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
6165            DEBUG_PRINT_ERROR("Failed to prepare bufs");
6166            /*TODO: How to handle this case */
6167            return OMX_ErrorInsufficientResources;
6168        }
6169
6170        if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
6171            enum v4l2_buf_type buf_type;
6172            buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6173            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
6174                return OMX_ErrorInsufficientResources;
6175            } else {
6176                streaming[CAPTURE_PORT] = true;
6177                DEBUG_PRINT_LOW("STREAMON Successful");
6178            }
6179
6180            DEBUG_PRINT_HIGH("Enabling Turbo mode");
6181            request_perf_level(VIDC_TURBO);
6182        }
6183
6184        (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
6185        if (m_enable_android_native_buffers) {
6186            DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
6187            (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
6188        } else {
6189            (*bufferHdr)->pBuffer = buff;
6190        }
6191        (*bufferHdr)->pAppPrivate = privateAppData;
6192        BITMASK_SET(&m_out_bm_count,i);
6193    }
6194    return eRet;
6195}
6196
6197/* ======================================================================
6198   FUNCTION
6199   omx_vdec::use_input_heap_buffers
6200
6201   DESCRIPTION
6202   OMX Use Buffer Heap allocation method implementation.
6203
6204   PARAMETERS
6205   <TBD>.
6206
6207   RETURN VALUE
6208   OMX Error None , if everything successful.
6209
6210   ========================================================================== */
6211OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
6212        OMX_IN OMX_HANDLETYPE            hComp,
6213        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6214        OMX_IN OMX_U32                   port,
6215        OMX_IN OMX_PTR                   appData,
6216        OMX_IN OMX_U32                   bytes,
6217        OMX_IN OMX_U8*                   buffer)
6218{
6219    DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
6220    OMX_ERRORTYPE eRet = OMX_ErrorNone;
6221
6222    if (secure_mode) {
6223        DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
6224        return OMX_ErrorUndefined;
6225    }
6226
6227    if (!m_inp_heap_ptr)
6228        m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
6229            calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6230                    drv_ctx.ip_buf.actualcount);
6231    if (!m_phdr_pmem_ptr)
6232        m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
6233            calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6234                    drv_ctx.ip_buf.actualcount);
6235    if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
6236        DEBUG_PRINT_ERROR("Insufficent memory");
6237        eRet = OMX_ErrorInsufficientResources;
6238    } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
6239        input_use_buffer = true;
6240        memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
6241        m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
6242        m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
6243        m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
6244        m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
6245        m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
6246        *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
6247        eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
6248        DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
6249        if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
6250                    (unsigned)NULL, (unsigned)NULL)) {
6251            DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6252            return OMX_ErrorInsufficientResources;
6253        }
6254        m_in_alloc_cnt++;
6255    } else {
6256        DEBUG_PRINT_ERROR("All i/p buffers have been set!");
6257        eRet = OMX_ErrorInsufficientResources;
6258    }
6259    return eRet;
6260}
6261
6262/* ======================================================================
6263   FUNCTION
6264   omx_vdec::UseBuffer
6265
6266   DESCRIPTION
6267   OMX Use Buffer method implementation.
6268
6269   PARAMETERS
6270   <TBD>.
6271
6272   RETURN VALUE
6273   OMX Error None , if everything successful.
6274
6275   ========================================================================== */
6276OMX_ERRORTYPE  omx_vdec::use_buffer(
6277        OMX_IN OMX_HANDLETYPE            hComp,
6278        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6279        OMX_IN OMX_U32                   port,
6280        OMX_IN OMX_PTR                   appData,
6281        OMX_IN OMX_U32                   bytes,
6282        OMX_IN OMX_U8*                   buffer)
6283{
6284    OMX_ERRORTYPE error = OMX_ErrorNone;
6285    struct vdec_setbuffer_cmd setbuffers;
6286
6287    if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
6288            DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
6289            return OMX_ErrorBadParameter;
6290    }
6291    if (m_state == OMX_StateInvalid) {
6292        DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
6293        return OMX_ErrorInvalidState;
6294    }
6295    if (port == OMX_CORE_INPUT_PORT_INDEX) {
6296        // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6297        // ensure that use-buffer was called for previous allocation.
6298        // Mix-and-match of useBuffer and allocateBuffer is not allowed
6299        if (m_inp_mem_ptr && !input_use_buffer) {
6300            DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
6301            return OMX_ErrorUndefined;
6302        }
6303        error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
6304    } else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
6305        error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
6306    else {
6307        DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6308        error = OMX_ErrorBadPortIndex;
6309    }
6310    DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
6311    if (error == OMX_ErrorNone) {
6312        if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6313            // Send the callback now
6314            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6315            post_event(OMX_CommandStateSet,OMX_StateIdle,
6316                    OMX_COMPONENT_GENERATE_EVENT);
6317        }
6318        if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
6319                BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6320            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6321            post_event(OMX_CommandPortEnable,
6322                    OMX_CORE_INPUT_PORT_INDEX,
6323                    OMX_COMPONENT_GENERATE_EVENT);
6324        } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6325                BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6326            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6327            post_event(OMX_CommandPortEnable,
6328                    OMX_CORE_OUTPUT_PORT_INDEX,
6329                    OMX_COMPONENT_GENERATE_EVENT);
6330        }
6331    }
6332    return error;
6333}
6334
6335OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6336        OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6337{
6338    if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
6339        if (m_inp_heap_ptr[bufferindex].pBuffer)
6340            free(m_inp_heap_ptr[bufferindex].pBuffer);
6341        m_inp_heap_ptr[bufferindex].pBuffer = NULL;
6342    }
6343    if (pmem_bufferHdr)
6344        free_input_buffer(pmem_bufferHdr);
6345    return OMX_ErrorNone;
6346}
6347
6348OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6349{
6350    unsigned int index = 0;
6351    if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6352        return OMX_ErrorBadParameter;
6353    }
6354
6355    index = bufferHdr - m_inp_mem_ptr;
6356    DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6357
6358    auto_lock l(buf_lock);
6359    bufferHdr->pInputPortPrivate = NULL;
6360
6361    if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6362        DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6363        if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6364            struct vdec_setbuffer_cmd setbuffers;
6365            setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
6366            memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
6367                    sizeof (vdec_bufferpayload));
6368            if (!secure_mode) {
6369                DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
6370                        drv_ctx.ptr_inputbuffer[index].pmem_fd);
6371                DEBUG_PRINT_LOW("unmap the input buffer size=%u  address = %p",
6372                        (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
6373                        drv_ctx.ptr_inputbuffer[index].bufferaddr);
6374                munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6375                        drv_ctx.ptr_inputbuffer[index].mmaped_size);
6376            }
6377
6378            if (allocate_native_handle){
6379                native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6380                native_handle_close(nh);
6381                native_handle_delete(nh);
6382            } else {
6383                // Close fd for non-secure and secure non-native-handle case
6384                close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6385            }
6386            drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6387
6388            if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6389                free(m_desc_buffer_ptr[index].buf_addr);
6390                m_desc_buffer_ptr[index].buf_addr = NULL;
6391                m_desc_buffer_ptr[index].desc_data_size = 0;
6392            }
6393#ifdef USE_ION
6394            free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6395#endif
6396            m_in_alloc_cnt--;
6397        }
6398    }
6399
6400    return OMX_ErrorNone;
6401}
6402
6403OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6404{
6405    unsigned int index = 0;
6406
6407    if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6408        return OMX_ErrorBadParameter;
6409    }
6410
6411    index = bufferHdr - m_out_mem_ptr;
6412    DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
6413
6414    if (index < drv_ctx.op_buf.actualcount
6415            && drv_ctx.ptr_outputbuffer) {
6416        DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6417                drv_ctx.ptr_outputbuffer[index].bufferaddr);
6418
6419        struct vdec_setbuffer_cmd setbuffers;
6420        setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6421        memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
6422                sizeof (vdec_bufferpayload));
6423
6424        if (!dynamic_buf_mode) {
6425            if (streaming[CAPTURE_PORT] &&
6426                !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6427                if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6428                    DEBUG_PRINT_ERROR("STREAMOFF Failed");
6429                } else {
6430                    DEBUG_PRINT_LOW("STREAMOFF Successful");
6431                }
6432            }
6433#ifdef _ANDROID_
6434            if (m_enable_android_native_buffers) {
6435                if (!secure_mode) {
6436                    if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6437                        munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6438                                drv_ctx.ptr_outputbuffer[index].mmaped_size);
6439                    }
6440                }
6441                drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6442            } else {
6443#endif
6444                if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0
6445                    && !ouput_egl_buffers && !m_use_output_pmem) {
6446                    if (drv_ctx.op_buf_map_info[index].free_buffer) {
6447                        if (!secure_mode) {
6448                            DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
6449                                    drv_ctx.ptr_outputbuffer[0].pmem_fd);
6450                            DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
6451                                    (unsigned int)drv_ctx.op_buf_map_info[index].map_size,
6452                                    drv_ctx.op_buf_map_info[index].base_address);
6453                            munmap (drv_ctx.op_buf_map_info[index].base_address,
6454                                    drv_ctx.op_buf_map_info[index].map_size);
6455                        }
6456                        close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
6457                        drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6458#ifdef USE_ION
6459                        free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
6460#endif
6461                    } else {
6462                        drv_ctx.op_buf_ion_info[index].ion_device_fd = -1;
6463                        drv_ctx.op_buf_ion_info[index].ion_alloc_data.handle = 0;
6464                        drv_ctx.op_buf_ion_info[index].fd_ion_data.fd = -1;
6465                    }
6466                    drv_ctx.op_buf_map_info[index].free_buffer = false;
6467                    drv_ctx.op_buf_map_info[index].base_address = NULL;
6468                    drv_ctx.op_buf_map_info[index].map_size = 0;
6469                    drv_ctx.op_buf_map_info[index].offset = 0;
6470                }
6471#ifdef _ANDROID_
6472            }
6473#endif
6474        } //!dynamic_buf_mode
6475        if (release_output_done()) {
6476            free_extradata();
6477        }
6478    }
6479
6480    return OMX_ErrorNone;
6481
6482}
6483
6484OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
6485        OMX_BUFFERHEADERTYPE **bufferHdr,
6486        OMX_U32              port,
6487        OMX_PTR              appData,
6488        OMX_U32              bytes)
6489{
6490    OMX_BUFFERHEADERTYPE *input = NULL;
6491    unsigned char *buf_addr = NULL;
6492    OMX_ERRORTYPE eRet = OMX_ErrorNone;
6493    unsigned   i = 0;
6494
6495    /* Sanity Check*/
6496    if (bufferHdr == NULL) {
6497        return OMX_ErrorBadParameter;
6498    }
6499
6500    if (m_inp_heap_ptr == NULL) {
6501        m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6502                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6503                         drv_ctx.ip_buf.actualcount);
6504        m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6505                  calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6506                          drv_ctx.ip_buf.actualcount);
6507
6508        if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6509            DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6510            return OMX_ErrorInsufficientResources;
6511        }
6512    }
6513
6514    /*Find a Free index*/
6515    for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6516        if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6517            DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6518            break;
6519        }
6520    }
6521
6522    if (i < drv_ctx.ip_buf.actualcount) {
6523        buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6524
6525        if (buf_addr == NULL) {
6526            return OMX_ErrorInsufficientResources;
6527        }
6528
6529        *bufferHdr = (m_inp_heap_ptr + i);
6530        input = *bufferHdr;
6531        BITMASK_SET(&m_heap_inp_bm_count,i);
6532
6533        input->pBuffer           = (OMX_U8 *)buf_addr;
6534        input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6535        input->nVersion.nVersion = OMX_SPEC_VERSION;
6536        input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6537        input->pAppPrivate       = appData;
6538        input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6539        DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6540        eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6541        DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6542        /*Add the Buffers to freeq*/
6543        if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6544                    (unsigned)NULL, (unsigned)NULL)) {
6545            DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6546            return OMX_ErrorInsufficientResources;
6547        }
6548    } else {
6549        return OMX_ErrorBadParameter;
6550    }
6551
6552    return eRet;
6553
6554}
6555
6556
6557/* ======================================================================
6558   FUNCTION
6559   omx_vdec::AllocateInputBuffer
6560
6561   DESCRIPTION
6562   Helper function for allocate buffer in the input pin
6563
6564   PARAMETERS
6565   None.
6566
6567   RETURN VALUE
6568   true/false
6569
6570   ========================================================================== */
6571OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6572        OMX_IN OMX_HANDLETYPE            hComp,
6573        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6574        OMX_IN OMX_U32                   port,
6575        OMX_IN OMX_PTR                   appData,
6576        OMX_IN OMX_U32                   bytes)
6577{
6578    OMX_ERRORTYPE eRet = OMX_ErrorNone;
6579    struct vdec_setbuffer_cmd setbuffers;
6580    OMX_BUFFERHEADERTYPE *input = NULL;
6581    unsigned   i = 0;
6582    unsigned char *buf_addr = NULL;
6583    int pmem_fd = -1;
6584
6585    (void) hComp;
6586    (void) port;
6587
6588
6589    if (bytes != drv_ctx.ip_buf.buffer_size) {
6590        DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6591                (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6592        return OMX_ErrorBadParameter;
6593    }
6594
6595    if (!m_inp_mem_ptr) {
6596        DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6597                drv_ctx.ip_buf.actualcount,
6598                (unsigned int)drv_ctx.ip_buf.buffer_size);
6599
6600        m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6601                calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6602
6603        if (m_inp_mem_ptr == NULL) {
6604            return OMX_ErrorInsufficientResources;
6605        }
6606
6607        drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6608                      calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6609
6610        if (drv_ctx.ptr_inputbuffer == NULL) {
6611            return OMX_ErrorInsufficientResources;
6612        }
6613#ifdef USE_ION
6614        drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6615                      calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6616
6617        if (drv_ctx.ip_buf_ion_info == NULL) {
6618            return OMX_ErrorInsufficientResources;
6619        }
6620#endif
6621
6622        for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6623            drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6624#ifdef USE_ION
6625            drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6626#endif
6627        }
6628    }
6629
6630    for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6631        if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6632            DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6633            break;
6634        }
6635    }
6636
6637    if (i < drv_ctx.ip_buf.actualcount) {
6638        struct v4l2_buffer buf;
6639        struct v4l2_plane plane;
6640        int rc;
6641        DEBUG_PRINT_LOW("Allocate input Buffer");
6642#ifdef USE_ION
6643        drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6644                drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
6645                &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6646                &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6647                SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6648        if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6649            return OMX_ErrorInsufficientResources;
6650        }
6651        pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6652#else
6653        pmem_fd = open (MEM_DEVICE,O_RDWR);
6654
6655        if (pmem_fd < 0) {
6656            DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6657            return OMX_ErrorInsufficientResources;
6658        }
6659
6660        if (pmem_fd == 0) {
6661            pmem_fd = open (MEM_DEVICE,O_RDWR);
6662
6663            if (pmem_fd < 0) {
6664                DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6665                return OMX_ErrorInsufficientResources;
6666            }
6667        }
6668
6669        if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6670                    drv_ctx.ip_buf.alignment)) {
6671            DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6672            close(pmem_fd);
6673            return OMX_ErrorInsufficientResources;
6674        }
6675#endif
6676        if (!secure_mode) {
6677            buf_addr = (unsigned char *)mmap(NULL,
6678                    drv_ctx.ip_buf.buffer_size,
6679                    PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6680
6681            if (buf_addr == MAP_FAILED) {
6682                close(pmem_fd);
6683#ifdef USE_ION
6684                free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6685#endif
6686                DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6687                return OMX_ErrorInsufficientResources;
6688            }
6689        }
6690        *bufferHdr = (m_inp_mem_ptr + i);
6691        if (secure_mode)
6692            drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6693        else
6694            drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6695        drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6696        drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6697        drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6698        drv_ctx.ptr_inputbuffer [i].offset = 0;
6699
6700
6701        buf.index = i;
6702        buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6703        buf.memory = V4L2_MEMORY_USERPTR;
6704        plane.bytesused = 0;
6705        plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6706        plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6707        plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6708        plane.reserved[1] = 0;
6709        plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6710        buf.m.planes = &plane;
6711        buf.length = 1;
6712
6713        DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6714                drv_ctx.ptr_inputbuffer[i].bufferaddr);
6715
6716        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6717
6718        if (rc) {
6719            DEBUG_PRINT_ERROR("Failed to prepare bufs");
6720            /*TODO: How to handle this case */
6721            return OMX_ErrorInsufficientResources;
6722        }
6723
6724        input = *bufferHdr;
6725        BITMASK_SET(&m_inp_bm_count,i);
6726        DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6727        if (allocate_native_handle) {
6728            native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6729            if (!nh) {
6730                DEBUG_PRINT_ERROR("Native handle create failed");
6731                return OMX_ErrorInsufficientResources;
6732            }
6733            nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6734            input->pBuffer = (OMX_U8 *)nh;
6735        } else if (secure_mode || m_input_pass_buffer_fd) {
6736            /*Legacy method, pass ion fd stashed directly in pBuffer*/
6737            input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6738        } else {
6739            input->pBuffer           = (OMX_U8 *)buf_addr;
6740        }
6741        input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6742        input->nVersion.nVersion = OMX_SPEC_VERSION;
6743        input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6744        input->pAppPrivate       = appData;
6745        input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6746        input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6747
6748        if (drv_ctx.disable_dmx) {
6749            eRet = allocate_desc_buffer(i);
6750        }
6751    } else {
6752        DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6753        eRet = OMX_ErrorInsufficientResources;
6754    }
6755    return eRet;
6756}
6757
6758
6759/* ======================================================================
6760   FUNCTION
6761   omx_vdec::AllocateOutputBuffer
6762
6763   DESCRIPTION
6764   Helper fn for AllocateBuffer in the output pin
6765
6766   PARAMETERS
6767   <TBD>.
6768
6769   RETURN VALUE
6770   OMX Error None if everything went well.
6771
6772   ========================================================================== */
6773OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6774        OMX_IN OMX_HANDLETYPE            hComp,
6775        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6776        OMX_IN OMX_U32                   port,
6777        OMX_IN OMX_PTR                   appData,
6778        OMX_IN OMX_U32                   bytes)
6779{
6780    (void)hComp;
6781    (void)port;
6782    OMX_ERRORTYPE eRet = OMX_ErrorNone;
6783    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6784    unsigned                         i= 0; // Temporary counter
6785    struct vdec_setbuffer_cmd setbuffers;
6786    int extra_idx = 0;
6787#ifdef USE_ION
6788    int ion_device_fd =-1;
6789    struct ion_allocation_data ion_alloc_data;
6790    struct ion_fd_data fd_ion_data;
6791#endif
6792    if (!m_out_mem_ptr) {
6793        DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6794                drv_ctx.op_buf.actualcount,
6795                (unsigned int)drv_ctx.op_buf.buffer_size);
6796        int nBufHdrSize        = 0;
6797        int nPlatformEntrySize = 0;
6798        int nPlatformListSize  = 0;
6799        int nPMEMInfoSize = 0;
6800
6801        OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6802        OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6803        OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6804
6805        DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6806                drv_ctx.op_buf.actualcount);
6807        nBufHdrSize        = drv_ctx.op_buf.actualcount *
6808            sizeof(OMX_BUFFERHEADERTYPE);
6809
6810        nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6811            sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6812        nPlatformListSize  = drv_ctx.op_buf.actualcount *
6813            sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6814        nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6815            sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6816
6817        DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6818                (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6819                nPMEMInfoSize,
6820                nPlatformListSize);
6821        DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6822                drv_ctx.op_buf.actualcount);
6823        unsigned char *pmem_baseaddress_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {NULL};
6824        int pmem_fd[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {-1};
6825        int alloc_size[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {0};
6826        static const int block_max_size = 128 * 1024 * 1024;
6827        unsigned int block_buf_count = block_max_size / drv_ctx.op_buf.buffer_size;
6828        unsigned int last_block_buf_count = 0, block_count = 1;
6829        if (drv_ctx.op_buf.actualcount <= block_buf_count) {
6830            block_buf_count = drv_ctx.op_buf.actualcount;
6831        } else {
6832            last_block_buf_count = drv_ctx.op_buf.actualcount % block_buf_count;
6833            block_count = (drv_ctx.op_buf.actualcount + block_buf_count - 1) / block_buf_count;
6834        }
6835        unsigned int idx = 0;
6836        DEBUG_PRINT_LOW("block_count = %d block_buf_count = %d last_block_buf_count = %d",
6837            block_count, block_buf_count, last_block_buf_count);
6838#ifdef USE_ION
6839        struct vdec_ion op_buf_ion_info_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS];
6840        int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6841        for (; idx < block_count; idx++) {
6842            int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
6843                last_block_buf_count : block_buf_count;
6844            alloc_size[idx] = drv_ctx.op_buf.buffer_size * cnt;
6845            // Allocate output buffers as cached to improve performance of software-reading
6846            // of the YUVs. Output buffers are cache-invalidated in driver.
6847            // If color-conversion is involved, Only the C2D output buffers are cached, no
6848            // need to cache the decoder's output buffers
6849            op_buf_ion_info_temp[idx].ion_device_fd = alloc_map_ion_memory(
6850                    alloc_size[idx],
6851                    secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6852                    &op_buf_ion_info_temp[idx].ion_alloc_data, &op_buf_ion_info_temp[idx].fd_ion_data,
6853                    (secure_mode && !secure_scaling_to_non_secure_opb) ?
6854                    SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6855            if (op_buf_ion_info_temp[idx].ion_device_fd < 0) {
6856                DEBUG_PRINT_LOW("Failed to allocate chunk %ul size = %d", idx, alloc_size[idx]);
6857                break;
6858            }
6859            pmem_fd[idx] = op_buf_ion_info_temp[idx].fd_ion_data.fd;
6860            DEBUG_PRINT_LOW("Allocated chunk %ul fd = %ul size = %d", idx, pmem_fd[idx], alloc_size[idx]);
6861        }
6862        if (idx != block_count) {
6863            for (OMX_U32 i = 0; i < idx; i++) {
6864                close(pmem_fd[i]);
6865                free_ion_memory(&op_buf_ion_info_temp[i]);
6866            }
6867            return OMX_ErrorInsufficientResources;
6868        }
6869
6870#else
6871        for (idx = 0; idx < block_count; idx++) {
6872            pmem_fd[idx] = open (MEM_DEVICE,O_RDWR);
6873
6874            if (pmem_fd[idx] < 0) {
6875                DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6876                        drv_ctx.op_buf.buffer_size);
6877                break;
6878            }
6879            int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
6880                last_block_buf_count : block_buf_count;
6881            if (!align_pmem_buffers(pmem_fd[idx], drv_ctx.op_buf.buffer_size * cnt,
6882                        drv_ctx.op_buf.alignment)) {
6883                DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6884                close(pmem_fd[idx]);
6885                break;
6886            }
6887        }
6888        if (idx != block_count) {
6889            for (i = 0; i < idx; i++) {
6890                close(pmem_fd[i]);
6891            }
6892            return OMX_ErrorInsufficientResources;
6893        }
6894#endif
6895        if (!secure_mode) {
6896            idx = 0;
6897            for (; idx < block_count; idx++) {
6898                pmem_baseaddress_temp[idx] = (unsigned char *)mmap(NULL,
6899                        alloc_size[idx],
6900                        PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd[idx], 0);
6901
6902                if (pmem_baseaddress_temp[idx] == MAP_FAILED) {
6903                    DEBUG_PRINT_ERROR("MMAP failed for Size %u for fd = %d",
6904                            (unsigned int)alloc_size[idx], pmem_fd[idx]);
6905                    close(pmem_fd[idx]);
6906#ifdef USE_ION
6907                    free_ion_memory(&op_buf_ion_info_temp[idx]);
6908#endif
6909                    break;
6910                }
6911            }
6912            if (idx != block_count) {
6913                for (i = 0; i < idx; i++) {
6914                    munmap(pmem_baseaddress_temp[idx], alloc_size[idx]);
6915                    close(pmem_fd[i]);
6916#ifdef USE_ION
6917                    free_ion_memory(&op_buf_ion_info_temp[i]);
6918#endif
6919                }
6920                return OMX_ErrorInsufficientResources;
6921            }
6922        }
6923        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
6924        // Alloc mem for platform specific info
6925        char *pPtr=NULL;
6926        pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6927                nPMEMInfoSize,1);
6928        drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6929                       calloc (sizeof(struct vdec_bufferpayload),
6930                               drv_ctx.op_buf.actualcount);
6931        drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
6932                     calloc (sizeof (struct vdec_output_frameinfo),
6933                             drv_ctx.op_buf.actualcount);
6934        if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6935            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6936            return OMX_ErrorInsufficientResources;
6937        }
6938
6939#ifdef USE_ION
6940        drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6941                      calloc (sizeof(struct vdec_ion),
6942                              drv_ctx.op_buf.actualcount);
6943        if (!drv_ctx.op_buf_ion_info) {
6944            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6945            return OMX_ErrorInsufficientResources;
6946        }
6947#endif
6948        drv_ctx.op_buf_map_info = (struct vdec_ion_map_info *)\
6949                      calloc (sizeof(struct vdec_ion_map_info),
6950                              drv_ctx.op_buf.actualcount);
6951        if (!drv_ctx.op_buf_map_info) {
6952            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_map_info");
6953            return OMX_ErrorInsufficientResources;
6954        }
6955
6956        if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6957                && drv_ctx.ptr_respbuffer) {
6958            drv_ctx.ptr_outputbuffer[0].mmaped_size =
6959                (drv_ctx.op_buf.buffer_size *
6960                 drv_ctx.op_buf.actualcount);
6961            bufHdr          =  m_out_mem_ptr;
6962            m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6963            m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6964                (((char *) m_platform_list)  + nPlatformListSize);
6965            m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6966                (((char *) m_platform_entry) + nPlatformEntrySize);
6967            pPlatformList   = m_platform_list;
6968            pPlatformEntry  = m_platform_entry;
6969            pPMEMInfo       = m_pmem_info;
6970
6971            DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6972
6973            // Settting the entire storage nicely
6974            DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
6975            DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
6976            for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6977                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6978                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6979                // Set the values when we determine the right HxW param
6980                bufHdr->nAllocLen          = bytes;
6981                bufHdr->nFilledLen         = 0;
6982                bufHdr->pAppPrivate        = appData;
6983                bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
6984                // Platform specific PMEM Information
6985                // Initialize the Platform Entry
6986                //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6987                pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6988                pPlatformEntry->entry      = pPMEMInfo;
6989                // Initialize the Platform List
6990                pPlatformList->nEntries    = 1;
6991                pPlatformList->entryList   = pPlatformEntry;
6992                // Keep pBuffer NULL till vdec is opened
6993                bufHdr->pBuffer            = NULL;
6994                bufHdr->nOffset            = 0;
6995
6996                pPMEMInfo->offset          =  drv_ctx.op_buf.buffer_size*i;
6997                pPMEMInfo->pmem_fd = -1;
6998                bufHdr->pPlatformPrivate = pPlatformList;
6999
7000                int block_idx = i / block_buf_count;
7001                drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd[block_idx];
7002                m_pmem_info[i].pmem_fd = pmem_fd[block_idx];
7003#ifdef USE_ION
7004                drv_ctx.op_buf_ion_info[i].ion_device_fd = op_buf_ion_info_temp[block_idx].ion_device_fd;
7005                drv_ctx.op_buf_ion_info[i].ion_alloc_data = op_buf_ion_info_temp[block_idx].ion_alloc_data;
7006                drv_ctx.op_buf_ion_info[i].fd_ion_data = op_buf_ion_info_temp[block_idx].fd_ion_data;
7007#endif
7008                drv_ctx.op_buf_map_info[i].free_buffer = !(i % block_buf_count);
7009                drv_ctx.op_buf_map_info[i].base_address = pmem_baseaddress_temp[block_idx];
7010                drv_ctx.op_buf_map_info[i].map_size = alloc_size[block_idx];
7011                drv_ctx.op_buf_map_info[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7012
7013                /*Create a mapping between buffers*/
7014                bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7015                drv_ctx.ptr_respbuffer[i].client_data = (void *)\
7016                                    &drv_ctx.ptr_outputbuffer[i];
7017                drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7018                drv_ctx.ptr_outputbuffer[i].bufferaddr =
7019                    pmem_baseaddress_temp[block_idx] + (drv_ctx.op_buf.buffer_size * (i % block_buf_count));
7020                m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
7021                m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
7022                m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
7023
7024                DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
7025                        pmem_fd[block_idx], (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
7026                        drv_ctx.ptr_outputbuffer[i].bufferaddr);
7027                // Move the buffer and buffer header pointers
7028                bufHdr++;
7029                pPMEMInfo++;
7030                pPlatformEntry++;
7031                pPlatformList++;
7032            }
7033        } else {
7034            DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7035                    m_out_mem_ptr, pPtr);
7036            if (m_out_mem_ptr) {
7037                free(m_out_mem_ptr);
7038                m_out_mem_ptr = NULL;
7039            }
7040            if (pPtr) {
7041                free(pPtr);
7042                pPtr = NULL;
7043            }
7044            if (drv_ctx.ptr_outputbuffer) {
7045                free(drv_ctx.ptr_outputbuffer);
7046                drv_ctx.ptr_outputbuffer = NULL;
7047            }
7048            if (drv_ctx.ptr_respbuffer) {
7049                free(drv_ctx.ptr_respbuffer);
7050                drv_ctx.ptr_respbuffer = NULL;
7051            }
7052#ifdef USE_ION
7053            if (drv_ctx.op_buf_ion_info) {
7054                DEBUG_PRINT_LOW("Free o/p ion context");
7055                free(drv_ctx.op_buf_ion_info);
7056                drv_ctx.op_buf_ion_info = NULL;
7057            }
7058#endif
7059            free(drv_ctx.op_buf_map_info);
7060            drv_ctx.op_buf_map_info = NULL;
7061           eRet =  OMX_ErrorInsufficientResources;
7062        }
7063        if (eRet == OMX_ErrorNone)
7064            eRet = allocate_extradata();
7065    }
7066
7067    for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
7068        if (BITMASK_ABSENT(&m_out_bm_count,i)) {
7069            DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
7070            break;
7071        }
7072    }
7073
7074    if (eRet == OMX_ErrorNone) {
7075        if (i < drv_ctx.op_buf.actualcount) {
7076            struct v4l2_buffer buf;
7077            struct v4l2_plane plane[VIDEO_MAX_PLANES];
7078            int rc;
7079            m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
7080
7081            drv_ctx.ptr_outputbuffer[i].buffer_len =
7082                drv_ctx.op_buf.buffer_size;
7083
7084            *bufferHdr = (m_out_mem_ptr + i );
7085            if (secure_mode) {
7086#ifdef USE_ION
7087                drv_ctx.ptr_outputbuffer[i].bufferaddr =
7088                    (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7089#else
7090                drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
7091#endif
7092            }
7093            drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
7094
7095            buf.index = i;
7096            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7097            buf.memory = V4L2_MEMORY_USERPTR;
7098            plane[0].length = drv_ctx.op_buf.buffer_size;
7099            plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
7100                (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
7101#ifdef USE_ION
7102            plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7103#endif
7104            plane[0].reserved[1] = drv_ctx.op_buf_map_info[i].offset;
7105            plane[0].data_offset = 0;
7106            extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7107            if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7108                plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7109                plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
7110#ifdef USE_ION
7111                plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7112#endif
7113                plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
7114                plane[extra_idx].data_offset = 0;
7115            } else if (extra_idx >= VIDEO_MAX_PLANES) {
7116                DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
7117                return OMX_ErrorBadParameter;
7118            }
7119            buf.m.planes = plane;
7120            buf.length = drv_ctx.num_planes;
7121            DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
7122            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
7123            if (rc) {
7124                /*TODO: How to handle this case */
7125                return OMX_ErrorInsufficientResources;
7126            }
7127
7128            if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
7129                enum v4l2_buf_type buf_type;
7130                buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7131                rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7132                if (rc) {
7133                    return OMX_ErrorInsufficientResources;
7134                } else {
7135                    streaming[CAPTURE_PORT] = true;
7136                    DEBUG_PRINT_LOW("STREAMON Successful");
7137                }
7138
7139                DEBUG_PRINT_HIGH("Enabling Turbo mode");
7140                request_perf_level(VIDC_TURBO);
7141            }
7142
7143            (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
7144            (*bufferHdr)->pAppPrivate = appData;
7145            BITMASK_SET(&m_out_bm_count,i);
7146        } else {
7147            DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
7148            eRet = OMX_ErrorInsufficientResources;
7149        }
7150    }
7151
7152    return eRet;
7153}
7154
7155
7156// AllocateBuffer  -- API Call
7157/* ======================================================================
7158   FUNCTION
7159   omx_vdec::AllocateBuffer
7160
7161   DESCRIPTION
7162   Returns zero if all the buffers released..
7163
7164   PARAMETERS
7165   None.
7166
7167   RETURN VALUE
7168   true/false
7169
7170   ========================================================================== */
7171OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
7172        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7173        OMX_IN OMX_U32                        port,
7174        OMX_IN OMX_PTR                     appData,
7175        OMX_IN OMX_U32                       bytes)
7176{
7177    unsigned i = 0;
7178    OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
7179
7180    DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
7181    if (m_state == OMX_StateInvalid) {
7182        DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
7183        return OMX_ErrorInvalidState;
7184    }
7185
7186    if (port == OMX_CORE_INPUT_PORT_INDEX) {
7187        // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
7188        // ensure that use-buffer was never called.
7189        // Mix-and-match of useBuffer and allocateBuffer is not allowed
7190        if (m_inp_mem_ptr && input_use_buffer) {
7191            DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
7192            return OMX_ErrorUndefined;
7193        }
7194        if (arbitrary_bytes) {
7195            eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
7196        } else {
7197            eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
7198        }
7199    } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7200        eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
7201                appData,bytes);
7202    } else {
7203        DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
7204        eRet = OMX_ErrorBadPortIndex;
7205    }
7206    DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
7207    if (eRet == OMX_ErrorNone) {
7208        if (allocate_done()) {
7209            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
7210                // Send the callback now
7211                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
7212                post_event(OMX_CommandStateSet,OMX_StateIdle,
7213                        OMX_COMPONENT_GENERATE_EVENT);
7214            }
7215        }
7216        if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
7217            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
7218                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
7219                post_event(OMX_CommandPortEnable,
7220                        OMX_CORE_INPUT_PORT_INDEX,
7221                        OMX_COMPONENT_GENERATE_EVENT);
7222            }
7223        }
7224        if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
7225            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
7226                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
7227                post_event(OMX_CommandPortEnable,
7228                        OMX_CORE_OUTPUT_PORT_INDEX,
7229                        OMX_COMPONENT_GENERATE_EVENT);
7230            }
7231        }
7232    }
7233    DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
7234    return eRet;
7235}
7236
7237// Free Buffer - API call
7238/* ======================================================================
7239   FUNCTION
7240   omx_vdec::FreeBuffer
7241
7242   DESCRIPTION
7243
7244   PARAMETERS
7245   None.
7246
7247   RETURN VALUE
7248   true/false
7249
7250   ========================================================================== */
7251OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7252        OMX_IN OMX_U32                 port,
7253        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7254{
7255    OMX_ERRORTYPE eRet = OMX_ErrorNone;
7256    unsigned int nPortIndex;
7257    (void) hComp;
7258    DEBUG_PRINT_LOW("In for decoder free_buffer");
7259
7260    if (m_state == OMX_StateIdle &&
7261            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7262        DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
7263    } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
7264            (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
7265        DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
7266    } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
7267                BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
7268            (port == OMX_CORE_OUTPUT_PORT_INDEX &&
7269             BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
7270        DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
7271    } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
7272        DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
7273        post_event(OMX_EventError,
7274                OMX_ErrorPortUnpopulated,
7275                OMX_COMPONENT_GENERATE_EVENT);
7276
7277        return OMX_ErrorIncorrectStateOperation;
7278    } else if (m_state != OMX_StateInvalid) {
7279        DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
7280        post_event(OMX_EventError,
7281                OMX_ErrorPortUnpopulated,
7282                OMX_COMPONENT_GENERATE_EVENT);
7283    }
7284
7285    if (port == OMX_CORE_INPUT_PORT_INDEX) {
7286        /*Check if arbitrary bytes*/
7287        if (!arbitrary_bytes && !input_use_buffer)
7288            nPortIndex = buffer - m_inp_mem_ptr;
7289        else
7290            nPortIndex = buffer - m_inp_heap_ptr;
7291
7292        DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
7293        if (nPortIndex < drv_ctx.ip_buf.actualcount &&
7294                BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
7295            // Clear the bit associated with it.
7296            BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
7297            BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
7298            if (input_use_buffer == true) {
7299
7300                DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
7301                if (m_phdr_pmem_ptr)
7302                    free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
7303            } else {
7304                if (arbitrary_bytes) {
7305                    if (m_phdr_pmem_ptr)
7306                        free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
7307                    else
7308                        free_input_buffer(nPortIndex,NULL);
7309                } else
7310                    free_input_buffer(buffer);
7311            }
7312            m_inp_bPopulated = OMX_FALSE;
7313            if(release_input_done())
7314                release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
7315            /*Free the Buffer Header*/
7316            if (release_input_done()) {
7317                DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
7318                free_input_buffer_header();
7319            }
7320        } else {
7321            DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
7322            eRet = OMX_ErrorBadPortIndex;
7323        }
7324
7325        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
7326                && release_input_done()) {
7327            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7328            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
7329            post_event(OMX_CommandPortDisable,
7330                    OMX_CORE_INPUT_PORT_INDEX,
7331                    OMX_COMPONENT_GENERATE_EVENT);
7332        }
7333    } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7334        // check if the buffer is valid
7335        nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7336        if (nPortIndex < drv_ctx.op_buf.actualcount &&
7337                BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
7338            DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
7339            // Clear the bit associated with it.
7340            BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
7341            m_out_bPopulated = OMX_FALSE;
7342            client_buffers.free_output_buffer (buffer);
7343
7344            if(release_output_done()) {
7345                release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
7346            }
7347            if (release_output_done()) {
7348                free_output_buffer_header();
7349            }
7350        } else {
7351            DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
7352            eRet = OMX_ErrorBadPortIndex;
7353        }
7354        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
7355                && release_output_done()) {
7356            DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
7357
7358            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7359            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
7360#ifdef _ANDROID_ICS_
7361            if (m_enable_android_native_buffers) {
7362                DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
7363                memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7364            }
7365#endif
7366
7367            post_event(OMX_CommandPortDisable,
7368                    OMX_CORE_OUTPUT_PORT_INDEX,
7369                    OMX_COMPONENT_GENERATE_EVENT);
7370        }
7371    } else {
7372        eRet = OMX_ErrorBadPortIndex;
7373    }
7374    if ((eRet == OMX_ErrorNone) &&
7375            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7376        if (release_done()) {
7377            /*
7378             * Reset buffer requirements here to ensure setting buffer requirement
7379             * when component move to executing state from loaded state via idle.
7380             */
7381            drv_ctx.op_buf.buffer_size = 0;
7382            drv_ctx.op_buf.actualcount = 0;
7383
7384            // Send the callback now
7385            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
7386            post_event(OMX_CommandStateSet, OMX_StateLoaded,
7387                    OMX_COMPONENT_GENERATE_EVENT);
7388        }
7389    }
7390    return eRet;
7391}
7392
7393
7394/* ======================================================================
7395   FUNCTION
7396   omx_vdec::EmptyThisBuffer
7397
7398   DESCRIPTION
7399   This routine is used to push the encoded video frames to
7400   the video decoder.
7401
7402   PARAMETERS
7403   None.
7404
7405   RETURN VALUE
7406   OMX Error None if everything went successful.
7407
7408   ========================================================================== */
7409OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7410        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7411{
7412    OMX_ERRORTYPE ret1 = OMX_ErrorNone;
7413    unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
7414
7415    if (m_state != OMX_StateExecuting &&
7416            m_state != OMX_StatePause &&
7417            m_state != OMX_StateIdle) {
7418        DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
7419        return OMX_ErrorInvalidState;
7420    }
7421
7422    if (buffer == NULL) {
7423        DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
7424        return OMX_ErrorBadParameter;
7425    }
7426
7427    if (!m_inp_bEnabled) {
7428        DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7429        return OMX_ErrorIncorrectStateOperation;
7430    }
7431
7432    if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7433        DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7434        return OMX_ErrorBadPortIndex;
7435    }
7436
7437    if (perf_flag) {
7438        if (!latency) {
7439            dec_time.stop();
7440            latency = dec_time.processing_time_us();
7441            dec_time.start();
7442        }
7443    }
7444
7445    if (arbitrary_bytes) {
7446        nBufferIndex = buffer - m_inp_heap_ptr;
7447    } else {
7448        if (input_use_buffer == true) {
7449            nBufferIndex = buffer - m_inp_heap_ptr;
7450            if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7451                DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7452                return OMX_ErrorBadParameter;
7453            }
7454            m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7455            m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7456            m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7457            buffer = &m_inp_mem_ptr[nBufferIndex];
7458            DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7459                    &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7460        } else {
7461            nBufferIndex = buffer - m_inp_mem_ptr;
7462        }
7463    }
7464
7465    if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7466        DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7467        return OMX_ErrorBadParameter;
7468    }
7469
7470    if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7471        codec_config_flag = true;
7472        DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7473    }
7474
7475    /* The client should not set this when codec is in arbitrary bytes mode */
7476    if (m_input_pass_buffer_fd) {
7477        buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7478    }
7479
7480    DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7481            buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7482    if (arbitrary_bytes) {
7483        post_event ((unsigned long)hComp,(unsigned long)buffer,
7484                OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7485    } else {
7486        post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7487    }
7488    time_stamp_dts.insert_timestamp(buffer);
7489    return OMX_ErrorNone;
7490}
7491
7492/* ======================================================================
7493   FUNCTION
7494   omx_vdec::empty_this_buffer_proxy
7495
7496   DESCRIPTION
7497   This routine is used to push the encoded video frames to
7498   the video decoder.
7499
7500   PARAMETERS
7501   None.
7502
7503   RETURN VALUE
7504   OMX Error None if everything went successful.
7505
7506   ========================================================================== */
7507OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
7508        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7509{
7510    VIDC_TRACE_NAME_HIGH("ETB");
7511    (void) hComp;
7512    int push_cnt = 0,i=0;
7513    unsigned nPortIndex = 0;
7514    OMX_ERRORTYPE ret = OMX_ErrorNone;
7515    struct vdec_input_frameinfo frameinfo;
7516    struct vdec_bufferpayload *temp_buffer;
7517    struct vdec_seqheader seq_header;
7518    bool port_setting_changed = true;
7519
7520    /*Should we generate a Aync error event*/
7521    if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7522        DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7523        return OMX_ErrorBadParameter;
7524    }
7525
7526    nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7527
7528    if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7529        DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7530                nPortIndex);
7531        return OMX_ErrorBadParameter;
7532    }
7533
7534    pending_input_buffers++;
7535    VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
7536
7537    /* return zero length and not an EOS buffer */
7538    if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7539            ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7540        DEBUG_PRINT_HIGH("return zero legth buffer");
7541        post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7542                OMX_COMPONENT_GENERATE_EBD);
7543        return OMX_ErrorNone;
7544    }
7545
7546    if (input_flush_progress == true) {
7547        DEBUG_PRINT_LOW("Flush in progress return buffer ");
7548        post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7549                OMX_COMPONENT_GENERATE_EBD);
7550        return OMX_ErrorNone;
7551    }
7552
7553    auto_lock l(buf_lock);
7554    temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7555
7556    if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7557        return OMX_ErrorBadParameter;
7558    }
7559    /* If its first frame, H264 codec and reject is true, then parse the nal
7560       and get the profile. Based on this, reject the clip playback */
7561    if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
7562            m_reject_avc_1080p_mp) {
7563        first_frame = 1;
7564        DEBUG_PRINT_ERROR("Parse nal to get the profile");
7565        h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
7566                NALU_TYPE_SPS);
7567        m_profile = h264_parser->get_profile();
7568        ret = is_video_session_supported();
7569        if (ret) {
7570            post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7571            post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7572            /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7573            m_state = OMX_StateInvalid;
7574            return OMX_ErrorNone;
7575        }
7576    }
7577
7578    VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7579    VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7580    DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7581    /*for use buffer we need to memcpy the data*/
7582    temp_buffer->buffer_len = buffer->nFilledLen;
7583
7584    if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7585        if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7586            if (arbitrary_bytes) {
7587                memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7588            } else {
7589                memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7590                        buffer->nFilledLen);
7591            }
7592        } else {
7593            return OMX_ErrorBadParameter;
7594        }
7595
7596    }
7597
7598    frameinfo.bufferaddr = temp_buffer->bufferaddr;
7599    frameinfo.client_data = (void *) buffer;
7600    frameinfo.datalen = temp_buffer->buffer_len;
7601    frameinfo.flags = 0;
7602    frameinfo.offset = buffer->nOffset;
7603    frameinfo.pmem_fd = temp_buffer->pmem_fd;
7604    frameinfo.pmem_offset = temp_buffer->offset;
7605    frameinfo.timestamp = buffer->nTimeStamp;
7606    if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7607        DEBUG_PRINT_LOW("ETB: dmx enabled");
7608        if (m_demux_entries == 0) {
7609            extract_demux_addr_offsets(buffer);
7610        }
7611
7612        DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7613        handle_demux_data(buffer);
7614        frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7615        frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7616    } else {
7617        frameinfo.desc_addr = NULL;
7618        frameinfo.desc_size = 0;
7619    }
7620    if (!arbitrary_bytes) {
7621        frameinfo.flags |= buffer->nFlags;
7622    }
7623
7624#ifdef _ANDROID_
7625    if (m_debug_timestamp) {
7626        if (arbitrary_bytes) {
7627            DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7628            m_timestamp_list.insert_ts(buffer->nTimeStamp);
7629        } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7630            DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7631            m_timestamp_list.insert_ts(buffer->nTimeStamp);
7632        }
7633    }
7634#endif
7635
7636    log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7637
7638if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7639        frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7640        buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7641    }
7642
7643    if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7644        DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7645        frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7646        h264_scratch.nFilledLen = 0;
7647        nal_count = 0;
7648        look_ahead_nal = false;
7649        frame_count = 0;
7650        if (m_frame_parser.mutils)
7651            m_frame_parser.mutils->initialize_frame_checking_environment();
7652        m_frame_parser.flush();
7653        h264_last_au_ts = LLONG_MAX;
7654        h264_last_au_flags = 0;
7655        memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7656        m_demux_entries = 0;
7657    }
7658    struct v4l2_buffer buf;
7659    struct v4l2_plane plane;
7660    memset( (void *)&buf, 0, sizeof(buf));
7661    memset( (void *)&plane, 0, sizeof(plane));
7662    int rc;
7663    unsigned long  print_count;
7664    if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7665        buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7666        DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7667    }
7668    OMX_ERRORTYPE eRet = OMX_ErrorNone;
7669    buf.index = nPortIndex;
7670    buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7671    buf.memory = V4L2_MEMORY_USERPTR;
7672    plane.bytesused = temp_buffer->buffer_len;
7673    plane.length = drv_ctx.ip_buf.buffer_size;
7674    plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7675        (unsigned long)temp_buffer->offset;
7676    plane.reserved[0] = temp_buffer->pmem_fd;
7677    plane.reserved[1] = temp_buffer->offset;
7678    plane.data_offset = 0;
7679    buf.m.planes = &plane;
7680    buf.length = 1;
7681    if (frameinfo.timestamp >= LLONG_MAX) {
7682        buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7683    }
7684    //assumption is that timestamp is in milliseconds
7685    buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7686    buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7687    buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7688    buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7689
7690    if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7691        DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7692        android_atomic_inc(&m_queued_codec_config_count);
7693    }
7694
7695    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7696    if (rc) {
7697        DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7698        m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7699        return OMX_ErrorHardware;
7700    }
7701
7702    if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7703        codec_config_flag = false;
7704    }
7705    if (!streaming[OUTPUT_PORT]) {
7706        enum v4l2_buf_type buf_type;
7707        int ret,r;
7708
7709        buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7710        DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7711        ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7712        if (!ret) {
7713            DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7714            streaming[OUTPUT_PORT] = true;
7715        } else if (errno == EBUSY) {
7716            DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7717            post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7718                    OMX_COMPONENT_GENERATE_EBD);
7719            return OMX_ErrorInsufficientResources;
7720        } else {
7721            DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7722            DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7723            post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7724                    OMX_COMPONENT_GENERATE_EBD);
7725            return OMX_ErrorBadParameter;
7726        }
7727    }
7728    DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7729            frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7730            (unsigned int)frameinfo.datalen);
7731
7732    return ret;
7733}
7734
7735/* ======================================================================
7736   FUNCTION
7737   omx_vdec::FillThisBuffer
7738
7739   DESCRIPTION
7740   IL client uses this method to release the frame buffer
7741   after displaying them.
7742
7743   PARAMETERS
7744   None.
7745
7746   RETURN VALUE
7747   true/false
7748
7749   ========================================================================== */
7750OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7751        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7752{
7753    if (m_state != OMX_StateExecuting &&
7754            m_state != OMX_StatePause &&
7755            m_state != OMX_StateIdle) {
7756        DEBUG_PRINT_ERROR("FTB in Invalid State");
7757        return OMX_ErrorInvalidState;
7758    }
7759
7760    if (!m_out_bEnabled) {
7761        DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7762        return OMX_ErrorIncorrectStateOperation;
7763    }
7764
7765    unsigned nPortIndex = 0;
7766    if (dynamic_buf_mode) {
7767        private_handle_t *handle = NULL;
7768        struct VideoDecoderOutputMetaData *meta;
7769        unsigned int nPortIndex = 0;
7770
7771        if (!buffer || !buffer->pBuffer) {
7772            DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7773            return OMX_ErrorBadParameter;
7774        }
7775
7776        //get the buffer type and fd info
7777        meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7778        handle = (private_handle_t *)meta->pHandle;
7779        DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7780
7781        if (!handle) {
7782            DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7783            return OMX_ErrorBadParameter;
7784        }
7785        //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7786        nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7787        if (nPortIndex < drv_ctx.op_buf.actualcount &&
7788            nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7789            drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7790            drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7791
7792           //Store private handle from GraphicBuffer
7793            native_buffer[nPortIndex].privatehandle = handle;
7794            native_buffer[nPortIndex].nativehandle = handle;
7795        } else {
7796            DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7797            return OMX_ErrorBadParameter;
7798        }
7799
7800        //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7801        //this with a more sane size so that we don't compensate in rest of code
7802        //We'll restore this size later on, so that it's transparent to client
7803        buffer->nFilledLen = 0;
7804        buffer->nAllocLen = handle->size;
7805
7806        if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
7807            m_is_display_session = true;
7808        } else {
7809            m_is_display_session = false;
7810        }
7811        DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
7812
7813        drv_ctx.op_buf.buffer_size = handle->size;
7814    }
7815
7816    nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7817    if (buffer == NULL ||
7818            (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7819        DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7820            nPortIndex, drv_ctx.op_buf.actualcount);
7821        return OMX_ErrorBadParameter;
7822    }
7823
7824    if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7825        DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7826        return OMX_ErrorBadPortIndex;
7827    }
7828
7829    DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7830    post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7831    return OMX_ErrorNone;
7832}
7833/* ======================================================================
7834   FUNCTION
7835   omx_vdec::fill_this_buffer_proxy
7836
7837   DESCRIPTION
7838   IL client uses this method to release the frame buffer
7839   after displaying them.
7840
7841   PARAMETERS
7842   None.
7843
7844   RETURN VALUE
7845   true/false
7846
7847   ========================================================================== */
7848OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
7849        OMX_IN OMX_HANDLETYPE        hComp,
7850        OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7851{
7852    VIDC_TRACE_NAME_HIGH("FTB");
7853    OMX_ERRORTYPE nRet = OMX_ErrorNone;
7854    OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7855    unsigned nPortIndex = 0;
7856    struct vdec_fillbuffer_cmd fillbuffer;
7857    struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
7858    struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
7859
7860    nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7861
7862    if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
7863        DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7864            nPortIndex, drv_ctx.op_buf.actualcount);
7865        return OMX_ErrorBadParameter;
7866    }
7867
7868    DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
7869            bufferAdd, bufferAdd->pBuffer);
7870    /*Return back the output buffer to client*/
7871    if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
7872        DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7873        buffer->nFilledLen = 0;
7874        m_cb.FillBufferDone (hComp,m_app_data,buffer);
7875        return OMX_ErrorNone;
7876    }
7877
7878    if (dynamic_buf_mode) {
7879        drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7880        drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7881        buf_ref_add(nPortIndex);
7882        drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7883    }
7884
7885    pending_output_buffers++;
7886    VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7887    buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7888    if (!buffer) {
7889       DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7890       return OMX_ErrorBadParameter;
7891    }
7892    ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7893    if (ptr_respbuffer) {
7894        ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7895    }
7896
7897    if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7898        DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
7899        buffer->nFilledLen = 0;
7900        m_cb.FillBufferDone (hComp,m_app_data,buffer);
7901        pending_output_buffers--;
7902        VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7903        return OMX_ErrorBadParameter;
7904    }
7905
7906    int rc = 0;
7907    struct v4l2_buffer buf;
7908    struct v4l2_plane plane[VIDEO_MAX_PLANES];
7909    memset( (void *)&buf, 0, sizeof(buf));
7910    memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7911    unsigned int extra_idx = 0;
7912
7913    buf.index = nPortIndex;
7914    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7915    buf.memory = V4L2_MEMORY_USERPTR;
7916    plane[0].bytesused = buffer->nFilledLen;
7917    plane[0].length = buffer->nAllocLen;
7918    plane[0].m.userptr =
7919        (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7920        (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7921    plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7922    plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7923    plane[0].data_offset = 0;
7924    extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7925    if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7926        plane[extra_idx].bytesused = 0;
7927        plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7928        plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7929#ifdef USE_ION
7930        plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7931#endif
7932        plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7933        plane[extra_idx].data_offset = 0;
7934    } else if (extra_idx >= VIDEO_MAX_PLANES) {
7935        DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7936        return OMX_ErrorBadParameter;
7937    }
7938    buf.m.planes = plane;
7939    buf.length = drv_ctx.num_planes;
7940    DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
7941             plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
7942
7943    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7944    if (rc) {
7945        buffer->nFilledLen = 0;
7946        DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
7947        m_cb.FillBufferDone(hComp, m_app_data, buffer);
7948        return OMX_ErrorHardware;
7949    }
7950
7951    return OMX_ErrorNone;
7952}
7953
7954/* ======================================================================
7955   FUNCTION
7956   omx_vdec::SetCallbacks
7957
7958   DESCRIPTION
7959   Set the callbacks.
7960
7961   PARAMETERS
7962   None.
7963
7964   RETURN VALUE
7965   OMX Error None if everything successful.
7966
7967   ========================================================================== */
7968OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
7969        OMX_IN OMX_CALLBACKTYPE* callbacks,
7970        OMX_IN OMX_PTR             appData)
7971{
7972    (void) hComp;
7973    m_cb       = *callbacks;
7974    DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7975            m_cb.EventHandler,m_cb.FillBufferDone);
7976    m_app_data =    appData;
7977    return OMX_ErrorNotImplemented;
7978}
7979
7980/* ======================================================================
7981   FUNCTION
7982   omx_vdec::ComponentDeInit
7983
7984   DESCRIPTION
7985   Destroys the component and release memory allocated to the heap.
7986
7987   PARAMETERS
7988   <TBD>.
7989
7990   RETURN VALUE
7991   OMX Error None if everything successful.
7992
7993   ========================================================================== */
7994OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7995{
7996   (void) hComp;
7997
7998    unsigned i = 0;
7999    if (OMX_StateLoaded != m_state) {
8000        DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
8001                m_state);
8002        DEBUG_PRINT_ERROR("Playback Ended - FAILED");
8003    } else {
8004        DEBUG_PRINT_HIGH("Playback Ended - PASSED");
8005    }
8006
8007    /*Check if the output buffers have to be cleaned up*/
8008    if (m_out_mem_ptr) {
8009        DEBUG_PRINT_LOW("Freeing the Output Memory");
8010        for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
8011            if (BITMASK_PRESENT(&m_out_bm_count, i)) {
8012                BITMASK_CLEAR(&m_out_bm_count, i);
8013                client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
8014            }
8015
8016            if (release_output_done()) {
8017                break;
8018            }
8019        }
8020#ifdef _ANDROID_ICS_
8021        memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
8022#endif
8023    }
8024
8025    /*Check if the input buffers have to be cleaned up*/
8026    if (m_inp_mem_ptr || m_inp_heap_ptr) {
8027        DEBUG_PRINT_LOW("Freeing the Input Memory");
8028        for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
8029
8030            if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
8031                BITMASK_CLEAR(&m_inp_bm_count, i);
8032                if (m_inp_mem_ptr)
8033                    free_input_buffer (i,&m_inp_mem_ptr[i]);
8034                else
8035                    free_input_buffer (i,NULL);
8036            }
8037
8038            if (release_input_done()) {
8039                break;
8040            }
8041       }
8042    }
8043    free_input_buffer_header();
8044    free_output_buffer_header();
8045    if (h264_scratch.pBuffer) {
8046        free(h264_scratch.pBuffer);
8047        h264_scratch.pBuffer = NULL;
8048    }
8049
8050    if (h264_parser) {
8051        delete h264_parser;
8052        h264_parser = NULL;
8053    }
8054
8055    if (m_frame_parser.mutils) {
8056        DEBUG_PRINT_LOW("Free utils parser");
8057        delete (m_frame_parser.mutils);
8058        m_frame_parser.mutils = NULL;
8059    }
8060
8061    if (m_platform_list) {
8062        free(m_platform_list);
8063        m_platform_list = NULL;
8064    }
8065    if (m_vendor_config.pData) {
8066        free(m_vendor_config.pData);
8067        m_vendor_config.pData = NULL;
8068    }
8069
8070    // Reset counters in mesg queues
8071    m_ftb_q.m_size=0;
8072    m_cmd_q.m_size=0;
8073    m_etb_q.m_size=0;
8074    m_ftb_q.m_read = m_ftb_q.m_write =0;
8075    m_cmd_q.m_read = m_cmd_q.m_write =0;
8076    m_etb_q.m_read = m_etb_q.m_write =0;
8077#ifdef _ANDROID_
8078    if (m_debug_timestamp) {
8079        m_timestamp_list.reset_ts_list();
8080    }
8081#endif
8082
8083    DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
8084    //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
8085    // NULL);
8086    DEBUG_PRINT_HIGH("Close the driver instance");
8087
8088    if (m_debug.infile) {
8089        fclose(m_debug.infile);
8090        m_debug.infile = NULL;
8091    }
8092    if (m_debug.outfile) {
8093        fclose(m_debug.outfile);
8094        m_debug.outfile = NULL;
8095    }
8096    if (m_debug.out_ymeta_file) {
8097        fclose(m_debug.out_ymeta_file);
8098        m_debug.out_ymeta_file = NULL;
8099    }
8100    if (m_debug.out_uvmeta_file) {
8101        fclose(m_debug.out_uvmeta_file);
8102        m_debug.out_uvmeta_file = NULL;
8103    }
8104#ifdef OUTPUT_EXTRADATA_LOG
8105    if (outputExtradataFile)
8106        fclose (outputExtradataFile);
8107#endif
8108    DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
8109    return OMX_ErrorNone;
8110}
8111
8112/* ======================================================================
8113   FUNCTION
8114   omx_vdec::UseEGLImage
8115
8116   DESCRIPTION
8117   OMX Use EGL Image method implementation <TBD>.
8118
8119   PARAMETERS
8120   <TBD>.
8121
8122   RETURN VALUE
8123   Not Implemented error.
8124
8125   ========================================================================== */
8126OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
8127        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
8128        OMX_IN OMX_U32                        port,
8129        OMX_IN OMX_PTR                     appData,
8130        OMX_IN void*                      eglImage)
8131{
8132    (void) appData;
8133    OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
8134    OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
8135    OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
8136
8137#ifdef USE_EGL_IMAGE_GPU
8138    PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
8139    EGLint fd = -1, offset = 0,pmemPtr = 0;
8140#else
8141    int fd = -1, offset = 0;
8142#endif
8143    DEBUG_PRINT_HIGH("use EGL image support for decoder");
8144    if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
8145        DEBUG_PRINT_ERROR("Invalid EGL image");
8146    }
8147#ifdef USE_EGL_IMAGE_GPU
8148    if (m_display_id == NULL) {
8149        DEBUG_PRINT_ERROR("Display ID is not set by IL client");
8150        return OMX_ErrorInsufficientResources;
8151    }
8152    egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
8153        eglGetProcAddress("eglQueryImageKHR");
8154    egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
8155    egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
8156    egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
8157#else //with OMX test app
8158    struct temp_egl {
8159        int pmem_fd;
8160        int offset;
8161    };
8162    struct temp_egl *temp_egl_id = NULL;
8163    void * pmemPtr = (void *) eglImage;
8164    temp_egl_id = (struct temp_egl *)eglImage;
8165    if (temp_egl_id != NULL) {
8166        fd = temp_egl_id->pmem_fd;
8167        offset = temp_egl_id->offset;
8168    }
8169#endif
8170    if (fd < 0) {
8171        DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
8172        return OMX_ErrorInsufficientResources;
8173    }
8174    pmem_info.pmem_fd = (OMX_U32) fd;
8175    pmem_info.offset = (OMX_U32) offset;
8176    pmem_entry.entry = (void *) &pmem_info;
8177    pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8178    pmem_list.entryList = &pmem_entry;
8179    pmem_list.nEntries = 1;
8180    ouput_egl_buffers = true;
8181    if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
8182                (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
8183                (OMX_U8 *)pmemPtr)) {
8184        DEBUG_PRINT_ERROR("use buffer call failed for egl image");
8185        return OMX_ErrorInsufficientResources;
8186    }
8187    return OMX_ErrorNone;
8188}
8189
8190/* ======================================================================
8191   FUNCTION
8192   omx_vdec::ComponentRoleEnum
8193
8194   DESCRIPTION
8195   OMX Component Role Enum method implementation.
8196
8197   PARAMETERS
8198   <TBD>.
8199
8200   RETURN VALUE
8201   OMX Error None if everything is successful.
8202   ========================================================================== */
8203OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
8204        OMX_OUT OMX_U8*        role,
8205        OMX_IN OMX_U32        index)
8206{
8207    (void) hComp;
8208    OMX_ERRORTYPE eRet = OMX_ErrorNone;
8209
8210    if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
8211        if ((0 == index) && role) {
8212            strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
8213            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8214        } else {
8215            eRet = OMX_ErrorNoMore;
8216        }
8217    }
8218    if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
8219        if ((0 == index) && role) {
8220            strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
8221            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8222        } else {
8223            eRet = OMX_ErrorNoMore;
8224        }
8225    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
8226        if ((0 == index) && role) {
8227            strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
8228            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8229        } else {
8230            DEBUG_PRINT_LOW("No more roles");
8231            eRet = OMX_ErrorNoMore;
8232        }
8233    }
8234
8235    else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
8236            (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
8237        if ((0 == index) && role) {
8238            strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
8239            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8240        } else {
8241            DEBUG_PRINT_LOW("No more roles");
8242            eRet = OMX_ErrorNoMore;
8243        }
8244    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
8245        if ((0 == index) && role) {
8246            strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
8247            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8248        } else {
8249            DEBUG_PRINT_LOW("No more roles");
8250            eRet = OMX_ErrorNoMore;
8251        }
8252    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
8253        if ((0 == index) && role) {
8254            strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
8255            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8256        } else {
8257            DEBUG_PRINT_LOW("No more roles");
8258            eRet = OMX_ErrorNoMore;
8259        }
8260    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
8261        if ((0 == index) && role) {
8262            strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
8263            DEBUG_PRINT_LOW("component_role_enum: role %s", role);
8264        } else {
8265            DEBUG_PRINT_LOW("No more roles");
8266            eRet = OMX_ErrorNoMore;
8267        }
8268    } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
8269            (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
8270          ) {
8271        if ((0 == index) && role) {
8272            strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
8273            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8274        } else {
8275            DEBUG_PRINT_LOW("No more roles");
8276            eRet = OMX_ErrorNoMore;
8277        }
8278    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
8279        if ((0 == index) && role) {
8280            strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
8281            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8282        } else {
8283            DEBUG_PRINT_LOW("No more roles");
8284            eRet = OMX_ErrorNoMore;
8285        }
8286    } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
8287        if ((0 == index) && role) {
8288            strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
8289            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8290        } else {
8291            DEBUG_PRINT_LOW("No more roles");
8292            eRet = OMX_ErrorNoMore;
8293        }
8294    } else {
8295        DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
8296        eRet = OMX_ErrorInvalidComponentName;
8297    }
8298    return eRet;
8299}
8300
8301
8302
8303
8304/* ======================================================================
8305   FUNCTION
8306   omx_vdec::AllocateDone
8307
8308   DESCRIPTION
8309   Checks if entire buffer pool is allocated by IL Client or not.
8310   Need this to move to IDLE state.
8311
8312   PARAMETERS
8313   None.
8314
8315   RETURN VALUE
8316   true/false.
8317
8318   ========================================================================== */
8319bool omx_vdec::allocate_done(void)
8320{
8321    bool bRet = false;
8322    bool bRet_In = false;
8323    bool bRet_Out = false;
8324
8325    bRet_In = allocate_input_done();
8326    bRet_Out = allocate_output_done();
8327
8328    if (bRet_In && bRet_Out) {
8329        bRet = true;
8330    }
8331
8332    return bRet;
8333}
8334/* ======================================================================
8335   FUNCTION
8336   omx_vdec::AllocateInputDone
8337
8338   DESCRIPTION
8339   Checks if I/P buffer pool is allocated by IL Client or not.
8340
8341   PARAMETERS
8342   None.
8343
8344   RETURN VALUE
8345   true/false.
8346
8347   ========================================================================== */
8348bool omx_vdec::allocate_input_done(void)
8349{
8350    bool bRet = false;
8351    unsigned i=0;
8352
8353    if (m_inp_mem_ptr == NULL) {
8354        return bRet;
8355    }
8356    if (m_inp_mem_ptr ) {
8357        for (; i<drv_ctx.ip_buf.actualcount; i++) {
8358            if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
8359                break;
8360            }
8361        }
8362    }
8363    if (i == drv_ctx.ip_buf.actualcount) {
8364        bRet = true;
8365        DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
8366    }
8367    if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
8368        m_inp_bPopulated = OMX_TRUE;
8369    }
8370    return bRet;
8371}
8372/* ======================================================================
8373   FUNCTION
8374   omx_vdec::AllocateOutputDone
8375
8376   DESCRIPTION
8377   Checks if entire O/P buffer pool is allocated by IL Client or not.
8378
8379   PARAMETERS
8380   None.
8381
8382   RETURN VALUE
8383   true/false.
8384
8385   ========================================================================== */
8386bool omx_vdec::allocate_output_done(void)
8387{
8388    bool bRet = false;
8389    unsigned j=0;
8390
8391    if (m_out_mem_ptr == NULL) {
8392        return bRet;
8393    }
8394
8395    if (m_out_mem_ptr) {
8396        for (; j < drv_ctx.op_buf.actualcount; j++) {
8397            if (BITMASK_ABSENT(&m_out_bm_count,j)) {
8398                break;
8399            }
8400        }
8401    }
8402
8403    if (j == drv_ctx.op_buf.actualcount) {
8404        bRet = true;
8405        DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
8406        if (m_out_bEnabled)
8407            m_out_bPopulated = OMX_TRUE;
8408    }
8409
8410    return bRet;
8411}
8412
8413/* ======================================================================
8414   FUNCTION
8415   omx_vdec::ReleaseDone
8416
8417   DESCRIPTION
8418   Checks if IL client has released all the buffers.
8419
8420   PARAMETERS
8421   None.
8422
8423   RETURN VALUE
8424   true/false
8425
8426   ========================================================================== */
8427bool omx_vdec::release_done(void)
8428{
8429    bool bRet = false;
8430
8431    if (release_input_done()) {
8432        if (release_output_done()) {
8433            bRet = true;
8434        }
8435    }
8436    return bRet;
8437}
8438
8439
8440/* ======================================================================
8441   FUNCTION
8442   omx_vdec::ReleaseOutputDone
8443
8444   DESCRIPTION
8445   Checks if IL client has released all the buffers.
8446
8447   PARAMETERS
8448   None.
8449
8450   RETURN VALUE
8451   true/false
8452
8453   ========================================================================== */
8454bool omx_vdec::release_output_done(void)
8455{
8456    bool bRet = false;
8457    unsigned i=0,j=0;
8458
8459    DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
8460    if (m_out_mem_ptr) {
8461        for (; j < drv_ctx.op_buf.actualcount ; j++) {
8462            if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8463                break;
8464            }
8465        }
8466        if (j == drv_ctx.op_buf.actualcount) {
8467            m_out_bm_count = 0;
8468            bRet = true;
8469        }
8470    } else {
8471        m_out_bm_count = 0;
8472        bRet = true;
8473    }
8474    return bRet;
8475}
8476/* ======================================================================
8477   FUNCTION
8478   omx_vdec::ReleaseInputDone
8479
8480   DESCRIPTION
8481   Checks if IL client has released all the buffers.
8482
8483   PARAMETERS
8484   None.
8485
8486   RETURN VALUE
8487   true/false
8488
8489   ========================================================================== */
8490bool omx_vdec::release_input_done(void)
8491{
8492    bool bRet = false;
8493    unsigned i=0,j=0;
8494
8495    DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
8496    if (m_inp_mem_ptr) {
8497        for (; j<drv_ctx.ip_buf.actualcount; j++) {
8498            if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8499                break;
8500            }
8501        }
8502        if (j==drv_ctx.ip_buf.actualcount) {
8503            bRet = true;
8504        }
8505    } else {
8506        bRet = true;
8507    }
8508    return bRet;
8509}
8510
8511OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8512        OMX_BUFFERHEADERTYPE * buffer)
8513{
8514    VIDC_TRACE_NAME_HIGH("FBD");
8515    OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8516    if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
8517        DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8518        return OMX_ErrorBadParameter;
8519    } else if (output_flush_progress) {
8520        DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8521        buffer->nFilledLen = 0;
8522        buffer->nTimeStamp = 0;
8523        buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8524        buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8525        buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8526    }
8527
8528    if (m_debug_extradata) {
8529        if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8530            DEBUG_PRINT_HIGH("***************************************************");
8531            DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8532            DEBUG_PRINT_HIGH("***************************************************");
8533        }
8534
8535        if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8536            DEBUG_PRINT_HIGH("***************************************************");
8537            DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8538            DEBUG_PRINT_HIGH("***************************************************");
8539        }
8540    }
8541
8542
8543    DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
8544            buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
8545    pending_output_buffers --;
8546    VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8547
8548    if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8549        DEBUG_PRINT_HIGH("Output EOS has been reached");
8550        if (!output_flush_progress)
8551            post_event((unsigned)NULL, (unsigned)NULL,
8552                    OMX_COMPONENT_GENERATE_EOS_DONE);
8553
8554        if (psource_frame) {
8555            m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8556            psource_frame = NULL;
8557        }
8558        if (pdest_frame) {
8559            pdest_frame->nFilledLen = 0;
8560            m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8561                    (unsigned)NULL);
8562            pdest_frame = NULL;
8563        }
8564    }
8565
8566#ifdef OUTPUT_EXTRADATA_LOG
8567    if (outputExtradataFile) {
8568        int buf_index = buffer - m_out_mem_ptr;
8569        OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8570
8571        OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8572        p_extra = (OMX_OTHER_EXTRADATATYPE *)
8573            ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8574
8575        while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8576            DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8577                                    p_extra->nSize, p_extra->eType);
8578            fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8579
8580            if (p_extra->eType == OMX_ExtraDataNone) {
8581                break;
8582            }
8583            p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8584        }
8585    }
8586#endif
8587
8588    /* For use buffer we need to copy the data */
8589    if (!output_flush_progress) {
8590        /* This is the error check for non-recoverable errros */
8591        bool is_duplicate_ts_valid = true;
8592        bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8593
8594        if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8595                output_capability == V4L2_PIX_FMT_MPEG2 ||
8596                output_capability == V4L2_PIX_FMT_DIVX ||
8597                output_capability == V4L2_PIX_FMT_DIVX_311)
8598            is_duplicate_ts_valid = false;
8599
8600        if ((output_capability == V4L2_PIX_FMT_H264 ||
8601                output_capability == V4L2_PIX_FMT_H264_MVC) &&
8602                is_interlaced) {
8603            if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8604                is_interlaced = false;
8605            }
8606        }
8607
8608        if (buffer->nFilledLen > 0) {
8609            time_stamp_dts.get_next_timestamp(buffer,
8610                    is_interlaced && is_duplicate_ts_valid);
8611            if (m_debug_timestamp) {
8612                {
8613                    OMX_TICKS expected_ts = 0;
8614                    m_timestamp_list.pop_min_ts(expected_ts);
8615                    if (is_interlaced && is_duplicate_ts_valid) {
8616                        m_timestamp_list.pop_min_ts(expected_ts);
8617                    }
8618                    DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8619                            buffer->nTimeStamp, expected_ts);
8620
8621                    if (buffer->nTimeStamp != expected_ts) {
8622                        DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8623                    }
8624                }
8625            }
8626        }
8627    }
8628    VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8629
8630    if (m_cb.FillBufferDone) {
8631        if (buffer->nFilledLen > 0) {
8632            if (arbitrary_bytes)
8633                adjust_timestamp(buffer->nTimeStamp);
8634            else
8635                set_frame_rate(buffer->nTimeStamp);
8636
8637            proc_frms++;
8638            if (perf_flag) {
8639                if (1 == proc_frms) {
8640                    dec_time.stop();
8641                    latency = dec_time.processing_time_us() - latency;
8642                    DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8643                    dec_time.start();
8644                    fps_metrics.start();
8645                }
8646                if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8647                    OMX_U64 proc_time = 0;
8648                    fps_metrics.stop();
8649                    proc_time = fps_metrics.processing_time_us();
8650                    DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8651                            (unsigned int)proc_frms, (float)proc_time / 1e6,
8652                            (float)(1e6 * proc_frms) / proc_time);
8653                }
8654            }
8655        }
8656        if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8657            prev_ts = LLONG_MAX;
8658            rst_prev_ts = true;
8659            proc_frms = 0;
8660        }
8661
8662        pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8663            ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8664             buffer->pPlatformPrivate)->entryList->entry;
8665        DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8666        OMX_BUFFERHEADERTYPE *il_buffer;
8667        il_buffer = client_buffers.get_il_buf_hdr(buffer);
8668        OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8669
8670        if (il_buffer && m_last_rendered_TS >= 0) {
8671            OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8672
8673            // Current frame can be send for rendering if
8674            // (a) current FPS is <=  60
8675            // (b) is the next frame after the frame with TS 0
8676            // (c) is the first frame after seek
8677            // (d) the delta TS b\w two consecutive frames is > 16 ms
8678            // (e) its TS is equal to previous frame TS
8679            // (f) if marked EOS
8680
8681            if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8682               il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8683               ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8684               m_last_rendered_TS = il_buffer->nTimeStamp;
8685            } else {
8686               //mark for droping
8687               buffer->nFilledLen = 0;
8688            }
8689
8690            DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8691                              buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8692                              il_buffer->nTimeStamp,ts_delta);
8693
8694            //above code makes sure that delta b\w two consecutive frames is not
8695            //greater than 16ms, slow-mo feature, so cap fps to max 60
8696            if (current_framerate > 60 ) {
8697                current_framerate = 60;
8698            }
8699        }
8700
8701        // add current framerate to gralloc meta data
8702        if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && m_out_mem_ptr) {
8703            // If valid fps was received, directly send it to display for the 1st fbd.
8704            // Otherwise, calculate fps using fbd timestamps
8705            float refresh_rate = m_fps_prev;
8706            if (m_fps_received) {
8707                if (1 == proc_frms) {
8708                    refresh_rate = m_fps_received / (float)(1<<16);
8709                }
8710            } else {
8711                // check if dynamic refresh rate change feature enabled or not
8712                if (m_drc_enable) {
8713                    // set coarse fps when 2 fbds received and
8714                    // set fps again when 30 fbds received as it should be
8715                    // more accurate than the one set when only 2 fbds received.
8716                    if (2 == proc_frms || 30 == proc_frms) {
8717                        if (drv_ctx.frame_rate.fps_denominator) {
8718                            refresh_rate = drv_ctx.frame_rate.fps_numerator /
8719                                    (float) drv_ctx.frame_rate.fps_denominator;
8720                        }
8721                    }
8722                } else {
8723                    // calculate and set refresh rate for every frame from second frame onwards
8724                    // display will assume the default refresh rate for first frame (which is 60 fps)
8725                    if (m_fps_prev) {
8726                        if (drv_ctx.frame_rate.fps_denominator) {
8727                            refresh_rate = drv_ctx.frame_rate.fps_numerator /
8728                                    (float) drv_ctx.frame_rate.fps_denominator;
8729                        }
8730                    }
8731                }
8732            }
8733            if (refresh_rate > 60) {
8734                refresh_rate = 60;
8735            }
8736            DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8737            OMX_U32 buf_index = buffer - m_out_mem_ptr;
8738            setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8739                         UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8740            m_fps_prev = refresh_rate;
8741        }
8742
8743        if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) {
8744            OMX_U32 buf_index = buffer - m_out_mem_ptr;
8745            DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8746            setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8747                               S3D_FORMAT, (void*)&stereo_output_mode);
8748        }
8749
8750        if (il_buffer) {
8751            log_output_buffers(il_buffer);
8752            if (dynamic_buf_mode) {
8753                unsigned int nPortIndex = 0;
8754                nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8755
8756                // Since we're passing around handles, adjust nFilledLen and nAllocLen
8757                // to size of the handle. Do it _after_ log_output_buffers which
8758                // requires the respective sizes to be accurate.
8759
8760                buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8761                buffer->nFilledLen = buffer->nFilledLen ?
8762                        sizeof(struct VideoDecoderOutputMetaData) : 0;
8763
8764                //Clear graphic buffer handles in dynamic mode
8765                if (nPortIndex < drv_ctx.op_buf.actualcount &&
8766                    nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8767                    native_buffer[nPortIndex].privatehandle = NULL;
8768                    native_buffer[nPortIndex].nativehandle = NULL;
8769                } else {
8770                    DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8771                    return OMX_ErrorBadParameter;
8772                }
8773            }
8774            m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8775        } else {
8776            DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8777            return OMX_ErrorBadParameter;
8778        }
8779        DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
8780    } else {
8781        return OMX_ErrorBadParameter;
8782    }
8783
8784#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8785    if (m_smoothstreaming_mode && m_out_mem_ptr) {
8786        OMX_U32 buf_index = buffer - m_out_mem_ptr;
8787        BufferDim_t dim;
8788        private_handle_t *private_handle = NULL;
8789        dim.sliceWidth = framesize.nWidth;
8790        dim.sliceHeight = framesize.nHeight;
8791        if (buf_index < drv_ctx.op_buf.actualcount &&
8792            buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8793            native_buffer[buf_index].privatehandle)
8794            private_handle = native_buffer[buf_index].privatehandle;
8795        if (private_handle) {
8796            DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8797                dim.sliceWidth, dim.sliceHeight);
8798            setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8799        }
8800    }
8801#endif
8802
8803    return OMX_ErrorNone;
8804}
8805
8806OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
8807        OMX_BUFFERHEADERTYPE* buffer)
8808{
8809    VIDC_TRACE_NAME_HIGH("EBD");
8810    int nBufferIndex = buffer - m_inp_mem_ptr;
8811
8812    if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8813        DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8814        return OMX_ErrorBadParameter;
8815    }
8816
8817    DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
8818            buffer, buffer->pBuffer, buffer->nFlags);
8819    pending_input_buffers--;
8820    VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
8821
8822    if (arbitrary_bytes) {
8823        if (pdest_frame == NULL && input_flush_progress == false) {
8824            DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8825            pdest_frame = buffer;
8826            buffer->nFilledLen = 0;
8827            buffer->nTimeStamp = LLONG_MAX;
8828            push_input_buffer (hComp);
8829        } else {
8830            DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8831            buffer->nFilledLen = 0;
8832            if (!m_input_free_q.insert_entry((unsigned long)buffer,
8833                        (unsigned)NULL, (unsigned)NULL)) {
8834                DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8835            }
8836        }
8837    } else if (m_cb.EmptyBufferDone) {
8838        buffer->nFilledLen = 0;
8839        if (input_use_buffer == true) {
8840            buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8841        }
8842
8843        /* Restore the FD that we over-wrote in ETB */
8844        if (m_input_pass_buffer_fd) {
8845            buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8846        }
8847
8848        m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8849    }
8850    return OMX_ErrorNone;
8851}
8852
8853int omx_vdec::async_message_process (void *context, void* message)
8854{
8855    omx_vdec* omx = NULL;
8856    struct vdec_msginfo *vdec_msg = NULL;
8857    OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8858    struct v4l2_buffer *v4l2_buf_ptr = NULL;
8859    struct v4l2_plane *plane = NULL;
8860    struct vdec_output_frameinfo *output_respbuf = NULL;
8861    int rc=1;
8862    if (context == NULL || message == NULL) {
8863        DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8864        return -1;
8865    }
8866    vdec_msg = (struct vdec_msginfo *)message;
8867
8868    omx = reinterpret_cast<omx_vdec*>(context);
8869
8870    switch (vdec_msg->msgcode) {
8871
8872        case VDEC_MSG_EVT_HW_ERROR:
8873            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8874                    OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8875            break;
8876
8877        case VDEC_MSG_EVT_HW_OVERLOAD:
8878            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8879                    OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8880            break;
8881
8882        case VDEC_MSG_EVT_HW_UNSUPPORTED:
8883            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8884                    OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8885            break;
8886
8887        case VDEC_MSG_RESP_START_DONE:
8888            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8889                    OMX_COMPONENT_GENERATE_START_DONE);
8890            break;
8891
8892        case VDEC_MSG_RESP_STOP_DONE:
8893            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8894                    OMX_COMPONENT_GENERATE_STOP_DONE);
8895            break;
8896
8897        case VDEC_MSG_RESP_RESUME_DONE:
8898            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8899                    OMX_COMPONENT_GENERATE_RESUME_DONE);
8900            break;
8901
8902        case VDEC_MSG_RESP_PAUSE_DONE:
8903            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8904                    OMX_COMPONENT_GENERATE_PAUSE_DONE);
8905            break;
8906
8907        case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8908            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8909                    OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8910            break;
8911        case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8912            omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8913                    OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8914            break;
8915        case VDEC_MSG_RESP_INPUT_FLUSHED:
8916        case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8917
8918            /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8919               vdec_msg->msgdata.input_frame_clientdata; */
8920
8921            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8922            if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8923                v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8924                omxhdr = NULL;
8925                vdec_msg->status_code = VDEC_S_EFATAL;
8926                break;
8927
8928            }
8929            omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8930
8931            if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8932                DEBUG_PRINT_HIGH("Unsupported input");
8933                omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8934                        OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8935            }
8936            if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8937                omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8938                vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8939            }
8940            if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8941
8942                DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8943                android_atomic_dec(&omx->m_queued_codec_config_count);
8944                if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8945                    BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8946                    DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8947                    sem_post(&omx->m_safe_flush);
8948                }
8949            }
8950            if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8951                v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8952                omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8953            }
8954            omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8955                    OMX_COMPONENT_GENERATE_EBD);
8956            break;
8957        case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8958            int64_t *timestamp;
8959            timestamp = (int64_t *) malloc(sizeof(int64_t));
8960            if (timestamp) {
8961                *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8962                omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8963                        OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8964                DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8965                        (long long)vdec_msg->msgdata.output_frame.time_stamp);
8966            }
8967            break;
8968        case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8969        case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8970
8971           v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8972           if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8973               v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8974               omxhdr = NULL;
8975               vdec_msg->status_code = VDEC_S_EFATAL;
8976               break;
8977           }
8978           plane = v4l2_buf_ptr->m.planes;
8979           omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8980
8981           if (omxhdr && omxhdr->pOutputPortPrivate &&
8982                   ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8983                   (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8984                     - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8985
8986               if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
8987                   omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8988                   omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8989                   omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8990                   omxhdr->nFlags = 0;
8991
8992                   if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8993                        omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8994                        //rc = -1;
8995                   }
8996                   if (omxhdr->nFilledLen) {
8997                       omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8998                   }
8999                   if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
9000                       omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9001                   } else {
9002                       omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
9003                   }
9004                   if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
9005                       omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9006                   }
9007                   if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
9008                       omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
9009                   }
9010                   if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
9011                       omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
9012                   }
9013                   if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
9014                        omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
9015                        DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
9016                                   omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
9017                   }
9018
9019                   if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
9020                           !omx->output_flush_progress &&
9021                           !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
9022                           !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
9023                       omx->time_stamp_dts.remove_time_stamp(
9024                               omxhdr->nTimeStamp,
9025                               (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
9026                               ?true:false);
9027
9028                       omxhdr->nFilledLen = 0;
9029                       omx->pending_output_buffers--;
9030                       omx->post_event ((unsigned long)NULL,(unsigned long)omx->client_buffers.get_il_buf_hdr(omxhdr),
9031                               OMX_COMPONENT_GENERATE_FTB);
9032                       break;
9033                   }
9034                   if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
9035                       omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9036                   }
9037
9038                   output_respbuf = (struct vdec_output_frameinfo *)\
9039                            omxhdr->pOutputPortPrivate;
9040                   if (!output_respbuf) {
9041                     DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
9042                     return -1;
9043                   }
9044                   output_respbuf->len = vdec_msg->msgdata.output_frame.len;
9045                   output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
9046
9047                   if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
9048                       output_respbuf->pic_type = PICTURE_TYPE_I;
9049                   }
9050                   if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
9051                       output_respbuf->pic_type = PICTURE_TYPE_P;
9052                   }
9053                   if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
9054                       output_respbuf->pic_type = PICTURE_TYPE_B;
9055                   }
9056
9057                   if (vdec_msg->msgdata.output_frame.len) {
9058                       if (!omx->output_flush_progress && (omxhdr->nFilledLen > 0)) {
9059                           // set the default colorspace advised by client, since the bitstream may be
9060                           // devoid of colorspace-info.
9061                           if (omx->m_enable_android_native_buffers) {
9062                               ColorSpace_t color_space = ITU_R_601;
9063
9064                           // Disabled ?
9065                           // WA for VP8. Vp8 encoder does not embed color-info (yet!).
9066                           // Encoding RGBA results in 601-LR for all resolutions.
9067                           // This conflicts with the client't defaults which are based on resolution.
9068                           //   Eg: 720p will be encoded as 601-LR. Client will say 709.
9069                           // Re-enable this code once vp8 encoder generates color-info and hence the
9070                           // decoder will be able to override with the correct source color.
9071#if 0
9072                               switch (omx->m_client_color_space.sAspects.mPrimaries) {
9073                                   case ColorAspects::PrimariesBT601_6_625:
9074                                   case ColorAspects::PrimariesBT601_6_525:
9075                                   {
9076                                       color_space = omx->m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
9077                                               ITU_R_601_FR : ITU_R_601;
9078                                       break;
9079                                   }
9080                                   case ColorAspects::PrimariesBT709_5:
9081                                   {
9082                                       color_space = ITU_R_709;
9083                                       break;
9084                                   }
9085                                   default:
9086                                   {
9087                                       break;
9088                                   }
9089                               }
9090#endif
9091                               DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
9092                                       color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
9093                               omx->set_colorspace_in_handle(color_space, omxhdr - omx->m_out_mem_ptr);
9094                           }
9095                       }
9096
9097                       DEBUG_PRINT_LOW("Processing extradata");
9098                       omx->handle_extradata(omxhdr);
9099
9100                       if (omx->m_extradata_info.output_crop_updated) {
9101                           DEBUG_PRINT_LOW("Read FBD crop from output extra data");
9102                           vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
9103                           vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
9104                           vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
9105                           vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
9106                           vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
9107                           vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
9108                       } else {
9109                           DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
9110                           vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
9111                           vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
9112                           vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
9113                           vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
9114                           vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
9115                           vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
9116
9117                           /* Copy these values back to OMX internal variables to make both handlign same*/
9118
9119                           omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
9120                           omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
9121                           omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
9122                           omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
9123                           omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9124                           omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9125                       }
9126                   }
9127
9128                   vdec_msg->msgdata.output_frame.bufferaddr =
9129                       omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
9130
9131                   if (vdec_msg->msgdata.output_frame.len)
9132                       memcpy(&omx->drv_ctx.frame_size,
9133                               &vdec_msg->msgdata.output_frame.framesize,
9134                               sizeof(struct vdec_framesize));
9135
9136                   DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
9137                           " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
9138                           omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
9139                           omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
9140                           vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
9141                           (unsigned int)vdec_msg->msgdata.output_frame.len,
9142                           vdec_msg->msgdata.output_frame.framesize.left,
9143                           vdec_msg->msgdata.output_frame.framesize.top,
9144                           vdec_msg->msgdata.output_frame.framesize.right,
9145                           vdec_msg->msgdata.output_frame.framesize.bottom);
9146
9147                   /* Post event if resolution OR crop changed */
9148                   /* filled length will be changed if resolution changed */
9149                   /* Crop parameters can be changed even without resolution change */
9150                   if (omxhdr->nFilledLen
9151                       && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
9152                       || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
9153                       || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
9154                       || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
9155                       || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
9156                       || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
9157                       || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
9158
9159                       DEBUG_PRINT_HIGH("Parameters 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",
9160                               omx->prev_n_filled_len,
9161                               omx->drv_ctx.video_resolution.frame_width,
9162                               omx->drv_ctx.video_resolution.frame_height,
9163                               omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
9164                               omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
9165                               omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
9166                               vdec_msg->msgdata.output_frame.picsize.frame_height,
9167                               vdec_msg->msgdata.output_frame.framesize.left,
9168                               vdec_msg->msgdata.output_frame.framesize.top,
9169                               vdec_msg->msgdata.output_frame.framesize.right,
9170                               vdec_msg->msgdata.output_frame.framesize.bottom);
9171
9172                       omx->drv_ctx.video_resolution.frame_width =
9173                               vdec_msg->msgdata.output_frame.picsize.frame_width;
9174                       omx->drv_ctx.video_resolution.frame_height =
9175                               vdec_msg->msgdata.output_frame.picsize.frame_height;
9176                       if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
9177                           omx->drv_ctx.video_resolution.stride =
9178                               VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
9179                           omx->drv_ctx.video_resolution.scan_lines =
9180                               VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
9181                       } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
9182                           omx->drv_ctx.video_resolution.stride =
9183                               VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
9184                           omx->drv_ctx.video_resolution.scan_lines =
9185                               VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
9186                       } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
9187                           omx->drv_ctx.video_resolution.stride =
9188                               VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
9189                           omx->drv_ctx.video_resolution.scan_lines =
9190                               VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
9191                        }
9192
9193                       omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9194                                OMX_IndexConfigCommonOutputCrop,
9195                                OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9196                   }
9197
9198                   if (omxhdr->nFilledLen)
9199                       omx->prev_n_filled_len = omxhdr->nFilledLen;
9200
9201                   if (omxhdr && omxhdr->nFilledLen && !omx->m_need_turbo) {
9202                        omx->request_perf_level(VIDC_NOMINAL);
9203                   }
9204                   if (omx->output_use_buffer && omxhdr->pBuffer &&
9205                       vdec_msg->msgdata.output_frame.bufferaddr)
9206                       memcpy ( omxhdr->pBuffer, (void *)
9207                               ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
9208                                (unsigned long)vdec_msg->msgdata.output_frame.offset),
9209                               vdec_msg->msgdata.output_frame.len);
9210               } else {
9211                   DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
9212                           (unsigned int)vdec_msg->msgdata.output_frame.len,
9213                           omxhdr->nAllocLen, omx->prev_n_filled_len);
9214                   omxhdr->nFilledLen = 0;
9215               }
9216
9217               omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
9218                        OMX_COMPONENT_GENERATE_FBD);
9219
9220            } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
9221                omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
9222                        OMX_COMPONENT_GENERATE_EOS_DONE);
9223            } else {
9224                omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
9225                        OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9226            }
9227            break;
9228        case VDEC_MSG_EVT_CONFIG_CHANGED:
9229            DEBUG_PRINT_HIGH("Port settings changed");
9230            omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9231            omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9232            omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
9233                    OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9234            if (!omx->m_need_turbo) {
9235                omx->request_perf_level(VIDC_NOMINAL);
9236            }
9237            break;
9238        default:
9239            break;
9240    }
9241    return rc;
9242}
9243
9244OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
9245        OMX_HANDLETYPE hComp,
9246        OMX_BUFFERHEADERTYPE *buffer
9247        )
9248{
9249    unsigned address,p2,id;
9250    DEBUG_PRINT_LOW("Empty this arbitrary");
9251
9252    if (buffer == NULL) {
9253        return OMX_ErrorBadParameter;
9254    }
9255    DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
9256    DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
9257            (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
9258
9259    /* return zero length and not an EOS buffer */
9260    /* return buffer if input flush in progress */
9261    if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
9262                ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
9263        DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
9264        m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
9265        return OMX_ErrorNone;
9266    }
9267
9268    if (psource_frame == NULL) {
9269        DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
9270        psource_frame = buffer;
9271        DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
9272        push_input_buffer (hComp);
9273    } else {
9274        DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
9275        if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
9276                    (unsigned)NULL)) {
9277            return OMX_ErrorBadParameter;
9278        }
9279    }
9280
9281    if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
9282        codec_config_flag = false;
9283    }
9284    return OMX_ErrorNone;
9285}
9286
9287OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
9288{
9289    unsigned long address,p2,id;
9290    OMX_ERRORTYPE ret = OMX_ErrorNone;
9291
9292    if (pdest_frame == NULL || psource_frame == NULL) {
9293        /*Check if we have a destination buffer*/
9294        if (pdest_frame == NULL) {
9295            DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
9296            if (m_input_free_q.m_size) {
9297                m_input_free_q.pop_entry(&address,&p2,&id);
9298                pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
9299                pdest_frame->nFilledLen = 0;
9300                pdest_frame->nTimeStamp = LLONG_MAX;
9301                DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
9302            }
9303        }
9304
9305        /*Check if we have a destination buffer*/
9306        if (psource_frame == NULL) {
9307            DEBUG_PRINT_LOW("Get a source buffer from the queue");
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 %p time stamp %lld",psource_frame,
9312                        psource_frame->nTimeStamp);
9313                DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9314                        (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9315
9316            }
9317        }
9318
9319    }
9320
9321    while ((pdest_frame != NULL) && (psource_frame != NULL)) {
9322        switch (codec_type_parse) {
9323            case CODEC_TYPE_MPEG4:
9324            case CODEC_TYPE_H263:
9325            case CODEC_TYPE_MPEG2:
9326                ret =  push_input_sc_codec(hComp);
9327                break;
9328            case CODEC_TYPE_H264:
9329                ret = push_input_h264(hComp);
9330                break;
9331            case CODEC_TYPE_HEVC:
9332                ret = push_input_hevc(hComp);
9333                break;
9334            case CODEC_TYPE_VC1:
9335                ret = push_input_vc1(hComp);
9336                break;
9337            default:
9338                break;
9339        }
9340        if (ret != OMX_ErrorNone) {
9341            DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
9342            omx_report_error ();
9343            break;
9344        }
9345    }
9346
9347    return ret;
9348}
9349
9350OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
9351{
9352    OMX_U32 partial_frame = 1;
9353    OMX_BOOL generate_ebd = OMX_TRUE;
9354    unsigned long address = 0, p2 = 0, id = 0;
9355
9356    DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
9357            psource_frame,psource_frame->nTimeStamp);
9358    if (m_frame_parser.parse_sc_frame(psource_frame,
9359                pdest_frame,&partial_frame) == -1) {
9360        DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9361        return OMX_ErrorBadParameter;
9362    }
9363
9364    if (partial_frame == 0) {
9365        DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
9366                (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
9367
9368
9369        DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
9370        /*First Parsed buffer will have only header Hence skip*/
9371        if (frame_count == 0) {
9372            DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
9373
9374            if (codec_type_parse == CODEC_TYPE_MPEG4 ||
9375                    codec_type_parse == CODEC_TYPE_DIVX) {
9376                mp4StreamType psBits;
9377                psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
9378                psBits.numBytes = pdest_frame->nFilledLen;
9379                mp4_headerparser.parseHeader(&psBits);
9380            }
9381
9382            frame_count++;
9383        } else {
9384            pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9385            if (pdest_frame->nFilledLen) {
9386                /*Push the frame to the Decoder*/
9387                if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9388                    return OMX_ErrorBadParameter;
9389                }
9390                frame_count++;
9391                pdest_frame = NULL;
9392
9393                if (m_input_free_q.m_size) {
9394                    m_input_free_q.pop_entry(&address,&p2,&id);
9395                    pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9396                    pdest_frame->nFilledLen = 0;
9397                }
9398            } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
9399                DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
9400                m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
9401                        (unsigned)NULL);
9402                pdest_frame = NULL;
9403            }
9404        }
9405    } else {
9406        DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
9407        /*Check if Destination Buffer is full*/
9408        if (pdest_frame->nAllocLen ==
9409                pdest_frame->nFilledLen + pdest_frame->nOffset) {
9410            DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
9411            return OMX_ErrorStreamCorrupt;
9412        }
9413    }
9414
9415    if (psource_frame->nFilledLen == 0) {
9416        if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9417            if (pdest_frame) {
9418                pdest_frame->nFlags |= psource_frame->nFlags;
9419                pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
9420                DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
9421                        (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9422                DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9423                        (unsigned int)pdest_frame->nFilledLen,frame_count++);
9424                /*Push the frame to the Decoder*/
9425                if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9426                    return OMX_ErrorBadParameter;
9427                }
9428                frame_count++;
9429                pdest_frame = NULL;
9430            } else {
9431                DEBUG_PRINT_LOW("Last frame in else dest addr") ;
9432                generate_ebd = OMX_FALSE;
9433            }
9434        }
9435        if (generate_ebd) {
9436            DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
9437            m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9438            psource_frame = NULL;
9439
9440            if (m_input_pending_q.m_size) {
9441                DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9442                m_input_pending_q.pop_entry(&address,&p2,&id);
9443                psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9444                DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9445                        psource_frame->nTimeStamp);
9446                DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9447                        (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9448            }
9449        }
9450    }
9451    return OMX_ErrorNone;
9452}
9453
9454OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
9455{
9456    OMX_U32 partial_frame = 1;
9457    unsigned long address = 0, p2 = 0, id = 0;
9458    OMX_BOOL isNewFrame = OMX_FALSE;
9459    OMX_BOOL generate_ebd = OMX_TRUE;
9460
9461    if (h264_scratch.pBuffer == NULL) {
9462        DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
9463        return OMX_ErrorBadParameter;
9464    }
9465    DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
9466            "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
9467    DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
9468    if (h264_scratch.nFilledLen && look_ahead_nal) {
9469        look_ahead_nal = false;
9470        if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9471                h264_scratch.nFilledLen) {
9472            memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9473                    h264_scratch.pBuffer,h264_scratch.nFilledLen);
9474            pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9475            DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
9476            h264_scratch.nFilledLen = 0;
9477        } else {
9478            DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
9479            return OMX_ErrorBadParameter;
9480        }
9481    }
9482
9483    /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
9484       in EOS flag getting associated with the destination
9485    */
9486    if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
9487            pdest_frame->nFilledLen) {
9488        DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
9489        generate_ebd = OMX_FALSE;
9490    }
9491
9492    if (nal_length == 0) {
9493        DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
9494        if (m_frame_parser.parse_sc_frame(psource_frame,
9495                    &h264_scratch,&partial_frame) == -1) {
9496            DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9497            return OMX_ErrorBadParameter;
9498        }
9499    } else {
9500        DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9501        if (m_frame_parser.parse_h264_nallength(psource_frame,
9502                    &h264_scratch,&partial_frame) == -1) {
9503            DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9504            return OMX_ErrorBadParameter;
9505        }
9506    }
9507
9508    if (partial_frame == 0) {
9509        if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9510            DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9511            nal_count++;
9512            h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9513            h264_scratch.nFlags = psource_frame->nFlags;
9514        } else {
9515            DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9516            if (h264_scratch.nFilledLen) {
9517                h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9518                        NALU_TYPE_SPS);
9519#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9520                if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9521                    h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9522                            h264_scratch.nFilledLen, NALU_TYPE_SEI);
9523                else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9524                    // If timeinfo is present frame info from SEI is already processed
9525                    h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9526                            h264_scratch.nFilledLen, NALU_TYPE_SEI);
9527#endif
9528                m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9529                nal_count++;
9530                if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9531                    pdest_frame->nTimeStamp = h264_last_au_ts;
9532                    pdest_frame->nFlags = h264_last_au_flags;
9533#ifdef PANSCAN_HDLR
9534                    if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9535                        h264_parser->update_panscan_data(h264_last_au_ts);
9536#endif
9537                }
9538                if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9539                        m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9540                    h264_last_au_ts = h264_scratch.nTimeStamp;
9541                    h264_last_au_flags = h264_scratch.nFlags;
9542#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9543                    if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9544                        OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9545                        if (!VALID_TS(h264_last_au_ts))
9546                            h264_last_au_ts = ts_in_sei;
9547                    }
9548#endif
9549                } else
9550                    h264_last_au_ts = LLONG_MAX;
9551            }
9552
9553            if (!isNewFrame) {
9554                if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9555                        h264_scratch.nFilledLen) {
9556                    DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9557                            (unsigned int)h264_scratch.nFilledLen);
9558                    memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9559                            h264_scratch.pBuffer,h264_scratch.nFilledLen);
9560                    pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9561                    if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9562                        pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9563                    h264_scratch.nFilledLen = 0;
9564                } else {
9565                    DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9566                    return OMX_ErrorBadParameter;
9567                }
9568            } else if(h264_scratch.nFilledLen) {
9569                look_ahead_nal = true;
9570                DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9571                        (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9572                DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9573                        (unsigned int)pdest_frame->nFilledLen,frame_count++);
9574
9575                if (pdest_frame->nFilledLen == 0) {
9576                    DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9577                    look_ahead_nal = false;
9578                    if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9579                            h264_scratch.nFilledLen) {
9580                        memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9581                                h264_scratch.pBuffer,h264_scratch.nFilledLen);
9582                        pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9583                        h264_scratch.nFilledLen = 0;
9584                    } else {
9585                        DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9586                        return OMX_ErrorBadParameter;
9587                    }
9588                } else {
9589                    if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9590                        DEBUG_PRINT_LOW("Reset the EOS Flag");
9591                        pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9592                    }
9593                    /*Push the frame to the Decoder*/
9594                    if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9595                        return OMX_ErrorBadParameter;
9596                    }
9597                    //frame_count++;
9598                    pdest_frame = NULL;
9599                    if (m_input_free_q.m_size) {
9600                        m_input_free_q.pop_entry(&address,&p2,&id);
9601                        pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9602                        DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9603                        pdest_frame->nFilledLen = 0;
9604                        pdest_frame->nFlags = 0;
9605                        pdest_frame->nTimeStamp = LLONG_MAX;
9606                    }
9607                }
9608            }
9609        }
9610    } else {
9611        DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9612        /*Check if Destination Buffer is full*/
9613        if (h264_scratch.nAllocLen ==
9614                h264_scratch.nFilledLen + h264_scratch.nOffset) {
9615            DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9616            return OMX_ErrorStreamCorrupt;
9617        }
9618    }
9619
9620    if (!psource_frame->nFilledLen) {
9621        DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9622
9623        if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9624            if (pdest_frame) {
9625                DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9626                if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9627                        h264_scratch.nFilledLen) {
9628                    if(pdest_frame->nFilledLen == 0) {
9629                        /* No residual frame from before, send whatever
9630                         * we have left */
9631                        memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9632                                h264_scratch.pBuffer, h264_scratch.nFilledLen);
9633                        pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9634                        h264_scratch.nFilledLen = 0;
9635                        pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9636                    } else {
9637                        m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9638                        if(!isNewFrame) {
9639                            /* Have a residual frame, but we know that the
9640                             * AU in this frame is belonging to whatever
9641                             * frame we had left over.  So append it */
9642                             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9643                                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
9644                             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9645                             h264_scratch.nFilledLen = 0;
9646                             if (h264_last_au_ts != LLONG_MAX)
9647                                 pdest_frame->nTimeStamp = h264_last_au_ts;
9648                        } else {
9649                            /* Completely new frame, let's just push what
9650                             * we have now.  The resulting EBD would trigger
9651                             * another push */
9652                            generate_ebd = OMX_FALSE;
9653                            pdest_frame->nTimeStamp = h264_last_au_ts;
9654                            h264_last_au_ts = h264_scratch.nTimeStamp;
9655                        }
9656                    }
9657                } else {
9658                    DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9659                    return OMX_ErrorBadParameter;
9660                }
9661
9662                /* Iff we coalesced two buffers, inherit the flags of both bufs */
9663                if(generate_ebd == OMX_TRUE) {
9664                     pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9665                }
9666
9667                DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9668                        (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9669                DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9670#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9671                if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9672                    OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9673                    if (!VALID_TS(pdest_frame->nTimeStamp))
9674                        pdest_frame->nTimeStamp = ts_in_sei;
9675                }
9676#endif
9677                /*Push the frame to the Decoder*/
9678                if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9679                    return OMX_ErrorBadParameter;
9680                }
9681                frame_count++;
9682                pdest_frame = NULL;
9683            } else {
9684                DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9685                        pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9686                generate_ebd = OMX_FALSE;
9687            }
9688        }
9689    }
9690    if (generate_ebd && !psource_frame->nFilledLen) {
9691        m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9692        psource_frame = NULL;
9693        if (m_input_pending_q.m_size) {
9694            DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9695            m_input_pending_q.pop_entry(&address,&p2,&id);
9696            psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9697            DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9698                    (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9699        }
9700    }
9701    return OMX_ErrorNone;
9702}
9703
9704OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9705{
9706    OMX_ERRORTYPE rc = OMX_ErrorNone;
9707    if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9708        memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9709        if (pDst->nTimeStamp == LLONG_MAX) {
9710            pDst->nTimeStamp = pSrc->nTimeStamp;
9711            DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9712        }
9713        pDst->nFilledLen += pSrc->nFilledLen;
9714        pSrc->nFilledLen = 0;
9715    } else {
9716        DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9717        rc = OMX_ErrorBadParameter;
9718    }
9719    return rc;
9720}
9721
9722OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9723{
9724    OMX_U32 partial_frame = 1;
9725    unsigned long address,p2,id;
9726    OMX_BOOL isNewFrame = OMX_FALSE;
9727    OMX_BOOL generate_ebd = OMX_TRUE;
9728    OMX_ERRORTYPE rc = OMX_ErrorNone;
9729    if (h264_scratch.pBuffer == NULL) {
9730        DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9731        return OMX_ErrorBadParameter;
9732    }
9733
9734    DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9735            pdest_frame nFilledLen %u nTimeStamp %lld",
9736            (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9737
9738    if (h264_scratch.nFilledLen && look_ahead_nal) {
9739        look_ahead_nal = false;
9740        rc = copy_buffer(pdest_frame, &h264_scratch);
9741        if (rc != OMX_ErrorNone) {
9742            return rc;
9743        }
9744    }
9745
9746    if (nal_length == 0) {
9747        if (m_frame_parser.parse_sc_frame(psource_frame,
9748                    &h264_scratch,&partial_frame) == -1) {
9749            DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9750            return OMX_ErrorBadParameter;
9751        }
9752    } else {
9753        DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9754        if (m_frame_parser.parse_h264_nallength(psource_frame,
9755                    &h264_scratch,&partial_frame) == -1) {
9756            DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9757            return OMX_ErrorBadParameter;
9758        }
9759    }
9760
9761    if (partial_frame == 0) {
9762        if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9763            DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9764            nal_count++;
9765            h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9766            h264_scratch.nFlags = psource_frame->nFlags;
9767        } else {
9768            DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9769            if (h264_scratch.nFilledLen) {
9770                m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9771                nal_count++;
9772            }
9773
9774            if (!isNewFrame) {
9775                DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9776                        nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9777                        (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9778                        (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9779                rc = copy_buffer(pdest_frame, &h264_scratch);
9780                if (rc != OMX_ErrorNone) {
9781                    return rc;
9782                }
9783            } else {
9784                look_ahead_nal = true;
9785                if (pdest_frame->nFilledLen == 0) {
9786                    look_ahead_nal = false;
9787                    DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9788                    rc = copy_buffer(pdest_frame, &h264_scratch);
9789                    if (rc != OMX_ErrorNone) {
9790                        return OMX_ErrorBadParameter;
9791                    }
9792                } else {
9793                    if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9794                        pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9795                    }
9796                    DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9797                            nTimeStamp %lld, look_ahead_nal in h264_scratch \
9798                            nFilledLen %u nTimeStamp %lld",
9799                            frame_count++, (unsigned int)pdest_frame->nFilledLen,
9800                            pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9801                            h264_scratch.nTimeStamp);
9802                    if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9803                        return OMX_ErrorBadParameter;
9804                    }
9805                    pdest_frame = NULL;
9806                    if (m_input_free_q.m_size) {
9807                        m_input_free_q.pop_entry(&address, &p2, &id);
9808                        pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9809                        DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9810                        pdest_frame->nFilledLen = 0;
9811                        pdest_frame->nFlags = 0;
9812                        pdest_frame->nTimeStamp = LLONG_MAX;
9813                    }
9814                }
9815            }
9816        }
9817    } else {
9818        DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9819                pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9820                nFilledLen %u nTimeStamp %lld",
9821                (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9822                (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9823                (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9824
9825        if (h264_scratch.nAllocLen ==
9826                h264_scratch.nFilledLen + h264_scratch.nOffset) {
9827            DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9828            return OMX_ErrorStreamCorrupt;
9829        }
9830    }
9831
9832    if (!psource_frame->nFilledLen) {
9833        DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9834        if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9835            if (pdest_frame) {
9836                DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9837                rc = copy_buffer(pdest_frame, &h264_scratch);
9838                if ( rc != OMX_ErrorNone ) {
9839                    return rc;
9840                }
9841                pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9842                pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9843                DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9844                        frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9845                if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9846                    return OMX_ErrorBadParameter;
9847                }
9848                frame_count++;
9849                pdest_frame = NULL;
9850            } else {
9851                DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9852                        pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9853                generate_ebd = OMX_FALSE;
9854            }
9855        }
9856    }
9857
9858    if (generate_ebd && !psource_frame->nFilledLen) {
9859        m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9860        psource_frame = NULL;
9861        if (m_input_pending_q.m_size) {
9862            m_input_pending_q.pop_entry(&address, &p2, &id);
9863            psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9864            DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9865                    (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9866        }
9867    }
9868    return OMX_ErrorNone;
9869}
9870
9871OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
9872{
9873    OMX_U8 *buf, *pdest;
9874    OMX_U32 partial_frame = 1;
9875    OMX_U32 buf_len, dest_len;
9876
9877    if (first_frame == 0) {
9878        first_frame = 1;
9879        DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
9880        if (!m_vendor_config.pData) {
9881            DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
9882            buf = psource_frame->pBuffer;
9883            buf_len = psource_frame->nFilledLen;
9884
9885            if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
9886                    VC1_SP_MP_START_CODE) {
9887                m_vc1_profile = VC1_SP_MP_RCV;
9888            } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
9889                m_vc1_profile = VC1_AP;
9890            } else {
9891                DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
9892                return OMX_ErrorStreamCorrupt;
9893            }
9894        } else {
9895            pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
9896                pdest_frame->nOffset;
9897            dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
9898                    pdest_frame->nOffset);
9899
9900            if (dest_len < m_vendor_config.nDataSize) {
9901                DEBUG_PRINT_ERROR("Destination buffer full");
9902                return OMX_ErrorBadParameter;
9903            } else {
9904                memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
9905                pdest_frame->nFilledLen += m_vendor_config.nDataSize;
9906            }
9907        }
9908    }
9909
9910    switch (m_vc1_profile) {
9911        case VC1_AP:
9912            DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
9913            if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
9914                DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
9915                return OMX_ErrorBadParameter;
9916            }
9917            break;
9918
9919        case VC1_SP_MP_RCV:
9920        default:
9921            DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
9922            return OMX_ErrorBadParameter;
9923    }
9924    return OMX_ErrorNone;
9925}
9926
9927#ifndef USE_ION
9928bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9929        OMX_U32 alignment)
9930{
9931    struct pmem_allocation allocation;
9932    allocation.size = buffer_size;
9933    allocation.align = clip2(alignment);
9934    if (allocation.align < 4096) {
9935        allocation.align = 4096;
9936    }
9937    if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9938        DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9939                allocation.align, allocation.size);
9940        return false;
9941    }
9942    return true;
9943}
9944#endif
9945#ifdef USE_ION
9946int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
9947        OMX_U32 alignment, struct ion_allocation_data *alloc_data,
9948        struct ion_fd_data *fd_data, int flag)
9949{
9950    int fd = -EINVAL;
9951    int rc = -EINVAL;
9952    int ion_dev_flag;
9953    struct vdec_ion ion_buf_info;
9954    if (!alloc_data || buffer_size <= 0 || !fd_data) {
9955        DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9956        return -EINVAL;
9957    }
9958    ion_dev_flag = O_RDONLY;
9959    fd = open (MEM_DEVICE, ion_dev_flag);
9960    if (fd < 0) {
9961        DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
9962        return fd;
9963    }
9964
9965    alloc_data->flags = flag;
9966    alloc_data->len = buffer_size;
9967    alloc_data->align = clip2(alignment);
9968    if (alloc_data->align < 4096) {
9969        alloc_data->align = 4096;
9970    }
9971
9972    alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
9973    if (secure_mode && (alloc_data->flags & ION_SECURE)) {
9974        alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9975    }
9976
9977    /* Use secure display cma heap for obvious reasons. */
9978    if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
9979        alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9980    }
9981
9982    rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
9983    if (rc || !alloc_data->handle) {
9984        DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9985        alloc_data->handle = 0;
9986        close(fd);
9987        fd = -ENOMEM;
9988        return fd;
9989    }
9990    fd_data->handle = alloc_data->handle;
9991    rc = ioctl(fd,ION_IOC_MAP,fd_data);
9992    if (rc) {
9993        DEBUG_PRINT_ERROR("ION MAP failed ");
9994        ion_buf_info.ion_alloc_data = *alloc_data;
9995        ion_buf_info.ion_device_fd = fd;
9996        ion_buf_info.fd_ion_data = *fd_data;
9997        free_ion_memory(&ion_buf_info);
9998        fd_data->fd =-1;
9999        fd = -ENOMEM;
10000    }
10001
10002    return fd;
10003}
10004
10005void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
10006{
10007
10008    if (!buf_ion_info) {
10009        DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
10010        return;
10011    }
10012    if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
10013                &buf_ion_info->ion_alloc_data.handle)) {
10014        DEBUG_PRINT_ERROR("ION: free failed" );
10015    }
10016    close(buf_ion_info->ion_device_fd);
10017    buf_ion_info->ion_device_fd = -1;
10018    buf_ion_info->ion_alloc_data.handle = 0;
10019    buf_ion_info->fd_ion_data.fd = -1;
10020}
10021#endif
10022void omx_vdec::free_output_buffer_header()
10023{
10024    DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
10025    output_use_buffer = false;
10026    ouput_egl_buffers = false;
10027
10028    if (m_out_mem_ptr) {
10029        free (m_out_mem_ptr);
10030        m_out_mem_ptr = NULL;
10031    }
10032
10033    if (m_platform_list) {
10034        free(m_platform_list);
10035        m_platform_list = NULL;
10036    }
10037
10038    if (drv_ctx.ptr_respbuffer) {
10039        free (drv_ctx.ptr_respbuffer);
10040        drv_ctx.ptr_respbuffer = NULL;
10041    }
10042    if (drv_ctx.ptr_outputbuffer) {
10043        free (drv_ctx.ptr_outputbuffer);
10044        drv_ctx.ptr_outputbuffer = NULL;
10045    }
10046#ifdef USE_ION
10047    if (drv_ctx.op_buf_ion_info) {
10048        DEBUG_PRINT_LOW("Free o/p ion context");
10049        free(drv_ctx.op_buf_ion_info);
10050        drv_ctx.op_buf_ion_info = NULL;
10051    }
10052#endif
10053    free(drv_ctx.op_buf_map_info);
10054    drv_ctx.op_buf_map_info = NULL;
10055    buf_ref_remove();
10056}
10057
10058void omx_vdec::free_input_buffer_header()
10059{
10060    input_use_buffer = false;
10061    if (arbitrary_bytes) {
10062        if (m_inp_heap_ptr) {
10063            DEBUG_PRINT_LOW("Free input Heap Pointer");
10064            free (m_inp_heap_ptr);
10065            m_inp_heap_ptr = NULL;
10066        }
10067
10068        if (m_phdr_pmem_ptr) {
10069            DEBUG_PRINT_LOW("Free input pmem header Pointer");
10070            free (m_phdr_pmem_ptr);
10071            m_phdr_pmem_ptr = NULL;
10072        }
10073    }
10074    if (m_inp_mem_ptr) {
10075        DEBUG_PRINT_LOW("Free input pmem Pointer area");
10076        free (m_inp_mem_ptr);
10077        m_inp_mem_ptr = NULL;
10078    }
10079    /* We just freed all the buffer headers, every thing in m_input_free_q,
10080     * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
10081    while (m_input_free_q.m_size) {
10082        unsigned long address, p2, id;
10083        m_input_free_q.pop_entry(&address, &p2, &id);
10084    }
10085    while (m_input_pending_q.m_size) {
10086        unsigned long address, p2, id;
10087        m_input_pending_q.pop_entry(&address, &p2, &id);
10088    }
10089    pdest_frame = NULL;
10090    psource_frame = NULL;
10091    if (drv_ctx.ptr_inputbuffer) {
10092        DEBUG_PRINT_LOW("Free Driver Context pointer");
10093        free (drv_ctx.ptr_inputbuffer);
10094        drv_ctx.ptr_inputbuffer = NULL;
10095    }
10096#ifdef USE_ION
10097    if (drv_ctx.ip_buf_ion_info) {
10098        DEBUG_PRINT_LOW("Free ion context");
10099        free(drv_ctx.ip_buf_ion_info);
10100        drv_ctx.ip_buf_ion_info = NULL;
10101    }
10102#endif
10103}
10104
10105int omx_vdec::stream_off(OMX_U32 port)
10106{
10107    enum v4l2_buf_type btype;
10108    int rc = 0;
10109    enum v4l2_ports v4l2_port = OUTPUT_PORT;
10110
10111    if (port == OMX_CORE_INPUT_PORT_INDEX) {
10112        btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10113        v4l2_port = OUTPUT_PORT;
10114    } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10115        btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10116        v4l2_port = CAPTURE_PORT;
10117    } else if (port == OMX_ALL) {
10118        int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
10119        int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
10120
10121        if (!rc_input)
10122            return rc_input;
10123        else
10124            return rc_output;
10125    }
10126
10127    if (!streaming[v4l2_port]) {
10128        // already streamed off, warn and move on
10129        DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
10130                " which is already streamed off", v4l2_port);
10131        return 0;
10132    }
10133
10134    DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
10135
10136    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
10137    if (rc) {
10138        /*TODO: How to handle this case */
10139        DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
10140    } else {
10141        streaming[v4l2_port] = false;
10142    }
10143
10144    return rc;
10145}
10146
10147OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
10148{
10149    OMX_ERRORTYPE eRet = OMX_ErrorNone;
10150    struct v4l2_requestbuffers bufreq;
10151    unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
10152    unsigned int final_extra_data_size = 0;
10153    struct v4l2_format fmt;
10154    int ret = 0;
10155    DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10156            buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10157    bufreq.memory = V4L2_MEMORY_USERPTR;
10158    bufreq.count = 1;
10159    if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10160        bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10161        fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10162        fmt.fmt.pix_mp.pixelformat = output_capability;
10163    } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10164        bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10165        fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10166        fmt.fmt.pix_mp.pixelformat = capture_capability;
10167    } else {
10168        eRet = OMX_ErrorBadParameter;
10169    }
10170    if (eRet==OMX_ErrorNone) {
10171        ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10172    }
10173    if (ret) {
10174        DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10175        /*TODO: How to handle this case */
10176        eRet = OMX_ErrorInsufficientResources;
10177        return eRet;
10178    } else {
10179        bool is_res_1080p_or_below = (drv_ctx.video_resolution.frame_width <= 1920 &&
10180                                     drv_ctx.video_resolution.frame_height <= 1088) ||
10181                                     (drv_ctx.video_resolution.frame_height <= 1088 &&
10182                                      drv_ctx.video_resolution.frame_width <= 1920);
10183
10184        int fps = drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator;
10185        bool fps_above_180 =  (fps >= 180 || operating_frame_rate >= 180) ? true : false;
10186        bool increase_output = (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) && (bufreq.count >= 16);
10187
10188        if (increase_output && fps_above_180 &&
10189            output_capability == V4L2_PIX_FMT_H264 &&
10190            is_res_1080p_or_below) {
10191            m_need_turbo |= TURBO_MODE_HIGH_FPS;
10192            DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate);
10193            DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps",
10194                            bufreq.count, bufreq.count + 10);
10195            bufreq.count += 10;
10196            ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10197            if (ret) {
10198                DEBUG_PRINT_ERROR("(Failed to set updated buffer count to driver");
10199                eRet = OMX_ErrorInsufficientResources;
10200                return eRet;
10201            }
10202            DEBUG_PRINT_LOW("new buf count = %d set to driver", bufreq.count);
10203            request_perf_level(VIDC_TURBO);
10204        }
10205
10206        buffer_prop->actualcount = bufreq.count;
10207        buffer_prop->mincount = bufreq.count;
10208        DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
10209    }
10210    DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10211            buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10212
10213    ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10214
10215    if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
10216        drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
10217    DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
10218
10219    if (ret) {
10220        /*TODO: How to handle this case */
10221        DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10222        eRet = OMX_ErrorInsufficientResources;
10223    } else {
10224        int extra_idx = 0;
10225
10226        eRet = is_video_session_supported();
10227        if (eRet)
10228            return eRet;
10229
10230        buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10231        buf_size = buffer_prop->buffer_size;
10232        extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
10233        if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
10234            extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
10235        } else if (extra_idx >= VIDEO_MAX_PLANES) {
10236            DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
10237            return OMX_ErrorBadParameter;
10238        }
10239
10240        default_extra_data_size = VENUS_EXTRADATA_SIZE(
10241                drv_ctx.video_resolution.frame_height,
10242                drv_ctx.video_resolution.frame_width);
10243        final_extra_data_size = extra_data_size > default_extra_data_size ?
10244            extra_data_size : default_extra_data_size;
10245
10246        final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
10247            (~(buffer_prop->alignment - 1));
10248
10249        drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
10250        drv_ctx.extradata_info.count = buffer_prop->actualcount;
10251        drv_ctx.extradata_info.buffer_size = final_extra_data_size;
10252        buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10253        DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
10254                buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
10255        if (extra_data_size)
10256            DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
10257                drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
10258
10259        if (in_reconfig) // BufReq will be set to driver when port is disabled
10260            buffer_prop->buffer_size = buf_size;
10261        else if (buf_size != buffer_prop->buffer_size) {
10262            buffer_prop->buffer_size = buf_size;
10263            eRet = set_buffer_req(buffer_prop);
10264        }
10265    }
10266    DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
10267            buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10268    return eRet;
10269}
10270
10271OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
10272{
10273    OMX_ERRORTYPE eRet = OMX_ErrorNone;
10274    unsigned buf_size = 0;
10275    struct v4l2_format fmt, c_fmt;
10276    struct v4l2_requestbuffers bufreq;
10277    int ret = 0;
10278    DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
10279            buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10280    buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10281    if (buf_size != buffer_prop->buffer_size) {
10282        DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
10283                (unsigned int)buffer_prop->buffer_size, buf_size);
10284        eRet = OMX_ErrorBadParameter;
10285    } else {
10286        memset(&fmt, 0x0, sizeof(struct v4l2_format));
10287        memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
10288        fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10289        fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10290        fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10291
10292        if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10293            fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10294            fmt.fmt.pix_mp.pixelformat = output_capability;
10295            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10296        } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10297            c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10298            c_fmt.fmt.pix_mp.pixelformat = capture_capability;
10299            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
10300            c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10301            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
10302        } else {
10303            eRet = OMX_ErrorBadParameter;
10304        }
10305
10306        if (ret) {
10307            /*TODO: How to handle this case */
10308            DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
10309            eRet = OMX_ErrorInsufficientResources;
10310        }
10311
10312        bufreq.memory = V4L2_MEMORY_USERPTR;
10313        bufreq.count = buffer_prop->actualcount;
10314        if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10315            bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10316        } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10317            bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10318        } else {
10319            eRet = OMX_ErrorBadParameter;
10320        }
10321
10322        if (eRet==OMX_ErrorNone) {
10323            ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10324        }
10325
10326        if (ret) {
10327            DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
10328            /*TODO: How to handle this case */
10329            eRet = OMX_ErrorInsufficientResources;
10330        } else if (bufreq.count < buffer_prop->actualcount) {
10331            DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
10332                    " on v4l2 port %d to %d (prefers %d)", bufreq.type,
10333                    buffer_prop->actualcount, bufreq.count);
10334            eRet = OMX_ErrorInsufficientResources;
10335        } else {
10336            if (!client_buffers.update_buffer_req()) {
10337                DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
10338                eRet = OMX_ErrorInsufficientResources;
10339            }
10340        }
10341    }
10342    return eRet;
10343}
10344
10345OMX_ERRORTYPE omx_vdec::update_picture_resolution()
10346{
10347    OMX_ERRORTYPE eRet = OMX_ErrorNone;
10348    return eRet;
10349}
10350
10351OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
10352{
10353    OMX_ERRORTYPE eRet = OMX_ErrorNone;
10354    struct v4l2_format fmt;
10355    if (!portDefn) {
10356        return OMX_ErrorBadParameter;
10357    }
10358    DEBUG_PRINT_LOW("omx_vdec::update_portdef");
10359    portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
10360    portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10361    portDefn->eDomain    = OMX_PortDomainVideo;
10362    memset(&fmt, 0x0, sizeof(struct v4l2_format));
10363    if (0 == portDefn->nPortIndex) {
10364        portDefn->eDir =  OMX_DirInput;
10365        portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
10366        portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
10367        portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
10368        portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10369        portDefn->format.video.eCompressionFormat = eCompressionFormat;
10370        //for input port, always report the fps value set by client,
10371        //to distinguish whether client got valid fps from parser.
10372        portDefn->format.video.xFramerate = m_fps_received;
10373        portDefn->bEnabled   = m_inp_bEnabled;
10374        portDefn->bPopulated = m_inp_bPopulated;
10375
10376        fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10377        fmt.fmt.pix_mp.pixelformat = output_capability;
10378        ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10379    } else if (1 == portDefn->nPortIndex) {
10380        unsigned int buf_size = 0;
10381        int ret = 0;
10382       if (in_reconfig && !is_down_scalar_enabled) {
10383           fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10384           ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10385           fmt.fmt.pix_mp.pixelformat = capture_capability;
10386           fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10387           ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10388       }
10389
10390       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10391       fmt.fmt.pix_mp.pixelformat = capture_capability;
10392       ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10393       if (ret) {
10394           DEBUG_PRINT_ERROR("Get Resolution failed");
10395           return OMX_ErrorHardware;
10396       }
10397       drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10398       if (!client_buffers.update_buffer_req()) {
10399           DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
10400           return OMX_ErrorHardware;
10401       }
10402
10403        if (!client_buffers.get_buffer_req(buf_size)) {
10404            DEBUG_PRINT_ERROR("update buffer requirements");
10405            return OMX_ErrorHardware;
10406        }
10407        portDefn->nBufferSize = buf_size;
10408        portDefn->eDir =  OMX_DirOutput;
10409        portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
10410        portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
10411        portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10412        if (drv_ctx.frame_rate.fps_denominator > 0)
10413            portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
10414                drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
10415        else {
10416            DEBUG_PRINT_ERROR("Error: Divide by zero");
10417            return OMX_ErrorBadParameter;
10418        }
10419        portDefn->bEnabled   = m_out_bEnabled;
10420        portDefn->bPopulated = m_out_bPopulated;
10421        if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
10422            DEBUG_PRINT_ERROR("Error in getting color format");
10423            return OMX_ErrorHardware;
10424        }
10425        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10426        fmt.fmt.pix_mp.pixelformat = capture_capability;
10427    } else {
10428        portDefn->eDir = OMX_DirMax;
10429        DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
10430                (int)portDefn->nPortIndex);
10431        eRet = OMX_ErrorBadPortIndex;
10432    }
10433    update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10434        fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
10435
10436        portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
10437        portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
10438        portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10439        portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10440
10441    if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
10442       (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
10443           portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
10444           portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
10445    }
10446    DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
10447            "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
10448            (unsigned int)portDefn->nPortIndex,
10449            (unsigned int)portDefn->format.video.nFrameWidth,
10450            (unsigned int)portDefn->format.video.nFrameHeight,
10451            (int)portDefn->format.video.nStride,
10452            (unsigned int)portDefn->format.video.nSliceHeight,
10453            (unsigned int)portDefn->format.video.eColorFormat,
10454            (unsigned int)portDefn->nBufferSize,
10455            (unsigned int)portDefn->nBufferCountActual);
10456
10457    return eRet;
10458}
10459
10460OMX_ERRORTYPE omx_vdec::allocate_output_headers()
10461{
10462    OMX_ERRORTYPE eRet = OMX_ErrorNone;
10463    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
10464    unsigned i= 0;
10465
10466    if (!m_out_mem_ptr) {
10467        DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
10468        int nBufHdrSize        = 0;
10469        int nPlatformEntrySize = 0;
10470        int nPlatformListSize  = 0;
10471        int nPMEMInfoSize = 0;
10472        OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
10473        OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
10474        OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
10475
10476        DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
10477                drv_ctx.op_buf.actualcount);
10478        nBufHdrSize        = drv_ctx.op_buf.actualcount *
10479            sizeof(OMX_BUFFERHEADERTYPE);
10480
10481        nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
10482            sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
10483        nPlatformListSize  = drv_ctx.op_buf.actualcount *
10484            sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
10485        nPlatformEntrySize = drv_ctx.op_buf.actualcount *
10486            sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
10487
10488        DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
10489                (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
10490                nPMEMInfoSize,
10491                nPlatformListSize);
10492        DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
10493                m_out_bm_count);
10494        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
10495        // Alloc mem for platform specific info
10496        char *pPtr=NULL;
10497        pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
10498                nPMEMInfoSize,1);
10499        drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
10500                       calloc (sizeof(struct vdec_bufferpayload),
10501                               drv_ctx.op_buf.actualcount);
10502        drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
10503                     calloc (sizeof (struct vdec_output_frameinfo),
10504                             drv_ctx.op_buf.actualcount);
10505        if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
10506            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
10507            return OMX_ErrorInsufficientResources;
10508        }
10509
10510#ifdef USE_ION
10511        drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
10512                      calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
10513        if (!drv_ctx.op_buf_ion_info) {
10514            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
10515            return OMX_ErrorInsufficientResources;
10516        }
10517#endif
10518        if (dynamic_buf_mode) {
10519            out_dynamic_list = (struct dynamic_buf_list *) \
10520                calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
10521            if (out_dynamic_list) {
10522               for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
10523                  out_dynamic_list[i].dup_fd = -1;
10524            }
10525        }
10526
10527        if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
10528                && drv_ctx.ptr_respbuffer) {
10529            bufHdr          =  m_out_mem_ptr;
10530            m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
10531            m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
10532                (((char *) m_platform_list)  + nPlatformListSize);
10533            m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10534                (((char *) m_platform_entry) + nPlatformEntrySize);
10535            pPlatformList   = m_platform_list;
10536            pPlatformEntry  = m_platform_entry;
10537            pPMEMInfo       = m_pmem_info;
10538
10539            DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
10540
10541            // Settting the entire storage nicely
10542            DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10543                    m_out_mem_ptr,pPlatformEntry);
10544            DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10545            for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10546                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
10547                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
10548                // Set the values when we determine the right HxW param
10549                bufHdr->nAllocLen          = 0;
10550                bufHdr->nFilledLen         = 0;
10551                bufHdr->pAppPrivate        = NULL;
10552                bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
10553                pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10554                pPlatformEntry->entry      = pPMEMInfo;
10555                // Initialize the Platform List
10556                pPlatformList->nEntries    = 1;
10557                pPlatformList->entryList   = pPlatformEntry;
10558                // Keep pBuffer NULL till vdec is opened
10559                bufHdr->pBuffer            = NULL;
10560                pPMEMInfo->offset          =  0;
10561                pPMEMInfo->pmem_fd = -1;
10562                bufHdr->pPlatformPrivate = pPlatformList;
10563                drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
10564#ifdef USE_ION
10565                drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
10566#endif
10567                /*Create a mapping between buffers*/
10568                bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
10569                drv_ctx.ptr_respbuffer[i].client_data = (void *) \
10570                                    &drv_ctx.ptr_outputbuffer[i];
10571                // Move the buffer and buffer header pointers
10572                bufHdr++;
10573                pPMEMInfo++;
10574                pPlatformEntry++;
10575                pPlatformList++;
10576            }
10577        } else {
10578            DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10579                    m_out_mem_ptr, pPtr);
10580            if (m_out_mem_ptr) {
10581                free(m_out_mem_ptr);
10582                m_out_mem_ptr = NULL;
10583            }
10584            if (pPtr) {
10585                free(pPtr);
10586                pPtr = NULL;
10587            }
10588            if (drv_ctx.ptr_outputbuffer) {
10589                free(drv_ctx.ptr_outputbuffer);
10590                drv_ctx.ptr_outputbuffer = NULL;
10591            }
10592            if (drv_ctx.ptr_respbuffer) {
10593                free(drv_ctx.ptr_respbuffer);
10594                drv_ctx.ptr_respbuffer = NULL;
10595            }
10596#ifdef USE_ION
10597            if (drv_ctx.op_buf_ion_info) {
10598                DEBUG_PRINT_LOW("Free o/p ion context");
10599                free(drv_ctx.op_buf_ion_info);
10600                drv_ctx.op_buf_ion_info = NULL;
10601            }
10602#endif
10603            free(drv_ctx.op_buf_map_info);
10604            drv_ctx.op_buf_map_info = NULL;
10605            eRet =  OMX_ErrorInsufficientResources;
10606        }
10607    } else {
10608        eRet =  OMX_ErrorInsufficientResources;
10609    }
10610    return eRet;
10611}
10612
10613void omx_vdec::complete_pending_buffer_done_cbs()
10614{
10615    unsigned long p1, p2, ident;
10616    omx_cmd_queue tmp_q, pending_bd_q;
10617    pthread_mutex_lock(&m_lock);
10618    // pop all pending GENERATE FDB from ftb queue
10619    while (m_ftb_q.m_size) {
10620        m_ftb_q.pop_entry(&p1,&p2,&ident);
10621        if (ident == OMX_COMPONENT_GENERATE_FBD) {
10622            pending_bd_q.insert_entry(p1,p2,ident);
10623        } else {
10624            tmp_q.insert_entry(p1,p2,ident);
10625        }
10626    }
10627    //return all non GENERATE FDB to ftb queue
10628    while (tmp_q.m_size) {
10629        tmp_q.pop_entry(&p1,&p2,&ident);
10630        m_ftb_q.insert_entry(p1,p2,ident);
10631    }
10632    // pop all pending GENERATE EDB from etb queue
10633    while (m_etb_q.m_size) {
10634        m_etb_q.pop_entry(&p1,&p2,&ident);
10635        if (ident == OMX_COMPONENT_GENERATE_EBD) {
10636            pending_bd_q.insert_entry(p1,p2,ident);
10637        } else {
10638            tmp_q.insert_entry(p1,p2,ident);
10639        }
10640    }
10641    //return all non GENERATE FDB to etb queue
10642    while (tmp_q.m_size) {
10643        tmp_q.pop_entry(&p1,&p2,&ident);
10644        m_etb_q.insert_entry(p1,p2,ident);
10645    }
10646    pthread_mutex_unlock(&m_lock);
10647    // process all pending buffer dones
10648    while (pending_bd_q.m_size) {
10649        pending_bd_q.pop_entry(&p1,&p2,&ident);
10650        switch (ident) {
10651            case OMX_COMPONENT_GENERATE_EBD:
10652                if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10653                    DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10654                    omx_report_error ();
10655                }
10656                break;
10657
10658            case OMX_COMPONENT_GENERATE_FBD:
10659                if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10660                    DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10661                    omx_report_error ();
10662                }
10663                break;
10664        }
10665    }
10666}
10667
10668void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10669{
10670    OMX_U32 new_frame_interval = 0;
10671    if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10672            && llabs(act_timestamp - prev_ts) > 2000) {
10673        new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10674            llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10675        if (new_frame_interval != frm_int || frm_int == 0) {
10676            frm_int = new_frame_interval;
10677            if (frm_int) {
10678                drv_ctx.frame_rate.fps_numerator = 1e6;
10679                drv_ctx.frame_rate.fps_denominator = frm_int;
10680                DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10681                        (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10682                        (float)drv_ctx.frame_rate.fps_denominator);
10683                m_perf_control.request_cores(frm_int);
10684                /* We need to report the difference between this FBD and the previous FBD
10685                 * back to the driver for clock scaling purposes. */
10686                struct v4l2_outputparm oparm;
10687                /*XXX: we're providing timing info as seconds per frame rather than frames
10688                 * per second.*/
10689                oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10690                oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10691
10692                struct v4l2_streamparm sparm;
10693                sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10694                sparm.parm.output = oparm;
10695                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10696                    DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10697                            performance might be affected");
10698                }
10699
10700            }
10701        }
10702    }
10703    prev_ts = act_timestamp;
10704}
10705
10706void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10707{
10708    if (rst_prev_ts && VALID_TS(act_timestamp)) {
10709        prev_ts = act_timestamp;
10710        prev_ts_actual = act_timestamp;
10711        rst_prev_ts = false;
10712    } else if (VALID_TS(prev_ts)) {
10713        bool codec_cond = (drv_ctx.timestamp_adjust)?
10714            (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10715            (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10716             prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10717        if (frm_int > 0 && codec_cond) {
10718            DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10719            act_timestamp = prev_ts + frm_int;
10720            DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10721            prev_ts = act_timestamp;
10722        } else {
10723            if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10724                // ensure that timestamps can never step backwards when in display order
10725                act_timestamp = prev_ts;
10726            }
10727            set_frame_rate(act_timestamp);
10728        }
10729    } else if (frm_int > 0)          // In this case the frame rate was set along
10730    {                               // with the port definition, start ts with 0
10731        act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
10732        rst_prev_ts = true;
10733    }
10734}
10735
10736OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index)
10737{
10738    return m_out_mem_ptr + index;
10739}
10740
10741void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10742    OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
10743{
10744    switch (primaries) {
10745        case MSM_VIDC_BT709_5:
10746            *color_space = ITU_R_709;
10747            aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10748            break;
10749        case MSM_VIDC_BT470_6_M:
10750            aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10751            break;
10752        case MSM_VIDC_BT601_6_625:
10753            aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10754            break;
10755        case MSM_VIDC_BT601_6_525:
10756            *color_space = range ? ITU_R_601_FR : ITU_R_601;
10757            aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10758            break;
10759        case MSM_VIDC_GENERIC_FILM:
10760            aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10761            break;
10762        case MSM_VIDC_BT2020:
10763            aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10764            break;
10765        case MSM_VIDC_UNSPECIFIED:
10766            //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10767        default:
10768            //aspects->mPrimaries = ColorAspects::PrimariesOther;
10769            aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10770            break;
10771    }
10772
10773    aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10774
10775    switch (transfer) {
10776        case MSM_VIDC_TRANSFER_BT709_5:
10777        case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10778            aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10779            break;
10780        case MSM_VIDC_TRANSFER_BT_470_6_M:
10781            aspects->mTransfer = ColorAspects::TransferGamma22;
10782            break;
10783        case MSM_VIDC_TRANSFER_BT_470_6_BG:
10784            aspects->mTransfer = ColorAspects::TransferGamma28;
10785            break;
10786        case MSM_VIDC_TRANSFER_SMPTE_240M:
10787            aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10788            break;
10789        case MSM_VIDC_TRANSFER_LINEAR:
10790            aspects->mTransfer = ColorAspects::TransferLinear;
10791            break;
10792        case MSM_VIDC_TRANSFER_IEC_61966:
10793            aspects->mTransfer = ColorAspects::TransferXvYCC;
10794            break;
10795        case MSM_VIDC_TRANSFER_BT_1361:
10796            aspects->mTransfer = ColorAspects::TransferBT1361;
10797            break;
10798        case MSM_VIDC_TRANSFER_SRGB:
10799            aspects->mTransfer = ColorAspects::TransferSRGB;
10800            break;
10801        default:
10802            //aspects->mTransfer = ColorAspects::TransferOther;
10803            aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10804            break;
10805    }
10806
10807    switch (matrix) {
10808        case MSM_VIDC_MATRIX_BT_709_5:
10809            aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10810            break;
10811        case MSM_VIDC_MATRIX_FCC_47:
10812            aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10813            break;
10814        case MSM_VIDC_MATRIX_601_6_625:
10815        case MSM_VIDC_MATRIX_601_6_525:
10816            aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10817            break;
10818        case MSM_VIDC_MATRIX_SMPTE_240M:
10819            aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10820            break;
10821        case MSM_VIDC_MATRIX_BT_2020:
10822            aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10823            break;
10824        case MSM_VIDC_MATRIX_BT_2020_CONST:
10825            aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10826            break;
10827        default:
10828            //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10829            aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10830            break;
10831    }
10832}
10833
10834void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
10835        DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
10836                prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
10837}
10838
10839void omx_vdec::prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range,
10840                                              OMX_U32 transfer, OMX_U32 matrix,
10841                                              ColorMetaData *color_mdata)
10842{
10843
10844    /* ColorAspects in qdMetaData */
10845    color_mdata->colorPrimaries = (enum ColorPrimaries) primaries;
10846    color_mdata->range = (enum ColorRange)range;
10847    color_mdata->transfer = (enum GammaTransfer)transfer;
10848    color_mdata->matrixCoefficients = (enum MatrixCoEfficients)matrix;
10849}
10850
10851bool omx_vdec::handle_color_space_info(void *data,
10852                                       ColorSpace_t *color_space,
10853                                       ColorMetaData *color_mdata,
10854                                       bool& set_color_aspects_only)
10855{
10856    ColorAspects tempAspects;
10857    memset(&tempAspects, 0x0, sizeof(ColorAspects));
10858    ColorAspects *aspects = &tempAspects;
10859
10860    /* Set default ColorAspects */
10861    prepare_color_aspects_metadata(ColorPrimaries_BT601_6_625, Range_Full,
10862                                           Transfer_SMPTE_170M, MatrixCoEff_BT601_6_625,
10863                                           color_mdata);
10864
10865    switch(output_capability) {
10866        case V4L2_PIX_FMT_MPEG2:
10867            {
10868                struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10869                seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10870
10871                /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10872                 * understand this code */
10873
10874                if (seqdisp_payload && seqdisp_payload->color_descp) {
10875
10876                    convert_color_space_info(seqdisp_payload->color_primaries, 1,
10877                            seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10878                            color_space,aspects);
10879                    m_disp_hor_size = seqdisp_payload->disp_width;
10880                    m_disp_vert_size = seqdisp_payload->disp_height;
10881                    set_color_aspects_only = true;
10882                    prepare_color_aspects_metadata(seqdisp_payload->color_primaries, 1,
10883                                                    seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10884                                                    color_mdata);
10885                }
10886            }
10887            break;
10888        case V4L2_PIX_FMT_H264:
10889        case V4L2_PIX_FMT_HEVC:
10890            {
10891                struct msm_vidc_vui_display_info_payload *display_info_payload;
10892                display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10893
10894                /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10895
10896                if (display_info_payload->video_signal_present_flag &&
10897                        display_info_payload->color_description_present_flag) {
10898                    convert_color_space_info(display_info_payload->color_primaries,
10899                            display_info_payload->video_full_range_flag,
10900                            display_info_payload->transfer_characteristics,
10901                            display_info_payload->matrix_coefficients,
10902                            color_space,aspects);
10903                    set_color_aspects_only = true;
10904                    prepare_color_aspects_metadata(display_info_payload->color_primaries,
10905                                                   display_info_payload->video_full_range_flag,
10906                                                   display_info_payload->transfer_characteristics,
10907                                                   display_info_payload->matrix_coefficients,
10908                                                   color_mdata);
10909                }
10910            }
10911            break;
10912        case V4L2_PIX_FMT_VC1_ANNEX_G:
10913        case V4L2_PIX_FMT_VC1_ANNEX_L:
10914            {
10915                struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
10916                vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
10917
10918                /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
10919                 * SMPTE 421M to understand this code */
10920
10921                if (m_enable_android_native_buffers &&
10922                        vc1_seq_disp_payload->color_primaries) {
10923
10924                    convert_color_space_info(vc1_seq_disp_payload->color_primaries,
10925                            1,
10926                            vc1_seq_disp_payload->transfer_char,
10927                            vc1_seq_disp_payload->matrix_coeffs,
10928                            color_space,aspects);
10929                    set_color_aspects_only = true;
10930                    prepare_color_aspects_metadata(vc1_seq_disp_payload->color_primaries,
10931                                                   1,
10932                                                   vc1_seq_disp_payload->transfer_char,
10933                                                   vc1_seq_disp_payload->matrix_coeffs,
10934                                                   color_mdata);
10935                }
10936            }
10937            break;
10938        case V4L2_PIX_FMT_VP8:
10939            {
10940                struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10941                vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10942                set_color_aspects_only = false;
10943                /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10944                 * to understand this code */
10945
10946                if (vpx_color_space_payload->color_space == 0) {
10947                    *color_space = ITU_R_601;
10948                } else {
10949                    DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10950                    break;
10951                }
10952            }
10953            break;
10954        case V4L2_PIX_FMT_VP9:
10955            {
10956                struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10957                vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10958                set_color_aspects_only = false;
10959                /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10960                 * to understand this code */
10961
10962                switch(vpx_color_space_payload->color_space) {
10963                    case MSM_VIDC_CS_BT_601:
10964                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10965                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10966                        aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10967                        aspects->mRange = m_client_color_space.sAspects.mRange;
10968                        break;
10969                    case MSM_VIDC_CS_BT_709:
10970                        *color_space = ITU_R_709;
10971                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10972                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10973                        aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
10974                        aspects->mRange = m_client_color_space.sAspects.mRange;
10975                        break;
10976                    case MSM_VIDC_CS_SMPTE_170:
10977                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10978                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10979                        aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10980                        aspects->mRange = m_client_color_space.sAspects.mRange;
10981                        break;
10982                    case MSM_VIDC_CS_SMPTE_240:
10983                        aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10984                        aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10985                        aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10986                        aspects->mRange = m_client_color_space.sAspects.mRange;
10987                        break;
10988                    case MSM_VIDC_CS_BT_2020:
10989                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10990                        aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
10991                        aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10992                        aspects->mRange = m_client_color_space.sAspects.mRange;
10993                        break;
10994                    case MSM_VIDC_CS_RESERVED:
10995                        aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10996                        aspects->mTransfer = ColorAspects::TransferOther;
10997                        aspects->mPrimaries = ColorAspects::PrimariesOther;
10998                        aspects->mRange = m_client_color_space.sAspects.mRange;
10999                        break;
11000                    case MSM_VIDC_CS_RGB:
11001                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11002                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11003                        aspects->mPrimaries = ColorAspects::PrimariesOther;
11004                        aspects->mRange = m_client_color_space.sAspects.mRange;
11005                        break;
11006                    default:
11007                        break;
11008                }
11009            }
11010            break;
11011        default:
11012            break;
11013    }
11014
11015    print_debug_color_aspects(aspects, "Bitstream");
11016
11017    if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
11018            m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
11019            m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
11020            m_internal_color_space.sAspects.mRange != aspects->mRange) {
11021        memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
11022        m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
11023
11024        m_color_mdata.colorPrimaries = color_mdata->colorPrimaries;
11025        m_color_mdata.range = color_mdata->range;
11026        m_color_mdata.transfer = color_mdata->transfer;
11027        m_color_mdata.matrixCoefficients = color_mdata->matrixCoefficients;
11028
11029        DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
11030        print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
11031        print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
11032
11033        post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11034                OMX_QTIIndexConfigDescribeColorAspects,
11035                OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11036        return true;
11037    }
11038    return false;
11039}
11040
11041void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
11042    private_handle_t *private_handle = NULL;
11043    if (buf_index < drv_ctx.op_buf.actualcount &&
11044            buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11045            native_buffer[buf_index].privatehandle) {
11046        private_handle = native_buffer[buf_index].privatehandle;
11047    }
11048    if (private_handle) {
11049        setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
11050    }
11051}
11052
11053void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
11054{
11055    if (!hdr_info->mID) {
11056        DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
11057                         hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
11058        DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
11059                         hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
11060        DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
11061                         hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
11062        DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
11063                         hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
11064        DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
11065                         hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
11066        DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
11067                        hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
11068    }
11069
11070}
11071
11072void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
11073{
11074    DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
11075                    color_mdata->colorPrimaries, color_mdata->range,
11076                    color_mdata->transfer, color_mdata->matrixCoefficients);
11077
11078    for(uint8_t i = 0; i < 3; i++) {
11079        for(uint8_t j = 0; j < 2; j++) {
11080            DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
11081        }
11082    }
11083
11084    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
11085                    color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
11086                    color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
11087
11088    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
11089                    color_mdata->masteringDisplayInfo.maxDisplayLuminance,
11090                    color_mdata->masteringDisplayInfo.minDisplayLuminance);
11091
11092    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
11093                    color_mdata->contentLightLevel.maxContentLightLevel,
11094                    color_mdata->contentLightLevel.minPicAverageLightLevel);
11095
11096
11097}
11098
11099bool omx_vdec::handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata)
11100{
11101    struct msm_vidc_content_light_level_sei_payload *light_level_payload =
11102        (msm_vidc_content_light_level_sei_payload*)(data);
11103
11104    light_level_mdata->lightLevelSEIEnabled = true;
11105    light_level_mdata->maxContentLightLevel = light_level_payload->nMaxContentLight;
11106    light_level_mdata->minPicAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11107
11108    if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
11109        (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
11110        m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
11111        m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11112        return true;
11113    }
11114    return false;
11115}
11116
11117bool omx_vdec::handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata)
11118{
11119    struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
11120        (msm_vidc_mastering_display_colour_sei_payload*)(data);
11121    HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
11122    bool internal_disp_changed_flag = false;
11123
11124    mastering_display_mdata->colorVolumeSEIEnabled = true;
11125    for (uint8_t i = 0; i < 3; i++) {
11126        mastering_display_mdata->primaries.rgbPrimaries[i][0] = mastering_display_payload->nDisplayPrimariesX[i];
11127        mastering_display_mdata->primaries.rgbPrimaries[i][1] = mastering_display_payload->nDisplayPrimariesY[i];
11128    }
11129    mastering_display_mdata->primaries.whitePoint[0] = mastering_display_payload->nWhitePointX;
11130    mastering_display_mdata->primaries.whitePoint[1] = mastering_display_payload->nWhitePointY;
11131    mastering_display_mdata->maxDisplayLuminance = mastering_display_payload->nMaxDisplayMasteringLuminance;
11132    mastering_display_mdata->minDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11133
11134    internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
11135        (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[0]);
11136    internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
11137        (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[1]);
11138    internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
11139        (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[2]);
11140
11141    internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
11142        (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
11143
11144    /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
11145       requires it in cd/m2, so dividing by 10000 and rounding the value after division
11146    */
11147    uint16_t max_display_luminance_cd_m2 =
11148        static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
11149    internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
11150        (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
11151
11152    if (internal_disp_changed_flag) {
11153        hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[0];
11154        hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[0];
11155        hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[1];
11156        hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[1];
11157        hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[2];
11158        hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[2];
11159        hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
11160        hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
11161
11162        hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
11163        hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11164    }
11165
11166    return internal_disp_changed_flag;
11167}
11168
11169void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
11170{
11171    private_handle_t *private_handle = NULL;
11172    if (buf_index < drv_ctx.op_buf.actualcount &&
11173        buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11174        native_buffer[buf_index].privatehandle) {
11175        private_handle = native_buffer[buf_index].privatehandle;
11176    }
11177    if (private_handle) {
11178        setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
11179    }
11180}
11181
11182void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11183{
11184    OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
11185    OMX_U8 *pBuffer = NULL;
11186    OMX_U32 num_conceal_MB = 0;
11187    OMX_TICKS time_stamp = 0;
11188    OMX_U32 frame_rate = 0;
11189    unsigned long consumed_len = 0;
11190    OMX_U32 num_MB_in_frame;
11191    OMX_U32 recovery_sei_flags = 1;
11192    int enable = OMX_InterlaceFrameProgressive;
11193    bool internal_hdr_info_changed_flag = false;
11194    bool color_event = false;
11195    ColorMetaData color_mdata;
11196    memset(&color_mdata, 0x0, sizeof(ColorMetaData));
11197    bool set_disp_color_aspects_only = false;
11198    ColorSpace_t color_space = ITU_R_601;
11199
11200    int buf_index = p_buf_hdr - m_out_mem_ptr;
11201    if (buf_index >= drv_ctx.extradata_info.count) {
11202        DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
11203                buf_index, drv_ctx.extradata_info.count);
11204        return;
11205    }
11206    struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
11207
11208    if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
11209        DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
11210        return;
11211    }
11212
11213    if (!drv_ctx.extradata_info.uaddr) {
11214        DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
11215        return;
11216    }
11217    if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
11218        DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
11219        p_extra = NULL;
11220        return;
11221    }
11222    if (!secure_mode) {
11223        pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
11224                    PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
11225        if (pBuffer == MAP_FAILED) {
11226            DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno);
11227            return;
11228        }
11229        p_extra = (OMX_OTHER_EXTRADATATYPE *)
11230            ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
11231    } else
11232        p_extra = m_other_extradata;
11233
11234    AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
11235    if (m_client_extradata_info.getBase() &&
11236        m_client_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
11237        p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (m_client_extradata_info.getBase() +
11238                            buf_index * m_client_extradata_info.getSize());
11239    }
11240
11241    char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
11242
11243    if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11244        p_extra = NULL;
11245        DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11246        return;
11247    }
11248    m_extradata_info.output_crop_updated = OMX_FALSE;
11249    OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
11250    if (data && p_extra) {
11251        while ((consumed_len < drv_ctx.extradata_info.buffer_size)
11252                && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
11253            if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
11254                DEBUG_PRINT_LOW("Invalid extra data size");
11255                break;
11256            }
11257
11258            if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11259                p_extra = NULL;
11260                DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11261                return;
11262            }
11263
11264            DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
11265            switch ((unsigned long)data->eType) {
11266                case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
11267                    struct msm_vidc_interlace_payload *payload;
11268                    OMX_U32 interlace_color_format;
11269                    payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
11270                    if (payload) {
11271                        enable = OMX_InterlaceFrameProgressive;
11272                        switch (payload->format) {
11273                            case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
11274                                drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11275                                break;
11276                            case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
11277                                drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11278                                enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
11279                                break;
11280                            case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
11281                                drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11282                                enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11283                                break;
11284                            default:
11285                                DEBUG_PRINT_LOW("default case - set to progressive");
11286                                drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11287                        }
11288                        switch (payload->color_format) {
11289                           case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
11290                               interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11291                               break;
11292                           case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
11293                               interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11294                               break;
11295                           default:
11296                               interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11297                               DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
11298                        }
11299                    }
11300
11301                    if (m_enable_android_native_buffers) {
11302                        DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
11303                                         payload->format, interlace_color_format ,enable,
11304                                        (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
11305
11306                        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11307                               PP_PARAM_INTERLACED, (void*)&enable);
11308
11309                        if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
11310                            setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11311                               LINEAR_FORMAT, (void*)&interlace_color_format);
11312                        } else if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11313                            setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11314                               LINEAR_FORMAT, NULL);
11315                        }
11316                    }
11317                    if (client_extradata & OMX_INTERLACE_EXTRADATA) {
11318                        append_interlace_extradata(p_extra, payload->format);
11319                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11320                        if (p_client_extra) {
11321                            append_interlace_extradata(p_client_extra, payload->format);
11322                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
11323                                (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11324                        }
11325                    }
11326                    break;
11327                case MSM_VIDC_EXTRADATA_FRAME_RATE:
11328                    struct msm_vidc_framerate_payload *frame_rate_payload;
11329                    frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
11330                    frame_rate = frame_rate_payload->frame_rate;
11331                    break;
11332                case MSM_VIDC_EXTRADATA_TIMESTAMP:
11333                    struct msm_vidc_ts_payload *time_stamp_payload;
11334                    time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
11335                    time_stamp = time_stamp_payload->timestamp_lo;
11336                    time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
11337                    p_buf_hdr->nTimeStamp = time_stamp;
11338                    break;
11339                case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
11340                    struct msm_vidc_concealmb_payload *conceal_mb_payload;
11341                    conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
11342                    num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11343                            (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11344                    num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
11345                    break;
11346                case MSM_VIDC_EXTRADATA_INDEX:
11347                    int *etype;
11348                    etype  = (int *)(void *)data->data;
11349                    if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
11350                        struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
11351                        aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
11352                        if (aspect_ratio_payload) {
11353                            ((struct vdec_output_frameinfo *)
11354                             p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
11355                            ((struct vdec_output_frameinfo *)
11356                             p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
11357                        }
11358                    } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
11359                        struct msm_vidc_output_crop_payload *output_crop_payload;
11360                        output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
11361                        if (output_crop_payload) {
11362                            m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
11363                            m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
11364                            m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
11365                            m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
11366                            m_extradata_info.output_width = output_crop_payload->width;
11367                            m_extradata_info.output_height = output_crop_payload->height;
11368                            m_extradata_info.output_crop_updated = OMX_TRUE;
11369                        }
11370                    }
11371                    break;
11372                case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
11373                    struct msm_vidc_recoverysei_payload *recovery_sei_payload;
11374                    recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
11375                    recovery_sei_flags = recovery_sei_payload->flags;
11376                    if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
11377                        p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
11378                        DEBUG_PRINT_HIGH("***************************************************");
11379                        DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
11380                        DEBUG_PRINT_HIGH("***************************************************");
11381                    }
11382                    break;
11383               case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
11384                    panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
11385                    if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
11386                        DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
11387                        DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
11388                            MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
11389                        return;
11390                    }
11391                    break;
11392                case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
11393                case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
11394                case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
11395                case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
11396                    color_event = handle_color_space_info((void *)data->data, &color_space, &color_mdata, set_disp_color_aspects_only);
11397                    break;
11398                case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
11399                    struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
11400                    s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
11401                    switch (s3d_frame_packing_payload->fpa_type) {
11402                        case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
11403                            if (s3d_frame_packing_payload->content_interprtation_type == 1)
11404                                stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
11405                            else if (s3d_frame_packing_payload->content_interprtation_type == 2)
11406                                stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
11407                            else {
11408                                DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
11409                                stereo_output_mode = HAL_NO_3D;
11410                            }
11411                            break;
11412                        case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
11413                            stereo_output_mode = HAL_3D_TOP_BOTTOM;
11414                            break;
11415                        default:
11416                            DEBUG_PRINT_ERROR("Unsupported framepacking type");
11417                            stereo_output_mode = HAL_NO_3D;
11418                    }
11419                    DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
11420                        s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
11421                    if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
11422                        append_framepack_extradata(p_extra, s3d_frame_packing_payload);
11423                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11424                        if (p_client_extra) {
11425                            append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
11426                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11427                        }
11428                    }
11429                    break;
11430                case MSM_VIDC_EXTRADATA_FRAME_QP:
11431                    struct msm_vidc_frame_qp_payload *qp_payload;
11432                    qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
11433                    if (client_extradata & OMX_QP_EXTRADATA) {
11434                        append_qp_extradata(p_extra, qp_payload);
11435                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11436                        if (p_client_extra) {
11437                            append_qp_extradata(p_client_extra, qp_payload);
11438                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11439                        }
11440                    }
11441                    break;
11442                case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
11443                    struct msm_vidc_frame_bits_info_payload *bits_info_payload;
11444                    bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
11445                    if (client_extradata & OMX_BITSINFO_EXTRADATA) {
11446                        append_bitsinfo_extradata(p_extra, bits_info_payload);
11447                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11448                        if (p_client_extra) {
11449                            append_bitsinfo_extradata(p_client_extra, bits_info_payload);
11450                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11451                        }
11452                    }
11453                    break;
11454                case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
11455                    if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
11456                        append_user_extradata(p_extra, data);
11457                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11458                        if (p_client_extra) {
11459                            append_user_extradata(p_client_extra, data);
11460                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11461                        }
11462                    }
11463                    break;
11464                case MSM_VIDC_EXTRADATA_VQZIP_SEI:
11465                    struct msm_vidc_vqzip_sei_payload *vqzip_payload;
11466                    vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
11467                    if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
11468                        p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11469                        append_vqzip_extradata(p_extra, vqzip_payload);
11470                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11471                        if (p_client_extra) {
11472                            append_vqzip_extradata(p_client_extra, vqzip_payload);
11473                            p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11474                        }
11475                    }
11476                    break;
11477                case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
11478
11479                    internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data,
11480                                                                                      &(color_mdata.contentLightLevel));
11481                    break;
11482                case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
11483                    internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data,
11484                                                                                          &(color_mdata.masteringDisplayInfo));
11485                    break;
11486                default:
11487                    DEBUG_PRINT_LOW("Unrecognized extradata");
11488                    goto unrecognized_extradata;
11489            }
11490            consumed_len += data->nSize;
11491            data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
11492        }
11493        if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
11494            p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11495            append_frame_info_extradata(p_extra,
11496                    num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11497                    time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11498                        p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11499            p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11500            if (p_client_extra) {
11501                append_frame_info_extradata(p_client_extra,
11502                        num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11503                        time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11504                            p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11505                p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11506            }
11507        }
11508        if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
11509            append_frame_dimension_extradata(p_extra);
11510            p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11511            if (p_client_extra) {
11512                append_frame_dimension_extradata(p_client_extra);
11513                p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11514            }
11515        }
11516
11517        if(internal_hdr_info_changed_flag) {
11518            print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
11519            print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
11520            memcpy(&m_color_mdata, &color_mdata, sizeof(ColorMetaData));
11521            auto_lock lock(m_hdr_info_client_lock);
11522            m_change_client_hdr_info = true;
11523            if(!color_event) {
11524                DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
11525                post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11526                           OMX_QTIIndexConfigDescribeHDRColorInfo,
11527                           OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11528            }
11529        }
11530
11531        if (m_enable_android_native_buffers) {
11532            if (set_disp_color_aspects_only) {
11533                print_debug_hdr_color_info_mdata(&m_color_mdata);
11534                set_colormetadata_in_handle(&m_color_mdata, buf_index);
11535            } else {
11536                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);
11537                set_colorspace_in_handle(color_space, buf_index);
11538            }
11539        }
11540
11541    }
11542unrecognized_extradata:
11543    if (client_extradata && p_extra) {
11544        p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11545        append_terminator_extradata(p_extra);
11546        if (p_client_extra) {
11547            append_terminator_extradata(p_client_extra);
11548        }
11549    }
11550    if (secure_mode && p_extradata && m_other_extradata) {
11551        struct vdec_output_frameinfo  *ptr_extradatabuff = NULL;
11552        memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
11553        ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
11554        ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
11555        ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
11556        ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd;
11557        ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size;
11558        ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size;
11559    }
11560    return;
11561}
11562
11563OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
11564        bool is_internal, bool enable)
11565{
11566    OMX_ERRORTYPE ret = OMX_ErrorNone;
11567    struct v4l2_control control;
11568    if (m_state != OMX_StateLoaded) {
11569        DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
11570        return OMX_ErrorIncorrectStateOperation;
11571    }
11572    DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
11573            (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
11574
11575    if (!is_internal) {
11576        if (enable)
11577            client_extradata |= requested_extradata;
11578        else
11579            client_extradata = client_extradata & ~requested_extradata;
11580    }
11581
11582    if (enable) {
11583        if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
11584            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11585            control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
11586            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11587                DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
11588                        " Quality of interlaced clips might be impacted.");
11589            }
11590        }
11591        if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
11592            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11593            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
11594            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11595                DEBUG_PRINT_HIGH("Failed to set framerate extradata");
11596            }
11597            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11598            control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
11599            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11600                DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
11601            }
11602            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11603            control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
11604            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11605                DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
11606            }
11607            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11608            control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
11609            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11610                DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11611            }
11612            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11613            control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
11614            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11615                DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11616            }
11617            if (output_capability == V4L2_PIX_FMT_MPEG2) {
11618                control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11619                control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11620                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11621                    DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11622                }
11623            }
11624        }
11625        if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
11626            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11627            control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
11628            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11629                DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
11630            }
11631        }
11632        if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
11633            if (output_capability == V4L2_PIX_FMT_H264) {
11634                DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
11635                control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11636                control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
11637                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11638                    DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
11639                }
11640            } else {
11641                DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
11642            }
11643        }
11644        if (requested_extradata & OMX_QP_EXTRADATA) {
11645            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11646            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11647            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11648                DEBUG_PRINT_HIGH("Failed to set QP extradata");
11649            }
11650        }
11651        if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
11652            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11653            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
11654            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11655                DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
11656            }
11657        }
11658        if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
11659            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11660            control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
11661            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11662                DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
11663            }
11664        }
11665        if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
11666            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11667            control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
11668            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11669                DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
11670            }
11671            client_extradata |= OMX_VQZIPSEI_EXTRADATA;
11672
11673            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11674            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11675            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11676                DEBUG_PRINT_HIGH("Failed to set QP extradata");
11677            }
11678            client_extradata |= OMX_QP_EXTRADATA;
11679        }
11680        if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11681            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11682            control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
11683            DEBUG_PRINT_LOW("Enable output crop extra data");
11684            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11685                DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11686            }
11687        }
11688        if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
11689            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11690            switch(output_capability) {
11691                case V4L2_PIX_FMT_H264:
11692                case V4L2_PIX_FMT_HEVC:
11693                    control.value =  V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
11694                    break;
11695                case CODEC_TYPE_MPEG2:
11696                    control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11697                    break;
11698                case V4L2_PIX_FMT_VP8:
11699                case V4L2_PIX_FMT_VP9:
11700                    control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
11701                    break;
11702                case V4L2_PIX_FMT_VC1_ANNEX_G:
11703                case V4L2_PIX_FMT_VC1_ANNEX_L:
11704                    control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
11705                    break;
11706                default:
11707                    DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
11708                    return ret;
11709            }
11710
11711            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11712                DEBUG_PRINT_HIGH("Failed to set Display info extradata");
11713            }
11714        }
11715        if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
11716            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11717            if (output_capability == V4L2_PIX_FMT_H264 ||
11718                output_capability == V4L2_PIX_FMT_HEVC) {
11719                control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
11720                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11721                    DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
11722                }
11723                control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
11724                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11725                    DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
11726                }
11727            }
11728        }
11729    }
11730    ret = get_buffer_req(&drv_ctx.op_buf);
11731    return ret;
11732}
11733
11734OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11735{
11736    OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
11737    OMX_U8 *data_ptr = extra->data, data = 0;
11738    while (byte_count < extra->nDataSize) {
11739        data = *data_ptr;
11740        while (data) {
11741            num_MB += (data&0x01);
11742            data >>= 1;
11743        }
11744        data_ptr++;
11745        byte_count++;
11746    }
11747    num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11748            (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11749    return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
11750}
11751
11752void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11753{
11754    if (!m_debug_extradata || !extra)
11755        return;
11756
11757
11758    DEBUG_PRINT_HIGH(
11759            "============== Extra Data ==============\n"
11760            "           Size: %u\n"
11761            "        Version: %u\n"
11762            "      PortIndex: %u\n"
11763            "           Type: %x\n"
11764            "       DataSize: %u",
11765            (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
11766            (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
11767
11768    if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
11769        OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11770        DEBUG_PRINT_HIGH(
11771                "------ Interlace Format ------\n"
11772                "                Size: %u\n"
11773                "             Version: %u\n"
11774                "           PortIndex: %u\n"
11775                " Is Interlace Format: %d\n"
11776                "   Interlace Formats: %u\n"
11777                "=========== End of Interlace ===========",
11778                (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
11779                intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
11780    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
11781        OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11782
11783        DEBUG_PRINT_HIGH(
11784                "-------- Frame Format --------\n"
11785                "             Picture Type: %d\n"
11786                "           Interlace Type: %d\n"
11787                " Pan Scan Total Frame Num: %u\n"
11788                "   Concealed Macro Blocks: %u\n"
11789                "        Recovery SEI Flag: %u\n"
11790                "               frame rate: %u\n"
11791                "               Time Stamp: %llu\n"
11792                "           Aspect Ratio X: %u\n"
11793                "           Aspect Ratio Y: %u",
11794                fminfo->ePicType,
11795                fminfo->interlaceType,
11796                (unsigned int)fminfo->panScan.numWindows,
11797                (unsigned int)fminfo->nConcealedMacroblocks,
11798                (unsigned int)fminfo->nRecoverySeiFlag,
11799                (unsigned int)fminfo->nFrameRate,
11800                fminfo->nTimeStamp,
11801                (unsigned int)fminfo->aspectRatio.aspectRatioX,
11802                (unsigned int)fminfo->aspectRatio.aspectRatioY);
11803
11804        for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
11805            DEBUG_PRINT_HIGH(
11806                    "------------------------------"
11807                    "     Pan Scan Frame Num: %u\n"
11808                    "            Rectangle x: %d\n"
11809                    "            Rectangle y: %d\n"
11810                    "           Rectangle dx: %d\n"
11811                    "           Rectangle dy: %d",
11812                    (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
11813                    (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
11814        }
11815
11816        DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
11817    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
11818        OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11819        DEBUG_PRINT_HIGH(
11820                "------------------ Framepack Format ----------\n"
11821                "                           id: %u \n"
11822                "                  cancel_flag: %u \n"
11823                "                         type: %u \n"
11824                " quincunx_sampling_flagFormat: %u \n"
11825                "  content_interpretation_type: %u \n"
11826                "        spatial_flipping_flag: %u \n"
11827                "          frame0_flipped_flag: %u \n"
11828                "             field_views_flag: %u \n"
11829                " current_frame_is_frame0_flag: %u \n"
11830                "   frame0_self_contained_flag: %u \n"
11831                "   frame1_self_contained_flag: %u \n"
11832                "       frame0_grid_position_x: %u \n"
11833                "       frame0_grid_position_y: %u \n"
11834                "       frame1_grid_position_x: %u \n"
11835                "       frame1_grid_position_y: %u \n"
11836                "                reserved_byte: %u \n"
11837                "            repetition_period: %u \n"
11838                "               extension_flag: %u \n"
11839                "================== End of Framepack ===========",
11840                (unsigned int)framepack->id,
11841                (unsigned int)framepack->cancel_flag,
11842                (unsigned int)framepack->type,
11843                (unsigned int)framepack->quincunx_sampling_flag,
11844                (unsigned int)framepack->content_interpretation_type,
11845                (unsigned int)framepack->spatial_flipping_flag,
11846                (unsigned int)framepack->frame0_flipped_flag,
11847                (unsigned int)framepack->field_views_flag,
11848                (unsigned int)framepack->current_frame_is_frame0_flag,
11849                (unsigned int)framepack->frame0_self_contained_flag,
11850                (unsigned int)framepack->frame1_self_contained_flag,
11851                (unsigned int)framepack->frame0_grid_position_x,
11852                (unsigned int)framepack->frame0_grid_position_y,
11853                (unsigned int)framepack->frame1_grid_position_x,
11854                (unsigned int)framepack->frame1_grid_position_y,
11855                (unsigned int)framepack->reserved_byte,
11856                (unsigned int)framepack->repetition_period,
11857                (unsigned int)framepack->extension_flag);
11858    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
11859        OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11860        DEBUG_PRINT_HIGH(
11861                "---- QP (Frame quantization parameter) ----\n"
11862                "    Frame QP: %u \n"
11863                "================ End of QP ================\n",
11864                (unsigned int)qp->nQP);
11865    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
11866        OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
11867        DEBUG_PRINT_HIGH(
11868                "--------- Input bits information --------\n"
11869                "    Header bits: %u \n"
11870                "     Frame bits: %u \n"
11871                "===== End of Input bits information =====\n",
11872                (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
11873    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
11874        OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
11875        OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
11876        OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
11877        OMX_U32 i = 0;
11878        DEBUG_PRINT_HIGH(
11879                "--------------  Userdata  -------------\n"
11880                "    Stream userdata type: %u\n"
11881                "          userdata size: %u\n"
11882                "    STREAM_USERDATA:",
11883                (unsigned int)userdata->type, (unsigned int)userdata_size);
11884                for (i = 0; i < userdata_size; i+=4) {
11885                    DEBUG_PRINT_HIGH("        %x %x %x %x",
11886                        data_ptr[i], data_ptr[i+1],
11887                        data_ptr[i+2], data_ptr[i+3]);
11888                }
11889        DEBUG_PRINT_HIGH(
11890                "=========== End of Userdata ===========");
11891    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
11892        OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11893        DEBUG_PRINT_HIGH(
11894                "--------------  VQZip  -------------\n"
11895                "    Size: %u\n",
11896                (unsigned int)vq->nSize);
11897        DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
11898    } else if (extra->eType == OMX_ExtraDataNone) {
11899        DEBUG_PRINT_HIGH("========== End of Terminator ===========");
11900    } else {
11901        DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
11902    }
11903}
11904
11905void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11906        OMX_U32 interlaced_format_type)
11907{
11908    OMX_STREAMINTERLACEFORMAT *interlace_format;
11909
11910    if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
11911        return;
11912    }
11913    if (!extra) {
11914       DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
11915       return;
11916    }
11917    extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
11918    extra->nVersion.nVersion = OMX_SPEC_VERSION;
11919    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11920    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
11921    extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11922    interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11923    interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11924    interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
11925    interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11926
11927    if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
11928        interlace_format->bInterlaceFormat = OMX_FALSE;
11929        interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11930        drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11931    } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
11932        interlace_format->bInterlaceFormat = OMX_TRUE;
11933        interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
11934        drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11935    } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
11936        interlace_format->bInterlaceFormat = OMX_TRUE;
11937        interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11938        drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11939    } else {
11940        //default case - set to progressive
11941        interlace_format->bInterlaceFormat = OMX_FALSE;
11942        interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11943        drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11944    }
11945    print_debug_extradata(extra);
11946}
11947
11948void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11949{
11950    OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
11951    if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
11952        return;
11953    }
11954    extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
11955    extra->nVersion.nVersion = OMX_SPEC_VERSION;
11956    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11957    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
11958    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
11959    frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
11960    frame_dimension->nDecWidth = rectangle.nLeft;
11961    frame_dimension->nDecHeight = rectangle.nTop;
11962    frame_dimension->nActualWidth = rectangle.nWidth;
11963    frame_dimension->nActualHeight = rectangle.nHeight;
11964}
11965
11966void omx_vdec::fill_aspect_ratio_info(
11967        struct vdec_aspectratioinfo *aspect_ratio_info,
11968        OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
11969{
11970    m_extradata = frame_info;
11971    m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
11972    m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
11973    DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
11974            (unsigned int)m_extradata->aspectRatio.aspectRatioY);
11975}
11976
11977void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11978        OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
11979        OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
11980        struct vdec_aspectratioinfo *aspect_ratio_info)
11981{
11982    OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
11983    struct msm_vidc_panscan_window *panscan_window;
11984    if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
11985        return;
11986    }
11987    extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
11988    extra->nVersion.nVersion = OMX_SPEC_VERSION;
11989    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11990    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
11991    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
11992    frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11993    switch (picture_type) {
11994        case PICTURE_TYPE_I:
11995            frame_info->ePicType = OMX_VIDEO_PictureTypeI;
11996            break;
11997        case PICTURE_TYPE_P:
11998            frame_info->ePicType = OMX_VIDEO_PictureTypeP;
11999            break;
12000        case PICTURE_TYPE_B:
12001            frame_info->ePicType = OMX_VIDEO_PictureTypeB;
12002            break;
12003        default:
12004            frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
12005    }
12006    if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
12007        frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
12008    else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
12009        frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
12010    else
12011        frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
12012    memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
12013    frame_info->nConcealedMacroblocks = num_conceal_mb;
12014    frame_info->nRecoverySeiFlag = recovery_sei_flag;
12015    frame_info->nFrameRate = frame_rate;
12016    frame_info->nTimeStamp = time_stamp;
12017    frame_info->panScan.numWindows = 0;
12018    if (output_capability == V4L2_PIX_FMT_MPEG2) {
12019        if (m_disp_hor_size && m_disp_vert_size) {
12020            frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
12021            frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
12022        } else {
12023            frame_info->displayAspectRatio.displayHorizontalSize = 0;
12024            frame_info->displayAspectRatio.displayVerticalSize = 0;
12025        }
12026    }
12027
12028    if (panscan_payload) {
12029        frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
12030        panscan_window = &panscan_payload->wnd[0];
12031        for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
12032            frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
12033            frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
12034            frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
12035            frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
12036            panscan_window++;
12037        }
12038    }
12039    fill_aspect_ratio_info(aspect_ratio_info, frame_info);
12040    print_debug_extradata(extra);
12041}
12042
12043void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12044{
12045    OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
12046    extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
12047    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12048    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12049    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
12050    extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
12051    portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
12052    *portDefn = m_port_def;
12053    DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
12054            "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
12055            (unsigned int)portDefn->format.video.nFrameWidth,
12056            (unsigned int)portDefn->format.video.nStride,
12057            (unsigned int)portDefn->format.video.nSliceHeight);
12058}
12059
12060void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12061        struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
12062{
12063    OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
12064    if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
12065        DEBUG_PRINT_ERROR("frame packing size mismatch");
12066        return;
12067    }
12068    extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
12069    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12070    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12071    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
12072    extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12073    framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12074    framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12075    framepack->nVersion.nVersion = OMX_SPEC_VERSION;
12076    framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12077    memcpy(&framepack->id, s3d_frame_packing_payload,
12078        sizeof(struct msm_vidc_s3d_frame_packing_payload));
12079    memcpy(&m_frame_pack_arrangement, framepack,
12080        sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
12081    print_debug_extradata(extra);
12082}
12083
12084void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12085            struct msm_vidc_frame_qp_payload *qp_payload)
12086{
12087    OMX_QCOM_EXTRADATA_QP * qp = NULL;
12088    if (!qp_payload) {
12089        DEBUG_PRINT_ERROR("QP payload is NULL");
12090        return;
12091    }
12092    extra->nSize = OMX_QP_EXTRADATA_SIZE;
12093    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12094    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12095    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
12096    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
12097    qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12098    qp->nQP = qp_payload->frame_qp;
12099    print_debug_extradata(extra);
12100}
12101
12102void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12103            struct msm_vidc_frame_bits_info_payload *bits_payload)
12104{
12105    OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
12106    if (!bits_payload) {
12107        DEBUG_PRINT_ERROR("bits info payload is NULL");
12108        return;
12109    }
12110    extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
12111    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12112    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12113    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
12114    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
12115    bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
12116    bits->frame_bits = bits_payload->frame_bits;
12117    bits->header_bits = bits_payload->header_bits;
12118    print_debug_extradata(extra);
12119}
12120
12121void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12122            OMX_OTHER_EXTRADATATYPE *p_user)
12123{
12124    int userdata_size = 0;
12125    struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
12126    userdata_payload =
12127        (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
12128    userdata_size = p_user->nDataSize;
12129    extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
12130    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12131    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12132    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
12133    extra->nDataSize = userdata_size;
12134    if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
12135        memcpy(extra->data, p_user->data, extra->nDataSize);
12136    print_debug_extradata(extra);
12137}
12138
12139void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12140{
12141    if (!client_extradata) {
12142        return;
12143    }
12144    extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
12145    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12146    extra->eType = OMX_ExtraDataNone;
12147    extra->nDataSize = 0;
12148    extra->data[0] = 0;
12149
12150    print_debug_extradata(extra);
12151}
12152
12153void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12154        struct msm_vidc_vqzip_sei_payload *vqzip_payload)
12155{
12156    OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
12157
12158    extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
12159    extra->nVersion.nVersion = OMX_SPEC_VERSION;
12160    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12161    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
12162    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
12163
12164    vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
12165    vq->nSize = vqzip_payload->size;
12166    memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
12167
12168    print_debug_extradata(extra);
12169}
12170
12171OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
12172{
12173    OMX_ERRORTYPE eRet = OMX_ErrorNone;
12174    if (index >= drv_ctx.ip_buf.actualcount) {
12175        DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
12176        return OMX_ErrorInsufficientResources;
12177    }
12178    if (m_desc_buffer_ptr == NULL) {
12179        m_desc_buffer_ptr = (desc_buffer_hdr*) \
12180                    calloc( (sizeof(desc_buffer_hdr)),
12181                            drv_ctx.ip_buf.actualcount);
12182        if (m_desc_buffer_ptr == NULL) {
12183            DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
12184            return OMX_ErrorInsufficientResources;
12185        }
12186    }
12187
12188    m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
12189    if (m_desc_buffer_ptr[index].buf_addr == NULL) {
12190        DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
12191        return OMX_ErrorInsufficientResources;
12192    }
12193
12194    return eRet;
12195}
12196
12197void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
12198{
12199    DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
12200    if (m_demux_entries < 8192) {
12201        m_demux_offsets[m_demux_entries++] = address_offset;
12202    }
12203    return;
12204}
12205
12206void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
12207{
12208    OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
12209    OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
12210    OMX_U32 index = 0;
12211
12212    m_demux_entries = 0;
12213
12214    while (index < bytes_to_parse) {
12215        if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12216                    (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
12217                ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12218                 (buf[index+2] == 0x01)) ) {
12219            //Found start code, insert address offset
12220            insert_demux_addr_offset(index);
12221            if (buf[index+2] == 0x01) // 3 byte start code
12222                index += 3;
12223            else                      //4 byte start code
12224                index += 4;
12225        } else
12226            index++;
12227    }
12228    DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
12229    return;
12230}
12231
12232OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
12233{
12234    //fix this, handle 3 byte start code, vc1 terminator entry
12235    OMX_U8 *p_demux_data = NULL;
12236    OMX_U32 desc_data = 0;
12237    OMX_U32 start_addr = 0;
12238    OMX_U32 nal_size = 0;
12239    OMX_U32 suffix_byte = 0;
12240    OMX_U32 demux_index = 0;
12241    OMX_U32 buffer_index = 0;
12242
12243    if (m_desc_buffer_ptr == NULL) {
12244        DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
12245        return OMX_ErrorBadParameter;
12246    }
12247
12248    buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
12249    if (buffer_index > drv_ctx.ip_buf.actualcount) {
12250        DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
12251        return OMX_ErrorBadParameter;
12252    }
12253
12254    p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
12255
12256    if ( ((OMX_U8*)p_demux_data == NULL) ||
12257            ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
12258        DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
12259        return OMX_ErrorBadParameter;
12260    } else {
12261        for (; demux_index < m_demux_entries; demux_index++) {
12262            desc_data = 0;
12263            start_addr = m_demux_offsets[demux_index];
12264            if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
12265                suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
12266            } else {
12267                suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
12268            }
12269            if (demux_index < (m_demux_entries - 1)) {
12270                nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
12271            } else {
12272                nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
12273            }
12274            DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
12275                    (unsigned int)start_addr,
12276                    (unsigned int)suffix_byte,
12277                    (unsigned int)nal_size,
12278                    (unsigned int)demux_index);
12279            desc_data = (start_addr >> 3) << 1;
12280            desc_data |= (start_addr & 7) << 21;
12281            desc_data |= suffix_byte << 24;
12282
12283            memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12284            memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
12285            memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12286            memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12287
12288            p_demux_data += 16;
12289        }
12290        if (codec_type_parse == CODEC_TYPE_VC1) {
12291            DEBUG_PRINT_LOW("VC1 terminator entry");
12292            desc_data = 0;
12293            desc_data = 0x82 << 24;
12294            memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12295            memset(p_demux_data + 4, 0, sizeof(OMX_U32));
12296            memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12297            memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12298            p_demux_data += 16;
12299            m_demux_entries++;
12300        }
12301        //Add zero word to indicate end of descriptors
12302        memset(p_demux_data, 0, sizeof(OMX_U32));
12303
12304        m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
12305        DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
12306    }
12307    memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
12308    m_demux_entries = 0;
12309    DEBUG_PRINT_LOW("Demux table complete!");
12310    return OMX_ErrorNone;
12311}
12312
12313void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
12314{
12315    struct v4l2_control control;
12316    char property_value[PROPERTY_VALUE_MAX] = {0};
12317
12318    property_get("vidc.debug.turbo", property_value, "0");
12319    memset(&control, 0, sizeof(v4l2_control));
12320    control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
12321    switch (perf_level) {
12322    case VIDC_NOMINAL:
12323        if (atoi(property_value))
12324            control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12325        else
12326            control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
12327        break;
12328    case VIDC_TURBO:
12329        control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12330        break;
12331     default:
12332        DEBUG_PRINT_ERROR("Requested PERF level not supported");
12333        break;
12334    }
12335    if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
12336        return;
12337
12338    DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
12339    if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
12340        current_perf_level = control.value;
12341    } else {
12342        DEBUG_PRINT_ERROR("Failed to set PERF level");
12343    }
12344}
12345
12346omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
12347{
12348    enabled = false;
12349    omx = NULL;
12350    init_members();
12351    ColorFormat = OMX_COLOR_FormatMax;
12352    dest_format = YCbCr420P;
12353    m_c2d_width = 0;
12354    m_c2d_height = 0;
12355}
12356
12357void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
12358{
12359    omx = reinterpret_cast<omx_vdec*>(client);
12360}
12361
12362void omx_vdec::allocate_color_convert_buf::init_members()
12363{
12364    allocated_count = 0;
12365    buffer_size_req = 0;
12366    buffer_alignment_req = 0;
12367    m_c2d_width = m_c2d_height = 0;
12368    memset(m_platform_list_client,0,sizeof(m_platform_list_client));
12369    memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
12370    memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
12371    memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
12372#ifdef USE_ION
12373    memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
12374#endif
12375    for (int i = 0; i < MAX_COUNT; i++)
12376        pmem_fd[i] = -1;
12377}
12378
12379omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
12380{
12381    c2d.destroy();
12382}
12383
12384bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
12385{
12386    bool status = true;
12387    unsigned int src_size = 0, destination_size = 0;
12388    unsigned int height, width;
12389    struct v4l2_format fmt;
12390    OMX_COLOR_FORMATTYPE drv_color_format;
12391
12392    if (!omx) {
12393        DEBUG_PRINT_ERROR("Invalid client in color convert");
12394        return false;
12395    }
12396    if (!enabled) {
12397        DEBUG_PRINT_HIGH("No color conversion required");
12398        return status;
12399    }
12400    pthread_mutex_lock(&omx->c_lock);
12401
12402    memset(&fmt, 0x0, sizeof(struct v4l2_format));
12403    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
12404    fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
12405    ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
12406    width = fmt.fmt.pix_mp.width;
12407    height =  fmt.fmt.pix_mp.height;
12408
12409    bool resolution_upgrade = (height > m_c2d_height ||
12410            width > m_c2d_width);
12411    if (resolution_upgrade) {
12412        // resolution upgraded ? ensure we are yet to allocate;
12413        // failing which, c2d buffers will never be reallocated and bad things will happen
12414        if (allocated_count > 0) {
12415            DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
12416                    allocated_count);
12417            status = false;
12418            goto fail_update_buf_req;
12419        }
12420    }
12421
12422    if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
12423            ColorFormat != OMX_COLOR_FormatYUV420Planar) {
12424        DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
12425        status = false;
12426        goto fail_update_buf_req;
12427    }
12428    c2d.close();
12429    status = c2d.open(height,
12430            width,
12431            NV12_128m,dest_format);
12432    if (status) {
12433        status = c2d.get_buffer_size(C2D_INPUT,src_size);
12434        if (status)
12435            status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
12436    }
12437    if (status) {
12438        if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
12439                !destination_size) {
12440            DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
12441                    "driver size %u destination size %d",
12442                    src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
12443                    destination_size);
12444            status = false;
12445            c2d.close();
12446            buffer_size_req = 0;
12447            // TODO: make this fatal. Driver is not supposed to quote size
12448            //  smaller than what C2D needs !!
12449        } else {
12450            buffer_size_req = destination_size;
12451            m_c2d_height = height;
12452            m_c2d_width = width;
12453        }
12454    }
12455fail_update_buf_req:
12456    pthread_mutex_unlock(&omx->c_lock);
12457    return status;
12458}
12459
12460bool omx_vdec::allocate_color_convert_buf::set_color_format(
12461        OMX_COLOR_FORMATTYPE dest_color_format)
12462{
12463    bool status = true, drv_colorformat_c2d_enable = false;
12464    bool dest_color_format_c2d_enable = false;
12465    OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
12466    if (!omx) {
12467        DEBUG_PRINT_ERROR("Invalid client in color convert");
12468        return false;
12469    }
12470    pthread_mutex_lock(&omx->c_lock);
12471    if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
12472        if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
12473            drv_color_format = (OMX_COLOR_FORMATTYPE)
12474                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12475        else
12476            drv_color_format = (OMX_COLOR_FORMATTYPE)
12477                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12478     else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
12479         drv_color_format = (OMX_COLOR_FORMATTYPE)
12480                  QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12481     } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
12482            drv_color_format = (OMX_COLOR_FORMATTYPE)
12483                    QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12484     } else {
12485        DEBUG_PRINT_ERROR("Incorrect color format");
12486        status = false;
12487    }
12488    drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
12489        (drv_color_format != (OMX_COLOR_FORMATTYPE)
12490                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
12491        (drv_color_format != (OMX_COLOR_FORMATTYPE)
12492                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12493        (drv_color_format != (OMX_COLOR_FORMATTYPE)
12494                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12495
12496    dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
12497            QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12498            (dest_color_format != (OMX_COLOR_FORMATTYPE)
12499                QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12500
12501    if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
12502        DEBUG_PRINT_LOW("Enabling C2D");
12503        if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
12504           (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
12505            DEBUG_PRINT_ERROR("Unsupported color format for c2d");
12506            status = false;
12507        } else {
12508            ColorFormat = dest_color_format;
12509            dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
12510                    YCbCr420P : YCbCr420SP;
12511            if (enabled)
12512                c2d.destroy();
12513            enabled = false;
12514            if (!c2d.init()) {
12515                DEBUG_PRINT_ERROR("open failed for c2d");
12516                status = false;
12517            } else
12518                enabled = true;
12519        }
12520    } else {
12521        if (enabled)
12522            c2d.destroy();
12523        enabled = false;
12524    }
12525    pthread_mutex_unlock(&omx->c_lock);
12526    return status;
12527}
12528
12529OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
12530{
12531    if (!omx) {
12532        DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12533        return NULL;
12534    }
12535    if (!enabled)
12536        return omx->m_out_mem_ptr;
12537    return m_out_mem_ptr_client;
12538}
12539
12540    OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
12541(OMX_BUFFERHEADERTYPE *bufadd)
12542{
12543    if (!omx) {
12544        DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12545        return NULL;
12546    }
12547    if (!enabled)
12548        return bufadd;
12549
12550    unsigned index = 0;
12551    index = bufadd - omx->m_out_mem_ptr;
12552    if (index < omx->drv_ctx.op_buf.actualcount) {
12553        m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12554        m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
12555        bool status;
12556        if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
12557            pthread_mutex_lock(&omx->c_lock);
12558            cache_clean_buffer(index);
12559            status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
12560                    omx->drv_ctx.op_buf_map_info[index].base_address, bufadd->pBuffer, pmem_fd[index],
12561                    pmem_baseaddress[index], pmem_baseaddress[index]);
12562            if (!status) {
12563                DEBUG_PRINT_ERROR("Failed color conversion %d", status);
12564                m_out_mem_ptr_client[index].nFilledLen = 0;
12565                pthread_mutex_unlock(&omx->c_lock);
12566                return &m_out_mem_ptr_client[index];
12567            } else {
12568                unsigned int filledLen = 0;
12569                c2d.get_output_filled_length(filledLen);
12570                m_out_mem_ptr_client[index].nFilledLen = filledLen;
12571                cache_clean_invalidate_buffer(index);
12572            }
12573            pthread_mutex_unlock(&omx->c_lock);
12574        } else
12575            m_out_mem_ptr_client[index].nFilledLen = 0;
12576        return &m_out_mem_ptr_client[index];
12577    }
12578    DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
12579    return NULL;
12580}
12581
12582    OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
12583(OMX_BUFFERHEADERTYPE *bufadd)
12584{
12585    if (!omx) {
12586        DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12587        return NULL;
12588    }
12589    if (!enabled)
12590        return bufadd;
12591    unsigned index = 0;
12592    index = bufadd - m_out_mem_ptr_client;
12593    if (index < omx->drv_ctx.op_buf.actualcount) {
12594        return &omx->m_out_mem_ptr[index];
12595    }
12596    DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
12597    return NULL;
12598}
12599    bool omx_vdec::allocate_color_convert_buf::get_buffer_req
12600(unsigned int &buffer_size)
12601{
12602    bool status = true;
12603    pthread_mutex_lock(&omx->c_lock);
12604    if (!enabled)
12605        buffer_size = omx->drv_ctx.op_buf.buffer_size;
12606    else {
12607        if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
12608            DEBUG_PRINT_ERROR("Get buffer size failed");
12609            status = false;
12610            goto fail_get_buffer_size;
12611        }
12612    }
12613fail_get_buffer_size:
12614    pthread_mutex_unlock(&omx->c_lock);
12615    return status;
12616}
12617
12618OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
12619        OMX_U32 buffer_size, OMX_U32 actual_count) {
12620    OMX_U32 expectedSize = enabled ? buffer_size_req : omx->drv_ctx.op_buf.buffer_size;
12621
12622    if (buffer_size < expectedSize) {
12623        DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
12624                buffer_size, expectedSize);
12625        return OMX_ErrorBadParameter;
12626    }
12627    if (actual_count < omx->drv_ctx.op_buf.actualcount) {
12628        DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
12629                actual_count, omx->drv_ctx.op_buf.actualcount);
12630        return OMX_ErrorBadParameter;
12631    }
12632
12633    bool reqs_updated = false;
12634    if (enabled) {
12635        // disallow changing buffer size/count while we have active allocated buffers
12636        if (allocated_count > 0) {
12637            DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
12638                    buffer_size_req, buffer_size, allocated_count);
12639            return OMX_ErrorInvalidState;
12640        }
12641
12642        buffer_size_req = buffer_size;
12643    } else {
12644        if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
12645            omx->drv_ctx.op_buf.buffer_size = buffer_size;
12646            reqs_updated = true;
12647        }
12648    }
12649
12650    if (actual_count > omx->drv_ctx.op_buf.actualcount) {
12651        omx->drv_ctx.op_buf.actualcount = actual_count;
12652        reqs_updated = true;
12653    }
12654
12655    if (reqs_updated) {
12656        omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
12657        omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
12658                omx->drv_ctx.extradata_info.buffer_size;
12659        return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
12660    }
12661    return OMX_ErrorNone;
12662}
12663
12664OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
12665        OMX_BUFFERHEADERTYPE *bufhdr)
12666{
12667    unsigned int index = 0;
12668
12669    if (!enabled)
12670        return omx->free_output_buffer(bufhdr);
12671    if (enabled && omx->is_component_secure())
12672        return OMX_ErrorNone;
12673    if (!allocated_count || !bufhdr) {
12674        DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
12675        return OMX_ErrorBadParameter;
12676    }
12677    index = bufhdr - m_out_mem_ptr_client;
12678    if (index >= omx->drv_ctx.op_buf.actualcount) {
12679        DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
12680        return OMX_ErrorBadParameter;
12681    }
12682    if (pmem_fd[index] >= 0) {
12683        munmap(pmem_baseaddress[index], buffer_size_req);
12684        close(pmem_fd[index]);
12685    }
12686    pmem_fd[index] = -1;
12687#ifdef USE_ION
12688    omx->free_ion_memory(&op_buf_ion_info[index]);
12689#endif
12690    m_heap_ptr[index].video_heap_ptr = NULL;
12691    if (allocated_count > 0)
12692        allocated_count--;
12693    else
12694        allocated_count = 0;
12695    if (!allocated_count) {
12696        pthread_mutex_lock(&omx->c_lock);
12697        c2d.close();
12698        init_members();
12699        pthread_mutex_unlock(&omx->c_lock);
12700    }
12701    return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
12702}
12703
12704OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
12705        OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
12706{
12707    OMX_ERRORTYPE eRet = OMX_ErrorNone;
12708    if (!enabled) {
12709        eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
12710        return eRet;
12711    }
12712    if (enabled && omx->is_component_secure()) {
12713        DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
12714                omx->is_component_secure());
12715        return OMX_ErrorUnsupportedSetting;
12716    }
12717    if (!bufferHdr || bytes > buffer_size_req) {
12718        DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
12719        DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
12720                (unsigned int)buffer_size_req, (unsigned int)bytes);
12721        return OMX_ErrorBadParameter;
12722    }
12723    if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
12724        DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
12725        return OMX_ErrorInsufficientResources;
12726    }
12727    OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
12728    eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
12729            port,appData,omx->drv_ctx.op_buf.buffer_size);
12730    if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
12731        DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
12732        return eRet;
12733    }
12734    if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
12735            (int)omx->drv_ctx.op_buf.actualcount) {
12736        DEBUG_PRINT_ERROR("Invalid header index %ld",
12737               (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
12738        return OMX_ErrorUndefined;
12739    }
12740    unsigned int i = allocated_count;
12741#ifdef USE_ION
12742    // Allocate color-conversion buffers as cached to improve software-reading
12743    // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
12744    // cache invalidation.
12745    op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
12746            buffer_size_req,buffer_alignment_req,
12747            &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
12748            ION_FLAG_CACHED);
12749    pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
12750    if (op_buf_ion_info[i].ion_device_fd < 0) {
12751        DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
12752        return OMX_ErrorInsufficientResources;
12753    }
12754    pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
12755            PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
12756
12757    if (pmem_baseaddress[i] == MAP_FAILED) {
12758        DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
12759        close(pmem_fd[i]);
12760        omx->free_ion_memory(&op_buf_ion_info[i]);
12761        return OMX_ErrorInsufficientResources;
12762    }
12763    m_heap_ptr[i].video_heap_ptr = new VideoHeap (
12764            op_buf_ion_info[i].ion_device_fd,buffer_size_req,
12765            pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
12766#endif
12767    m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
12768    m_pmem_info_client[i].offset = 0;
12769    m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
12770    m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
12771    m_platform_list_client[i].nEntries = 1;
12772    m_platform_list_client[i].entryList = &m_platform_entry_client[i];
12773    m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
12774    m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
12775    m_out_mem_ptr_client[i].nFilledLen = 0;
12776    m_out_mem_ptr_client[i].nFlags = 0;
12777    m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12778    m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
12779    m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
12780    m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
12781    m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
12782    m_out_mem_ptr_client[i].pAppPrivate = appData;
12783    *bufferHdr = &m_out_mem_ptr_client[i];
12784    DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
12785    allocated_count++;
12786    return eRet;
12787}
12788
12789bool omx_vdec::is_component_secure()
12790{
12791    return secure_mode;
12792}
12793
12794bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
12795{
12796    bool status = true;
12797    if (!enabled) {
12798        if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
12799            if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
12800                    dest_color_format = (OMX_COLOR_FORMATTYPE)
12801                        QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12802                else
12803                    dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12804        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
12805             dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12806        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC){
12807             dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12808        } else
12809            status = false;
12810    } else {
12811        if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
12812            ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
12813            dest_color_format = ColorFormat;
12814        } else
12815            status = false;
12816    }
12817    return status;
12818}
12819
12820OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
12821        unsigned int index, unsigned int cmd)
12822{
12823    if (!enabled) {
12824        return OMX_ErrorNone;
12825    }
12826
12827    if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
12828        DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
12829        return OMX_ErrorBadParameter;
12830    }
12831
12832    struct ion_flush_data flush_data;
12833    struct ion_custom_data custom_data;
12834
12835    memset(&flush_data, 0x0, sizeof(flush_data));
12836    memset(&custom_data, 0x0, sizeof(custom_data));
12837
12838    flush_data.vaddr = pmem_baseaddress[index];
12839    flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
12840    flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
12841    flush_data.length = buffer_size_req;
12842    custom_data.cmd = cmd;
12843    custom_data.arg = (unsigned long)&flush_data;
12844
12845    DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
12846            (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
12847            flush_data.fd, flush_data.handle, flush_data.vaddr,
12848            flush_data.length);
12849    int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
12850    if (ret < 0) {
12851        DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
12852                (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
12853                strerror(errno));
12854        return OMX_ErrorUndefined;
12855    }
12856    return OMX_ErrorNone;
12857}
12858
12859void omx_vdec::buf_ref_add(int nPortIndex)
12860{
12861    unsigned long i = 0;
12862    bool buf_present = false;
12863    long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
12864    OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
12865
12866    if (!dynamic_buf_mode || !out_dynamic_list) {
12867        return;
12868    }
12869
12870    pthread_mutex_lock(&m_lock);
12871    for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
12872        //check the buffer fd, offset, uv addr with list contents
12873        //If present increment reference.
12874        if ((out_dynamic_list[i].fd == fd) &&
12875            (out_dynamic_list[i].offset == offset)) {
12876               DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
12877                     (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
12878               if (!secure_mode) {
12879                   drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
12880               }
12881               buf_present = true;
12882               break;
12883        }
12884    }
12885    if (!buf_present) {
12886        for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
12887            //search for a entry to insert details of the new buffer
12888            if (out_dynamic_list[i].dup_fd < 0) {
12889                out_dynamic_list[i].fd = fd;
12890                out_dynamic_list[i].offset = offset;
12891                out_dynamic_list[i].dup_fd = dup(fd);
12892                out_dynamic_list[i].ref_count++;
12893                DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
12894                     (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
12895
12896                if (!secure_mode) {
12897                    drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
12898                            (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
12899                                          PROT_READ|PROT_WRITE, MAP_SHARED,
12900                                          drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
12901                    //mmap returns (void *)-1 on failure and sets error code in errno.
12902                    if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
12903                        DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
12904                        drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
12905                        break;
12906                    }
12907                    out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
12908                    out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
12909                    DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
12910                }
12911                break;
12912            }
12913        }
12914    }
12915   pthread_mutex_unlock(&m_lock);
12916}
12917
12918void omx_vdec::buf_ref_remove()
12919{
12920    unsigned long i = 0;
12921
12922    if (!dynamic_buf_mode || !out_dynamic_list) {
12923        return;
12924    }
12925
12926    pthread_mutex_lock(&m_lock);
12927    for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
12928        if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
12929            DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
12930            munmap(out_dynamic_list[i].buffaddr,
12931                        out_dynamic_list[i].mapped_size);
12932        }
12933
12934         DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
12935                 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
12936         close(out_dynamic_list[i].dup_fd);
12937         out_dynamic_list[i].dup_fd = -1;
12938    }
12939    pthread_mutex_unlock(&m_lock);
12940
12941    if (out_dynamic_list) {
12942        free(out_dynamic_list);
12943        out_dynamic_list = NULL;
12944    }
12945}
12946
12947#ifdef _MSM8974_
12948void omx_vdec::send_codec_config() {
12949    if (codec_config_flag) {
12950        unsigned long p1 = 0; // Parameter - 1
12951        unsigned long p2 = 0; // Parameter - 2
12952        unsigned long ident = 0;
12953        pthread_mutex_lock(&m_lock);
12954        DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
12955        while (m_etb_q.m_size) {
12956            m_etb_q.pop_entry(&p1,&p2,&ident);
12957            if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
12958                if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12959                    if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
12960                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12961                        DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
12962                        omx_report_error();
12963                    }
12964                } else {
12965                    DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
12966                    m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
12967                }
12968            } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
12969                if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12970                    if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
12971                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12972                        DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
12973                        omx_report_error ();
12974                    }
12975                } else {
12976                    pending_input_buffers++;
12977                    VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
12978                    DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
12979                            (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
12980                    empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
12981                }
12982            } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
12983                DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
12984                        (OMX_BUFFERHEADERTYPE *)p1);
12985                empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
12986            }
12987        }
12988        pthread_mutex_unlock(&m_lock);
12989    }
12990}
12991#endif
12992
12993omx_vdec::perf_control::perf_control()
12994{
12995    m_perf_lib = NULL;
12996    m_perf_handle = 0;
12997    m_perf_lock_acquire = NULL;
12998    m_perf_lock_release = NULL;
12999}
13000
13001omx_vdec::perf_control::~perf_control()
13002{
13003    if (m_perf_handle != 0 && m_perf_lock_release) {
13004        DEBUG_PRINT_LOW("NOTE2: release perf lock");
13005        m_perf_lock_release(m_perf_handle);
13006    }
13007    if (m_perf_lib) {
13008        dlclose(m_perf_lib);
13009    }
13010}
13011
13012struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
13013
13014omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
13015
13016void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
13017{
13018    if (load_lib() == false) {
13019       return;
13020    }
13021    m_perf_lock.lock();
13022    /* 0x4401 maps to video decode playback hint
13023     * in perflock, enum number is 44 and state
13024     * being sent on perflock acquire is 01 (true)
13025     */
13026    int arg = 0x4401;
13027
13028    if (state == true) {
13029        mpctl_obj.vid_inst_count++;
13030    } else if (state == false) {
13031        mpctl_obj.vid_inst_count--;
13032    }
13033
13034    if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
13035        mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
13036        mpctl_obj.vid_acquired = true;
13037        DEBUG_PRINT_INFO("Video slvp perflock acquired");
13038    } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
13039        m_perf_lock_release(mpctl_obj.vid_disp_handle);
13040        mpctl_obj.vid_acquired = false;
13041        DEBUG_PRINT_INFO("Video slvp perflock released");
13042    }
13043    m_perf_lock.unlock();
13044}
13045
13046void omx_vdec::perf_control::request_cores(int frame_duration_us)
13047{
13048    if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
13049        return;
13050    }
13051    bool retVal = load_lib();
13052    if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
13053        int arg = 0x700 /*base value*/ + 2 /*cores*/;
13054        m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
13055        if (m_perf_handle) {
13056            DEBUG_PRINT_HIGH("perf lock acquired");
13057        }
13058    }
13059}
13060
13061bool omx_vdec::perf_control::load_lib()
13062{
13063    char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
13064    if (m_perf_lib)
13065        return true;
13066
13067    if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
13068        DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
13069        goto handle_err;
13070    }
13071
13072    if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
13073        DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
13074        goto handle_err;
13075    } else {
13076        m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
13077        if (m_perf_lock_acquire == NULL) {
13078            DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
13079            goto handle_err;
13080        }
13081        m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
13082        if (m_perf_lock_release == NULL) {
13083            DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
13084            goto handle_err;
13085        }
13086    }
13087    return true;
13088
13089handle_err:
13090    if (m_perf_lib) {
13091        dlclose(m_perf_lib);
13092    }
13093    m_perf_lib = NULL;
13094    return false;
13095}
13096
13097OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
13098                            unsigned long nMaxFrameHeight)
13099{
13100
13101    OMX_ERRORTYPE eRet = OMX_ErrorNone;
13102    int ret = 0;
13103    unsigned long min_res_buf_count = 0;
13104
13105    eRet = enable_smoothstreaming();
13106    if (eRet != OMX_ErrorNone) {
13107         DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
13108         return eRet;
13109     }
13110
13111     DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
13112             nMaxFrameWidth,
13113             nMaxFrameHeight);
13114     m_smoothstreaming_mode = true;
13115     m_smoothstreaming_width = nMaxFrameWidth;
13116     m_smoothstreaming_height = nMaxFrameHeight;
13117
13118     //Get upper limit buffer count for min supported resolution
13119     struct v4l2_format fmt;
13120     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13121     fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
13122     fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
13123     fmt.fmt.pix_mp.pixelformat = output_capability;
13124
13125     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13126     if (ret) {
13127         DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
13128                           m_decoder_capability.min_height,
13129                           m_decoder_capability.min_width);
13130         return OMX_ErrorUnsupportedSetting;
13131     }
13132
13133     eRet = get_buffer_req(&drv_ctx.op_buf);
13134     if (eRet != OMX_ErrorNone) {
13135         DEBUG_PRINT_ERROR("failed to get_buffer_req");
13136         return eRet;
13137     }
13138
13139     min_res_buf_count = drv_ctx.op_buf.mincount;
13140     DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
13141                     min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
13142
13143     m_extradata_info.output_crop_rect.nLeft = 0;
13144     m_extradata_info.output_crop_rect.nTop = 0;
13145     m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
13146     m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
13147
13148     update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
13149                       m_smoothstreaming_width, m_smoothstreaming_height);
13150     eRet = is_video_session_supported();
13151     if (eRet != OMX_ErrorNone) {
13152         DEBUG_PRINT_ERROR("video session is not supported");
13153         return eRet;
13154     }
13155
13156     //Get upper limit buffer size for max smooth streaming resolution set
13157     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13158     fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
13159     fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
13160     fmt.fmt.pix_mp.pixelformat = output_capability;
13161     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13162     if (ret) {
13163         DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
13164         return OMX_ErrorUnsupportedSetting;
13165     }
13166
13167     eRet = get_buffer_req(&drv_ctx.op_buf);
13168     if (eRet != OMX_ErrorNone) {
13169         DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
13170         return eRet;
13171     }
13172     DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
13173                     (unsigned int)drv_ctx.op_buf.buffer_size);
13174
13175     drv_ctx.op_buf.mincount = min_res_buf_count;
13176     drv_ctx.op_buf.actualcount = min_res_buf_count;
13177     drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
13178     eRet = set_buffer_req(&drv_ctx.op_buf);
13179     if (eRet != OMX_ErrorNone) {
13180         DEBUG_PRINT_ERROR("failed to set_buffer_req");
13181         return eRet;
13182     }
13183
13184     eRet = get_buffer_req(&drv_ctx.op_buf);
13185     if (eRet != OMX_ErrorNone) {
13186         DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
13187         return eRet;
13188     }
13189     DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
13190                      drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
13191     return eRet;
13192}
13193
13194//static
13195OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
13196
13197#ifndef FLEXYUV_SUPPORTED
13198    return OMX_ErrorUndefined;
13199#else
13200
13201    if (pParam == NULL) {
13202        DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
13203        return OMX_ErrorBadParameter;
13204    }
13205
13206    DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
13207
13208    MediaImage *img = &(params->sMediaImage);
13209    switch(params->eColorFormat) {
13210        case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
13211        {
13212            img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
13213            img->mNumPlanes = 3;
13214            // mWidth and mHeight represent the W x H of the largest plane
13215            // In our case, this happens to be the Stride x Scanlines of Y plane
13216            img->mWidth = params->nFrameWidth;
13217            img->mHeight = params->nFrameHeight;
13218            size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13219            size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
13220            img->mBitDepth = 8;
13221            //Plane 0 (Y)
13222            img->mPlane[MediaImage::Y].mOffset = 0;
13223            img->mPlane[MediaImage::Y].mColInc = 1;
13224            img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
13225            img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
13226            img->mPlane[MediaImage::Y].mVertSubsampling = 1;
13227            //Plane 1 (U)
13228            img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
13229            img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
13230            img->mPlane[MediaImage::U].mRowInc =
13231                    VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13232            img->mPlane[MediaImage::U].mHorizSubsampling = 2;
13233            img->mPlane[MediaImage::U].mVertSubsampling = 2;
13234            //Plane 2 (V)
13235            img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
13236            img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
13237            img->mPlane[MediaImage::V].mRowInc =
13238                    VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13239            img->mPlane[MediaImage::V].mHorizSubsampling = 2;
13240            img->mPlane[MediaImage::V].mVertSubsampling = 2;
13241            break;
13242        }
13243
13244        case OMX_COLOR_FormatYUV420Planar:
13245        case OMX_COLOR_FormatYUV420SemiPlanar:
13246            // We need not describe the standard OMX linear formats as these are
13247            // understood by client. Fail this deliberately to let client fill-in
13248            return OMX_ErrorUnsupportedSetting;
13249
13250        default:
13251            // Rest all formats which are non-linear cannot be described
13252            DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
13253            img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
13254            return OMX_ErrorNone;
13255    };
13256
13257    DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
13258    DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
13259    DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
13260    for (size_t i = 0; i < img->mNumPlanes; ++i) {
13261        DEBUG_PRINT_LOW("  Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
13262                i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
13263    }
13264    return OMX_ErrorNone;
13265#endif //FLEXYUV_SUPPORTED
13266}
13267
13268void omx_vdec::prefetchNewBuffers() {
13269
13270    struct v4l2_decoder_cmd dec;
13271    uint32_t prefetch_count;
13272    uint32_t prefetch_size;
13273    uint32_t want_size;
13274    uint32_t have_size;
13275    int color_fmt, rc;
13276    uint32_t new_calculated_size;
13277    uint32_t new_buffer_size;
13278    uint32_t new_buffer_count;
13279    uint32_t old_buffer_size;
13280    uint32_t old_buffer_count;
13281
13282    memset((void *)&dec, 0 , sizeof(dec));
13283    DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n",
13284            drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
13285            drv_ctx.video_resolution.frame_width,
13286            drv_ctx.video_resolution.frame_height);
13287    dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
13288    if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
13289        DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
13290    } else {
13291        DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
13292                dec.raw.data[0], dec.raw.data[1]);
13293    }
13294
13295    switch ((int)drv_ctx.output_format) {
13296    case VDEC_YUV_FORMAT_NV12:
13297        color_fmt = COLOR_FMT_NV12;
13298        break;
13299    case VDEC_YUV_FORMAT_NV12_UBWC:
13300        color_fmt = COLOR_FMT_NV12_UBWC;
13301        break;
13302    case VDEC_YUV_FORMAT_NV12_TP10_UBWC:
13303        color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
13304        break;
13305    default:
13306        color_fmt = -1;
13307        DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format);
13308        return;
13309    }
13310
13311    new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
13312    DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
13313            m_reconfig_width, m_reconfig_height, new_calculated_size);
13314    new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
13315    new_buffer_count = dec.raw.data[1];
13316    old_buffer_size = drv_ctx.op_buf.buffer_size;
13317    old_buffer_count = drv_ctx.op_buf.actualcount;
13318
13319    new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
13320
13321    prefetch_count = new_buffer_count;
13322    prefetch_size = new_buffer_size - old_buffer_size;
13323    want_size = new_buffer_size * new_buffer_count;
13324    have_size = old_buffer_size * old_buffer_count;
13325
13326    if (want_size > have_size) {
13327        DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
13328        DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
13329
13330        int ion_fd = open(MEM_DEVICE, O_RDONLY);
13331        if (ion_fd < 0) {
13332            DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
13333            return;
13334        }
13335
13336        struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
13337        struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
13338        struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
13339        size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
13340
13341        if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
13342            DEBUG_PRINT_ERROR("prefetch data allocation failed");
13343            goto prefetch_exit;
13344        }
13345
13346        for (uint32_t i = 0; i < prefetch_count; i++) {
13347            sizes[i] = prefetch_size;
13348        }
13349
13350        regions[0].nr_sizes = prefetch_count;
13351        regions[0].sizes = sizes;
13352        regions[0].vmid = ION_FLAG_CP_PIXEL;
13353
13354        prefetch_data->nr_regions = 1;
13355        prefetch_data->regions = regions;
13356        prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
13357
13358        custom_data->cmd = ION_IOC_PREFETCH;
13359        custom_data->arg = (unsigned long )prefetch_data;
13360
13361        rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
13362        if (rc) {
13363            DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
13364        }
13365
13366prefetch_exit:
13367        close(ion_fd);
13368        free(sizes);
13369        free(regions);
13370        free(prefetch_data);
13371        free(custom_data);
13372    }
13373}
13374