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