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