1/*--------------------------------------------------------------------------
2Copyright (c) 2010-2017, Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6    * Redistributions of source code must retain the above copyright
7      notice, this list of conditions and the following disclaimer.
8    * Redistributions in binary form must reproduce the above copyright
9      notice, this list of conditions and the following disclaimer in the
10      documentation and/or other materials provided with the distribution.
11    * Neither the name of The Linux Foundation nor
12      the names of its contributors may be used to endorse or promote
13      products derived from this software without specific prior written
14      permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27--------------------------------------------------------------------------*/
28/*============================================================================
29                            O p e n M A X   w r a p p e r s
30                             O p e n  M A X   C o r e
31
32*//** @file omx_video_base.cpp
33  This module contains the implementation of the OpenMAX core & component.
34
35*//*========================================================================*/
36
37//////////////////////////////////////////////////////////////////////////////
38//                             Include Files
39//////////////////////////////////////////////////////////////////////////////
40
41#define __STDC_FORMAT_MACROS //enables the format specifiers in inttypes.h
42#include <inttypes.h>
43#include <string.h>
44#include "omx_video_base.h"
45#include <stdlib.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <unistd.h>
49#include <sys/prctl.h>
50#ifdef _ANDROID_ICS_
51#include <media/hardware/HardwareAPI.h>
52#include <gralloc_priv.h>
53#endif
54#ifndef _ANDROID_
55#include <glib.h>
56#define strlcpy g_strlcpy
57#endif
58#define H264_SUPPORTED_WIDTH (480)
59#define H264_SUPPORTED_HEIGHT (368)
60
61#define MPEG4_SUPPORTED_WIDTH (480)
62#define MPEG4_SUPPORTED_HEIGHT (368)
63
64#define VC1_SP_MP_START_CODE        0xC5000000
65#define VC1_SP_MP_START_CODE_MASK   0xFF000000
66#define VC1_AP_START_CODE           0x00000100
67#define VC1_AP_START_CODE_MASK      0xFFFFFF00
68#define VC1_STRUCT_C_PROFILE_MASK   0xF0
69#define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
70#define VC1_SIMPLE_PROFILE          0
71#define VC1_MAIN_PROFILE            1
72#define VC1_ADVANCE_PROFILE         3
73#define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
74#define VC1_SIMPLE_PROFILE_MED_LEVEL  2
75#define VC1_STRUCT_C_LEN            4
76#define VC1_STRUCT_C_POS            8
77#define VC1_STRUCT_A_POS            12
78#define VC1_STRUCT_B_POS            24
79#define VC1_SEQ_LAYER_SIZE          36
80
81#define SZ_4K                       0x1000
82#define SZ_1M                       0x100000
83
84typedef struct OMXComponentCapabilityFlagsType {
85    ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
86    OMX_U32 nSize;
87    OMX_VERSIONTYPE nVersion;
88    OMX_BOOL iIsOMXComponentMultiThreaded;
89    OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
90    OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc;
91    OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
92    OMX_BOOL iOMXComponentSupportsPartialFrames;
93    OMX_BOOL iOMXComponentUsesNALStartCodes;
94    OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
95    OMX_BOOL iOMXComponentUsesFullAVCFrames;
96
97} OMXComponentCapabilityFlagsType;
98#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347
99
100void* message_thread(void *input)
101{
102    omx_video* omx = reinterpret_cast<omx_video*>(input);
103    unsigned char id;
104    int n;
105
106    DEBUG_PRINT_LOW("omx_venc: message thread start");
107    prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0);
108    while (1) {
109        n = read(omx->m_pipe_in, &id, 1);
110        if (0 == n) {
111            break;
112        }
113
114        if (1 == n) {
115            omx->process_event_cb(omx, id);
116        }
117#ifdef QLE_BUILD
118        if (n < 0) break;
119#else
120        if ((n < 0) && (errno != EINTR)) break;
121#endif
122    }
123    DEBUG_PRINT_LOW("omx_venc: message thread stop");
124    return 0;
125}
126
127void post_message(omx_video *omx, unsigned char id)
128{
129    DEBUG_PRINT_LOW("omx_venc: post_message %d", id);
130    write(omx->m_pipe_out, &id, 1);
131}
132
133// omx_cmd_queue destructor
134omx_video::omx_cmd_queue::~omx_cmd_queue()
135{
136    // Nothing to do
137}
138
139// omx cmd queue constructor
140omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
141{
142    memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
143}
144
145// omx cmd queue insert
146bool omx_video::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
147{
148    bool ret = true;
149    if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
150        m_q[m_write].id       = id;
151        m_q[m_write].param1   = p1;
152        m_q[m_write].param2   = p2;
153        m_write++;
154        m_size ++;
155        if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
156            m_write = 0;
157        }
158    } else {
159        ret = false;
160        DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full");
161    }
162    return ret;
163}
164
165// omx cmd queue pop
166bool omx_video::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
167{
168    bool ret = true;
169    if (m_size > 0) {
170        *id = m_q[m_read].id;
171        *p1 = m_q[m_read].param1;
172        *p2 = m_q[m_read].param2;
173        // Move the read pointer ahead
174        ++m_read;
175        --m_size;
176        if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
177            m_read = 0;
178        }
179    } else {
180        ret = false;
181    }
182    return ret;
183}
184
185// Retrieve the first mesg type in the queue
186unsigned omx_video::omx_cmd_queue::get_q_msg_type()
187{
188    return m_q[m_read].id;
189}
190
191
192
193#ifdef _ANDROID_
194VideoHeap::VideoHeap(int fd, size_t size, void* base)
195{
196    // dup file descriptor, map once, use pmem
197    init(dup(fd), base, size, 0 , MEM_DEVICE);
198}
199#endif // _ANDROID_
200
201/* ======================================================================
202   FUNCTION
203   omx_venc::omx_venc
204
205   DESCRIPTION
206   Constructor
207
208   PARAMETERS
209   None
210
211   RETURN VALUE
212   None.
213   ========================================================================== */
214omx_video::omx_video():
215    c2d_opened(false),
216    psource_frame(NULL),
217    pdest_frame(NULL),
218    secure_session(false),
219    mEmptyEosBuffer(NULL),
220    m_pipe_in(-1),
221    m_pipe_out(-1),
222    m_pInput_pmem(NULL),
223    m_pOutput_pmem(NULL),
224#ifdef USE_ION
225    m_pInput_ion(NULL),
226    m_pOutput_ion(NULL),
227#endif
228    m_error_propogated(false),
229    m_state(OMX_StateInvalid),
230    m_app_data(NULL),
231    m_use_input_pmem(OMX_FALSE),
232    m_use_output_pmem(OMX_FALSE),
233    m_input_msg_id(OMX_COMPONENT_GENERATE_ETB),
234    m_inp_mem_ptr(NULL),
235    m_out_mem_ptr(NULL),
236    input_flush_progress (false),
237    output_flush_progress (false),
238    input_use_buffer (false),
239    output_use_buffer (false),
240    pending_input_buffers(0),
241    pending_output_buffers(0),
242    m_out_bm_count(0),
243    m_inp_bm_count(0),
244    m_flags(0),
245    m_etb_count(0),
246    m_fbd_count(0),
247    m_event_port_settings_sent(false),
248    hw_overload(false)
249{
250    DEBUG_PRINT_HIGH("omx_video(): Inside Constructor()");
251    memset(&m_cmp,0,sizeof(m_cmp));
252    memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
253    async_thread_created = false;
254    msg_thread_created = false;
255
256    mUsesColorConversion = false;
257    pthread_mutex_init(&m_lock, NULL);
258    sem_init(&m_cmd_lock,0,0);
259    DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr);
260    pthread_mutex_init(&m_buf_lock, NULL);
261}
262
263
264/* ======================================================================
265   FUNCTION
266   omx_venc::~omx_venc
267
268   DESCRIPTION
269   Destructor
270
271   PARAMETERS
272   None
273
274   RETURN VALUE
275   None.
276   ========================================================================== */
277omx_video::~omx_video()
278{
279    DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()");
280    if (m_pipe_in >= 0) close(m_pipe_in);
281    if (m_pipe_out >= 0) close(m_pipe_out);
282    DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
283    if (msg_thread_created)
284        pthread_join(msg_thread_id,NULL);
285    DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit");
286    /*For V4L2 based drivers, pthread_join is done in device_close
287     * so no need to do it here*/
288#ifndef _MSM8974_
289    if (async_thread_created)
290        pthread_join(async_thread_id,NULL);
291#endif
292    pthread_mutex_destroy(&m_lock);
293    sem_destroy(&m_cmd_lock);
294    DEBUG_PRINT_HIGH("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count,
295            m_fbd_count);
296    pthread_mutex_destroy(&m_buf_lock);
297    DEBUG_PRINT_HIGH("omx_video: Destructor exit");
298    DEBUG_PRINT_HIGH("Exiting OMX Video Encoder ...");
299}
300
301/* ======================================================================
302   FUNCTION
303   omx_venc::OMXCntrlProcessMsgCb
304
305   DESCRIPTION
306   IL Client callbacks are generated through this routine. The decoder
307   provides the thread context for this routine.
308
309   PARAMETERS
310   ctxt -- Context information related to the self.
311   id   -- Event identifier. This could be any of the following:
312   1. Command completion event
313   2. Buffer done callback event
314   3. Frame done callback event
315
316   RETURN VALUE
317   None.
318
319   ========================================================================== */
320void omx_video::process_event_cb(void *ctxt, unsigned char id)
321{
322    unsigned long p1; // Parameter - 1
323    unsigned long p2; // Parameter - 2
324    unsigned long ident;
325    unsigned qsize=0; // qsize
326    omx_video *pThis = (omx_video *) ctxt;
327
328    if (!pThis) {
329        DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out");
330        return;
331    }
332
333    // Protect the shared queue data structure
334    do {
335        /*Read the message id's from the queue*/
336
337        pthread_mutex_lock(&pThis->m_lock);
338        qsize = pThis->m_cmd_q.m_size;
339        if (qsize) {
340            pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
341        }
342
343        if (qsize == 0) {
344            qsize = pThis->m_ftb_q.m_size;
345            if (qsize) {
346                pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
347            }
348        }
349
350        if (qsize == 0) {
351            qsize = pThis->m_etb_q.m_size;
352            if (qsize) {
353                pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
354            }
355        }
356
357        pthread_mutex_unlock(&pThis->m_lock);
358
359        /*process message if we have one*/
360        if (qsize > 0) {
361            id = ident;
362            switch (id) {
363                case OMX_COMPONENT_GENERATE_EVENT:
364                    if (pThis->m_pCallbacks.EventHandler) {
365                        switch (p1) {
366                            case OMX_CommandStateSet:
367                                pThis->m_state = (OMX_STATETYPE) p2;
368                                DEBUG_PRINT_LOW("Process -> state set to %d", pThis->m_state);
369                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
370                                        OMX_EventCmdComplete, p1, p2, NULL);
371                                break;
372
373                            case OMX_EventError:
374                                DEBUG_PRINT_ERROR("ERROR: OMX_EventError: p2 = %lu", p2);
375                                if (p2 == (unsigned)OMX_ErrorHardware) {
376                                    pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
377                                            OMX_EventError,OMX_ErrorHardware,0,NULL);
378                                } else {
379                                    pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
380                                            OMX_EventError, p2, 0, 0);
381
382                                }
383                                break;
384
385                            case OMX_CommandPortDisable:
386                                DEBUG_PRINT_LOW("Process -> Port %lu set to PORT_STATE_DISABLED" \
387                                        "state", p2);
388                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
389                                        OMX_EventCmdComplete, p1, p2, NULL );
390                                break;
391                            case OMX_CommandPortEnable:
392                                DEBUG_PRINT_LOW("Process ->Port %lu set PORT_STATE_ENABLED state" \
393                                        , p2);
394                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
395                                        OMX_EventCmdComplete, p1, p2, NULL );
396                                break;
397
398                            default:
399                                DEBUG_PRINT_LOW("process_event_cb forwarding EventCmdComplete %lu", p1);
400                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
401                                        OMX_EventCmdComplete, p1, p2, NULL );
402                                break;
403
404                        }
405                    } else {
406                        DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks");
407                    }
408                    break;
409                case OMX_COMPONENT_GENERATE_ETB_OPQ:
410                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB_OPQ");
411                    if (pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\
412                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
413                        DEBUG_PRINT_ERROR("ERROR: ETBProxy() failed!");
414                        pThis->omx_report_error ();
415                    }
416                    break;
417                case OMX_COMPONENT_GENERATE_ETB: {
418                        OMX_ERRORTYPE iret;
419                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB");
420                        iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
421                        if (iret == OMX_ErrorInsufficientResources) {
422                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
423                            pThis->omx_report_hw_overload ();
424                        } else if (iret != OMX_ErrorNone) {
425                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
426                        pThis->omx_report_error ();
427                    }
428                    }
429                    break;
430
431                case OMX_COMPONENT_GENERATE_FTB:
432                    if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
433                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
434                        DEBUG_PRINT_ERROR("ERROR: FTBProxy() failed!");
435                        pThis->omx_report_error ();
436                    }
437                    break;
438
439                case OMX_COMPONENT_GENERATE_COMMAND:
440                    pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
441                            (OMX_U32)p2,(OMX_PTR)NULL);
442                    break;
443
444                case OMX_COMPONENT_GENERATE_EBD:
445                    if ( pThis->empty_buffer_done(&pThis->m_cmp,
446                                (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
447                        DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
448                        pThis->omx_report_error ();
449                    }
450                    break;
451
452                case OMX_COMPONENT_GENERATE_FBD:
453                    if ( pThis->fill_buffer_done(&pThis->m_cmp,
454                                (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
455                        DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
456                        pThis->omx_report_error ();
457                    }
458                    break;
459
460                case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
461
462                    pThis->input_flush_progress = false;
463                    DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %" PRIu64, m_etb_count);
464                    m_etb_count = 0;
465                    if (pThis->m_pCallbacks.EventHandler) {
466                        /*Check if we need generate event for Flush done*/
467                        if (BITMASK_PRESENT(&pThis->m_flags,
468                                    OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
469                            BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
470                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
471                                    OMX_EventCmdComplete,OMX_CommandFlush,
472                                    PORT_INDEX_IN,NULL );
473                        } else if (BITMASK_PRESENT(&pThis->m_flags,
474                                    OMX_COMPONENT_IDLE_PENDING)) {
475                            if (!pThis->output_flush_progress) {
476                                DEBUG_PRINT_LOW("dev_stop called after input flush complete");
477                                if (dev_stop() != 0) {
478                                    DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in i/p flush!");
479                                    pThis->omx_report_error ();
480                                }
481                            }
482                        }
483                    }
484
485                    break;
486
487                case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
488
489                    pThis->output_flush_progress = false;
490                    DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %" PRIu64, m_fbd_count);
491                    m_fbd_count = 0;
492                    if (pThis->m_pCallbacks.EventHandler) {
493                        /*Check if we need generate event for Flush done*/
494                        if (BITMASK_PRESENT(&pThis->m_flags,
495                                    OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
496                            BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
497
498                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
499                                    OMX_EventCmdComplete,OMX_CommandFlush,
500                                    PORT_INDEX_OUT,NULL );
501                        } else if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
502                            DEBUG_PRINT_LOW("dev_stop called after Output flush complete");
503                            if (!pThis->input_flush_progress) {
504                                if (dev_stop() != 0) {
505                                    DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in o/p flush!");
506                                    pThis->omx_report_error ();
507                                }
508                            }
509                        }
510                    }
511                    break;
512
513                case OMX_COMPONENT_GENERATE_START_DONE:
514                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE msg");
515
516                    if (pThis->m_pCallbacks.EventHandler) {
517                        DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
518                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
519                            DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Move to \
520                                    executing");
521                            // Send the callback now
522                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
523                            pThis->m_state = OMX_StateExecuting;
524                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
525                                    OMX_EventCmdComplete,OMX_CommandStateSet,
526                                    OMX_StateExecuting, NULL);
527                        } else if (BITMASK_PRESENT(&pThis->m_flags,
528                                    OMX_COMPONENT_PAUSE_PENDING)) {
529                            if (dev_pause()) {
530                                DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in Start Done!");
531                                pThis->omx_report_error ();
532                            }
533                        } else if (BITMASK_PRESENT(&pThis->m_flags,
534                                    OMX_COMPONENT_LOADED_START_PENDING)) {
535                            if (dev_loaded_start_done()) {
536                                DEBUG_PRINT_LOW("successful loaded Start Done!");
537                            } else {
538                                DEBUG_PRINT_ERROR("ERROR: failed in loaded Start Done!");
539                                pThis->omx_report_error ();
540                            }
541                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING);
542                        } else {
543                            DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
544                        }
545                    } else {
546                        DEBUG_PRINT_LOW("Event Handler callback is NULL");
547                    }
548                    break;
549
550                case OMX_COMPONENT_GENERATE_PAUSE_DONE:
551                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE msg");
552                    if (pThis->m_pCallbacks.EventHandler) {
553                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
554                            //Send the callback now
555                            pThis->complete_pending_buffer_done_cbs();
556                            DEBUG_PRINT_LOW("omx_video::process_event_cb() Sending PAUSE complete after all pending EBD/FBD");
557                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
558                            pThis->m_state = OMX_StatePause;
559                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
560                                    OMX_EventCmdComplete,OMX_CommandStateSet,
561                                    OMX_StatePause, NULL);
562                        }
563                    }
564
565                    break;
566
567                case OMX_COMPONENT_GENERATE_RESUME_DONE:
568                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_RESUME_DONE msg");
569                    if (pThis->m_pCallbacks.EventHandler) {
570                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
571                            // Send the callback now
572                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
573                            pThis->m_state = OMX_StateExecuting;
574                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
575                                    OMX_EventCmdComplete,OMX_CommandStateSet,
576                                    OMX_StateExecuting,NULL);
577                        }
578                    }
579
580                    break;
581
582                case OMX_COMPONENT_GENERATE_STOP_DONE:
583                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE msg");
584                    if (pThis->m_pCallbacks.EventHandler) {
585                        pThis->complete_pending_buffer_done_cbs();
586                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
587                            // Send the callback now
588                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
589                            pThis->m_state = OMX_StateIdle;
590                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data,
591                                    OMX_EventCmdComplete,OMX_CommandStateSet,
592                                    OMX_StateIdle,NULL);
593                        } else if (BITMASK_PRESENT(&pThis->m_flags,
594                                    OMX_COMPONENT_LOADED_STOP_PENDING)) {
595                            if (dev_loaded_stop_done()) {
596                                DEBUG_PRINT_LOW("successful loaded Stop Done!");
597                            } else {
598                                DEBUG_PRINT_ERROR("ERROR: failed in loaded Stop Done!");
599                                pThis->omx_report_error ();
600                            }
601                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING);
602                        } else {
603                            DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
604                        }
605                    }
606
607                    break;
608
609                case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
610                    DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!");
611                    pThis->omx_report_error ();
612                    break;
613#ifndef _MSM8974_
614                case OMX_COMPONENT_GENERATE_LTRUSE_FAILED:
615                    DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_LTRUSE_FAILED!");
616                    if (pThis->m_pCallbacks.EventHandler) {
617                        DEBUG_PRINT_ERROR("Sending QOMX_ErrorLTRUseFailed, p2 = 0x%x", p2);
618                        pThis->m_pCallbacks.EventHandler(
619                                &pThis->m_cmp, pThis->m_app_data,
620                                OMX_EventError, QOMX_ErrorLTRUseFailed, NULL, NULL);
621                    }
622                    break;
623#endif
624                default:
625                    DEBUG_PRINT_LOW("process_event_cb unknown msg id 0x%02x", id);
626                    break;
627            }
628        }
629
630        pthread_mutex_lock(&pThis->m_lock);
631        qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\
632                pThis->m_etb_q.m_size;
633
634        pthread_mutex_unlock(&pThis->m_lock);
635
636    } while (qsize>0);
637    DEBUG_PRINT_LOW("exited the while loop");
638
639}
640
641
642
643
644/* ======================================================================
645   FUNCTION
646   omx_venc::GetComponentVersion
647
648   DESCRIPTION
649   Returns the component version.
650
651   PARAMETERS
652   TBD.
653
654   RETURN VALUE
655   OMX_ErrorNone.
656
657   ========================================================================== */
658OMX_ERRORTYPE  omx_video::get_component_version
659(
660 OMX_IN OMX_HANDLETYPE hComp,
661 OMX_OUT OMX_STRING componentName,
662 OMX_OUT OMX_VERSIONTYPE* componentVersion,
663 OMX_OUT OMX_VERSIONTYPE* specVersion,
664 OMX_OUT OMX_UUIDTYPE* componentUUID
665 )
666{
667    (void)hComp;
668    (void)componentName;
669    (void)componentVersion;
670    (void)componentUUID;
671    if (m_state == OMX_StateInvalid) {
672        DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State");
673        return OMX_ErrorInvalidState;
674    }
675    /* TBD -- Return the proper version */
676    if (specVersion) {
677        specVersion->nVersion = OMX_SPEC_VERSION;
678    }
679    return OMX_ErrorNone;
680}
681/* ======================================================================
682   FUNCTION
683   omx_venc::SendCommand
684
685   DESCRIPTION
686   Returns zero if all the buffers released..
687
688   PARAMETERS
689   None.
690
691   RETURN VALUE
692   true/false
693
694   ========================================================================== */
695OMX_ERRORTYPE  omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp,
696        OMX_IN OMX_COMMANDTYPE cmd,
697        OMX_IN OMX_U32 param1,
698        OMX_IN OMX_PTR cmdData
699        )
700{
701    (void)hComp;
702    if (m_state == OMX_StateInvalid) {
703        DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
704        return OMX_ErrorInvalidState;
705    }
706
707    if (cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) {
708        if ((param1 != (OMX_U32)PORT_INDEX_IN) && (param1 != (OMX_U32)PORT_INDEX_OUT) && (param1 != (OMX_U32)PORT_INDEX_BOTH)) {
709            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
710            return OMX_ErrorBadPortIndex;
711        }
712    }
713    if (cmd == OMX_CommandMarkBuffer) {
714        if (param1 != PORT_INDEX_IN) {
715            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
716            return OMX_ErrorBadPortIndex;
717        }
718        if (!cmdData) {
719            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null");
720            return OMX_ErrorBadParameter;
721        }
722    }
723
724    post_event((unsigned long)cmd,(unsigned long)param1,OMX_COMPONENT_GENERATE_COMMAND);
725    sem_wait(&m_cmd_lock);
726    return OMX_ErrorNone;
727}
728
729/* ======================================================================
730   FUNCTION
731   omx_venc::SendCommand
732
733   DESCRIPTION
734   Returns zero if all the buffers released..
735
736   PARAMETERS
737   None.
738
739   RETURN VALUE
740   true/false
741
742   ========================================================================== */
743OMX_ERRORTYPE  omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
744        OMX_IN OMX_COMMANDTYPE cmd,
745        OMX_IN OMX_U32 param1,
746        OMX_IN OMX_PTR cmdData
747        )
748{
749    (void)hComp;
750    (void)cmdData;
751
752    OMX_ERRORTYPE eRet = OMX_ErrorNone;
753    OMX_STATETYPE eState = (OMX_STATETYPE) param1;
754    int bFlag = 1;
755
756    if (cmd == OMX_CommandStateSet) {
757        /***************************/
758        /* Current State is Loaded */
759        /***************************/
760        if (m_state == OMX_StateLoaded) {
761            if (eState == OMX_StateIdle) {
762                //if all buffers are allocated or all ports disabled
763                if (allocate_done() ||
764                        ( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) {
765                    DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle");
766                } else {
767                    DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending");
768                    BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
769                    // Skip the event notification
770                    bFlag = 0;
771                }
772            }
773            /* Requesting transition from Loaded to Loaded */
774            else if (eState == OMX_StateLoaded) {
775                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded");
776                post_event(OMX_EventError,OMX_ErrorSameState,\
777                        OMX_COMPONENT_GENERATE_EVENT);
778                eRet = OMX_ErrorSameState;
779            }
780            /* Requesting transition from Loaded to WaitForResources */
781            else if (eState == OMX_StateWaitForResources) {
782                /* Since error is None , we will post an event
783                   at the end of this function definition */
784                DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources");
785            }
786            /* Requesting transition from Loaded to Executing */
787            else if (eState == OMX_StateExecuting) {
788                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing");
789                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
790                        OMX_COMPONENT_GENERATE_EVENT);
791                eRet = OMX_ErrorIncorrectStateTransition;
792            }
793            /* Requesting transition from Loaded to Pause */
794            else if (eState == OMX_StatePause) {
795                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause");
796                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
797                        OMX_COMPONENT_GENERATE_EVENT);
798                eRet = OMX_ErrorIncorrectStateTransition;
799            }
800            /* Requesting transition from Loaded to Invalid */
801            else if (eState == OMX_StateInvalid) {
802                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid");
803                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
804                eRet = OMX_ErrorInvalidState;
805            } else {
806                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled",\
807                        eState);
808                eRet = OMX_ErrorBadParameter;
809            }
810        }
811
812        /***************************/
813        /* Current State is IDLE */
814        /***************************/
815        else if (m_state == OMX_StateIdle) {
816            if (eState == OMX_StateLoaded) {
817                if (release_done()) {
818                    /*
819                       Since error is None , we will post an event at the end
820                       of this function definition
821                     */
822                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded");
823                    if (dev_stop() != 0) {
824                        DEBUG_PRINT_ERROR("ERROR: dev_stop() failed at Idle --> Loaded");
825                        eRet = OMX_ErrorHardware;
826                    }
827                } else {
828                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending");
829                    BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
830                    // Skip the event notification
831                    bFlag = 0;
832                }
833            }
834            /* Requesting transition from Idle to Executing */
835            else if (eState == OMX_StateExecuting) {
836                if ( dev_start() ) {
837                    DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Exe");
838                    omx_report_error ();
839                    eRet = OMX_ErrorHardware;
840                } else {
841                    BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
842                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing");
843                    bFlag = 0;
844                }
845
846                dev_start_done();
847            }
848            /* Requesting transition from Idle to Idle */
849            else if (eState == OMX_StateIdle) {
850                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle");
851                post_event(OMX_EventError,OMX_ErrorSameState,\
852                        OMX_COMPONENT_GENERATE_EVENT);
853                eRet = OMX_ErrorSameState;
854            }
855            /* Requesting transition from Idle to WaitForResources */
856            else if (eState == OMX_StateWaitForResources) {
857                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources");
858                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
859                        OMX_COMPONENT_GENERATE_EVENT);
860                eRet = OMX_ErrorIncorrectStateTransition;
861            }
862            /* Requesting transition from Idle to Pause */
863            else if (eState == OMX_StatePause) {
864                /*To pause the Video core we need to start the driver*/
865                if ( dev_start() ) {
866                    DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Pause");
867                    omx_report_error ();
868                    eRet = OMX_ErrorHardware;
869                } else {
870                    BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
871                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause");
872                    bFlag = 0;
873                }
874            }
875            /* Requesting transition from Idle to Invalid */
876            else if (eState == OMX_StateInvalid) {
877                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid");
878                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
879                eRet = OMX_ErrorInvalidState;
880            } else {
881                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled",eState);
882                eRet = OMX_ErrorBadParameter;
883            }
884        }
885
886        /******************************/
887        /* Current State is Executing */
888        /******************************/
889        else if (m_state == OMX_StateExecuting) {
890            /* Requesting transition from Executing to Idle */
891            if (eState == OMX_StateIdle) {
892                /* Since error is None , we will post an event
893                   at the end of this function definition
894                 */
895                DEBUG_PRINT_LOW("OMXCORE-SM: Executing --> Idle");
896                //here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle
897                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
898                execute_omx_flush(OMX_ALL);
899                bFlag = 0;
900            }
901            /* Requesting transition from Executing to Paused */
902            else if (eState == OMX_StatePause) {
903
904                if (dev_pause()) {
905                    DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in SCP on Exe --> Pause");
906                    post_event(OMX_EventError,OMX_ErrorHardware,\
907                            OMX_COMPONENT_GENERATE_EVENT);
908                    eRet = OMX_ErrorHardware;
909                } else {
910                    BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
911                    DEBUG_PRINT_LOW("OMXCORE-SM: Executing-->Pause");
912                    bFlag = 0;
913                }
914            }
915            /* Requesting transition from Executing to Loaded */
916            else if (eState == OMX_StateLoaded) {
917                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Loaded");
918                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
919                        OMX_COMPONENT_GENERATE_EVENT);
920                eRet = OMX_ErrorIncorrectStateTransition;
921            }
922            /* Requesting transition from Executing to WaitForResources */
923            else if (eState == OMX_StateWaitForResources) {
924                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> WaitForResources");
925                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
926                        OMX_COMPONENT_GENERATE_EVENT);
927                eRet = OMX_ErrorIncorrectStateTransition;
928            }
929            /* Requesting transition from Executing to Executing */
930            else if (eState == OMX_StateExecuting) {
931                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Executing");
932                post_event(OMX_EventError,OMX_ErrorSameState,\
933                        OMX_COMPONENT_GENERATE_EVENT);
934                eRet = OMX_ErrorSameState;
935            }
936            /* Requesting transition from Executing to Invalid */
937            else if (eState == OMX_StateInvalid) {
938                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Invalid");
939                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
940                eRet = OMX_ErrorInvalidState;
941            } else {
942                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled",eState);
943                eRet = OMX_ErrorBadParameter;
944            }
945        }
946        /***************************/
947        /* Current State is Pause  */
948        /***************************/
949        else if (m_state == OMX_StatePause) {
950            /* Requesting transition from Pause to Executing */
951            if (eState == OMX_StateExecuting) {
952                DEBUG_PRINT_LOW("Pause --> Executing");
953                if ( dev_resume() ) {
954                    post_event(OMX_EventError,OMX_ErrorHardware,\
955                            OMX_COMPONENT_GENERATE_EVENT);
956                    eRet = OMX_ErrorHardware;
957                } else {
958                    BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
959                    DEBUG_PRINT_LOW("OMXCORE-SM: Pause-->Executing");
960                    post_event (0, 0, OMX_COMPONENT_GENERATE_RESUME_DONE);
961                    bFlag = 0;
962                }
963            }
964            /* Requesting transition from Pause to Idle */
965            else if (eState == OMX_StateIdle) {
966                /* Since error is None , we will post an event
967                   at the end of this function definition */
968                DEBUG_PRINT_LOW("Pause --> Idle");
969                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
970                execute_omx_flush(OMX_ALL);
971                bFlag = 0;
972            }
973            /* Requesting transition from Pause to loaded */
974            else if (eState == OMX_StateLoaded) {
975                DEBUG_PRINT_ERROR("ERROR: Pause --> loaded");
976                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
977                        OMX_COMPONENT_GENERATE_EVENT);
978                eRet = OMX_ErrorIncorrectStateTransition;
979            }
980            /* Requesting transition from Pause to WaitForResources */
981            else if (eState == OMX_StateWaitForResources) {
982                DEBUG_PRINT_ERROR("ERROR: Pause --> WaitForResources");
983                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
984                        OMX_COMPONENT_GENERATE_EVENT);
985                eRet = OMX_ErrorIncorrectStateTransition;
986            }
987            /* Requesting transition from Pause to Pause */
988            else if (eState == OMX_StatePause) {
989                DEBUG_PRINT_ERROR("ERROR: Pause --> Pause");
990                post_event(OMX_EventError,OMX_ErrorSameState,\
991                        OMX_COMPONENT_GENERATE_EVENT);
992                eRet = OMX_ErrorSameState;
993            }
994            /* Requesting transition from Pause to Invalid */
995            else if (eState == OMX_StateInvalid) {
996                DEBUG_PRINT_ERROR("ERROR: Pause --> Invalid");
997                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
998                eRet = OMX_ErrorInvalidState;
999            } else {
1000                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled",eState);
1001                eRet = OMX_ErrorBadParameter;
1002            }
1003        }
1004        /***************************/
1005        /* Current State is WaitForResources  */
1006        /***************************/
1007        else if (m_state == OMX_StateWaitForResources) {
1008            /* Requesting transition from WaitForResources to Loaded */
1009            if (eState == OMX_StateLoaded) {
1010                /* Since error is None , we will post an event
1011                   at the end of this function definition */
1012                DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded");
1013            }
1014            /* Requesting transition from WaitForResources to WaitForResources */
1015            else if (eState == OMX_StateWaitForResources) {
1016                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources");
1017                post_event(OMX_EventError,OMX_ErrorSameState,
1018                        OMX_COMPONENT_GENERATE_EVENT);
1019                eRet = OMX_ErrorSameState;
1020            }
1021            /* Requesting transition from WaitForResources to Executing */
1022            else if (eState == OMX_StateExecuting) {
1023                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing");
1024                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1025                        OMX_COMPONENT_GENERATE_EVENT);
1026                eRet = OMX_ErrorIncorrectStateTransition;
1027            }
1028            /* Requesting transition from WaitForResources to Pause */
1029            else if (eState == OMX_StatePause) {
1030                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause");
1031                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1032                        OMX_COMPONENT_GENERATE_EVENT);
1033                eRet = OMX_ErrorIncorrectStateTransition;
1034            }
1035            /* Requesting transition from WaitForResources to Invalid */
1036            else if (eState == OMX_StateInvalid) {
1037                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid");
1038                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1039                eRet = OMX_ErrorInvalidState;
1040            }
1041            /* Requesting transition from WaitForResources to Loaded -
1042               is NOT tested by Khronos TS */
1043
1044        } else {
1045            DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)",m_state,eState);
1046            eRet = OMX_ErrorBadParameter;
1047        }
1048    }
1049    /********************************/
1050    /* Current State is Invalid */
1051    /*******************************/
1052    else if (m_state == OMX_StateInvalid) {
1053        /* State Transition from Inavlid to any state */
1054        if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
1055                    || OMX_StateIdle || OMX_StateExecuting
1056                    || OMX_StatePause || OMX_StateInvalid)) {
1057            DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded");
1058            post_event(OMX_EventError,OMX_ErrorInvalidState,\
1059                    OMX_COMPONENT_GENERATE_EVENT);
1060            eRet = OMX_ErrorInvalidState;
1061        }
1062    } else if (cmd == OMX_CommandFlush) {
1063        if (0 == param1 || OMX_ALL == param1) {
1064            BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
1065        }
1066        if (1 == param1 || OMX_ALL == param1) {
1067            //generate output flush event only.
1068            BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1069        }
1070
1071        execute_omx_flush(param1);
1072        bFlag = 0;
1073    } else if ( cmd == OMX_CommandPortEnable) {
1074        if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
1075            m_sInPortDef.bEnabled = OMX_TRUE;
1076
1077            if ( (m_state == OMX_StateLoaded &&
1078                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
1079                    || allocate_input_done()) {
1080                post_event(OMX_CommandPortEnable,PORT_INDEX_IN,
1081                        OMX_COMPONENT_GENERATE_EVENT);
1082            } else {
1083                DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
1084                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
1085                // Skip the event notification
1086                bFlag = 0;
1087            }
1088        }
1089        if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
1090            m_sOutPortDef.bEnabled = OMX_TRUE;
1091
1092            if ( (m_state == OMX_StateLoaded &&
1093                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
1094                    || (allocate_output_done())) {
1095                post_event(OMX_CommandPortEnable,PORT_INDEX_OUT,
1096                        OMX_COMPONENT_GENERATE_EVENT);
1097
1098            } else {
1099                DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
1100                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
1101                // Skip the event notification
1102                bFlag = 0;
1103            }
1104        }
1105    } else if (cmd == OMX_CommandPortDisable) {
1106        if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
1107            m_sInPortDef.bEnabled = OMX_FALSE;
1108            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
1109                    && release_input_done()) {
1110                post_event(OMX_CommandPortDisable,PORT_INDEX_IN,
1111                        OMX_COMPONENT_GENERATE_EVENT);
1112            } else {
1113                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
1114                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
1115                    execute_omx_flush(PORT_INDEX_IN);
1116                }
1117
1118                // Skip the event notification
1119                bFlag = 0;
1120            }
1121        }
1122        if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
1123            m_sOutPortDef.bEnabled = OMX_FALSE;
1124
1125            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
1126                    && release_output_done()) {
1127                post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\
1128                        OMX_COMPONENT_GENERATE_EVENT);
1129            } else {
1130                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1131                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
1132                    execute_omx_flush(PORT_INDEX_OUT);
1133                }
1134                // Skip the event notification
1135                bFlag = 0;
1136
1137            }
1138        }
1139    } else {
1140        DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)",cmd);
1141        eRet = OMX_ErrorNotImplemented;
1142    }
1143    if (eRet == OMX_ErrorNone && bFlag) {
1144        post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
1145    }
1146    sem_post(&m_cmd_lock);
1147    return eRet;
1148}
1149
1150/* ======================================================================
1151   FUNCTION
1152   omx_venc::ExecuteOmxFlush
1153
1154   DESCRIPTION
1155   Executes the OMX flush.
1156
1157   PARAMETERS
1158   flushtype - input flush(1)/output flush(0)/ both.
1159
1160   RETURN VALUE
1161   true/false
1162
1163   ========================================================================== */
1164bool omx_video::execute_omx_flush(OMX_U32 flushType)
1165{
1166    bool bRet = false;
1167    DEBUG_PRINT_LOW("execute_omx_flush -  %u", (unsigned int)flushType);
1168#ifdef _MSM8974_
1169    /* XXX: The driver/hardware does not support flushing of individual ports
1170     * in all states. So we pretty much need to flush both ports internally,
1171     * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
1172     * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
1173     * we automatically omit sending the FLUSH done for the "opposite" port. */
1174
1175    input_flush_progress = true;
1176    output_flush_progress = true;
1177    bRet = execute_flush_all();
1178#else
1179    if (flushType == 0 || flushType == OMX_ALL) {
1180        input_flush_progress = true;
1181        //flush input only
1182        bRet = execute_input_flush();
1183    }
1184    if (flushType == 1 || flushType == OMX_ALL) {
1185        //flush output only
1186        output_flush_progress = true;
1187        bRet = execute_output_flush();
1188    }
1189#endif
1190    return bRet;
1191}
1192/*=========================================================================
1193FUNCTION : execute_output_flush
1194
1195DESCRIPTION
1196Executes the OMX flush at OUTPUT PORT.
1197
1198PARAMETERS
1199None.
1200
1201RETURN VALUE
1202true/false
1203==========================================================================*/
1204bool omx_video::execute_output_flush(void)
1205{
1206    unsigned long p1 = 0; // Parameter - 1
1207    unsigned long p2 = 0; // Parameter - 2
1208    unsigned long ident = 0;
1209    bool bRet = true;
1210
1211    /*Generate FBD for all Buffers in the FTBq*/
1212    DEBUG_PRINT_LOW("execute_output_flush");
1213    pthread_mutex_lock(&m_lock);
1214    while (m_ftb_q.m_size) {
1215        m_ftb_q.pop_entry(&p1,&p2,&ident);
1216
1217        if (ident == OMX_COMPONENT_GENERATE_FTB ) {
1218            pending_output_buffers++;
1219            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
1220        } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
1221            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
1222        }
1223    }
1224
1225    pthread_mutex_unlock(&m_lock);
1226    /*Check if there are buffers with the Driver*/
1227    if (dev_flush(PORT_INDEX_OUT)) {
1228        DEBUG_PRINT_ERROR("ERROR: o/p dev_flush() Failed");
1229        return false;
1230    }
1231
1232    return bRet;
1233}
1234/*=========================================================================
1235FUNCTION : execute_input_flush
1236
1237DESCRIPTION
1238Executes the OMX flush at INPUT PORT.
1239
1240PARAMETERS
1241None.
1242
1243RETURN VALUE
1244true/false
1245==========================================================================*/
1246bool omx_video::execute_input_flush(void)
1247{
1248    unsigned long p1 = 0; // Parameter - 1
1249    unsigned long p2 = 0; // Parameter - 2
1250    unsigned long ident = 0;
1251    bool bRet = true;
1252
1253    /*Generate EBD for all Buffers in the ETBq*/
1254    DEBUG_PRINT_LOW("execute_input_flush");
1255
1256    pthread_mutex_lock(&m_lock);
1257    while (m_etb_q.m_size) {
1258        m_etb_q.pop_entry(&p1,&p2,&ident);
1259        if (ident == OMX_COMPONENT_GENERATE_ETB) {
1260            pending_input_buffers++;
1261            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
1262        } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
1263            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
1264        } else if (ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
1265            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
1266        }
1267    }
1268    if (mUseProxyColorFormat) {
1269        if (psource_frame) {
1270            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
1271            psource_frame = NULL;
1272        }
1273        while (m_opq_meta_q.m_size) {
1274            unsigned long p1,p2,id;
1275            m_opq_meta_q.pop_entry(&p1,&p2,&id);
1276            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
1277                    (OMX_BUFFERHEADERTYPE  *)p1);
1278        }
1279        if (pdest_frame) {
1280            m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
1281            pdest_frame = NULL;
1282        }
1283    }
1284    pthread_mutex_unlock(&m_lock);
1285    /*Check if there are buffers with the Driver*/
1286    if (dev_flush(PORT_INDEX_IN)) {
1287        DEBUG_PRINT_ERROR("ERROR: i/p dev_flush() Failed");
1288        return false;
1289    }
1290
1291    return bRet;
1292}
1293
1294
1295/*=========================================================================
1296FUNCTION : execute_flush
1297
1298DESCRIPTION
1299Executes the OMX flush at INPUT & OUTPUT PORT.
1300
1301PARAMETERS
1302None.
1303
1304RETURN VALUE
1305true/false
1306==========================================================================*/
1307#ifdef _MSM8974_
1308bool omx_video::execute_flush_all(void)
1309{
1310    unsigned long p1 = 0; // Parameter - 1
1311    unsigned long p2 = 0; // Parameter - 2
1312    unsigned long ident = 0;
1313    bool bRet = true;
1314
1315    DEBUG_PRINT_LOW("execute_flush_all");
1316
1317    /*Generate EBD for all Buffers in the ETBq*/
1318    pthread_mutex_lock(&m_lock);
1319    while (m_etb_q.m_size) {
1320        m_etb_q.pop_entry(&p1,&p2,&ident);
1321        if (ident == OMX_COMPONENT_GENERATE_ETB) {
1322            pending_input_buffers++;
1323            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
1324        } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
1325            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
1326        } else if(ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
1327            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
1328        }
1329    }
1330    if(mUseProxyColorFormat) {
1331        if(psource_frame) {
1332            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
1333            psource_frame = NULL;
1334        }
1335        while(m_opq_meta_q.m_size) {
1336            unsigned long p1,p2,id;
1337            m_opq_meta_q.pop_entry(&p1,&p2,&id);
1338            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
1339                (OMX_BUFFERHEADERTYPE  *)p1);
1340        }
1341        if(pdest_frame){
1342            m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
1343            pdest_frame = NULL;
1344        }
1345    }
1346
1347    /*Generate FBD for all Buffers in the FTBq*/
1348    DEBUG_PRINT_LOW("execute_output_flush");
1349    while (m_ftb_q.m_size) {
1350        m_ftb_q.pop_entry(&p1,&p2,&ident);
1351
1352        if (ident == OMX_COMPONENT_GENERATE_FTB ) {
1353            pending_output_buffers++;
1354            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
1355        } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
1356            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
1357        }
1358    }
1359
1360    pthread_mutex_unlock(&m_lock);
1361
1362    /*Check if there are buffers with the Driver*/
1363    if (dev_flush(PORT_INDEX_BOTH)) {
1364        DEBUG_PRINT_ERROR("ERROR: dev_flush() Failed");
1365        return false;
1366    }
1367    return bRet;
1368}
1369
1370#endif
1371
1372/* ======================================================================
1373   FUNCTION
1374   omx_venc::SendCommandEvent
1375
1376   DESCRIPTION
1377   Send the event to decoder pipe.  This is needed to generate the callbacks
1378   in decoder thread context.
1379
1380   PARAMETERS
1381   None.
1382
1383   RETURN VALUE
1384   true/false
1385
1386   ========================================================================== */
1387bool omx_video::post_event(unsigned long p1,
1388        unsigned long p2,
1389        unsigned long id)
1390{
1391    bool bRet =  false;
1392
1393    pthread_mutex_lock(&m_lock);
1394
1395    if ((id == OMX_COMPONENT_GENERATE_FTB) ||
1396            (id == OMX_COMPONENT_GENERATE_FBD) ||
1397            (id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH)) {
1398        m_ftb_q.insert_entry(p1,p2,id);
1399    } else if ((id == OMX_COMPONENT_GENERATE_ETB) ||
1400            (id == OMX_COMPONENT_GENERATE_EBD) ||
1401            (id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH)) {
1402        m_etb_q.insert_entry(p1,p2,id);
1403    } else {
1404        m_cmd_q.insert_entry(p1,p2,id);
1405    }
1406
1407    bRet = true;
1408    DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
1409    post_message(this, id);
1410    pthread_mutex_unlock(&m_lock);
1411
1412    return bRet;
1413}
1414
1415/* ======================================================================
1416   FUNCTION
1417   omx_venc::GetParameter
1418
1419   DESCRIPTION
1420   OMX Get Parameter method implementation
1421
1422   PARAMETERS
1423   <TBD>.
1424
1425   RETURN VALUE
1426   Error None if successful.
1427
1428   ========================================================================== */
1429OMX_ERRORTYPE  omx_video::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
1430        OMX_IN OMX_INDEXTYPE paramIndex,
1431        OMX_INOUT OMX_PTR     paramData)
1432{
1433    (void)hComp;
1434    OMX_ERRORTYPE eRet = OMX_ErrorNone;
1435    unsigned int height=0,width = 0;
1436
1437    DEBUG_PRINT_LOW("get_parameter:");
1438    if (m_state == OMX_StateInvalid) {
1439        DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State");
1440        return OMX_ErrorInvalidState;
1441    }
1442    if (paramData == NULL) {
1443        DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData");
1444        return OMX_ErrorBadParameter;
1445    }
1446    switch ((int)paramIndex) {
1447        case OMX_IndexParamPortDefinition:
1448            {
1449                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
1450                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
1451                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
1452
1453                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
1454                if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
1455                    dev_get_buf_req (&m_sInPortDef.nBufferCountMin,
1456                        &m_sInPortDef.nBufferCountActual,
1457                        &m_sInPortDef.nBufferSize,
1458                        m_sInPortDef.nPortIndex);
1459                    DEBUG_PRINT_LOW("m_sInPortDef: size = %u, min cnt = %u, actual cnt = %u",
1460                            (unsigned int)m_sInPortDef.nBufferSize, (unsigned int)m_sInPortDef.nBufferCountMin,
1461                            (unsigned int)m_sInPortDef.nBufferCountActual);
1462                    memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef));
1463#ifdef _ANDROID_ICS_
1464                    if (meta_mode_enable) {
1465                        portDefn->nBufferSize = sizeof(encoder_media_buffer_type);
1466                    }
1467                    if (mUseProxyColorFormat) {
1468                        portDefn->format.video.eColorFormat =
1469                            (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque;
1470                    }
1471#endif
1472                } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1473                    if (m_state != OMX_StateExecuting) {
1474                    dev_get_buf_req (&m_sOutPortDef.nBufferCountMin,
1475                            &m_sOutPortDef.nBufferCountActual,
1476                            &m_sOutPortDef.nBufferSize,
1477                            m_sOutPortDef.nPortIndex);
1478                    }
1479                    DEBUG_PRINT_LOW("m_sOutPortDef: size = %u, min cnt = %u, actual cnt = %u",
1480                            (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountMin,
1481                            (unsigned int)m_sOutPortDef.nBufferCountActual);
1482                    memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef));
1483                } else {
1484                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
1485                    eRet = OMX_ErrorBadPortIndex;
1486                }
1487                break;
1488            }
1489        case OMX_IndexParamVideoInit:
1490            {
1491                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
1492                OMX_PORT_PARAM_TYPE *portParamType =
1493                    (OMX_PORT_PARAM_TYPE *) paramData;
1494                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
1495
1496                memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam));
1497                break;
1498            }
1499        case OMX_IndexParamVideoPortFormat:
1500            {
1501                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
1502                OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
1503                    (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
1504                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
1505
1506                if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
1507                    unsigned index = portFmt->nIndex;
1508                    //we support two formats
1509                    //index 0 - Venus flavour of YUV420SP
1510                    //index 1 - opaque which internally maps to YUV420SP.
1511                    //index 2 - vannilla YUV420SP
1512                    //this can be extended in the future
1513                    int supportedFormats[] = {
1514                        [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1515                        [1] = QOMX_COLOR_FormatAndroidOpaque,
1516                        [2] = OMX_COLOR_FormatYUV420SemiPlanar,
1517                    };
1518
1519                    if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1))
1520                        eRet = OMX_ErrorNoMore;
1521                    else {
1522                        memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat));
1523                        portFmt->nIndex = index; //restore index set from client
1524                        portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)supportedFormats[index];
1525                    }
1526                } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1527                    memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat));
1528                } else {
1529                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
1530                    eRet = OMX_ErrorBadPortIndex;
1531                }
1532                break;
1533            }
1534        case OMX_IndexParamVideoBitrate:
1535            {
1536                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE);
1537                OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
1538                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate");
1539
1540                if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1541                    memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate));
1542                } else {
1543                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
1544                    eRet = OMX_ErrorBadPortIndex;
1545                }
1546
1547                break;
1548            }
1549        case OMX_IndexParamVideoMpeg4:
1550            {
1551                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE);
1552                OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
1553                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4");
1554                memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
1555                break;
1556            }
1557        case OMX_IndexParamVideoH263:
1558            {
1559                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_H263TYPE);
1560                OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
1561                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263");
1562                memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
1563                break;
1564            }
1565        case OMX_IndexParamVideoAvc:
1566            {
1567                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE);
1568                OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
1569                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc");
1570                memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
1571                break;
1572            }
1573        case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
1574            {
1575                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE);
1576                OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
1577                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoVp8");
1578                memcpy(pParam, &m_sParamVP8, sizeof(m_sParamVP8));
1579                break;
1580            }
1581        case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
1582            {
1583                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE);
1584                OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
1585                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoHevc");
1586                memcpy(pParam, &m_sParamHEVC, sizeof(m_sParamHEVC));
1587                break;
1588            }
1589        case OMX_IndexParamVideoProfileLevelQuerySupported:
1590            {
1591                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
1592                OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
1593                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported");
1594                eRet = get_supported_profile_level(pParam);
1595                if (eRet && eRet != OMX_ErrorNoMore)
1596                    DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %u, %u",
1597                            (unsigned int)pParam->eProfile, (unsigned int)pParam->eLevel);
1598                break;
1599            }
1600        case OMX_IndexParamVideoProfileLevelCurrent:
1601            {
1602                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
1603                OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
1604                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent");
1605                memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
1606                break;
1607            }
1608            /*Component should support this port definition*/
1609        case OMX_IndexParamAudioInit:
1610            {
1611                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
1612                OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
1613                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
1614                memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio));
1615                break;
1616            }
1617            /*Component should support this port definition*/
1618        case OMX_IndexParamImageInit:
1619            {
1620                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
1621                OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
1622                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
1623                memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img));
1624                break;
1625
1626            }
1627            /*Component should support this port definition*/
1628        case OMX_IndexParamOtherInit:
1629            {
1630                DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x", paramIndex);
1631                eRet =OMX_ErrorUnsupportedIndex;
1632                break;
1633            }
1634        case OMX_IndexParamStandardComponentRole:
1635            {
1636                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
1637                OMX_PARAM_COMPONENTROLETYPE *comp_role;
1638                comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
1639                comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
1640                comp_role->nSize = sizeof(*comp_role);
1641
1642                DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",paramIndex);
1643                strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE);
1644                break;
1645            }
1646            /* Added for parameter test */
1647        case OMX_IndexParamPriorityMgmt:
1648            {
1649                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
1650                OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData;
1651                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
1652                memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt));
1653                break;
1654            }
1655            /* Added for parameter test */
1656        case OMX_IndexParamCompBufferSupplier:
1657            {
1658                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
1659                OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
1660                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
1661                if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) {
1662                    memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier));
1663                } else if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) {
1664                    memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier));
1665                } else {
1666                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
1667                    eRet = OMX_ErrorBadPortIndex;
1668                }
1669                break;
1670            }
1671
1672        case OMX_IndexParamVideoQuantization:
1673            {
1674                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
1675                OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
1676                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization");
1677                memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization));
1678                break;
1679            }
1680
1681        case OMX_QcomIndexParamVideoQPRange:
1682            {
1683                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_QPRANGETYPE);
1684                OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData;
1685                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoQPRange");
1686                memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange));
1687                break;
1688            }
1689
1690        case OMX_IndexParamVideoErrorCorrection:
1691            {
1692                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
1693                OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData;
1694                DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection");
1695                errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC;
1696                errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync;
1697                errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing;
1698                break;
1699            }
1700        case OMX_IndexParamVideoIntraRefresh:
1701            {
1702                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
1703                OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData;
1704                DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh");
1705                DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET");
1706                intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode;
1707                intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs;
1708                break;
1709            }
1710        case OMX_QcomIndexPortDefn:
1711            //TODO
1712            break;
1713        case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
1714            {
1715                VALIDATE_OMX_PARAM_DATA(paramData, OMXComponentCapabilityFlagsType);
1716                OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData);
1717                DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX");
1718                pParam->iIsOMXComponentMultiThreaded = OMX_TRUE;
1719                pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE;
1720                pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
1721                pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
1722                pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE;
1723                pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE;
1724                pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE;
1725                pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
1726                m_use_input_pmem = OMX_TRUE;
1727                DEBUG_PRINT_LOW("Supporting capability index in encoder node");
1728                break;
1729            }
1730#if !defined(MAX_RES_720P) || defined(_MSM8974_)
1731        case OMX_QcomIndexParamIndexExtraDataType:
1732            {
1733                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
1734                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType");
1735                QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData;
1736                if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) {
1737                    if (pParam->nPortIndex == PORT_INDEX_OUT) {
1738                        pParam->bEnabled =
1739                            (OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_SLICEINFO);
1740                        DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled);
1741                    } else {
1742                        DEBUG_PRINT_ERROR("get_parameter: slice information is "
1743                                "valid for output port only");
1744                        eRet =OMX_ErrorUnsupportedIndex;
1745                    }
1746                } else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderMBInfo) {
1747                    if (pParam->nPortIndex == PORT_INDEX_OUT) {
1748                        pParam->bEnabled =
1749                            (OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_MBINFO);
1750                        DEBUG_PRINT_HIGH("MB Info extradata %d", pParam->bEnabled);
1751                    } else {
1752                        DEBUG_PRINT_ERROR("get_parameter: MB information is "
1753                                "valid for output port only");
1754                        eRet = OMX_ErrorUnsupportedIndex;
1755                    }
1756                }
1757#ifndef _MSM8974_
1758                else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) {
1759                    if (pParam->nPortIndex == PORT_INDEX_OUT) {
1760                        pParam->bEnabled =
1761                            (OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_LTRINFO);
1762                        DEBUG_PRINT_HIGH("LTR Info extradata %d", pParam->bEnabled);
1763                    } else {
1764                        DEBUG_PRINT_ERROR("get_parameter: LTR information is "
1765                                "valid for output port only");
1766                        eRet = OMX_ErrorUnsupportedIndex;
1767                    }
1768                }
1769#endif
1770                else {
1771                    DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
1772                            pParam->nIndex);
1773                    eRet = OMX_ErrorUnsupportedIndex;
1774                }
1775                break;
1776            }
1777        case QOMX_IndexParamVideoLTRCountRangeSupported:
1778            {
1779                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_RANGETYPE);
1780                DEBUG_PRINT_HIGH("get_parameter: QOMX_IndexParamVideoLTRCountRangeSupported");
1781                QOMX_EXTNINDEX_RANGETYPE *pParam = (QOMX_EXTNINDEX_RANGETYPE *)paramData;
1782                if (pParam->nPortIndex == PORT_INDEX_OUT) {
1783                    OMX_U32 min = 0, max = 0, step_size = 0;
1784                    if (dev_get_capability_ltrcount(&min, &max, &step_size)) {
1785                        pParam->nMin = min;
1786                        pParam->nMax = max;
1787                        pParam->nStepSize = step_size;
1788                    } else {
1789                        DEBUG_PRINT_ERROR("get_parameter: get_capability_ltrcount failed");
1790                        eRet = OMX_ErrorUndefined;
1791                    }
1792                } else {
1793                    DEBUG_PRINT_ERROR("LTR count range is valid for output port only");
1794                    eRet = OMX_ErrorUnsupportedIndex;
1795                }
1796            }
1797            break;
1798        case OMX_QcomIndexParamVideoLTRCount:
1799            {
1800                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE);
1801                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoLTRCount");
1802                OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE *pParam =
1803                        reinterpret_cast<OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*>(paramData);
1804                memcpy(pParam, &m_sParamLTRCount, sizeof(m_sParamLTRCount));
1805                break;
1806            }
1807#endif
1808        case QOMX_IndexParamVideoSyntaxHdr:
1809            {
1810                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE);
1811                DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr");
1812                QOMX_EXTNINDEX_PARAMTYPE* pParam =
1813                    reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData);
1814                if (pParam->pData == NULL) {
1815                    DEBUG_PRINT_ERROR("Error: Data buffer is NULL");
1816                    eRet = OMX_ErrorBadParameter;
1817                    break;
1818                }
1819                if (get_syntaxhdr_enable == false) {
1820                    DEBUG_PRINT_ERROR("ERROR: get_parameter: Get syntax header disabled");
1821                    eRet = OMX_ErrorUnsupportedIndex;
1822                    break;
1823                }
1824                BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
1825                if (dev_loaded_start()) {
1826                    DEBUG_PRINT_LOW("device start successful");
1827                } else {
1828                    DEBUG_PRINT_ERROR("device start failed");
1829                    BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
1830                    return OMX_ErrorHardware;
1831                }
1832                if (dev_get_seq_hdr(pParam->pData,
1833                            (unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)),
1834                            (unsigned *)(void *)&pParam->nDataSize)) {
1835                    DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %u)",
1836                            (unsigned int)pParam->nDataSize);
1837                    for (unsigned i = 0; i < pParam->nDataSize; i++) {
1838                        DEBUG_PRINT_LOW("Header[%d] = %x", i, *((char *)pParam->pData + i));
1839                    }
1840                } else {
1841                    DEBUG_PRINT_ERROR("Error returned from GetSyntaxHeader()");
1842                    eRet = OMX_ErrorHardware;
1843                }
1844                BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
1845                if (dev_loaded_stop()) {
1846                    DEBUG_PRINT_LOW("device stop successful");
1847                } else {
1848                    DEBUG_PRINT_ERROR("device stop failed");
1849                    BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
1850                    eRet = OMX_ErrorHardware;
1851                }
1852                break;
1853            }
1854        case OMX_QcomIndexHierarchicalStructure:
1855            {
1856                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS);
1857                QOMX_VIDEO_HIERARCHICALLAYERS* hierp = (QOMX_VIDEO_HIERARCHICALLAYERS*) paramData;
1858                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexHierarchicalStructure");
1859                memcpy(hierp, &m_sHierLayers, sizeof(m_sHierLayers));
1860                break;
1861            }
1862        case OMX_QcomIndexParamPerfLevel:
1863            {
1864                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PERF_LEVEL);
1865                OMX_U32 perflevel;
1866                OMX_QCOM_VIDEO_PARAM_PERF_LEVEL *pParam =
1867                    reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PERF_LEVEL*>(paramData);
1868                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPerfLevel");
1869                if (!dev_get_performance_level(&perflevel)) {
1870                    DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d",
1871                        pParam->ePerfLevel);
1872                } else {
1873                    pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel;
1874                }
1875                break;
1876            }
1877        case OMX_QcomIndexParamH264VUITimingInfo:
1878            {
1879                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO);
1880                OMX_U32 enabled;
1881                OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
1882                    reinterpret_cast<OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO*>(paramData);
1883                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamH264VUITimingInfo");
1884                if (!dev_get_vui_timing_info(&enabled)) {
1885                    DEBUG_PRINT_ERROR("Invalid entry returned from get_vui_Timing_info %d",
1886                        pParam->bEnable);
1887                } else {
1888                    pParam->bEnable = (OMX_BOOL)enabled;
1889                }
1890                break;
1891            }
1892        case OMX_QcomIndexParamPeakBitrate:
1893            {
1894                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE);
1895                OMX_U32 peakbitrate;
1896                OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam =
1897                    reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE*>(paramData);
1898                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPeakBitrate");
1899                if (!dev_get_peak_bitrate(&peakbitrate)) {
1900                    DEBUG_PRINT_ERROR("Invalid entry returned from get_peak_bitrate %u",
1901                        (unsigned int)pParam->nPeakBitrate);
1902                } else {
1903                    pParam->nPeakBitrate = peakbitrate;
1904                }
1905                break;
1906            }
1907         case QOMX_IndexParamVideoInitialQp:
1908            {
1909                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP);
1910                 QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp =
1911                     reinterpret_cast<QOMX_EXTNINDEX_VIDEO_INITIALQP *>(paramData);
1912                     memcpy(initqp, &m_sParamInitqp, sizeof(m_sParamInitqp));
1913                break;
1914            }
1915        case OMX_IndexParamAndroidVideoTemporalLayering:
1916            {
1917                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE);
1918                OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pLayerInfo =
1919                        reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE*>(paramData);
1920                if (!dev_get_temporal_layer_caps(&m_sParamTemporalLayers.nLayerCountMax,
1921                        &m_sParamTemporalLayers.nBLayerCountMax)) {
1922                    DEBUG_PRINT_ERROR("Failed to get temporal layer capabilities");
1923                    eRet = OMX_ErrorHardware;
1924                }
1925                memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers));
1926                break;
1927            }
1928        case OMX_IndexParamVideoSliceFMO:
1929        default:
1930            {
1931                DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x", paramIndex);
1932                eRet =OMX_ErrorUnsupportedIndex;
1933                break;
1934            }
1935
1936    }
1937
1938    return eRet;
1939
1940}
1941/* ======================================================================
1942   FUNCTION
1943   omx_video::GetConfig
1944
1945   DESCRIPTION
1946   OMX Get Config Method implementation.
1947
1948   PARAMETERS
1949   <TBD>.
1950
1951   RETURN VALUE
1952   OMX Error None if successful.
1953
1954   ========================================================================== */
1955OMX_ERRORTYPE  omx_video::get_config(OMX_IN OMX_HANDLETYPE      hComp,
1956        OMX_IN OMX_INDEXTYPE configIndex,
1957        OMX_INOUT OMX_PTR     configData)
1958{
1959    (void)hComp;
1960    ////////////////////////////////////////////////////////////////
1961    // Supported Config Index           Type
1962    // =============================================================
1963    // OMX_IndexConfigVideoBitrate      OMX_VIDEO_CONFIG_BITRATETYPE
1964    // OMX_IndexConfigVideoFramerate    OMX_CONFIG_FRAMERATETYPE
1965    // OMX_IndexConfigCommonRotate      OMX_CONFIG_ROTATIONTYPE
1966    ////////////////////////////////////////////////////////////////
1967
1968    if (configData == NULL) {
1969        DEBUG_PRINT_ERROR("ERROR: param is null");
1970        return OMX_ErrorBadParameter;
1971    }
1972
1973    if (m_state == OMX_StateInvalid) {
1974        DEBUG_PRINT_ERROR("ERROR: can't be in invalid state");
1975        return OMX_ErrorIncorrectStateOperation;
1976    }
1977
1978    //@todo need to validate params
1979    switch ((int)configIndex) {
1980        case OMX_IndexConfigVideoBitrate:
1981            {
1982                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE);
1983                OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
1984                memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
1985                break;
1986            }
1987        case OMX_IndexConfigVideoFramerate:
1988            {
1989                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE);
1990                OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
1991                memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
1992                break;
1993            }
1994        case OMX_IndexConfigCommonRotate:
1995            {
1996                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE);
1997                OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
1998                memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
1999                break;
2000            }
2001        case QOMX_IndexConfigVideoIntraperiod:
2002            {
2003                DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod");
2004                VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE);
2005                QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData);
2006                memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod));
2007                break;
2008            }
2009        case OMX_IndexConfigVideoAVCIntraPeriod:
2010            {
2011                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD);
2012                OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam =
2013                    reinterpret_cast<OMX_VIDEO_CONFIG_AVCINTRAPERIOD*>(configData);
2014                DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoAVCIntraPeriod");
2015                memcpy(pParam, &m_sConfigAVCIDRPeriod, sizeof(m_sConfigAVCIDRPeriod));
2016                break;
2017            }
2018        case OMX_IndexConfigCommonDeinterlace:
2019            {
2020                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_DEINTERLACE);
2021                OMX_VIDEO_CONFIG_DEINTERLACE *pParam =
2022                    reinterpret_cast<OMX_VIDEO_CONFIG_DEINTERLACE*>(configData);
2023                DEBUG_PRINT_LOW("get_config: OMX_IndexConfigCommonDeinterlace");
2024                memcpy(pParam, &m_sConfigDeinterlace, sizeof(m_sConfigDeinterlace));
2025                break;
2026            }
2027       case OMX_IndexConfigVideoVp8ReferenceFrame:
2028           {
2029                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE);
2030               OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam =
2031                   reinterpret_cast<OMX_VIDEO_VP8REFERENCEFRAMETYPE*>(configData);
2032               DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoVp8ReferenceFrame");
2033               memcpy(pParam, &m_sConfigVp8ReferenceFrame, sizeof(m_sConfigVp8ReferenceFrame));
2034               break;
2035           }
2036        case OMX_QcomIndexConfigPerfLevel:
2037            {
2038                VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
2039                OMX_U32 perflevel;
2040                OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *pParam =
2041                    reinterpret_cast<OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL*>(configData);
2042                DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigPerfLevel");
2043                if (!dev_get_performance_level(&perflevel)) {
2044                    DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d",
2045                        pParam->ePerfLevel);
2046                } else {
2047                    pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel;
2048                }
2049                break;
2050            }
2051      case OMX_IndexConfigAndroidIntraRefresh:
2052           {
2053               VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE);
2054               OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE* pParam =
2055                   reinterpret_cast<OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE*>(configData);
2056               DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidIntraRefresh");
2057               memcpy(pParam, &m_sConfigIntraRefresh, sizeof(m_sConfigIntraRefresh));
2058               break;
2059           }
2060        case OMX_IndexParamAndroidVideoTemporalLayering:
2061            {
2062                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE);
2063                OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *layerConfig =
2064                        (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)configData;
2065                memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers));
2066                break;
2067            }
2068        default:
2069            DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
2070            return OMX_ErrorUnsupportedIndex;
2071    }
2072    return OMX_ErrorNone;
2073
2074}
2075
2076#define extn_equals(param, extn) (!strcmp(param, extn))
2077
2078/* ======================================================================
2079   FUNCTION
2080   omx_video::GetExtensionIndex
2081
2082   DESCRIPTION
2083   OMX GetExtensionIndex method implementaion.  <TBD>
2084
2085   PARAMETERS
2086   <TBD>.
2087
2088   RETURN VALUE
2089   OMX Error None if everything successful.
2090
2091   ========================================================================== */
2092OMX_ERRORTYPE  omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
2093        OMX_IN OMX_STRING      paramName,
2094        OMX_OUT OMX_INDEXTYPE* indexType)
2095{
2096    (void)hComp;
2097    if (m_state == OMX_StateInvalid) {
2098        DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State");
2099        return OMX_ErrorInvalidState;
2100    }
2101#ifdef MAX_RES_1080P
2102    if (extn_equals(paramName, "OMX.QCOM.index.param.SliceDeliveryMode")) {
2103        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode;
2104        return OMX_ErrorNone;
2105    }
2106#endif
2107#ifdef _ANDROID_ICS_
2108    if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
2109        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
2110        return OMX_ErrorNone;
2111    }
2112#endif
2113    if (extn_equals(paramName, "OMX.google.android.index.prependSPSPPSToIDRFrames")) {
2114        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR;
2115        return OMX_ErrorNone;
2116    }
2117    return OMX_ErrorNotImplemented;
2118}
2119
2120/* ======================================================================
2121   FUNCTION
2122   omx_video::GetState
2123
2124   DESCRIPTION
2125   Returns the state information back to the caller.<TBD>
2126
2127   PARAMETERS
2128   <TBD>.
2129
2130   RETURN VALUE
2131   Error None if everything is successful.
2132   ========================================================================== */
2133OMX_ERRORTYPE  omx_video::get_state(OMX_IN OMX_HANDLETYPE  hComp,
2134        OMX_OUT OMX_STATETYPE* state)
2135{
2136    (void)hComp;
2137    *state = m_state;
2138    DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
2139    return OMX_ErrorNone;
2140}
2141
2142/* ======================================================================
2143   FUNCTION
2144   omx_video::ComponentTunnelRequest
2145
2146   DESCRIPTION
2147   OMX Component Tunnel Request method implementation. <TBD>
2148
2149   PARAMETERS
2150   None.
2151
2152   RETURN VALUE
2153   OMX Error None if everything successful.
2154
2155   ========================================================================== */
2156OMX_ERRORTYPE  omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
2157        OMX_IN OMX_U32                        port,
2158        OMX_IN OMX_HANDLETYPE        peerComponent,
2159        OMX_IN OMX_U32                    peerPort,
2160        OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
2161{
2162    (void) hComp, (void) port, (void) peerComponent, (void) peerPort, (void) tunnelSetup;
2163    DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented");
2164    return OMX_ErrorNotImplemented;
2165}
2166
2167/* ======================================================================
2168   FUNCTION
2169   omx_video::UseInputBuffer
2170
2171   DESCRIPTION
2172   Helper function for Use buffer in the input pin
2173
2174   PARAMETERS
2175   None.
2176
2177   RETURN VALUE
2178   true/false
2179
2180   ========================================================================== */
2181OMX_ERRORTYPE  omx_video::use_input_buffer(
2182        OMX_IN OMX_HANDLETYPE            hComp,
2183        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
2184        OMX_IN OMX_U32                   port,
2185        OMX_IN OMX_PTR                   appData,
2186        OMX_IN OMX_U32                   bytes,
2187        OMX_IN OMX_U8*                   buffer)
2188{
2189    (void) hComp;
2190    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2191
2192    unsigned   i = 0;
2193    unsigned char *buf_addr = NULL;
2194
2195    DEBUG_PRINT_HIGH("use_input_buffer: port = %u appData = %p bytes = %u buffer = %p",(unsigned int)port,appData,(unsigned int)bytes,buffer);
2196    if (bytes != m_sInPortDef.nBufferSize) {
2197        DEBUG_PRINT_ERROR("ERROR: use_input_buffer: Size Mismatch!! "
2198                "bytes[%u] != Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize);
2199        return OMX_ErrorBadParameter;
2200    }
2201
2202    if (!m_inp_mem_ptr) {
2203        input_use_buffer = true;
2204        m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
2205                        calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
2206        if (m_inp_mem_ptr == NULL) {
2207            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr");
2208            return OMX_ErrorInsufficientResources;
2209        }
2210        DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr);
2211
2212
2213        m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
2214        if (m_pInput_pmem == NULL) {
2215            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_pmem");
2216            return OMX_ErrorInsufficientResources;
2217        }
2218#ifdef USE_ION
2219        m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual);
2220        if (m_pInput_ion == NULL) {
2221            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_ion");
2222            return OMX_ErrorInsufficientResources;
2223        }
2224#endif
2225
2226        for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
2227            m_pInput_pmem[i].fd = -1;
2228#ifdef USE_ION
2229            m_pInput_ion[i].ion_device_fd =-1;
2230            m_pInput_ion[i].fd_ion_data.fd =-1;
2231            m_pInput_ion[i].ion_alloc_data.handle = 0;
2232#endif
2233        }
2234
2235    }
2236
2237    for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
2238        if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
2239            break;
2240        }
2241    }
2242
2243    if (i < m_sInPortDef.nBufferCountActual) {
2244
2245        *bufferHdr = (m_inp_mem_ptr + i);
2246        BITMASK_SET(&m_inp_bm_count,i);
2247
2248        (*bufferHdr)->pBuffer           = (OMX_U8 *)buffer;
2249        (*bufferHdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
2250        (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
2251        (*bufferHdr)->nAllocLen         = m_sInPortDef.nBufferSize;
2252        (*bufferHdr)->pAppPrivate       = appData;
2253        (*bufferHdr)->nInputPortIndex   = PORT_INDEX_IN;
2254
2255        if (!m_use_input_pmem) {
2256#ifdef USE_ION
2257#ifdef _MSM8974_
2258            m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
2259                    &m_pInput_ion[i].ion_alloc_data,
2260                    &m_pInput_ion[i].fd_ion_data,0);
2261#else
2262            m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
2263                    &m_pInput_ion[i].ion_alloc_data,
2264                    &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED);
2265#endif
2266            if (m_pInput_ion[i].ion_device_fd < 0) {
2267                DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
2268                return OMX_ErrorInsufficientResources;
2269            }
2270            m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd;
2271#else
2272            m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2273            if (m_pInput_pmem[i].fd == 0) {
2274                m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2275            }
2276
2277            if (m_pInput_pmem[i] .fd < 0) {
2278                DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() Failed");
2279                return OMX_ErrorInsufficientResources;
2280            }
2281#endif
2282            m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
2283            m_pInput_pmem[i].offset = 0;
2284
2285            m_pInput_pmem[i].buffer = NULL;
2286            if(!secure_session) {
2287                m_pInput_pmem[i].buffer = (unsigned char *)mmap(
2288                    NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
2289                    MAP_SHARED,m_pInput_pmem[i].fd,0);
2290
2291            if (m_pInput_pmem[i].buffer == MAP_FAILED) {
2292                    DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
2293                m_pInput_pmem[i].buffer = NULL;
2294                close(m_pInput_pmem[i].fd);
2295#ifdef USE_ION
2296                free_ion_memory(&m_pInput_ion[i]);
2297#endif
2298                return OMX_ErrorInsufficientResources;
2299            }
2300            }
2301
2302        } else {
2303            OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate);
2304            DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (unsigned)pParam->offset);
2305
2306            if (pParam) {
2307                m_pInput_pmem[i].fd = pParam->pmem_fd;
2308                m_pInput_pmem[i].offset = pParam->offset;
2309                m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
2310                m_pInput_pmem[i].buffer = (unsigned char *)buffer;
2311                DEBUG_PRINT_LOW("DBG:: pParam->pmem_fd = %u, pParam->offset = %u",
2312                        (unsigned int)pParam->pmem_fd, (unsigned int)pParam->offset);
2313            } else {
2314                DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case");
2315                return OMX_ErrorBadParameter;
2316            }
2317        }
2318
2319        DEBUG_PRINT_LOW("use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p",
2320                (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer);
2321        if ( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) {
2322            DEBUG_PRINT_ERROR("ERROR: dev_use_buf() Failed for i/p buf");
2323            return OMX_ErrorInsufficientResources;
2324        }
2325    } else {
2326        DEBUG_PRINT_ERROR("ERROR: All buffers are already used, invalid use_buf call for "
2327                "index = %u", i);
2328        eRet = OMX_ErrorInsufficientResources;
2329    }
2330
2331    return eRet;
2332}
2333
2334
2335
2336/* ======================================================================
2337   FUNCTION
2338   omx_video::UseOutputBuffer
2339
2340   DESCRIPTION
2341   Helper function for Use buffer in the input pin
2342
2343   PARAMETERS
2344   None.
2345
2346   RETURN VALUE
2347   true/false
2348
2349   ========================================================================== */
2350OMX_ERRORTYPE  omx_video::use_output_buffer(
2351        OMX_IN OMX_HANDLETYPE            hComp,
2352        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
2353        OMX_IN OMX_U32                   port,
2354        OMX_IN OMX_PTR                   appData,
2355        OMX_IN OMX_U32                   bytes,
2356        OMX_IN OMX_U8*                   buffer)
2357{
2358    (void)hComp, (void)port;
2359    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2360    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
2361    unsigned                         i= 0; // Temporary counter
2362    unsigned char *buf_addr = NULL;
2363#ifdef _MSM8974_
2364    int align_size;
2365#endif
2366
2367    DEBUG_PRINT_HIGH("Inside use_output_buffer()");
2368    if (bytes != m_sOutPortDef.nBufferSize) {
2369        DEBUG_PRINT_ERROR("ERROR: use_output_buffer: Size Mismatch!! "
2370                "bytes[%u] != Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sOutPortDef.nBufferSize);
2371        return OMX_ErrorBadParameter;
2372    }
2373
2374    auto_lock l(m_buf_lock);
2375    if (!m_out_mem_ptr) {
2376        output_use_buffer = true;
2377        int nBufHdrSize        = 0;
2378
2379        DEBUG_PRINT_LOW("Allocating First Output Buffer(%u)",(unsigned int)m_sOutPortDef.nBufferCountActual);
2380        nBufHdrSize        = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
2381        /*
2382         * Memory for output side involves the following:
2383         * 1. Array of Buffer Headers
2384         * 2. Bitmask array to hold the buffer allocation details
2385         * In order to minimize the memory management entire allocation
2386         * is done in one step.
2387         */
2388        //OMX Buffer header
2389        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
2390        if (m_out_mem_ptr == NULL) {
2391            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_out_mem_ptr");
2392            return OMX_ErrorInsufficientResources;
2393        }
2394
2395        m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual);
2396        if (m_pOutput_pmem == NULL) {
2397            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_pmem");
2398            return OMX_ErrorInsufficientResources;
2399        }
2400#ifdef USE_ION
2401        m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual);
2402        if (m_pOutput_ion == NULL) {
2403            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_ion");
2404            return OMX_ErrorInsufficientResources;
2405        }
2406#endif
2407        if (m_out_mem_ptr) {
2408            bufHdr          =  m_out_mem_ptr;
2409            DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
2410            // Settting the entire storage nicely
2411            for (i=0; i < m_sOutPortDef.nBufferCountActual ; i++) {
2412                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
2413                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
2414                bufHdr->nAllocLen          = bytes;
2415                bufHdr->nFilledLen         = 0;
2416                bufHdr->pAppPrivate        = appData;
2417                bufHdr->nOutputPortIndex   = PORT_INDEX_OUT;
2418                bufHdr->pBuffer            = NULL;
2419                bufHdr++;
2420                m_pOutput_pmem[i].fd = -1;
2421#ifdef USE_ION
2422                m_pOutput_ion[i].ion_device_fd =-1;
2423                m_pOutput_ion[i].fd_ion_data.fd=-1;
2424                m_pOutput_ion[i].ion_alloc_data.handle = 0;
2425#endif
2426            }
2427        } else {
2428            DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%p]",m_out_mem_ptr);
2429            eRet =  OMX_ErrorInsufficientResources;
2430        }
2431    }
2432
2433    for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) {
2434        if (BITMASK_ABSENT(&m_out_bm_count,i)) {
2435            break;
2436        }
2437    }
2438
2439    if (eRet == OMX_ErrorNone) {
2440        if (i < m_sOutPortDef.nBufferCountActual) {
2441            *bufferHdr = (m_out_mem_ptr + i );
2442            (*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
2443            (*bufferHdr)->pAppPrivate = appData;
2444
2445            if (!m_use_output_pmem) {
2446#ifdef USE_ION
2447#ifdef _MSM8974_
2448                align_size = (m_sOutPortDef.nBufferSize + (SZ_4K - 1)) & ~(SZ_4K - 1);
2449                m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size,
2450                        &m_pOutput_ion[i].ion_alloc_data,
2451                        &m_pOutput_ion[i].fd_ion_data,0);
2452#else
2453                m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(
2454                        m_sOutPortDef.nBufferSize,
2455                        &m_pOutput_ion[i].ion_alloc_data,
2456                        &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED);
2457#endif
2458                if (m_pOutput_ion[i].ion_device_fd < 0) {
2459                    DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
2460                    return OMX_ErrorInsufficientResources;
2461                }
2462                m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd;
2463#else
2464                m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2465
2466                if (m_pOutput_pmem[i].fd == 0) {
2467                    m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2468                }
2469
2470                if (m_pOutput_pmem[i].fd < 0) {
2471                    DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() Failed");
2472                    return OMX_ErrorInsufficientResources;
2473                }
2474#endif
2475                m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
2476                m_pOutput_pmem[i].offset = 0;
2477
2478                m_pOutput_pmem[i].buffer = NULL;
2479                if(!secure_session) {
2480#ifdef _MSM8974_
2481                    m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
2482                        align_size,PROT_READ|PROT_WRITE,
2483                        MAP_SHARED,m_pOutput_pmem[i].fd,0);
2484#else
2485                    m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
2486                        m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
2487                        MAP_SHARED,m_pOutput_pmem[i].fd,0);
2488#endif
2489                if (m_pOutput_pmem[i].buffer == MAP_FAILED) {
2490                        DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
2491                    m_pOutput_pmem[i].buffer = NULL;
2492                    close(m_pOutput_pmem[i].fd);
2493#ifdef USE_ION
2494                    free_ion_memory(&m_pOutput_ion[i]);
2495#endif
2496                    return OMX_ErrorInsufficientResources;
2497                }
2498                }
2499            } else {
2500                OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate);
2501                DEBUG_PRINT_LOW("Inside qcom_ext pParam: %p", pParam);
2502
2503                if (pParam) {
2504                    DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (int)pParam->offset);
2505                    m_pOutput_pmem[i].fd = pParam->pmem_fd;
2506                    m_pOutput_pmem[i].offset = pParam->offset;
2507                    m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
2508                    m_pOutput_pmem[i].buffer = (unsigned char *)buffer;
2509                } else {
2510                    DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case");
2511                    return OMX_ErrorBadParameter;
2512                }
2513                buf_addr = (unsigned char *)buffer;
2514            }
2515
2516            DEBUG_PRINT_LOW("use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p",
2517                    (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer);
2518            if (dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) {
2519                DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf");
2520                return OMX_ErrorInsufficientResources;
2521            }
2522
2523            BITMASK_SET(&m_out_bm_count,i);
2524        } else {
2525            DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for "
2526                    "index = %u", i);
2527            eRet = OMX_ErrorInsufficientResources;
2528        }
2529    }
2530    return eRet;
2531}
2532
2533
2534/* ======================================================================
2535   FUNCTION
2536   omx_video::UseBuffer
2537
2538   DESCRIPTION
2539   OMX Use Buffer method implementation.
2540
2541   PARAMETERS
2542   <TBD>.
2543
2544   RETURN VALUE
2545   OMX Error None , if everything successful.
2546
2547   ========================================================================== */
2548OMX_ERRORTYPE  omx_video::use_buffer(
2549        OMX_IN OMX_HANDLETYPE            hComp,
2550        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
2551        OMX_IN OMX_U32                   port,
2552        OMX_IN OMX_PTR                   appData,
2553        OMX_IN OMX_U32                   bytes,
2554        OMX_IN OMX_U8*                   buffer)
2555{
2556    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2557    if (m_state == OMX_StateInvalid) {
2558        DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State");
2559        return OMX_ErrorInvalidState;
2560    }
2561    if (port == PORT_INDEX_IN) {
2562        eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
2563    } else if (port == PORT_INDEX_OUT) {
2564        eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
2565    } else {
2566        DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(int)port);
2567        eRet = OMX_ErrorBadPortIndex;
2568    }
2569
2570    if (eRet == OMX_ErrorNone) {
2571        if (allocate_done()) {
2572            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
2573                // Send the callback now
2574                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
2575                post_event(OMX_CommandStateSet,OMX_StateIdle,
2576                        OMX_COMPONENT_GENERATE_EVENT);
2577            }
2578        }
2579        if (port == PORT_INDEX_IN && m_sInPortDef.bPopulated) {
2580            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
2581                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
2582                post_event(OMX_CommandPortEnable,
2583                        PORT_INDEX_IN,
2584                        OMX_COMPONENT_GENERATE_EVENT);
2585            }
2586
2587        } else if (port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) {
2588            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
2589                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2590                post_event(OMX_CommandPortEnable,
2591                        PORT_INDEX_OUT,
2592                        OMX_COMPONENT_GENERATE_EVENT);
2593                m_event_port_settings_sent = false;
2594            }
2595        }
2596    }
2597    return eRet;
2598}
2599
2600OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
2601{
2602    unsigned int index = 0;
2603    OMX_U8 *temp_buff ;
2604
2605    if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
2606        DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]",
2607                bufferHdr, m_inp_mem_ptr);
2608        return OMX_ErrorBadParameter;
2609    }
2610
2611    index = bufferHdr - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);
2612#ifdef _ANDROID_ICS_
2613    if (meta_mode_enable) {
2614        if (index < m_sInPortDef.nBufferCountActual) {
2615            memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index]));
2616            memset(&meta_buffers[index], 0, sizeof(meta_buffers[index]));
2617        }
2618        if (!mUseProxyColorFormat)
2619            return OMX_ErrorNone;
2620        else {
2621            c2d_conv.close();
2622            opaque_buffer_hdr[index] = NULL;
2623        }
2624    }
2625#endif
2626    if (index < m_sInPortDef.nBufferCountActual && !mUseProxyColorFormat &&
2627            dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
2628        DEBUG_PRINT_LOW("ERROR: dev_free_buf() Failed for i/p buf");
2629    }
2630
2631    if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) {
2632        auto_lock l(m_lock);
2633
2634        if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) {
2635            DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case");
2636            if(!secure_session) {
2637            munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
2638            } else {
2639                free(m_pInput_pmem[index].buffer);
2640            }
2641            m_pInput_pmem[index].buffer = NULL;
2642            close (m_pInput_pmem[index].fd);
2643#ifdef USE_ION
2644            free_ion_memory(&m_pInput_ion[index]);
2645#endif
2646            m_pInput_pmem[index].fd = -1;
2647        } else if (m_pInput_pmem[index].fd > 0 && (input_use_buffer == true &&
2648                    m_use_input_pmem == OMX_FALSE)) {
2649            DEBUG_PRINT_LOW("FreeBuffer:: i/p Heap UseBuffer case");
2650            if (dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
2651                DEBUG_PRINT_ERROR("ERROR: dev_free_buf() Failed for i/p buf");
2652            }
2653            if(!secure_session) {
2654                munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
2655                m_pInput_pmem[index].buffer = NULL;
2656            }
2657            close (m_pInput_pmem[index].fd);
2658#ifdef USE_ION
2659            free_ion_memory(&m_pInput_ion[index]);
2660#endif
2661            m_pInput_pmem[index].fd = -1;
2662        } else {
2663            DEBUG_PRINT_ERROR("FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case");
2664        }
2665    }
2666    return OMX_ErrorNone;
2667}
2668
2669OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
2670{
2671    unsigned int index = 0;
2672    OMX_U8 *temp_buff ;
2673
2674    if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
2675        DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]",
2676                bufferHdr, m_out_mem_ptr);
2677        return OMX_ErrorBadParameter;
2678    }
2679    index = bufferHdr - m_out_mem_ptr;
2680
2681    if (index < m_sOutPortDef.nBufferCountActual &&
2682            dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
2683        DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
2684    }
2685
2686    if (index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) {
2687        if (m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) {
2688            DEBUG_PRINT_LOW("FreeBuffer:: o/p AllocateBuffer case");
2689            if(!secure_session) {
2690                munmap (m_pOutput_pmem[index].buffer,
2691                        m_pOutput_pmem[index].size);
2692            } else {
2693                char *data = (char*) m_pOutput_pmem[index].buffer;
2694                native_handle_t *handle = NULL;
2695                memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*));
2696                native_handle_delete(handle);
2697                free(m_pOutput_pmem[index].buffer);
2698            }
2699            close (m_pOutput_pmem[index].fd);
2700#ifdef USE_ION
2701            free_ion_memory(&m_pOutput_ion[index]);
2702#endif
2703            m_pOutput_pmem[index].fd = -1;
2704        } else if ( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true
2705                    && m_use_output_pmem == OMX_FALSE)) {
2706            DEBUG_PRINT_LOW("FreeBuffer:: o/p Heap UseBuffer case");
2707            if (dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
2708                DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
2709            }
2710            if(!secure_session) {
2711                munmap (m_pOutput_pmem[index].buffer,
2712                        m_pOutput_pmem[index].size);
2713            }
2714            close (m_pOutput_pmem[index].fd);
2715#ifdef USE_ION
2716            free_ion_memory(&m_pOutput_ion[index]);
2717#endif
2718            m_pOutput_pmem[index].fd = -1;
2719        } else {
2720            DEBUG_PRINT_LOW("FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case");
2721        }
2722    }
2723    return OMX_ErrorNone;
2724}
2725#ifdef _ANDROID_ICS_
2726OMX_ERRORTYPE omx_video::allocate_input_meta_buffer(
2727        OMX_HANDLETYPE       hComp,
2728        OMX_BUFFERHEADERTYPE **bufferHdr,
2729        OMX_PTR              appData,
2730        OMX_U32              bytes)
2731{
2732    unsigned index = 0;
2733    if (!bufferHdr || bytes < sizeof(encoder_media_buffer_type)) {
2734        DEBUG_PRINT_ERROR("wrong params allocate_input_meta_buffer Hdr %p len %u",
2735                bufferHdr, (unsigned int)bytes);
2736        return OMX_ErrorBadParameter;
2737    }
2738
2739    if (!m_inp_mem_ptr && !mUseProxyColorFormat) {
2740        m_inp_mem_ptr = meta_buffer_hdr;
2741        DEBUG_PRINT_LOW("use meta_buffer_hdr (%p) as m_inp_mem_ptr = %p",
2742                meta_buffer_hdr, m_inp_mem_ptr);
2743    }
2744    for (index = 0; ((index < m_sInPortDef.nBufferCountActual) &&
2745                meta_buffer_hdr[index].pBuffer); index++);
2746    if (index == m_sInPortDef.nBufferCountActual) {
2747        DEBUG_PRINT_ERROR("All buffers are allocated input_meta_buffer");
2748        return OMX_ErrorBadParameter;
2749    }
2750    if (mUseProxyColorFormat) {
2751        if (opaque_buffer_hdr[index]) {
2752            DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr");
2753            return OMX_ErrorBadParameter;
2754        }
2755        if (allocate_input_buffer(hComp,&opaque_buffer_hdr[index],
2756                    PORT_INDEX_IN,appData,m_sInPortDef.nBufferSize) != OMX_ErrorNone) {
2757            DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr");
2758            return OMX_ErrorBadParameter;
2759        }
2760    }
2761    BITMASK_SET(&m_inp_bm_count,index);
2762    *bufferHdr = &meta_buffer_hdr[index];
2763    memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index]));
2764    meta_buffer_hdr[index].nSize = sizeof(meta_buffer_hdr[index]);
2765    meta_buffer_hdr[index].nAllocLen = sizeof(meta_buffers[index]);
2766    meta_buffer_hdr[index].nVersion.nVersion = OMX_SPEC_VERSION;
2767    meta_buffer_hdr[index].nInputPortIndex = PORT_INDEX_IN;
2768    meta_buffer_hdr[index].pBuffer = (OMX_U8*)&meta_buffers[index];
2769    meta_buffer_hdr[index].pAppPrivate = appData;
2770    if (mUseProxyColorFormat) {
2771        m_opq_pmem_q.insert_entry((unsigned long)opaque_buffer_hdr[index],0,0);
2772        DEBUG_PRINT_HIGH("opaque_buffer_hdr insert %p", opaque_buffer_hdr[index]);
2773    }
2774    return OMX_ErrorNone;
2775}
2776#endif
2777/* ======================================================================
2778   FUNCTION
2779   omx_venc::AllocateInputBuffer
2780
2781   DESCRIPTION
2782   Helper function for allocate buffer in the input pin
2783
2784   PARAMETERS
2785   None.
2786
2787   RETURN VALUE
2788   true/false
2789
2790   ========================================================================== */
2791OMX_ERRORTYPE  omx_video::allocate_input_buffer(
2792        OMX_IN OMX_HANDLETYPE            hComp,
2793        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
2794        OMX_IN OMX_U32                   port,
2795        OMX_IN OMX_PTR                   appData,
2796        OMX_IN OMX_U32                   bytes)
2797{
2798    (void)hComp, (void)port;
2799    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2800    unsigned   i = 0;
2801
2802    DEBUG_PRINT_HIGH("allocate_input_buffer()::");
2803    if (bytes != m_sInPortDef.nBufferSize) {
2804        DEBUG_PRINT_ERROR("ERROR: Buffer size mismatch error: bytes[%u] != nBufferSize[%u]",
2805                (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize);
2806        return OMX_ErrorBadParameter;
2807    }
2808
2809    if (!m_inp_mem_ptr) {
2810        DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__,
2811                (unsigned int)m_sInPortDef.nBufferSize, (unsigned int)m_sInPortDef.nBufferCountActual);
2812        m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
2813                        calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
2814        if (m_inp_mem_ptr == NULL) {
2815            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr");
2816            return OMX_ErrorInsufficientResources;
2817        }
2818
2819        DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr);
2820        m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
2821
2822        if (m_pInput_pmem == NULL) {
2823            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_pmem");
2824            return OMX_ErrorInsufficientResources;
2825        }
2826#ifdef USE_ION
2827        m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual);
2828        if (m_pInput_ion == NULL) {
2829            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_ion");
2830            return OMX_ErrorInsufficientResources;
2831        }
2832#endif
2833        for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
2834            m_pInput_pmem[i].fd = -1;
2835#ifdef USE_ION
2836            m_pInput_ion[i].ion_device_fd =-1;
2837            m_pInput_ion[i].fd_ion_data.fd =-1;
2838            m_pInput_ion[i].ion_alloc_data.handle = 0;
2839#endif
2840        }
2841    }
2842
2843    for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
2844        if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
2845            break;
2846        }
2847    }
2848    if (i < m_sInPortDef.nBufferCountActual) {
2849
2850        *bufferHdr = (m_inp_mem_ptr + i);
2851        (*bufferHdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
2852        (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
2853        (*bufferHdr)->nAllocLen         = m_sInPortDef.nBufferSize;
2854        (*bufferHdr)->pAppPrivate       = appData;
2855        (*bufferHdr)->nInputPortIndex   = PORT_INDEX_IN;
2856        // make fd available to app layer, help with testing
2857        (*bufferHdr)->pInputPortPrivate = (OMX_PTR)&m_pInput_pmem[i];
2858
2859#ifdef USE_ION
2860#ifdef _MSM8974_
2861        m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
2862                &m_pInput_ion[i].ion_alloc_data,
2863                &m_pInput_ion[i].fd_ion_data,0);
2864#else
2865        m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
2866                &m_pInput_ion[i].ion_alloc_data,
2867                &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED);
2868#endif
2869        if (m_pInput_ion[i].ion_device_fd < 0) {
2870            DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
2871            return OMX_ErrorInsufficientResources;
2872        }
2873
2874        m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd;
2875#else
2876        m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2877
2878        if (m_pInput_pmem[i].fd == 0) {
2879            m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
2880        }
2881
2882        if (m_pInput_pmem[i].fd < 0) {
2883            DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() Failed");
2884            return OMX_ErrorInsufficientResources;
2885        }
2886#endif
2887        m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
2888        m_pInput_pmem[i].offset = 0;
2889
2890        m_pInput_pmem[i].buffer = NULL;
2891        if(!secure_session) {
2892            m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,
2893                m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
2894                MAP_SHARED,m_pInput_pmem[i].fd,0);
2895        if (m_pInput_pmem[i].buffer == MAP_FAILED) {
2896                DEBUG_PRINT_ERROR("ERROR: mmap FAILED= %d", errno);
2897            m_pInput_pmem[i].buffer = NULL;
2898            close(m_pInput_pmem[i].fd);
2899#ifdef USE_ION
2900            free_ion_memory(&m_pInput_ion[i]);
2901#endif
2902            return OMX_ErrorInsufficientResources;
2903        }
2904        } else {
2905            //This should only be used for passing reference to source type and
2906            //secure handle fd struct native_handle_t*
2907            m_pInput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*));
2908            if (m_pInput_pmem[i].buffer == NULL) {
2909                DEBUG_PRINT_ERROR("%s: failed to allocate native-handle", __func__);
2910                return OMX_ErrorInsufficientResources;
2911            }
2912        }
2913
2914        (*bufferHdr)->pBuffer           = (OMX_U8 *)m_pInput_pmem[i].buffer;
2915        DEBUG_PRINT_LOW("Virtual address in allocate buffer is %p", m_pInput_pmem[i].buffer);
2916        BITMASK_SET(&m_inp_bm_count,i);
2917        //here change the I/P param here from buf_adr to pmem
2918        if (!mUseProxyColorFormat && (dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true)) {
2919            DEBUG_PRINT_ERROR("ERROR: dev_use_buf FAILED for i/p buf");
2920            return OMX_ErrorInsufficientResources;
2921        }
2922    } else {
2923        DEBUG_PRINT_ERROR("ERROR: All i/p buffers are allocated, invalid allocate buf call"
2924                "for index [%d]", i);
2925        eRet = OMX_ErrorInsufficientResources;
2926    }
2927
2928    return eRet;
2929}
2930
2931
2932/* ======================================================================
2933   FUNCTION
2934   omx_venc::AllocateOutputBuffer
2935
2936   DESCRIPTION
2937   Helper fn for AllocateBuffer in the output pin
2938
2939   PARAMETERS
2940   <TBD>.
2941
2942   RETURN VALUE
2943   OMX Error None if everything went well.
2944
2945   ========================================================================== */
2946OMX_ERRORTYPE  omx_video::allocate_output_buffer(
2947        OMX_IN OMX_HANDLETYPE            hComp,
2948        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
2949        OMX_IN OMX_U32                   port,
2950        OMX_IN OMX_PTR                   appData,
2951        OMX_IN OMX_U32                   bytes)
2952{
2953    (void)hComp, (void)port;
2954    OMX_ERRORTYPE eRet = OMX_ErrorNone;
2955    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
2956    unsigned                         i= 0; // Temporary counter
2957#ifdef _MSM8974_
2958    int align_size;
2959#endif
2960    DEBUG_PRINT_HIGH("allocate_output_buffer()for %u bytes", (unsigned int)bytes);
2961    if (!m_out_mem_ptr) {
2962        int nBufHdrSize        = 0;
2963        DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__,
2964                (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountActual);
2965        nBufHdrSize        = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
2966
2967        /*
2968         * Memory for output side involves the following:
2969         * 1. Array of Buffer Headers
2970         * 2. Bitmask array to hold the buffer allocation details
2971         * In order to minimize the memory management entire allocation
2972         * is done in one step.
2973         */
2974        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
2975
2976#ifdef USE_ION
2977        m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual);
2978        if (m_pOutput_ion == NULL) {
2979            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_ion");
2980            return OMX_ErrorInsufficientResources;
2981        }
2982#endif
2983        m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual);
2984        if (m_pOutput_pmem == NULL) {
2985            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_pmem");
2986            return OMX_ErrorInsufficientResources;
2987        }
2988        if (m_out_mem_ptr && m_pOutput_pmem) {
2989            bufHdr          =  m_out_mem_ptr;
2990
2991            for (i=0; i < m_sOutPortDef.nBufferCountActual ; i++) {
2992                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
2993                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
2994                // Set the values when we determine the right HxW param
2995                bufHdr->nAllocLen          = m_sOutPortDef.nBufferSize;
2996                bufHdr->nFilledLen         = 0;
2997                bufHdr->pAppPrivate        = appData;
2998                bufHdr->nOutputPortIndex   = PORT_INDEX_OUT;
2999                // make fd available to app layer, help with testing
3000                bufHdr->pOutputPortPrivate = (OMX_PTR)&m_pOutput_pmem[i];
3001                bufHdr->pBuffer            = NULL;
3002                bufHdr++;
3003                m_pOutput_pmem[i].fd = -1;
3004#ifdef USE_ION
3005                m_pOutput_ion[i].ion_device_fd =-1;
3006                m_pOutput_ion[i].fd_ion_data.fd=-1;
3007                m_pOutput_ion[i].ion_alloc_data.handle = 0;
3008#endif
3009            }
3010        } else {
3011            DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem");
3012            eRet = OMX_ErrorInsufficientResources;
3013        }
3014    }
3015
3016    DEBUG_PRINT_HIGH("actual cnt = %u", (unsigned int)m_sOutPortDef.nBufferCountActual);
3017    for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) {
3018        if (BITMASK_ABSENT(&m_out_bm_count,i)) {
3019            DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
3020            break;
3021        }
3022    }
3023    if (eRet == OMX_ErrorNone) {
3024        if (i < m_sOutPortDef.nBufferCountActual) {
3025#ifdef USE_ION
3026#ifdef _MSM8974_
3027            align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096;
3028            m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size,
3029                    &m_pOutput_ion[i].ion_alloc_data,
3030                    &m_pOutput_ion[i].fd_ion_data, ION_FLAG_CACHED);
3031#else
3032            m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sOutPortDef.nBufferSize,
3033                    &m_pOutput_ion[i].ion_alloc_data,
3034                    &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED);
3035#endif
3036            if (m_pOutput_ion[i].ion_device_fd < 0) {
3037                DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
3038                return OMX_ErrorInsufficientResources;
3039            }
3040
3041            m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd;
3042#else
3043            m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
3044            if (m_pOutput_pmem[i].fd == 0) {
3045                m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
3046            }
3047
3048            if (m_pOutput_pmem[i].fd < 0) {
3049                DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() failed");
3050                return OMX_ErrorInsufficientResources;
3051            }
3052#endif
3053            m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
3054            m_pOutput_pmem[i].offset = 0;
3055
3056            m_pOutput_pmem[i].buffer = NULL;
3057            if(!secure_session) {
3058#ifdef _MSM8974_
3059                m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
3060                    align_size,PROT_READ|PROT_WRITE,
3061                    MAP_SHARED,m_pOutput_pmem[i].fd,0);
3062#else
3063                m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
3064                    m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
3065                    MAP_SHARED,m_pOutput_pmem[i].fd,0);
3066#endif
3067            if (m_pOutput_pmem[i].buffer == MAP_FAILED) {
3068                    DEBUG_PRINT_ERROR("ERROR: MMAP_FAILED in o/p alloc buffer");
3069                m_pOutput_pmem[i].buffer = NULL;
3070                close (m_pOutput_pmem[i].fd);
3071#ifdef USE_ION
3072                free_ion_memory(&m_pOutput_ion[i]);
3073#endif
3074                return OMX_ErrorInsufficientResources;
3075            }
3076            }
3077            else {
3078                //This should only be used for passing reference to source type and
3079                //secure handle fd struct native_handle_t*
3080                m_pOutput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*));
3081                if (m_pOutput_pmem[i].buffer == NULL) {
3082                    DEBUG_PRINT_ERROR("%s: Failed to allocate native-handle", __func__);
3083                    return OMX_ErrorInsufficientResources;
3084                }
3085                native_handle_t *handle = native_handle_create(1, 0);
3086                handle->data[0] = m_pOutput_pmem[i].fd;
3087                char *data = (char*) m_pOutput_pmem[i].buffer;
3088                OMX_U32 type = 1;
3089                memcpy(data, &type, sizeof(OMX_U32));
3090                memcpy(data + sizeof(OMX_U32), &handle, sizeof(native_handle_t*));
3091            }
3092
3093            *bufferHdr = (m_out_mem_ptr + i );
3094            (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer;
3095            (*bufferHdr)->pAppPrivate = appData;
3096
3097            BITMASK_SET(&m_out_bm_count,i);
3098
3099            if (dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) {
3100                DEBUG_PRINT_ERROR("ERROR: dev_use_buf FAILED for o/p buf");
3101                return OMX_ErrorInsufficientResources;
3102            }
3103        } else {
3104            DEBUG_PRINT_ERROR("ERROR: All o/p buffers are allocated, invalid allocate buf call"
3105                    "for index [%d] actual: %u", i, (unsigned int)m_sOutPortDef.nBufferCountActual);
3106        }
3107    }
3108
3109    return eRet;
3110}
3111
3112
3113// AllocateBuffer  -- API Call
3114/* ======================================================================
3115   FUNCTION
3116   omx_video::AllocateBuffer
3117
3118   DESCRIPTION
3119   Returns zero if all the buffers released..
3120
3121   PARAMETERS
3122   None.
3123
3124   RETURN VALUE
3125   true/false
3126
3127   ========================================================================== */
3128OMX_ERRORTYPE  omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
3129        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3130        OMX_IN OMX_U32                        port,
3131        OMX_IN OMX_PTR                     appData,
3132        OMX_IN OMX_U32                       bytes)
3133{
3134
3135    OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
3136
3137    DEBUG_PRINT_LOW("Allocate buffer of size = %u on port %d", (unsigned int)bytes, (int)port);
3138    if (m_state == OMX_StateInvalid) {
3139        DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State");
3140        return OMX_ErrorInvalidState;
3141    }
3142
3143    // What if the client calls again.
3144    if (port == PORT_INDEX_IN) {
3145#ifdef _ANDROID_ICS_
3146        if (meta_mode_enable)
3147            eRet = allocate_input_meta_buffer(hComp,bufferHdr,appData,bytes);
3148        else
3149#endif
3150            eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
3151    } else if (port == PORT_INDEX_OUT) {
3152        eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
3153    } else {
3154        DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(int)port);
3155        eRet = OMX_ErrorBadPortIndex;
3156    }
3157    DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
3158    if (eRet == OMX_ErrorNone) {
3159        if (allocate_done()) {
3160            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
3161                // Send the callback now
3162                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
3163                post_event(OMX_CommandStateSet,OMX_StateIdle,
3164                        OMX_COMPONENT_GENERATE_EVENT);
3165            }
3166        }
3167        if (port == PORT_INDEX_IN && m_sInPortDef.bPopulated) {
3168            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
3169                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
3170                post_event(OMX_CommandPortEnable,
3171                        PORT_INDEX_IN,
3172                        OMX_COMPONENT_GENERATE_EVENT);
3173            }
3174        }
3175        if (port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) {
3176            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
3177                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3178                post_event(OMX_CommandPortEnable,
3179                        PORT_INDEX_OUT,
3180                        OMX_COMPONENT_GENERATE_EVENT);
3181                m_event_port_settings_sent = false;
3182            }
3183        }
3184    }
3185    DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
3186    return eRet;
3187}
3188
3189
3190// Free Buffer - API call
3191/* ======================================================================
3192   FUNCTION
3193   omx_video::FreeBuffer
3194
3195   DESCRIPTION
3196
3197   PARAMETERS
3198   None.
3199
3200   RETURN VALUE
3201   true/false
3202
3203   ========================================================================== */
3204OMX_ERRORTYPE  omx_video::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
3205        OMX_IN OMX_U32                 port,
3206        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
3207{
3208    (void)hComp;
3209    OMX_ERRORTYPE eRet = OMX_ErrorNone;
3210    unsigned int nPortIndex;
3211
3212    DEBUG_PRINT_LOW("In for encoder free_buffer");
3213
3214    if (m_state == OMX_StateIdle &&
3215            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
3216        DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
3217    } else if ((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)||
3218            (m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT)) {
3219        DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
3220    } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
3221        DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled");
3222        post_event(OMX_EventError,
3223                OMX_ErrorPortUnpopulated,
3224                OMX_COMPONENT_GENERATE_EVENT);
3225        return eRet;
3226    } else {
3227        DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers");
3228        post_event(OMX_EventError,
3229                OMX_ErrorPortUnpopulated,
3230                OMX_COMPONENT_GENERATE_EVENT);
3231    }
3232
3233    if (port == PORT_INDEX_IN) {
3234        // check if the buffer is valid
3235        nPortIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);
3236
3237        DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %u, actual cnt %u",
3238                nPortIndex, (unsigned int)m_sInPortDef.nBufferCountActual);
3239        if (nPortIndex < m_sInPortDef.nBufferCountActual &&
3240                BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
3241            // Clear the bit associated with it.
3242            BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
3243            free_input_buffer (buffer);
3244            m_sInPortDef.bPopulated = OMX_FALSE;
3245
3246            /*Free the Buffer Header*/
3247            if (release_input_done()) {
3248                input_use_buffer = false;
3249                // "m_inp_mem_ptr" may point to "meta_buffer_hdr" in some modes,
3250                // in which case, it was not explicitly allocated
3251                if (m_inp_mem_ptr && m_inp_mem_ptr != meta_buffer_hdr) {
3252                    DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr");
3253                    free (m_inp_mem_ptr);
3254                }
3255                m_inp_mem_ptr = NULL;
3256                if (m_pInput_pmem) {
3257                    DEBUG_PRINT_LOW("Freeing m_pInput_pmem");
3258                    free(m_pInput_pmem);
3259                    m_pInput_pmem = NULL;
3260                }
3261#ifdef USE_ION
3262                if (m_pInput_ion) {
3263                    DEBUG_PRINT_LOW("Freeing m_pInput_ion");
3264                    free(m_pInput_ion);
3265                    m_pInput_ion = NULL;
3266                }
3267#endif
3268            }
3269        } else {
3270            DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid");
3271            eRet = OMX_ErrorBadPortIndex;
3272        }
3273
3274        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
3275                && release_input_done()) {
3276            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
3277            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
3278            post_event(OMX_CommandPortDisable,
3279                    PORT_INDEX_IN,
3280                    OMX_COMPONENT_GENERATE_EVENT);
3281        }
3282    } else if (port == PORT_INDEX_OUT) {
3283        // check if the buffer is valid
3284        nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
3285
3286        DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %u, actual cnt %u",
3287                nPortIndex, (unsigned int)m_sOutPortDef.nBufferCountActual);
3288        if (nPortIndex < m_sOutPortDef.nBufferCountActual &&
3289                BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
3290            auto_lock l(m_buf_lock);
3291            // Clear the bit associated with it.
3292            BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
3293            m_sOutPortDef.bPopulated = OMX_FALSE;
3294            free_output_buffer (buffer);
3295
3296            if (release_output_done()) {
3297                output_use_buffer = false;
3298                if (m_out_mem_ptr) {
3299                    DEBUG_PRINT_LOW("Freeing m_out_mem_ptr");
3300                    free (m_out_mem_ptr);
3301                    m_out_mem_ptr = NULL;
3302                }
3303                if (m_pOutput_pmem) {
3304                    DEBUG_PRINT_LOW("Freeing m_pOutput_pmem");
3305                    free(m_pOutput_pmem);
3306                    m_pOutput_pmem = NULL;
3307                }
3308#ifdef USE_ION
3309                if (m_pOutput_ion) {
3310                    DEBUG_PRINT_LOW("Freeing m_pOutput_ion");
3311                    free(m_pOutput_ion);
3312                    m_pOutput_ion = NULL;
3313                }
3314#endif
3315            }
3316        } else {
3317            DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid");
3318            eRet = OMX_ErrorBadPortIndex;
3319        }
3320        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
3321                && release_output_done() ) {
3322            DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
3323
3324            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
3325            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3326            post_event(OMX_CommandPortDisable,
3327                    PORT_INDEX_OUT,
3328                    OMX_COMPONENT_GENERATE_EVENT);
3329
3330        }
3331    } else {
3332        eRet = OMX_ErrorBadPortIndex;
3333    }
3334    if ((eRet == OMX_ErrorNone) &&
3335            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
3336        if (release_done()) {
3337            if (dev_stop() != 0) {
3338                DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED");
3339                eRet = OMX_ErrorHardware;
3340            }
3341            // Send the callback now
3342            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
3343            post_event(OMX_CommandStateSet, OMX_StateLoaded,
3344                    OMX_COMPONENT_GENERATE_EVENT);
3345        } else {
3346            DEBUG_PRINT_HIGH("in free buffer, release not done, need to free more buffers input %" PRIx64" output %" PRIx64,
3347                    m_out_bm_count, m_inp_bm_count);
3348        }
3349    }
3350
3351    return eRet;
3352}
3353
3354
3355/* ======================================================================
3356   FUNCTION
3357   omx_video::EmptyThisBuffer
3358
3359   DESCRIPTION
3360   This routine is used to push the encoded video frames to
3361   the video decoder.
3362
3363   PARAMETERS
3364   None.
3365
3366   RETURN VALUE
3367   OMX Error None if everything went successful.
3368
3369   ========================================================================== */
3370OMX_ERRORTYPE  omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
3371        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
3372{
3373    OMX_ERRORTYPE ret1 = OMX_ErrorNone;
3374    unsigned int nBufferIndex ;
3375
3376    DEBUG_PRINT_LOW("ETB: buffer = %p, buffer->pBuffer[%p]", buffer, buffer->pBuffer);
3377    if (m_state != OMX_StateExecuting &&
3378            m_state != OMX_StatePause &&
3379            m_state != OMX_StateIdle) {
3380        DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State");
3381        return OMX_ErrorInvalidState;
3382    }
3383
3384    if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) {
3385        DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> buffer is null or buffer size is invalid");
3386        return OMX_ErrorBadParameter;
3387    }
3388
3389    if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) {
3390        DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> OMX Version Invalid");
3391        return OMX_ErrorVersionMismatch;
3392    }
3393
3394    if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) {
3395        DEBUG_PRINT_ERROR("ERROR: Bad port index to call empty_this_buffer");
3396        return OMX_ErrorBadPortIndex;
3397    }
3398    if (!m_sInPortDef.bEnabled) {
3399        DEBUG_PRINT_ERROR("ERROR: Cannot call empty_this_buffer while I/P port is disabled");
3400        return OMX_ErrorIncorrectStateOperation;
3401    }
3402
3403    nBufferIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);
3404
3405    if (nBufferIndex > m_sInPortDef.nBufferCountActual ) {
3406        DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]", nBufferIndex);
3407        return OMX_ErrorBadParameter;
3408    }
3409
3410    m_etb_count++;
3411    DEBUG_PRINT_LOW("DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp);
3412    post_event ((unsigned long)hComp,(unsigned long)buffer,m_input_msg_id);
3413    return OMX_ErrorNone;
3414}
3415/* ======================================================================
3416   FUNCTION
3417   omx_video::empty_this_buffer_proxy
3418
3419   DESCRIPTION
3420   This routine is used to push the encoded video frames to
3421   the video decoder.
3422
3423   PARAMETERS
3424   None.
3425
3426   RETURN VALUE
3427   OMX Error None if everything went successful.
3428
3429   ========================================================================== */
3430OMX_ERRORTYPE  omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
3431        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
3432{
3433    (void)hComp;
3434    OMX_U8 *pmem_data_buf = NULL;
3435    int push_cnt = 0;
3436    unsigned nBufIndex = 0;
3437    OMX_ERRORTYPE ret = OMX_ErrorNone;
3438    encoder_media_buffer_type *media_buffer = NULL;
3439
3440#ifdef _MSM8974_
3441    int fd = 0;
3442#endif
3443    DEBUG_PRINT_LOW("ETBProxy: buffer->pBuffer[%p]", buffer->pBuffer);
3444    if (buffer == NULL) {
3445        DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid buffer[%p]", buffer);
3446        return OMX_ErrorBadParameter;
3447    }
3448
3449    // Buffer sanity checks
3450    if (meta_mode_enable && !mUsesColorConversion) {
3451        //For color-conversion case, we have an internal buffer and not a meta buffer
3452        bool met_error = false;
3453        nBufIndex = buffer - meta_buffer_hdr;
3454        if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
3455            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid meta-bufIndex = %u", nBufIndex);
3456            return OMX_ErrorBadParameter;
3457        }
3458        media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer;
3459        if (media_buffer) {
3460            if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource &&
3461                    media_buffer->buffer_type != kMetadataBufferTypeGrallocSource &&
3462                    media_buffer->buffer_type != kMetadataBufferTypeNativeHandleSource) {
3463                met_error = true;
3464            } else {
3465                if ((media_buffer->buffer_type == kMetadataBufferTypeCameraSource) ||
3466                        (media_buffer->buffer_type == kMetadataBufferTypeNativeHandleSource)) {
3467                    if (media_buffer->meta_handle == NULL)
3468                        met_error = true;
3469                    else if ((media_buffer->meta_handle->numFds != 1 &&
3470                                media_buffer->meta_handle->numInts != 2))
3471                        met_error = true;
3472                }
3473            }
3474        } else
3475            met_error = true;
3476        if (met_error) {
3477            DEBUG_PRINT_ERROR("ERROR: Unkown source/metahandle in ETB call");
3478            post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
3479            return OMX_ErrorBadParameter;
3480        }
3481    } else {
3482        nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
3483        if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
3484            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid bufIndex = %u", nBufIndex);
3485            return OMX_ErrorBadParameter;
3486        }
3487    }
3488
3489    pending_input_buffers++;
3490    if (input_flush_progress == true) {
3491        post_event ((unsigned long)buffer,0,
3492                OMX_COMPONENT_GENERATE_EBD);
3493        DEBUG_PRINT_ERROR("ERROR: ETBProxy: Input flush in progress");
3494        return OMX_ErrorNone;
3495    }
3496#ifdef _MSM8974_
3497    if (!meta_mode_enable) {
3498        fd = m_pInput_pmem[nBufIndex].fd;
3499    }
3500#endif
3501#ifdef _ANDROID_ICS_
3502    if (meta_mode_enable && !mUseProxyColorFormat) {
3503        // Camera or Gralloc-source meta-buffers queued with pre-announced color-format
3504        struct pmem Input_pmem_info;
3505        if (!media_buffer) {
3506            DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__);
3507            return OMX_ErrorBadParameter;
3508        }
3509        if (media_buffer->buffer_type == kMetadataBufferTypeCameraSource) {
3510            Input_pmem_info.buffer = media_buffer;
3511            Input_pmem_info.fd = media_buffer->meta_handle->data[0];
3512#ifdef _MSM8974_
3513            fd = Input_pmem_info.fd;
3514#endif
3515            Input_pmem_info.offset = media_buffer->meta_handle->data[1];
3516            Input_pmem_info.size = media_buffer->meta_handle->data[2];
3517            DEBUG_PRINT_LOW("ETB (meta-Camera) fd = %d, offset = %d, size = %d",
3518                    Input_pmem_info.fd, Input_pmem_info.offset,
3519                    Input_pmem_info.size);
3520        } else {
3521            private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
3522            Input_pmem_info.buffer = media_buffer;
3523            Input_pmem_info.fd = handle->fd;
3524#ifdef _MSM8974_
3525            fd = Input_pmem_info.fd;
3526#endif
3527            Input_pmem_info.offset = 0;
3528            Input_pmem_info.size = handle->size;
3529            DEBUG_PRINT_LOW("ETB (meta-gralloc) fd = %d, offset = %d, size = %d",
3530                    Input_pmem_info.fd, Input_pmem_info.offset,
3531                    Input_pmem_info.size);
3532        }
3533        if (dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) {
3534            DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
3535            post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
3536            return OMX_ErrorBadParameter;
3537        }
3538    } else if (meta_mode_enable && !mUsesColorConversion) {
3539        // Graphic-source meta-buffers queued with opaque color-format
3540        if (media_buffer->buffer_type == kMetadataBufferTypeGrallocSource) {
3541            private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
3542            fd = handle->fd;
3543            DEBUG_PRINT_LOW("ETB (opaque-gralloc) fd = %d, size = %d",
3544                    fd, handle->size);
3545        } else {
3546            DEBUG_PRINT_ERROR("ERROR: Invalid bufferType for buffer with Opaque"
3547                    " color format");
3548            post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
3549            return OMX_ErrorBadParameter;
3550        }
3551    } else if (input_use_buffer && !m_use_input_pmem &&  m_pInput_pmem[nBufIndex].buffer)
3552#else
3553    if (input_use_buffer && !m_use_input_pmem && m_pInput_pmem[nBufIndex].buffer)
3554#endif
3555    {
3556        DEBUG_PRINT_LOW("Heap UseBuffer case, so memcpy the data");
3557
3558        auto_lock l(m_lock);
3559        pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer;
3560        if (pmem_data_buf) {
3561            memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset),
3562                    buffer->nFilledLen);
3563        }
3564        DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf");
3565    } else if (mUseProxyColorFormat) {
3566        // Gralloc-source buffers with color-conversion
3567        fd = m_pInput_pmem[nBufIndex].fd;
3568        DEBUG_PRINT_LOW("ETB (color-converted) fd = %d, size = %u",
3569                fd, (unsigned int)buffer->nFilledLen);
3570    } else if (m_sInPortDef.format.video.eColorFormat ==
3571                    OMX_COLOR_FormatYUV420SemiPlanar) {
3572            //For the case where YUV420SP buffers are qeueued to component
3573            //by sources other than camera (Apps via MediaCodec), conversion
3574            //to vendor flavoured NV12 color format is required.
3575            if (!dev_color_align(buffer, m_sInPortDef.format.video.nFrameWidth,
3576                                    m_sInPortDef.format.video.nFrameHeight)) {
3577                    DEBUG_PRINT_ERROR("Failed to adjust buffer color");
3578                    post_event((unsigned long)buffer, 0, OMX_COMPONENT_GENERATE_EBD);
3579                    return OMX_ErrorUndefined;
3580            }
3581    }
3582#ifdef _MSM8974_
3583    if (dev_empty_buf(buffer, pmem_data_buf,nBufIndex,fd) != true)
3584#else
3585    if (dev_empty_buf(buffer, pmem_data_buf,0,0) != true)
3586#endif
3587    {
3588        DEBUG_PRINT_ERROR("ERROR: ETBProxy: dev_empty_buf failed");
3589#ifdef _ANDROID_ICS_
3590        omx_release_meta_buffer(buffer);
3591#endif
3592        post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
3593        /*Generate an async error and move to invalid state*/
3594        pending_input_buffers--;
3595        if (hw_overload) {
3596            return OMX_ErrorInsufficientResources;
3597        }
3598        return OMX_ErrorBadParameter;
3599    }
3600    return ret;
3601}
3602
3603/* ======================================================================
3604   FUNCTION
3605   omx_video::FillThisBuffer
3606
3607   DESCRIPTION
3608   IL client uses this method to release the frame buffer
3609   after displaying them.
3610
3611   PARAMETERS
3612   None.
3613
3614   RETURN VALUE
3615   true/false
3616
3617   ========================================================================== */
3618OMX_ERRORTYPE  omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
3619        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
3620{
3621    DEBUG_PRINT_LOW("FTB: buffer->pBuffer[%p]", buffer->pBuffer);
3622    if (m_state != OMX_StateExecuting &&
3623            m_state != OMX_StatePause &&
3624            m_state != OMX_StateIdle) {
3625        DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State");
3626        return OMX_ErrorInvalidState;
3627    }
3628
3629    if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) {
3630        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size");
3631        return OMX_ErrorBadParameter;
3632    }
3633
3634    if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) {
3635        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid");
3636        return OMX_ErrorVersionMismatch;
3637    }
3638
3639    if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) {
3640        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index");
3641        return OMX_ErrorBadPortIndex;
3642    }
3643
3644    if (!m_sOutPortDef.bEnabled) {
3645        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled");
3646        return OMX_ErrorIncorrectStateOperation;
3647    }
3648
3649    post_event((unsigned long) hComp, (unsigned long)buffer,OMX_COMPONENT_GENERATE_FTB);
3650    return OMX_ErrorNone;
3651}
3652
3653/* ======================================================================
3654   FUNCTION
3655   omx_video::fill_this_buffer_proxy
3656
3657   DESCRIPTION
3658   IL client uses this method to release the frame buffer
3659   after displaying them.
3660
3661   PARAMETERS
3662   None.
3663
3664   RETURN VALUE
3665   true/false
3666
3667   ========================================================================== */
3668OMX_ERRORTYPE  omx_video::fill_this_buffer_proxy(
3669        OMX_IN OMX_HANDLETYPE        hComp,
3670        OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
3671{
3672    (void)hComp;
3673    OMX_U8 *pmem_data_buf = NULL;
3674    OMX_ERRORTYPE nRet = OMX_ErrorNone;
3675
3676    DEBUG_PRINT_LOW("FTBProxy: bufferAdd->pBuffer[%p]", bufferAdd->pBuffer);
3677
3678    if (bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= (int)m_sOutPortDef.nBufferCountActual) ) {
3679        DEBUG_PRINT_ERROR("ERROR: FTBProxy: Invalid i/p params");
3680        return OMX_ErrorBadParameter;
3681    }
3682
3683    pending_output_buffers++;
3684    /*Return back the output buffer to client*/
3685    if ( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true) {
3686        DEBUG_PRINT_LOW("o/p port is Disabled or Flush in Progress");
3687        post_event ((unsigned long)bufferAdd,0,
3688                OMX_COMPONENT_GENERATE_FBD);
3689        return OMX_ErrorNone;
3690    }
3691
3692    if (output_use_buffer && !m_use_output_pmem) {
3693        DEBUG_PRINT_LOW("Heap UseBuffer case");
3694        pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer;
3695    }
3696
3697    if (dev_fill_buf(bufferAdd, pmem_data_buf,(bufferAdd - m_out_mem_ptr),m_pOutput_pmem[bufferAdd - m_out_mem_ptr].fd) != true) {
3698        DEBUG_PRINT_ERROR("ERROR: dev_fill_buf() Failed");
3699        post_event ((unsigned long)bufferAdd,0,OMX_COMPONENT_GENERATE_FBD);
3700        pending_output_buffers--;
3701        return OMX_ErrorBadParameter;
3702    }
3703
3704    return OMX_ErrorNone;
3705}
3706
3707/* ======================================================================
3708   FUNCTION
3709   omx_video::SetCallbacks
3710
3711   DESCRIPTION
3712   Set the callbacks.
3713
3714   PARAMETERS
3715   None.
3716
3717   RETURN VALUE
3718   OMX Error None if everything successful.
3719
3720   ========================================================================== */
3721OMX_ERRORTYPE  omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
3722        OMX_IN OMX_CALLBACKTYPE* callbacks,
3723        OMX_IN OMX_PTR             appData)
3724{
3725    (void)hComp;
3726    m_pCallbacks       = *callbacks;
3727    DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\
3728            m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone);
3729    m_app_data =    appData;
3730    return OMX_ErrorNotImplemented;
3731}
3732
3733
3734/* ======================================================================
3735   FUNCTION
3736   omx_venc::UseEGLImage
3737
3738   DESCRIPTION
3739   OMX Use EGL Image method implementation <TBD>.
3740
3741   PARAMETERS
3742   <TBD>.
3743
3744   RETURN VALUE
3745   Not Implemented error.
3746
3747   ========================================================================== */
3748OMX_ERRORTYPE  omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE   hComp,
3749        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3750        OMX_IN OMX_U32                        port,
3751        OMX_IN OMX_PTR                     appData,
3752        OMX_IN void*                      eglImage)
3753{
3754    (void)hComp, (void)bufferHdr, (void)port, (void)appData, (void)eglImage;
3755    DEBUG_PRINT_ERROR("ERROR: use_EGL_image:  Not Implemented");
3756    return OMX_ErrorNotImplemented;
3757}
3758
3759/* ======================================================================
3760   FUNCTION
3761   omx_venc::ComponentRoleEnum
3762
3763   DESCRIPTION
3764   OMX Component Role Enum method implementation.
3765
3766   PARAMETERS
3767   <TBD>.
3768
3769   RETURN VALUE
3770   OMX Error None if everything is successful.
3771   ========================================================================== */
3772OMX_ERRORTYPE  omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
3773        OMX_OUT OMX_U8*        role,
3774        OMX_IN OMX_U32        index)
3775{
3776    (void)hComp;
3777    OMX_ERRORTYPE eRet = OMX_ErrorNone;
3778    if (!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3779        if ((0 == index) && role) {
3780            strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
3781            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3782        } else {
3783            eRet = OMX_ErrorNoMore;
3784        }
3785    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
3786        if ((0 == index) && role) {
3787            strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
3788            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3789        } else {
3790            DEBUG_PRINT_ERROR("ERROR: No more roles");
3791            eRet = OMX_ErrorNoMore;
3792        }
3793    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3794        if ((0 == index) && role) {
3795            strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
3796            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3797        } else {
3798            DEBUG_PRINT_ERROR("ERROR: No more roles");
3799            eRet = OMX_ErrorNoMore;
3800        }
3801    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) {
3802        if ((0 == index) && role) {
3803            strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
3804            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3805        } else {
3806            DEBUG_PRINT_ERROR("ERROR: No more roles");
3807            eRet = OMX_ErrorNoMore;
3808        }
3809    }
3810    if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3811        if ((0 == index) && role) {
3812            strlcpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
3813            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3814        } else {
3815            eRet = OMX_ErrorNoMore;
3816        }
3817    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
3818        if ((0 == index) && role) {
3819            strlcpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE);
3820            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3821        } else {
3822            DEBUG_PRINT_ERROR("ERROR: No more roles");
3823            eRet = OMX_ErrorNoMore;
3824        }
3825    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3826        if ((0 == index) && role) {
3827            strlcpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE);
3828            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3829        } else {
3830            DEBUG_PRINT_ERROR("ERROR: No more roles");
3831            eRet = OMX_ErrorNoMore;
3832        }
3833    }
3834#ifdef _MSM8974_
3835    else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
3836        if ((0 == index) && role) {
3837            strlcpy((char *)role, "video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE);
3838            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
3839        } else {
3840            DEBUG_PRINT_ERROR("ERROR: No more roles");
3841            eRet = OMX_ErrorNoMore;
3842        }
3843    }
3844#endif
3845    else if ((!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE)) ||
3846            (!strncmp((char*)m_nkind, "OMX.qti.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE))) {
3847        if ((0 == index) && role) {
3848            strlcpy((char *)role, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE);
3849            DEBUG_PRINT_LOW("component_role_enum: role %s", role);
3850        } else {
3851            DEBUG_PRINT_ERROR("ERROR: No more roles");
3852            eRet = OMX_ErrorNoMore;
3853        }
3854    }
3855    else {
3856        DEBUG_PRINT_ERROR("ERROR: Querying Role on Unknown Component");
3857        eRet = OMX_ErrorInvalidComponentName;
3858    }
3859    return eRet;
3860}
3861
3862
3863
3864
3865/* ======================================================================
3866   FUNCTION
3867   omx_venc::AllocateDone
3868
3869   DESCRIPTION
3870   Checks if entire buffer pool is allocated by IL Client or not.
3871   Need this to move to IDLE state.
3872
3873   PARAMETERS
3874   None.
3875
3876   RETURN VALUE
3877   true/false.
3878
3879   ========================================================================== */
3880bool omx_video::allocate_done(void)
3881{
3882    bool bRet = false;
3883    bool bRet_In = false;
3884    bool bRet_Out = false;
3885
3886    bRet_In = allocate_input_done();
3887    bRet_Out = allocate_output_done();
3888
3889    if (bRet_In && bRet_Out) {
3890        bRet = true;
3891    }
3892
3893    return bRet;
3894}
3895/* ======================================================================
3896   FUNCTION
3897   omx_venc::AllocateInputDone
3898
3899   DESCRIPTION
3900   Checks if I/P buffer pool is allocated by IL Client or not.
3901
3902   PARAMETERS
3903   None.
3904
3905   RETURN VALUE
3906   true/false.
3907
3908   ========================================================================== */
3909bool omx_video::allocate_input_done(void)
3910{
3911    bool bRet = false;
3912    unsigned i=0;
3913
3914    if (m_inp_mem_ptr == NULL) {
3915        return bRet;
3916    }
3917    if (m_inp_mem_ptr ) {
3918        for (; i<m_sInPortDef.nBufferCountActual; i++) {
3919            if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
3920                break;
3921            }
3922        }
3923    }
3924    if (i==m_sInPortDef.nBufferCountActual) {
3925        bRet = true;
3926    }
3927    if (i==m_sInPortDef.nBufferCountActual && m_sInPortDef.bEnabled) {
3928        m_sInPortDef.bPopulated = OMX_TRUE;
3929    }
3930    return bRet;
3931}
3932/* ======================================================================
3933   FUNCTION
3934   omx_venc::AllocateOutputDone
3935
3936   DESCRIPTION
3937   Checks if entire O/P buffer pool is allocated by IL Client or not.
3938
3939   PARAMETERS
3940   None.
3941
3942   RETURN VALUE
3943   true/false.
3944
3945   ========================================================================== */
3946bool omx_video::allocate_output_done(void)
3947{
3948    bool bRet = false;
3949    unsigned j=0;
3950
3951    if (m_out_mem_ptr == NULL) {
3952        return bRet;
3953    }
3954
3955    if (m_out_mem_ptr ) {
3956        for (; j<m_sOutPortDef.nBufferCountActual; j++) {
3957            if (BITMASK_ABSENT(&m_out_bm_count,j)) {
3958                break;
3959            }
3960        }
3961    }
3962
3963    if (j==m_sOutPortDef.nBufferCountActual) {
3964        bRet = true;
3965    }
3966
3967    if (j==m_sOutPortDef.nBufferCountActual && m_sOutPortDef.bEnabled) {
3968        m_sOutPortDef.bPopulated = OMX_TRUE;
3969    }
3970    return bRet;
3971}
3972
3973/* ======================================================================
3974   FUNCTION
3975   omx_venc::ReleaseDone
3976
3977   DESCRIPTION
3978   Checks if IL client has released all the buffers.
3979
3980   PARAMETERS
3981   None.
3982
3983   RETURN VALUE
3984   true/false
3985
3986   ========================================================================== */
3987bool omx_video::release_done(void)
3988{
3989    bool bRet = false;
3990    DEBUG_PRINT_LOW("Inside release_done()");
3991    if (release_input_done()) {
3992        if (release_output_done()) {
3993            bRet = true;
3994        }
3995    }
3996    return bRet;
3997}
3998
3999
4000/* ======================================================================
4001   FUNCTION
4002   omx_venc::ReleaseOutputDone
4003
4004   DESCRIPTION
4005   Checks if IL client has released all the buffers.
4006
4007   PARAMETERS
4008   None.
4009
4010   RETURN VALUE
4011   true/false
4012
4013   ========================================================================== */
4014bool omx_video::release_output_done(void)
4015{
4016    bool bRet = false;
4017    unsigned i=0,j=0;
4018
4019    DEBUG_PRINT_LOW("Inside release_output_done()");
4020    if (m_out_mem_ptr) {
4021        for (; j<m_sOutPortDef.nBufferCountActual; j++) {
4022            if (BITMASK_PRESENT(&m_out_bm_count,j)) {
4023                break;
4024            }
4025        }
4026        if (j==m_sOutPortDef.nBufferCountActual) {
4027            bRet = true;
4028        }
4029    } else {
4030        bRet = true;
4031    }
4032    return bRet;
4033}
4034/* ======================================================================
4035   FUNCTION
4036   omx_venc::ReleaseInputDone
4037
4038   DESCRIPTION
4039   Checks if IL client has released all the buffers.
4040
4041   PARAMETERS
4042   None.
4043
4044   RETURN VALUE
4045   true/false
4046
4047   ========================================================================== */
4048bool omx_video::release_input_done(void)
4049{
4050    bool bRet = false;
4051    unsigned i=0,j=0;
4052
4053    DEBUG_PRINT_LOW("Inside release_input_done()");
4054    if (m_inp_mem_ptr) {
4055        for (; j<m_sInPortDef.nBufferCountActual; j++) {
4056            if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
4057                break;
4058            }
4059        }
4060        if (j==m_sInPortDef.nBufferCountActual) {
4061            bRet = true;
4062        }
4063    } else {
4064        bRet = true;
4065    }
4066    return bRet;
4067}
4068
4069OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp,
4070        OMX_BUFFERHEADERTYPE * buffer)
4071{
4072#ifdef _MSM8974_
4073    int index = buffer - m_out_mem_ptr;
4074#endif
4075    DEBUG_PRINT_LOW("fill_buffer_done: buffer->pBuffer[%p], flags=0x%x size = %u",
4076            buffer->pBuffer, (unsigned)buffer->nFlags, (unsigned int)buffer->nFilledLen);
4077    if (buffer == NULL || ((buffer - m_out_mem_ptr) > (int)m_sOutPortDef.nBufferCountActual)) {
4078        return OMX_ErrorBadParameter;
4079    }
4080
4081    pending_output_buffers--;
4082
4083    if(!secure_session) {
4084    extra_data_handle.create_extra_data(buffer);
4085#ifndef _MSM8974_
4086    if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
4087        DEBUG_PRINT_LOW("parsing extradata");
4088        extra_data_handle.parse_extra_data(buffer);
4089    }
4090#endif
4091    }
4092
4093    /* For use buffer we need to copy the data */
4094    if (m_pCallbacks.FillBufferDone) {
4095        if (buffer->nFilledLen > 0) {
4096            m_fbd_count++;
4097
4098            if (dev_get_output_log_flag()) {
4099                dev_output_log_buffers((const char*)buffer->pBuffer, buffer->nFilledLen);
4100            }
4101        }
4102#ifdef _MSM8974_
4103        if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
4104            if (!dev_handle_extradata((void *)buffer, index))
4105                DEBUG_PRINT_ERROR("Failed to parse extradata");
4106
4107            dev_extradata_log_buffers((char *)(((unsigned long)buffer->pBuffer + buffer->nOffset +
4108                        buffer->nFilledLen + 3) & (~3)));
4109        }
4110#endif
4111        m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer);
4112    } else {
4113        return OMX_ErrorBadParameter;
4114    }
4115    return OMX_ErrorNone;
4116}
4117
4118OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE         hComp,
4119        OMX_BUFFERHEADERTYPE* buffer)
4120{
4121    int buffer_index  = -1;
4122
4123    buffer_index = buffer - ((mUseProxyColorFormat && !mUsesColorConversion) ? meta_buffer_hdr : m_inp_mem_ptr);
4124    DEBUG_PRINT_LOW("empty_buffer_done: buffer[%p]", buffer);
4125    if (buffer == NULL ||
4126            ((buffer_index > (int)m_sInPortDef.nBufferCountActual))) {
4127        DEBUG_PRINT_ERROR("ERROR in empty_buffer_done due to index buffer");
4128        return OMX_ErrorBadParameter;
4129    }
4130
4131    pending_input_buffers--;
4132
4133    if (mUseProxyColorFormat &&
4134        (buffer_index >= 0 && (buffer_index < (int)m_sInPortDef.nBufferCountActual))) {
4135        if (!pdest_frame  && !input_flush_progress && mUsesColorConversion) {
4136            pdest_frame = buffer;
4137            DEBUG_PRINT_LOW("empty_buffer_done pdest_frame address is %p",pdest_frame);
4138            return push_input_buffer(hComp);
4139        }
4140        //check if empty-EOS-buffer is being returned, treat this same as the
4141        //color-conversion case as we queued a color-conversion buffer to encoder
4142        bool handleEmptyEosBuffer = (mEmptyEosBuffer == buffer);
4143        if (mUsesColorConversion || handleEmptyEosBuffer) {
4144            if (handleEmptyEosBuffer) {
4145                mEmptyEosBuffer = NULL;
4146            }
4147            // return color-conversion buffer back to the pool
4148            DEBUG_PRINT_LOW("empty_buffer_done insert address is %p",buffer);
4149            if (!m_opq_pmem_q.insert_entry((unsigned long)buffer, 0, 0)) {
4150                DEBUG_PRINT_ERROR("empty_buffer_done: pmem queue is full");
4151                return OMX_ErrorBadParameter;
4152            }
4153        } else {
4154            // We are not dealing with color-conversion, Buffer being returned
4155            // here is client's buffer, return it back to client
4156            if (m_pCallbacks.EmptyBufferDone && buffer) {
4157                m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
4158                DEBUG_PRINT_LOW("empty_buffer_done: Returning client buf %p", buffer);
4159            }
4160        }
4161    } else if (m_pCallbacks.EmptyBufferDone) {
4162        m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer);
4163    }
4164    return OMX_ErrorNone;
4165}
4166
4167void omx_video::complete_pending_buffer_done_cbs()
4168{
4169    unsigned long p1;
4170    unsigned long p2;
4171    unsigned long ident;
4172    omx_cmd_queue tmp_q, pending_bd_q;
4173    pthread_mutex_lock(&m_lock);
4174    // pop all pending GENERATE FDB from ftb queue
4175    while (m_ftb_q.m_size) {
4176        m_ftb_q.pop_entry(&p1,&p2,&ident);
4177        if (ident == OMX_COMPONENT_GENERATE_FBD) {
4178            pending_bd_q.insert_entry(p1,p2,ident);
4179        } else {
4180            tmp_q.insert_entry(p1,p2,ident);
4181        }
4182    }
4183    //return all non GENERATE FDB to ftb queue
4184    while (tmp_q.m_size) {
4185        tmp_q.pop_entry(&p1,&p2,&ident);
4186        m_ftb_q.insert_entry(p1,p2,ident);
4187    }
4188    // pop all pending GENERATE EDB from etb queue
4189    while (m_etb_q.m_size) {
4190        m_etb_q.pop_entry(&p1,&p2,&ident);
4191        if (ident == OMX_COMPONENT_GENERATE_EBD) {
4192            pending_bd_q.insert_entry(p1,p2,ident);
4193        } else {
4194            tmp_q.insert_entry(p1,p2,ident);
4195        }
4196    }
4197    //return all non GENERATE FDB to etb queue
4198    while (tmp_q.m_size) {
4199        tmp_q.pop_entry(&p1,&p2,&ident);
4200        m_etb_q.insert_entry(p1,p2,ident);
4201    }
4202    pthread_mutex_unlock(&m_lock);
4203    // process all pending buffer dones
4204    while (pending_bd_q.m_size) {
4205        pending_bd_q.pop_entry(&p1,&p2,&ident);
4206        switch (ident) {
4207            case OMX_COMPONENT_GENERATE_EBD:
4208                if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
4209                    DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
4210                    omx_report_error ();
4211                }
4212                break;
4213
4214            case OMX_COMPONENT_GENERATE_FBD:
4215                if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
4216                    DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
4217                    omx_report_error ();
4218                }
4219                break;
4220        }
4221    }
4222}
4223
4224#ifdef MAX_RES_720P
4225OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
4226{
4227    OMX_ERRORTYPE eRet = OMX_ErrorNone;
4228    if (!profileLevelType)
4229        return OMX_ErrorBadParameter;
4230
4231    if (profileLevelType->nPortIndex == 1) {
4232        if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) {
4233            if (profileLevelType->nProfileIndex == 0) {
4234                profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
4235                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
4236            } else if (profileLevelType->nProfileIndex == 1) {
4237                profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
4238                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
4239            } else if (profileLevelType->nProfileIndex == 2) {
4240                profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
4241                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
4242            } else {
4243                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
4244                        (int)profileLevelType->nProfileIndex);
4245                eRet = OMX_ErrorNoMore;
4246            }
4247        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) {
4248            if (profileLevelType->nProfileIndex == 0) {
4249                profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
4250                profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
4251            } else {
4252                DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", (int)profileLevelType->nProfileIndex);
4253                eRet = OMX_ErrorNoMore;
4254            }
4255        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
4256            if (profileLevelType->nProfileIndex == 0) {
4257                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
4258                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
4259            } else if (profileLevelType->nProfileIndex == 1) {
4260                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
4261                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
4262            } else {
4263                DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", (int)profileLevelType->nProfileIndex);
4264                eRet = OMX_ErrorNoMore;
4265            }
4266        }
4267    } else {
4268        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %d", (int)profileLevelType->nPortIndex);
4269        eRet = OMX_ErrorBadPortIndex;
4270    }
4271    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d",
4272            (int)profileLevelType->eProfile, (int)profileLevelType->eLevel);
4273    return eRet;
4274}
4275#endif
4276
4277#ifdef MAX_RES_1080P
4278OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
4279{
4280    OMX_ERRORTYPE eRet = OMX_ErrorNone;
4281    if (!profileLevelType)
4282        return OMX_ErrorBadParameter;
4283
4284    if (profileLevelType->nPortIndex == 1) {
4285        if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) {
4286#if defined _MSM8974_ && !defined _MSM8226_
4287            if (profileLevelType->nProfileIndex == 0) {
4288                profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
4289                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel52;
4290            } else if (profileLevelType->nProfileIndex == 1) {
4291                profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
4292                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel52;
4293            } else if (profileLevelType->nProfileIndex == 2) {
4294                profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
4295                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel52;
4296            } else if (profileLevelType->nProfileIndex == 3) {
4297                profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
4298                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel52;
4299            } else if (profileLevelType->nProfileIndex == 4) {
4300                profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
4301                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel52;
4302            } else {
4303                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
4304                        (unsigned int)profileLevelType->nProfileIndex);
4305                eRet = OMX_ErrorNoMore;
4306            }
4307#else
4308            if (profileLevelType->nProfileIndex == 0) {
4309                profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
4310                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
4311
4312            } else if (profileLevelType->nProfileIndex == 1) {
4313                profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
4314                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
4315            } else if (profileLevelType->nProfileIndex == 2) {
4316                profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
4317                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
4318#ifdef _MSM8226_
4319            } else if (profileLevelType->nProfileIndex == 3) {
4320                profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
4321                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
4322            } else if (profileLevelType->nProfileIndex == 4) {
4323                profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
4324                profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
4325#endif
4326            } else {
4327                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
4328                        (int)profileLevelType->nProfileIndex);
4329                eRet = OMX_ErrorNoMore;
4330            }
4331#endif
4332        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) {
4333            if (profileLevelType->nProfileIndex == 0) {
4334                profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
4335                profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
4336            } else {
4337                DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex);
4338                eRet = OMX_ErrorNoMore;
4339            }
4340        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
4341            if (profileLevelType->nProfileIndex == 0) {
4342                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
4343                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
4344            } else if (profileLevelType->nProfileIndex == 1) {
4345                profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
4346                profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
4347            } else {
4348                DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex);
4349                eRet = OMX_ErrorNoMore;
4350            }
4351        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
4352            if (profileLevelType->nProfileIndex == 0) {
4353                profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
4354                profileLevelType->eLevel   = OMX_VIDEO_VP8Level_Version0;
4355            } else if (profileLevelType->nProfileIndex == 1) {
4356                profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
4357                profileLevelType->eLevel   = OMX_VIDEO_VP8Level_Version1;
4358            } else {
4359                DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
4360                (unsigned int)profileLevelType->nProfileIndex);
4361                eRet = OMX_ErrorNoMore;
4362            }
4363        } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingHEVC) {
4364            if (profileLevelType->nProfileIndex == 0) {
4365                profileLevelType->eProfile =  OMX_VIDEO_HEVCProfileMain;
4366                profileLevelType->eLevel   =  OMX_VIDEO_HEVCMainTierLevel52;
4367            } else if (profileLevelType->nProfileIndex == 1) {
4368                profileLevelType->eProfile =  OMX_VIDEO_HEVCProfileMain10;
4369                profileLevelType->eLevel   =  OMX_VIDEO_HEVCMainTierLevel52;
4370            } else {
4371                DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
4372                (unsigned int)profileLevelType->nProfileIndex);
4373                eRet = OMX_ErrorNoMore;
4374            }
4375        } else {
4376            DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore");
4377            eRet = OMX_ErrorNoMore;
4378        }
4379    } else {
4380        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex);
4381        eRet = OMX_ErrorBadPortIndex;
4382    }
4383    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
4384            (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
4385    return eRet;
4386}
4387#endif
4388
4389#ifdef USE_ION
4390int omx_video::alloc_map_ion_memory(int size,
4391        struct ion_allocation_data *alloc_data,
4392        struct ion_fd_data *fd_data,int flag)
4393{
4394    struct venc_ion buf_ion_info;
4395    int ion_device_fd =-1,rc=0,ion_dev_flags = 0;
4396    if (size <=0 || !alloc_data || !fd_data) {
4397        DEBUG_PRINT_ERROR("Invalid input to alloc_map_ion_memory");
4398        return -EINVAL;
4399    }
4400
4401    ion_dev_flags = O_RDONLY;
4402    ion_device_fd = open (MEM_DEVICE,ion_dev_flags);
4403    if (ion_device_fd < 0) {
4404        DEBUG_PRINT_ERROR("ERROR: ION Device open() Failed");
4405        return ion_device_fd;
4406    }
4407
4408    if(secure_session) {
4409        alloc_data->len = (size + (SZ_1M - 1)) & ~(SZ_1M - 1);
4410        alloc_data->align = SZ_1M;
4411        alloc_data->flags = ION_SECURE;
4412        alloc_data->ION_HEAP_MASK = ION_HEAP(ION_CP_MM_HEAP_ID);
4413        DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u align %u flags %x",
4414                (unsigned int)alloc_data->len, (unsigned int)alloc_data->align,
4415                alloc_data->flags);
4416    } else {
4417        alloc_data->len = (size + (SZ_4K - 1)) & ~(SZ_4K - 1);
4418        alloc_data->align = SZ_4K;
4419        alloc_data->flags = (flag & ION_FLAG_CACHED ? ION_FLAG_CACHED : 0);
4420#ifdef MAX_RES_720P
4421        alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID);
4422#else
4423        alloc_data->ION_HEAP_MASK = (ION_HEAP(MEM_HEAP_ID) |
4424            ION_HEAP(ION_IOMMU_HEAP_ID));
4425#endif
4426        DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %u align %u flags %x",
4427                (unsigned int)alloc_data->len, (unsigned int)alloc_data->align,
4428                alloc_data->flags);
4429    }
4430
4431    rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data);
4432    if (rc || !alloc_data->handle) {
4433        DEBUG_PRINT_ERROR("ION ALLOC memory failed 0x%x", rc);
4434        alloc_data->handle = 0;
4435        close(ion_device_fd);
4436        ion_device_fd = -1;
4437        return ion_device_fd;
4438    }
4439    fd_data->handle = alloc_data->handle;
4440    rc = ioctl(ion_device_fd,ION_IOC_MAP,fd_data);
4441    if (rc) {
4442        DEBUG_PRINT_ERROR("ION MAP failed ");
4443        buf_ion_info.ion_alloc_data = *alloc_data;
4444        buf_ion_info.ion_device_fd = ion_device_fd;
4445        buf_ion_info.fd_ion_data = *fd_data;
4446        free_ion_memory(&buf_ion_info);
4447        fd_data->fd =-1;
4448        ion_device_fd =-1;
4449    }
4450    return ion_device_fd;
4451}
4452
4453void omx_video::free_ion_memory(struct venc_ion *buf_ion_info)
4454{
4455    if (!buf_ion_info) {
4456        DEBUG_PRINT_ERROR("Invalid input to free_ion_memory");
4457        return;
4458    }
4459    if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
4460                &buf_ion_info->ion_alloc_data.handle)) {
4461        DEBUG_PRINT_ERROR("ION free failed ");
4462        return;
4463    }
4464    close(buf_ion_info->ion_device_fd);
4465    buf_ion_info->ion_alloc_data.handle = 0;
4466    buf_ion_info->ion_device_fd = -1;
4467    buf_ion_info->fd_ion_data.fd = -1;
4468}
4469#endif
4470
4471#ifdef _ANDROID_ICS_
4472void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer)
4473{
4474    if (buffer && meta_mode_enable) {
4475        encoder_media_buffer_type *media_ptr;
4476        struct pmem Input_pmem;
4477        unsigned int index_pmem = 0;
4478        bool meta_error = false;
4479
4480        index_pmem = (buffer - m_inp_mem_ptr);
4481        if (mUsesColorConversion &&
4482                (index_pmem < m_sInPortDef.nBufferCountActual)) {
4483            if (!dev_free_buf((&m_pInput_pmem[index_pmem]),PORT_INDEX_IN)) {
4484                DEBUG_PRINT_ERROR("omx_release_meta_buffer dev free failed");
4485            }
4486        } else {
4487            media_ptr = (encoder_media_buffer_type *) buffer->pBuffer;
4488            if (media_ptr && media_ptr->meta_handle) {
4489                if ((media_ptr->buffer_type == kMetadataBufferTypeCameraSource ||
4490                        media_ptr->buffer_type == kMetadataBufferTypeNativeHandleSource) &&
4491                        media_ptr->meta_handle->numFds == 1 &&
4492                        media_ptr->meta_handle->numInts >= 2) {
4493                    Input_pmem.fd = media_ptr->meta_handle->data[0];
4494                    Input_pmem.buffer = media_ptr;
4495                    Input_pmem.size = media_ptr->meta_handle->data[2];
4496                    Input_pmem.offset = media_ptr->meta_handle->data[1];
4497                    DEBUG_PRINT_LOW("EBD fd = %d, offset = %d, size = %d",Input_pmem.fd,
4498                            Input_pmem.offset,
4499                            Input_pmem.size);
4500                } else if (media_ptr->buffer_type == kMetadataBufferTypeGrallocSource) {
4501                    private_handle_t *handle = (private_handle_t *)media_ptr->meta_handle;
4502                    Input_pmem.buffer = media_ptr;
4503                    Input_pmem.fd = handle->fd;
4504                    Input_pmem.offset = 0;
4505                    Input_pmem.size = handle->size;
4506                } else {
4507                    meta_error = true;
4508                    DEBUG_PRINT_ERROR(" Meta Error set in EBD");
4509                }
4510                if (!meta_error)
4511                    meta_error = !dev_free_buf(&Input_pmem,PORT_INDEX_IN);
4512                if (meta_error) {
4513                    DEBUG_PRINT_ERROR(" Warning dev_free_buf failed flush value is %d",
4514                            input_flush_progress);
4515                }
4516            }
4517        }
4518    }
4519}
4520#endif
4521omx_video::omx_c2d_conv::omx_c2d_conv()
4522{
4523    c2dcc = NULL;
4524    mLibHandle = NULL;
4525    mConvertOpen = NULL;
4526    mConvertClose = NULL;
4527    src_format = NV12_128m;
4528    pthread_mutex_init(&c_lock, NULL);
4529}
4530
4531bool omx_video::omx_c2d_conv::init()
4532{
4533    bool status = true;
4534    if (mLibHandle || mConvertOpen || mConvertClose) {
4535        DEBUG_PRINT_ERROR("omx_c2d_conv::init called twice");
4536        status = false;
4537    }
4538    if (status) {
4539        mLibHandle = dlopen("libc2dcolorconvert.so", RTLD_LAZY);
4540        if (mLibHandle) {
4541            mConvertOpen = (createC2DColorConverter_t *)
4542                dlsym(mLibHandle,"createC2DColorConverter");
4543            mConvertClose = (destroyC2DColorConverter_t *)
4544                dlsym(mLibHandle,"destroyC2DColorConverter");
4545            if (!mConvertOpen || !mConvertClose)
4546                status = false;
4547        } else
4548            status = false;
4549    }
4550    if (!status && mLibHandle) {
4551        dlclose(mLibHandle);
4552        mLibHandle = NULL;
4553        mConvertOpen = NULL;
4554        mConvertClose = NULL;
4555    }
4556    return status;
4557}
4558
4559bool omx_video::omx_c2d_conv::convert(int src_fd, void *src_base, void *src_viraddr,
4560        int dest_fd, void *dest_base, void *dest_viraddr)
4561{
4562    int result;
4563    if (!src_viraddr || !dest_viraddr || !c2dcc || !src_base || !dest_base) {
4564        DEBUG_PRINT_ERROR("Invalid arguments omx_c2d_conv::convert");
4565        return false;
4566    }
4567    pthread_mutex_lock(&c_lock);
4568    result =  c2dcc->convertC2D(src_fd, src_base, src_viraddr,
4569            dest_fd, dest_base, dest_viraddr);
4570    pthread_mutex_unlock(&c_lock);
4571    DEBUG_PRINT_LOW("Color convert status %d",result);
4572    return ((result < 0)?false:true);
4573}
4574
4575bool omx_video::omx_c2d_conv::open(unsigned int height,unsigned int width,
4576        ColorConvertFormat src, ColorConvertFormat dest,unsigned int src_stride)
4577{
4578    bool status = false;
4579    pthread_mutex_lock(&c_lock);
4580    if (!c2dcc) {
4581        c2dcc = mConvertOpen(width, height, width, height,
4582                src,dest,0,src_stride);
4583        if (c2dcc) {
4584            src_format = src;
4585            status = true;
4586        } else
4587            DEBUG_PRINT_ERROR("mConvertOpen failed");
4588    }
4589    pthread_mutex_unlock(&c_lock);
4590    return status;
4591}
4592
4593void omx_video::omx_c2d_conv::close()
4594{
4595    if (mLibHandle) {
4596        pthread_mutex_lock(&c_lock);
4597        if (mConvertClose && c2dcc)
4598            mConvertClose(c2dcc);
4599        pthread_mutex_unlock(&c_lock);
4600        c2dcc = NULL;
4601    }
4602}
4603omx_video::omx_c2d_conv::~omx_c2d_conv()
4604{
4605    DEBUG_PRINT_HIGH("Destroy C2D instance");
4606    if (mLibHandle) {
4607        if (mConvertClose && c2dcc) {
4608            pthread_mutex_lock(&c_lock);
4609            mConvertClose(c2dcc);
4610            pthread_mutex_unlock(&c_lock);
4611        }
4612        dlclose(mLibHandle);
4613    }
4614    c2dcc = NULL;
4615    mLibHandle = NULL;
4616    mConvertOpen = NULL;
4617    mConvertClose = NULL;
4618    pthread_mutex_destroy(&c_lock);
4619}
4620
4621int omx_video::omx_c2d_conv::get_src_format()
4622{
4623    int format = -1;
4624    if (src_format == NV12_128m) {
4625        format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;
4626    } else if (src_format == RGBA8888) {
4627        format = HAL_PIXEL_FORMAT_RGBA_8888;
4628    }
4629    return format;
4630}
4631
4632bool omx_video::omx_c2d_conv::get_buffer_size(int port,unsigned int &buf_size)
4633{
4634    int cret = 0;
4635    bool ret = false;
4636    C2DBuffReq bufferreq;
4637    if (c2dcc) {
4638        bufferreq.size = 0;
4639        pthread_mutex_lock(&c_lock);
4640        cret = c2dcc->getBuffReq(port,&bufferreq);
4641        pthread_mutex_unlock(&c_lock);
4642        DEBUG_PRINT_LOW("Status of getbuffer is %d", cret);
4643        ret = (cret)?false:true;
4644        buf_size = bufferreq.size;
4645    }
4646    return ret;
4647}
4648
4649OMX_ERRORTYPE  omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp,
4650        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4651{
4652    unsigned nBufIndex = 0;
4653    OMX_ERRORTYPE ret = OMX_ErrorNone;
4654    encoder_media_buffer_type *media_buffer;
4655    private_handle_t *handle = NULL;
4656    DEBUG_PRINT_LOW("ETBProxyOpaque: buffer[%p]", buffer);
4657
4658    if (buffer == NULL) {
4659        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid buffer[%p]",buffer);
4660        return OMX_ErrorBadParameter;
4661    }
4662    nBufIndex = buffer - meta_buffer_hdr;
4663    if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
4664        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid bufindex = %u",
4665                nBufIndex);
4666        return OMX_ErrorBadParameter;
4667    }
4668    media_buffer = (encoder_media_buffer_type *)buffer->pBuffer;
4669    if ((!media_buffer || !media_buffer->meta_handle) &&
4670            !(buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
4671        DEBUG_PRINT_ERROR("Incorrect Buffer queued media buffer = %p",
4672            media_buffer);
4673        m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
4674        return OMX_ErrorBadParameter;
4675    } else if (media_buffer) {
4676        handle = (private_handle_t *)media_buffer->meta_handle;
4677    }
4678
4679    if (buffer->nFilledLen > 0 && handle) {
4680        /*Enable following code once private handle color format is
4681            updated correctly*/
4682        if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888)
4683            mUsesColorConversion = true;
4684        else
4685            mUsesColorConversion = false;
4686
4687        if (c2d_opened && handle->format != c2d_conv.get_src_format()) {
4688            c2d_conv.close();
4689            c2d_opened = false;
4690        }
4691        if (!c2d_opened) {
4692            if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) {
4693                DEBUG_PRINT_INFO("open Color conv for RGBA888 W: %u, H: %u",
4694                        (unsigned int)m_sInPortDef.format.video.nFrameWidth,
4695                        (unsigned int)m_sInPortDef.format.video.nFrameHeight);
4696                if (!c2d_conv.open(m_sInPortDef.format.video.nFrameHeight,
4697                            m_sInPortDef.format.video.nFrameWidth,
4698                            RGBA8888, NV12_128m, handle->width)) {
4699                    m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
4700                    DEBUG_PRINT_ERROR("Color conv open failed");
4701                    return OMX_ErrorBadParameter;
4702                }
4703                c2d_opened = true;
4704#ifdef _MSM8974_
4705                if (!dev_set_format(handle->format))
4706                    DEBUG_PRINT_ERROR("cannot set color format for RGBA8888");
4707#endif
4708            } else if (handle->format != HAL_PIXEL_FORMAT_NV12_ENCODEABLE &&
4709                    handle->format != QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m &&
4710                    handle->format != QOMX_COLOR_FormatYVU420SemiPlanar) {
4711                DEBUG_PRINT_ERROR("Incorrect color format");
4712                m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
4713                return OMX_ErrorBadParameter;
4714            }
4715        }
4716    }
4717    if (input_flush_progress == true) {
4718        m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
4719        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Input flush in progress");
4720        return OMX_ErrorNone;
4721    }
4722
4723    if (!psource_frame) {
4724        psource_frame = buffer;
4725        ret = push_input_buffer(hComp);
4726    } else {
4727        if (!m_opq_meta_q.insert_entry((unsigned long)buffer,0,0)) {
4728            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Queue is full");
4729            m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
4730            ret = OMX_ErrorBadParameter;
4731        }
4732    }
4733    return ret;
4734}
4735
4736OMX_ERRORTYPE omx_video::queue_meta_buffer(OMX_HANDLETYPE hComp,
4737        struct pmem &Input_pmem_info)
4738{
4739
4740    OMX_ERRORTYPE ret = OMX_ErrorNone;
4741    unsigned long address = 0,p2,id;
4742
4743    DEBUG_PRINT_LOW("In queue Meta Buffer");
4744    if (!psource_frame || !pdest_frame) {
4745        DEBUG_PRINT_ERROR("convert_queue_buffer invalid params");
4746        return OMX_ErrorBadParameter;
4747    }
4748
4749    if (psource_frame->nFilledLen > 0) {
4750        if (dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) {
4751            DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
4752            post_event ((unsigned long)psource_frame,0,OMX_COMPONENT_GENERATE_EBD);
4753            ret = OMX_ErrorBadParameter;
4754        }
4755    }
4756
4757    if (ret == OMX_ErrorNone)
4758        ret = empty_this_buffer_proxy(hComp,psource_frame);
4759
4760    if (ret == OMX_ErrorNone) {
4761        psource_frame = NULL;
4762        if (!psource_frame && m_opq_meta_q.m_size) {
4763            m_opq_meta_q.pop_entry(&address,&p2,&id);
4764            psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
4765        }
4766    } else {
4767        // there has been an error and source frame has been scheduled for an EBD
4768        psource_frame = NULL;
4769    }
4770    return ret;
4771}
4772
4773OMX_ERRORTYPE omx_video::convert_queue_buffer(OMX_HANDLETYPE hComp,
4774        struct pmem &Input_pmem_info,unsigned long &index)
4775{
4776
4777    unsigned char *uva;
4778    OMX_ERRORTYPE ret = OMX_ErrorNone;
4779    unsigned long address = 0,p2,id;
4780
4781    DEBUG_PRINT_LOW("In Convert and queue Meta Buffer");
4782    if (!psource_frame || !pdest_frame) {
4783        DEBUG_PRINT_ERROR("convert_queue_buffer invalid params");
4784        return OMX_ErrorBadParameter;
4785    }
4786    if (secure_session) {
4787        DEBUG_PRINT_ERROR("cannot convert buffer during secure session");
4788        return OMX_ErrorInvalidState;
4789    }
4790
4791    if (!psource_frame->nFilledLen) {
4792        if(psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
4793            pdest_frame->nFilledLen = psource_frame->nFilledLen;
4794            pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
4795            pdest_frame->nFlags = psource_frame->nFlags;
4796            DEBUG_PRINT_HIGH("Skipping color conversion for empty EOS Buffer "
4797                    "header=%p filled-len=%u", pdest_frame, (unsigned int)pdest_frame->nFilledLen);
4798        } else {
4799            pdest_frame->nOffset = 0;
4800            pdest_frame->nFilledLen = 0;
4801            pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
4802            pdest_frame->nFlags = psource_frame->nFlags;
4803            DEBUG_PRINT_LOW("Buffer header %p Filled len size %u",
4804                    pdest_frame, (unsigned int)pdest_frame->nFilledLen);
4805        }
4806    } else {
4807        uva = (unsigned char *)mmap(NULL, Input_pmem_info.size,
4808                PROT_READ|PROT_WRITE,
4809                MAP_SHARED,Input_pmem_info.fd,0);
4810        if (uva == MAP_FAILED) {
4811            ret = OMX_ErrorBadParameter;
4812        } else {
4813            if (!c2d_conv.convert(Input_pmem_info.fd, uva, uva,
4814                        m_pInput_pmem[index].fd, pdest_frame->pBuffer, pdest_frame->pBuffer)) {
4815                DEBUG_PRINT_ERROR("Color Conversion failed");
4816                ret = OMX_ErrorBadParameter;
4817            } else {
4818                unsigned int buf_size = 0;
4819                if (!c2d_conv.get_buffer_size(C2D_OUTPUT,buf_size))
4820                    ret = OMX_ErrorBadParameter;
4821                else {
4822                    pdest_frame->nOffset = 0;
4823                    pdest_frame->nFilledLen = buf_size;
4824                    pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
4825                    pdest_frame->nFlags = psource_frame->nFlags;
4826                    DEBUG_PRINT_LOW("Buffer header %p Filled len size %u",
4827                            pdest_frame, (unsigned int)pdest_frame->nFilledLen);
4828                }
4829            }
4830            munmap(uva,Input_pmem_info.size);
4831        }
4832    }
4833    if (dev_use_buf(&m_pInput_pmem[index],PORT_INDEX_IN,0) != true) {
4834        DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
4835        post_event ((unsigned long)pdest_frame,0,OMX_COMPONENT_GENERATE_EBD);
4836        ret = OMX_ErrorBadParameter;
4837    }
4838    if (ret == OMX_ErrorNone)
4839        ret = empty_this_buffer_proxy(hComp,pdest_frame);
4840    if (ret == OMX_ErrorNone) {
4841        m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, psource_frame);
4842        psource_frame = NULL;
4843        pdest_frame = NULL;
4844        if (!psource_frame && m_opq_meta_q.m_size) {
4845            m_opq_meta_q.pop_entry(&address,&p2,&id);
4846            psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
4847        }
4848        if (!pdest_frame && m_opq_pmem_q.m_size) {
4849            m_opq_pmem_q.pop_entry(&address,&p2,&id);
4850            pdest_frame = (OMX_BUFFERHEADERTYPE* ) address;
4851            DEBUG_PRINT_LOW("pdest_frame pop address is %p",pdest_frame);
4852        }
4853    } else {
4854        // there has been an error and source frame has been scheduled for an EBD
4855        psource_frame = NULL;
4856    }
4857    return ret;
4858}
4859
4860OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp)
4861{
4862    unsigned long address = 0,p2,id, index = 0;
4863    OMX_ERRORTYPE ret = OMX_ErrorNone;
4864
4865    DEBUG_PRINT_LOW("In push input buffer");
4866    if (!psource_frame && m_opq_meta_q.m_size) {
4867        m_opq_meta_q.pop_entry(&address,&p2,&id);
4868        psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
4869    }
4870    if (!pdest_frame && m_opq_pmem_q.m_size) {
4871        m_opq_pmem_q.pop_entry(&address,&p2,&id);
4872        pdest_frame = (OMX_BUFFERHEADERTYPE* ) address;
4873    }
4874    while (psource_frame != NULL && pdest_frame != NULL &&
4875            ret == OMX_ErrorNone) {
4876        struct pmem Input_pmem_info;
4877        encoder_media_buffer_type *media_buffer;
4878        index = pdest_frame - m_inp_mem_ptr;
4879        if (index >= m_sInPortDef.nBufferCountActual) {
4880            DEBUG_PRINT_ERROR("Output buffer index is wrong %u act count %u",
4881                    (unsigned int)index, (unsigned int)m_sInPortDef.nBufferCountActual);
4882            return OMX_ErrorBadParameter;
4883        }
4884
4885        //Meta-Buffer with empty filled-length can contain garbage handle
4886        //Some clients queue such buffers to signal EOS. Handle this case
4887        // separately by queueing an intermediate color-conversion buffer
4888        // and propagate the EOS.
4889        if (psource_frame->nFilledLen == 0 && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
4890            return push_empty_eos_buffer(hComp, psource_frame);
4891        }
4892        media_buffer = (encoder_media_buffer_type *)psource_frame->pBuffer;
4893        /*Will enable to verify camcorder in current TIPS can be removed*/
4894        if (media_buffer->buffer_type == kMetadataBufferTypeCameraSource) {
4895            Input_pmem_info.buffer = media_buffer;
4896            Input_pmem_info.fd = media_buffer->meta_handle->data[0];
4897            Input_pmem_info.offset = media_buffer->meta_handle->data[1];
4898            Input_pmem_info.size = media_buffer->meta_handle->data[2];
4899            DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd,
4900                    Input_pmem_info.offset,
4901                    Input_pmem_info.size);
4902            ret = queue_meta_buffer(hComp,Input_pmem_info);
4903        } else {
4904            private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
4905            Input_pmem_info.buffer = media_buffer;
4906            Input_pmem_info.fd = handle->fd;
4907            Input_pmem_info.offset = 0;
4908            Input_pmem_info.size = handle->size;
4909            if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888)
4910                ret = convert_queue_buffer(hComp,Input_pmem_info,index);
4911            else if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE ||
4912                    handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)
4913                ret = queue_meta_buffer(hComp,Input_pmem_info);
4914            else
4915                ret = OMX_ErrorBadParameter;
4916        }
4917    }
4918    return ret;
4919}
4920
4921OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp,
4922        OMX_BUFFERHEADERTYPE* buffer) {
4923    OMX_BUFFERHEADERTYPE* opqBuf = NULL;
4924    OMX_ERRORTYPE retVal = OMX_ErrorNone;
4925    unsigned index = 0;
4926
4927    DEBUG_PRINT_LOW("In push empty eos buffer");
4928    do {
4929        if (mUsesColorConversion) {
4930        if (pdest_frame) {
4931            //[1] use a checked out conversion buffer, if one is available
4932            opqBuf = pdest_frame;
4933            pdest_frame = NULL;
4934        } else if (m_opq_pmem_q.m_size) {
4935            //[2] else pop out one from the queue, if available
4936            unsigned long address = 0, p2, id;
4937            m_opq_pmem_q.pop_entry(&address,&p2,&id);
4938            opqBuf = (OMX_BUFFERHEADERTYPE* ) address;
4939        }
4940            index = opqBuf - m_inp_mem_ptr;
4941        } else {
4942            opqBuf = (OMX_BUFFERHEADERTYPE* ) buffer;
4943            index = opqBuf - meta_buffer_hdr;
4944        }
4945
4946        if (!opqBuf || index >= m_sInPortDef.nBufferCountActual) {
4947            DEBUG_PRINT_ERROR("push_empty_eos_buffer: Could not find a "
4948                    "color-conversion buffer to queue ! defer until available");
4949            //[3] else, returning back will defer calling this function again
4950            //until a conversion buffer is returned by the encoder and also
4951            //hold on to the client's buffer
4952            return OMX_ErrorNone;
4953        }
4954        struct pmem Input_pmem_info;
4955        Input_pmem_info.buffer = opqBuf;
4956        Input_pmem_info.fd = m_pInput_pmem[index].fd;
4957        Input_pmem_info.offset = 0;
4958        Input_pmem_info.size = m_pInput_pmem[index].size;
4959
4960        if (dev_use_buf(&Input_pmem_info, PORT_INDEX_IN, 0) != true) {
4961            DEBUG_PRINT_ERROR("ERROR: in dev_use_buf for empty eos buffer");
4962            retVal = OMX_ErrorBadParameter;
4963            break;
4964        }
4965
4966        //Queue with null pBuffer, as pBuffer in client's hdr can be junk
4967        //Clone the color-conversion buffer to avoid overwriting original buffer
4968        OMX_BUFFERHEADERTYPE emptyEosBufHdr;
4969        memcpy(&emptyEosBufHdr, opqBuf, sizeof(OMX_BUFFERHEADERTYPE));
4970        emptyEosBufHdr.nFilledLen = 0;
4971        emptyEosBufHdr.nTimeStamp = buffer->nTimeStamp;
4972        emptyEosBufHdr.nFlags = buffer->nFlags;
4973        emptyEosBufHdr.pBuffer = NULL;
4974        if (!mUsesColorConversion)
4975            emptyEosBufHdr.nAllocLen = m_sInPortDef.nBufferSize;
4976        if (dev_empty_buf(&emptyEosBufHdr, 0, index, m_pInput_pmem[index].fd) != true) {
4977            DEBUG_PRINT_ERROR("ERROR: in dev_empty_buf for empty eos buffer");
4978            dev_free_buf(&Input_pmem_info, PORT_INDEX_IN);
4979            retVal = OMX_ErrorBadParameter;
4980            break;
4981        }
4982        mEmptyEosBuffer = opqBuf;
4983    } while(false);
4984
4985    //return client's buffer regardless since intermediate color-conversion
4986    //buffer is sent to the the encoder
4987    m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
4988    --pending_input_buffers;
4989    return retVal;
4990}
4991
4992