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