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