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