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