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