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