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