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