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