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