1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2013-2014, The 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 /*============================================================================ 30 O p e n M A X w r a p p e r s 31 O p e n M A X C o r e 32 33 *//** @file omx_vdec.cpp 34 This module contains the implementation of the OpenMAX core & component. 35 36 *//*========================================================================*/ 37 38 ////////////////////////////////////////////////////////////////////////////// 39 // Include Files 40 ////////////////////////////////////////////////////////////////////////////// 41 42 #include <string.h> 43 #include <pthread.h> 44 #include <sys/prctl.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <errno.h> 48 #include "omx_vdec_hevc_swvdec.h" 49 #include <fcntl.h> 50 #include <limits.h> 51 #include <stdlib.h> 52 #include <media/hardware/HardwareAPI.h> 53 #include <media/msm_media_info.h> 54 55 #ifndef _ANDROID_ 56 #include <sys/ioctl.h> 57 #include <sys/mman.h> 58 #endif //_ANDROID_ 59 60 #ifdef _ANDROID_ 61 #include <cutils/properties.h> 62 #undef USE_EGL_IMAGE_GPU 63 #endif 64 65 #include <qdMetaData.h> 66 67 #ifdef _ANDROID_ 68 #include "DivXDrmDecrypt.h" 69 #endif //_ANDROID_ 70 71 #ifdef USE_EGL_IMAGE_GPU 72 #include <EGL/egl.h> 73 #include <EGL/eglQCOM.h> 74 #define EGL_BUFFER_HANDLE_QCOM 0x4F00 75 #define EGL_BUFFER_OFFSET_QCOM 0x4F01 76 #endif 77 78 #define BUFFER_LOG_LOC "/data/misc/media" 79 80 #ifdef OUTPUT_EXTRADATA_LOG 81 FILE *outputExtradataFile; 82 char ouputextradatafilename [] = "/data/extradata"; 83 #endif 84 85 #define DEFAULT_FPS 30 86 #define MAX_INPUT_ERROR DEFAULT_FPS 87 #define MAX_SUPPORTED_FPS 120 88 #define DEFAULT_WIDTH_ALIGNMENT 128 89 #define DEFAULT_HEIGHT_ALIGNMENT 32 90 91 #define VC1_SP_MP_START_CODE 0xC5000000 92 #define VC1_SP_MP_START_CODE_MASK 0xFF000000 93 #define VC1_AP_SEQ_START_CODE 0x0F010000 94 #define VC1_STRUCT_C_PROFILE_MASK 0xF0 95 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 96 #define VC1_SIMPLE_PROFILE 0 97 #define VC1_MAIN_PROFILE 1 98 #define VC1_ADVANCE_PROFILE 3 99 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 100 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2 101 #define VC1_STRUCT_C_LEN 4 102 #define VC1_STRUCT_C_POS 8 103 #define VC1_STRUCT_A_POS 12 104 #define VC1_STRUCT_B_POS 24 105 #define VC1_SEQ_LAYER_SIZE 36 106 #define POLL_TIMEOUT 0x7fffffff 107 108 #define MEM_DEVICE "/dev/ion" 109 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID 110 111 #ifdef _ANDROID_ 112 extern "C"{ 113 #include<utils/Log.h> 114 } 115 #endif//_ANDROID_ 116 117 #define SZ_4K 0x1000 118 #define SZ_1M 0x100000 119 120 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } 121 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } 122 #define EXTRADATA_IDX(__num_planes) (__num_planes - 1) 123 124 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA) 125 126 int debug_level = PRIO_ERROR; 127 128 static OMX_U32 maxSmoothStreamingWidth = 1920; 129 static OMX_U32 maxSmoothStreamingHeight = 1088; 130 void* async_message_thread (void *input) 131 { 132 OMX_BUFFERHEADERTYPE *buffer; 133 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 134 struct pollfd pfd; 135 struct v4l2_buffer v4l2_buf; 136 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 137 struct v4l2_event dqevent; 138 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input); 139 pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI; 140 pfd.fd = omx->drv_ctx.video_driver_fd; 141 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0; 142 DEBUG_PRINT_HIGH("omx_vdec: Async thread start"); 143 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); 144 while (1) 145 { 146 rc = poll(&pfd, 1, POLL_TIMEOUT); 147 if (!rc) { 148 DEBUG_PRINT_ERROR("Poll timedout"); 149 break; 150 } else if (rc < 0) { 151 DEBUG_PRINT_ERROR("Error while polling: %d", rc); 152 break; 153 } 154 if ((pfd.revents & POLLIN) || (pfd.revents & POLLRDNORM)) { 155 struct vdec_msginfo vdec_msg; 156 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 157 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 158 v4l2_buf.length = omx->drv_ctx.num_planes; 159 v4l2_buf.m.planes = plane; 160 while(!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) { 161 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 162 vdec_msg.status_code=VDEC_S_SUCCESS; 163 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf; 164 vdec_msg.msgdata.output_frame.len=plane[0].bytesused; 165 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr; 166 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) + 167 (uint64_t)v4l2_buf.timestamp.tv_usec; 168 if (vdec_msg.msgdata.output_frame.len) { 169 vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2]; 170 vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3]; 171 vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4]; 172 vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5]; 173 } 174 if (omx->async_message_process(input,&vdec_msg) < 0) { 175 DEBUG_PRINT_HIGH("async_message_thread Exited"); 176 break; 177 } 178 } 179 } 180 if((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) { 181 struct vdec_msginfo vdec_msg; 182 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 183 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 184 v4l2_buf.length = 1; 185 v4l2_buf.m.planes = plane; 186 while(!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) { 187 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE; 188 vdec_msg.status_code=VDEC_S_SUCCESS; 189 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf; 190 if (omx->async_message_process(input,&vdec_msg) < 0) { 191 DEBUG_PRINT_HIGH("async_message_thread Exited"); 192 break; 193 } 194 } 195 } 196 if (pfd.revents & POLLPRI){ 197 rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent); 198 if(dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) { 199 struct vdec_msginfo vdec_msg; 200 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED; 201 vdec_msg.status_code=VDEC_S_SUCCESS; 202 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved insufficient"); 203 if (omx->async_message_process(input,&vdec_msg) < 0) { 204 DEBUG_PRINT_HIGH("async_message_thread Exited"); 205 break; 206 } 207 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) { 208 struct vdec_msginfo vdec_msg; 209 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE; 210 vdec_msg.status_code=VDEC_S_SUCCESS; 211 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved "); 212 if (omx->async_message_process(input,&vdec_msg) < 0) { 213 DEBUG_PRINT_HIGH("async_message_thread Exited"); 214 break; 215 } 216 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE; 217 vdec_msg.status_code=VDEC_S_SUCCESS; 218 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved "); 219 if (omx->async_message_process(input,&vdec_msg) < 0) { 220 DEBUG_PRINT_HIGH("async_message_thread Exited"); 221 break; 222 } 223 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) { 224 DEBUG_PRINT_HIGH("VIDC Close Done Recieved and async_message_thread Exited"); 225 break; 226 } else if(dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) { 227 struct vdec_msginfo vdec_msg; 228 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR; 229 vdec_msg.status_code=VDEC_S_SUCCESS; 230 DEBUG_PRINT_HIGH("SYS Error Recieved"); 231 if (omx->async_message_process(input,&vdec_msg) < 0) { 232 DEBUG_PRINT_HIGH("async_message_thread Exited"); 233 break; 234 } 235 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) { 236 unsigned int *ptr = (unsigned int *)dqevent.u.data; 237 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]); 238 omx->buf_ref_remove(ptr[0], ptr[1]); 239 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) { 240 unsigned int *ptr = (unsigned int *)dqevent.u.data; 241 struct vdec_msginfo vdec_msg; 242 243 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]); 244 245 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 246 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 247 v4l2_buf.length = omx->drv_ctx.num_planes; 248 v4l2_buf.m.planes = plane; 249 v4l2_buf.index = ptr[5]; 250 v4l2_buf.flags = 0; 251 252 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 253 vdec_msg.status_code = VDEC_S_SUCCESS; 254 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf; 255 vdec_msg.msgdata.output_frame.len = 0; 256 vdec_msg.msgdata.output_frame.bufferaddr = (void*)ptr[2]; 257 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) + 258 (uint64_t)ptr[4]; 259 if (omx->async_message_process(input,&vdec_msg) < 0) { 260 DEBUG_PRINT_HIGH("async_message_thread Exited "); 261 break; 262 } 263 } else { 264 DEBUG_PRINT_HIGH("VIDC Some Event recieved"); 265 continue; 266 } 267 } 268 } 269 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop"); 270 return NULL; 271 } 272 273 void* message_thread(void *input) 274 { 275 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input); 276 unsigned char id; 277 int n; 278 if (omx == NULL) 279 { 280 DEBUG_PRINT_ERROR("message thread null pointer rxd"); 281 return NULL; 282 } 283 284 DEBUG_PRINT_HIGH("omx_vdec: message thread start"); 285 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); 286 while (1) 287 { 288 289 n = read(omx->m_pipe_in, &id, 1); 290 291 if(0 == n) 292 { 293 break; 294 } 295 296 if (1 == n) 297 { 298 omx->process_event_cb(omx, id); 299 } 300 if ((n < 0) && (errno != EINTR)) 301 { 302 DEBUG_PRINT_ERROR("ERROR: read from pipe failed, ret %d errno %d", n, errno); 303 break; 304 } 305 } 306 DEBUG_PRINT_HIGH("omx_vdec: message thread stop"); 307 return NULL; 308 } 309 310 void post_message(omx_vdec *omx, unsigned char id) 311 { 312 int ret_value; 313 314 if (omx == NULL) 315 { 316 DEBUG_PRINT_ERROR("message thread null pointer rxd"); 317 return; 318 } 319 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out); 320 ret_value = write(omx->m_pipe_out, &id, 1); 321 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value); 322 } 323 324 // omx_cmd_queue destructor 325 omx_vdec::omx_cmd_queue::~omx_cmd_queue() 326 { 327 // Nothing to do 328 } 329 330 // omx cmd queue constructor 331 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) 332 { 333 memset(m_q,0,sizeof(m_q)); 334 } 335 336 // omx cmd queue insert 337 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) 338 { 339 bool ret = true; 340 if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) 341 { 342 m_q[m_write].id = id; 343 m_q[m_write].param1 = p1; 344 m_q[m_write].param2 = p2; 345 m_write++; 346 m_size ++; 347 if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) 348 { 349 m_write = 0; 350 } 351 } 352 else 353 { 354 ret = false; 355 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__); 356 } 357 return ret; 358 } 359 360 // omx cmd queue pop 361 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) 362 { 363 bool ret = true; 364 if (m_size > 0) 365 { 366 *id = m_q[m_read].id; 367 *p1 = m_q[m_read].param1; 368 *p2 = m_q[m_read].param2; 369 // Move the read pointer ahead 370 ++m_read; 371 --m_size; 372 if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) 373 { 374 m_read = 0; 375 } 376 } 377 else 378 { 379 ret = false; 380 } 381 return ret; 382 } 383 384 // Retrieve the first mesg type in the queue 385 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() 386 { 387 return m_q[m_read].id; 388 } 389 390 #ifdef _ANDROID_ 391 omx_vdec::ts_arr_list::ts_arr_list() 392 { 393 //initialize timestamps array 394 memset(m_ts_arr_list, 0, sizeof(m_ts_arr_list) ); 395 } 396 omx_vdec::ts_arr_list::~ts_arr_list() 397 { 398 //free m_ts_arr_list? 399 } 400 401 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) 402 { 403 bool ret = true; 404 bool duplicate_ts = false; 405 int idx = 0; 406 407 //insert at the first available empty location 408 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) 409 { 410 if (!m_ts_arr_list[idx].valid) 411 { 412 //found invalid or empty entry, save timestamp 413 m_ts_arr_list[idx].valid = true; 414 m_ts_arr_list[idx].timestamp = ts; 415 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", 416 ts, idx); 417 break; 418 } 419 } 420 421 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) 422 { 423 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); 424 ret = false; 425 } 426 return ret; 427 } 428 429 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) 430 { 431 bool ret = true; 432 int min_idx = -1; 433 OMX_TICKS min_ts = 0; 434 int idx = 0; 435 436 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) 437 { 438 439 if (m_ts_arr_list[idx].valid) 440 { 441 //found valid entry, save index 442 if (min_idx < 0) 443 { 444 //first valid entry 445 min_ts = m_ts_arr_list[idx].timestamp; 446 min_idx = idx; 447 } 448 else if (m_ts_arr_list[idx].timestamp < min_ts) 449 { 450 min_ts = m_ts_arr_list[idx].timestamp; 451 min_idx = idx; 452 } 453 } 454 455 } 456 457 if (min_idx < 0) 458 { 459 //no valid entries found 460 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); 461 ts = 0; 462 ret = false; 463 } 464 else 465 { 466 ts = m_ts_arr_list[min_idx].timestamp; 467 m_ts_arr_list[min_idx].valid = false; 468 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", 469 ts, min_idx); 470 } 471 472 return ret; 473 474 } 475 476 477 bool omx_vdec::ts_arr_list::reset_ts_list() 478 { 479 bool ret = true; 480 int idx = 0; 481 482 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); 483 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) 484 { 485 m_ts_arr_list[idx].valid = false; 486 } 487 return ret; 488 } 489 #endif 490 491 // factory function executed by the core to create instances 492 void *get_omx_component_factory_fn(void) 493 { 494 return (new omx_vdec); 495 } 496 497 #ifdef _ANDROID_ 498 #ifdef USE_ION 499 VideoHeap::VideoHeap(int devicefd, size_t size, void* base, 500 ion_user_handle_t handle, int ionMapfd) 501 { 502 // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); 503 } 504 #else 505 VideoHeap::VideoHeap(int fd, size_t size, void* base) 506 { 507 // dup file descriptor, map once, use pmem 508 init(dup(fd), base, size, 0 , MEM_DEVICE); 509 } 510 #endif 511 #endif // _ANDROID_ 512 /* ====================================================================== 513 FUNCTION 514 omx_vdec::omx_vdec 515 516 DESCRIPTION 517 Constructor 518 519 PARAMETERS 520 None 521 522 RETURN VALUE 523 None. 524 ========================================================================== */ 525 omx_vdec::omx_vdec(): 526 m_error_propogated(false), 527 m_state(OMX_StateInvalid), 528 m_app_data(NULL), 529 m_inp_mem_ptr(NULL), 530 m_out_mem_ptr(NULL), 531 m_inp_err_count(0), 532 input_flush_progress (false), 533 output_flush_progress (false), 534 input_use_buffer (false), 535 output_use_buffer (false), 536 ouput_egl_buffers(false), 537 m_use_output_pmem(OMX_FALSE), 538 m_out_mem_region_smi(OMX_FALSE), 539 m_out_pvt_entry_pmem(OMX_FALSE), 540 pending_input_buffers(0), 541 pending_output_buffers(0), 542 m_out_bm_count(0), 543 m_inp_bm_count(0), 544 m_inp_bPopulated(OMX_FALSE), 545 m_out_bPopulated(OMX_FALSE), 546 m_flags(0), 547 #ifdef _ANDROID_ 548 m_heap_ptr(NULL), 549 #endif 550 m_inp_bEnabled(OMX_TRUE), 551 m_out_bEnabled(OMX_TRUE), 552 m_in_alloc_cnt(0), 553 m_platform_list(NULL), 554 m_platform_entry(NULL), 555 m_pmem_info(NULL), 556 m_pSwVdec(NULL), 557 m_pSwVdecIpBuffer(NULL), 558 m_pSwVdecOpBuffer(NULL), 559 m_nInputBuffer(0), 560 m_nOutputBuffer(0), 561 m_interm_mem_ptr(NULL), 562 m_interm_flush_dsp_progress(OMX_FALSE), 563 m_interm_flush_swvdec_progress(OMX_FALSE), 564 m_interm_bPopulated(OMX_FALSE), 565 m_interm_bEnabled(OMX_TRUE), 566 m_swvdec_mode(-1), 567 m_fill_internal_bufers(OMX_TRUE), 568 arbitrary_bytes (true), 569 psource_frame (NULL), 570 pdest_frame (NULL), 571 m_inp_heap_ptr (NULL), 572 m_phdr_pmem_ptr(NULL), 573 m_heap_inp_bm_count (0), 574 codec_type_parse ((codec_type)0), 575 first_frame_meta (true), 576 frame_count (0), 577 nal_count (0), 578 nal_length(0), 579 look_ahead_nal (false), 580 first_frame(0), 581 first_buffer(NULL), 582 first_frame_size (0), 583 m_device_file_ptr(NULL), 584 m_vc1_profile((vc1_profile_type)0), 585 h264_last_au_ts(LLONG_MAX), 586 h264_last_au_flags(0), 587 prev_ts(LLONG_MAX), 588 rst_prev_ts(true), 589 frm_int(0), 590 in_reconfig(false), 591 m_display_id(NULL), 592 h264_parser(NULL), 593 client_extradata(0), 594 #ifdef _ANDROID_ 595 m_enable_android_native_buffers(OMX_FALSE), 596 m_use_android_native_buffers(OMX_FALSE), 597 iDivXDrmDecrypt(NULL), 598 #endif 599 m_desc_buffer_ptr(NULL), 600 secure_mode(false), 601 codec_config_flag(false) 602 { 603 /* Assumption is that , to begin with , we have all the frames with decoder */ 604 DEBUG_PRINT_HIGH("In OMX vdec Constructor"); 605 #ifdef _ANDROID_ 606 char property_value[PROPERTY_VALUE_MAX] = {0}; 607 property_get("vidc.debug.level", property_value, "1"); 608 debug_level = atoi(property_value); 609 610 property_value[0] = '\0'; 611 property_get("vidc.dec.debug.perf", property_value, "0"); 612 perf_flag = atoi(property_value); 613 if (perf_flag) 614 { 615 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); 616 dec_time.start(); 617 proc_frms = latency = 0; 618 } 619 prev_n_filled_len = 0; 620 property_value[0] = '\0'; 621 property_get("vidc.dec.debug.ts", property_value, "0"); 622 m_debug_timestamp = atoi(property_value); 623 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); 624 if (m_debug_timestamp) 625 { 626 time_stamp_dts.set_timestamp_reorder_mode(true); 627 time_stamp_dts.enable_debug_print(true); 628 } 629 memset(&m_debug, 0, sizeof(m_debug)); 630 property_value[0] = '\0'; 631 property_get("vidc.dec.debug.concealedmb", property_value, "0"); 632 m_debug_concealedmb = atoi(property_value); 633 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); 634 635 property_value[0] = '\0'; 636 property_get("vidc.dec.log.in", property_value, "0"); 637 m_debug.in_buffer_log = atoi(property_value); 638 639 property_value[0] = '\0'; 640 property_get("vidc.dec.log.out", property_value, "0"); 641 m_debug.out_buffer_log = atoi(property_value); 642 643 property_value[0] = '\0'; 644 property_get("vidc.dec.log.imb", property_value, "0"); 645 m_debug.im_buffer_log = atoi(property_value); 646 647 sprintf(m_debug.log_loc, "%s", BUFFER_LOG_LOC); 648 property_value[0] = '\0'; 649 property_get("vidc.log.loc", property_value, ""); 650 if (*property_value) 651 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX); 652 #endif 653 memset(&m_cmp,0,sizeof(m_cmp)); 654 memset(&m_cb,0,sizeof(m_cb)); 655 memset (&drv_ctx,0,sizeof(drv_ctx)); 656 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); 657 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); 658 memset(m_demux_offsets, 0, sizeof(m_demux_offsets) ); 659 m_demux_entries = 0; 660 msg_thread_id = 0; 661 async_thread_id = 0; 662 msg_thread_created = false; 663 async_thread_created = false; 664 #ifdef _ANDROID_ICS_ 665 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 666 #endif 667 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 668 drv_ctx.timestamp_adjust = false; 669 drv_ctx.video_driver_fd = -1; 670 m_vendor_config.pData = NULL; 671 pthread_mutexattr_t attr; 672 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 673 pthread_mutex_init(&m_lock, &attr); 674 pthread_mutex_init(&c_lock, &attr); 675 sem_init(&m_cmd_lock,0,0); 676 streaming[CAPTURE_PORT] = 677 streaming[OUTPUT_PORT] = false; 678 #ifdef _ANDROID_ 679 char extradata_value[PROPERTY_VALUE_MAX] = {0}; 680 property_get("vidc.dec.debug.extradata", extradata_value, "0"); 681 m_debug_extradata = atoi(extradata_value); 682 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata); 683 #endif 684 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB; 685 client_buffers.set_vdec_client(this); 686 687 dynamic_buf_mode = false; 688 out_dynamic_list = NULL; 689 m_smoothstreaming_mode = false; 690 m_smoothstreaming_width = 0; 691 m_smoothstreaming_height = 0; 692 } 693 694 static const int event_type[] = { 695 V4L2_EVENT_MSM_VIDC_FLUSH_DONE, 696 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT, 697 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT, 698 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE, 699 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER, 700 V4L2_EVENT_MSM_VIDC_CLOSE_DONE, 701 V4L2_EVENT_MSM_VIDC_SYS_ERROR 702 }; 703 704 static OMX_ERRORTYPE subscribe_to_events(int fd) 705 { 706 OMX_ERRORTYPE eRet = OMX_ErrorNone; 707 struct v4l2_event_subscription sub; 708 int array_sz = sizeof(event_type)/sizeof(int); 709 int i,rc; 710 if (fd < 0) { 711 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 712 return OMX_ErrorBadParameter; 713 } 714 715 for (i = 0; i < array_sz; ++i) { 716 memset(&sub, 0, sizeof(sub)); 717 sub.type = event_type[i]; 718 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); 719 if (rc) { 720 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type); 721 break; 722 } 723 } 724 if (i < array_sz) { 725 for (--i; i >=0 ; i--) { 726 memset(&sub, 0, sizeof(sub)); 727 sub.type = event_type[i]; 728 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 729 if (rc) 730 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 731 } 732 eRet = OMX_ErrorNotImplemented; 733 } 734 return eRet; 735 } 736 737 738 static OMX_ERRORTYPE unsubscribe_to_events(int fd) 739 { 740 OMX_ERRORTYPE eRet = OMX_ErrorNone; 741 struct v4l2_event_subscription sub; 742 int array_sz = sizeof(event_type)/sizeof(int); 743 int i,rc; 744 if (fd < 0) { 745 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 746 return OMX_ErrorBadParameter; 747 } 748 749 for (i = 0; i < array_sz; ++i) { 750 memset(&sub, 0, sizeof(sub)); 751 sub.type = event_type[i]; 752 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 753 if (rc) { 754 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 755 break; 756 } 757 } 758 return eRet; 759 } 760 761 /* ====================================================================== 762 FUNCTION 763 omx_vdec::~omx_vdec 764 765 DESCRIPTION 766 Destructor 767 768 PARAMETERS 769 None 770 771 RETURN VALUE 772 None. 773 ========================================================================== */ 774 omx_vdec::~omx_vdec() 775 { 776 m_pmem_info = NULL; 777 struct v4l2_decoder_cmd dec; 778 DEBUG_PRINT_HIGH("In OMX vdec Destructor"); 779 if(m_pipe_in) close(m_pipe_in); 780 if(m_pipe_out) close(m_pipe_out); 781 m_pipe_in = -1; 782 m_pipe_out = -1; 783 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); 784 785 if (msg_thread_created) 786 pthread_join(msg_thread_id,NULL); 787 if ((!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) && 788 (m_swvdec_mode != SWVDEC_MODE_PARSE_DECODE)) 789 { 790 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit driver id %d", drv_ctx.video_driver_fd); 791 dec.cmd = V4L2_DEC_CMD_STOP; 792 if (drv_ctx.video_driver_fd >=0 ) 793 { 794 DEBUG_PRINT_HIGH("Stop decoder driver instance"); 795 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) 796 { 797 DEBUG_PRINT_ERROR("STOP Command failed"); 798 } 799 } 800 801 if (async_thread_created) 802 pthread_join(async_thread_id,NULL); 803 804 unsubscribe_to_events(drv_ctx.video_driver_fd); 805 close(drv_ctx.video_driver_fd); 806 } 807 808 if (m_pSwVdec) 809 { 810 DEBUG_PRINT_HIGH("SwVdec_Stop"); 811 if (SWVDEC_S_SUCCESS != SwVdec_Stop(m_pSwVdec)) 812 { 813 DEBUG_PRINT_ERROR("SwVdec_Stop Command failed in vdec destructor"); 814 SwVdec_DeInit(m_pSwVdec); 815 m_pSwVdec = NULL; 816 } 817 } 818 819 pthread_mutex_destroy(&m_lock); 820 pthread_mutex_destroy(&c_lock); 821 sem_destroy(&m_cmd_lock); 822 if (perf_flag) 823 { 824 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); 825 dec_time.end(); 826 } 827 DEBUG_PRINT_HIGH("Exit OMX vdec Destructor"); 828 } 829 830 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type) 831 { 832 struct v4l2_requestbuffers bufreq; 833 int rc = 0; 834 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT){ 835 bufreq.memory = V4L2_MEMORY_USERPTR; 836 bufreq.count = 0; 837 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 838 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 839 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) { 840 bufreq.memory = V4L2_MEMORY_USERPTR; 841 bufreq.count = 0; 842 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 843 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 844 } 845 return rc; 846 } 847 848 /* ====================================================================== 849 FUNCTION 850 omx_vdec::OMXCntrlProcessMsgCb 851 852 DESCRIPTION 853 IL Client callbacks are generated through this routine. The decoder 854 provides the thread context for this routine. 855 856 PARAMETERS 857 ctxt -- Context information related to the self. 858 id -- Event identifier. This could be any of the following: 859 1. Command completion event 860 2. Buffer done callback event 861 3. Frame done callback event 862 863 RETURN VALUE 864 None. 865 866 ========================================================================== */ 867 void omx_vdec::process_event_cb(void *ctxt, unsigned char id) 868 { 869 signed int p1; // Parameter - 1 870 signed int p2; // Parameter - 2 871 unsigned int ident; 872 unsigned int qsize=0; // qsize 873 omx_vdec *pThis = (omx_vdec *) ctxt; 874 875 if(!pThis) 876 { 877 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out", 878 __func__); 879 return; 880 } 881 882 // Protect the shared queue data structure 883 do 884 { 885 /*Read the message id's from the queue*/ 886 pthread_mutex_lock(&pThis->m_lock); 887 qsize = pThis->m_cmd_q.m_size; 888 if(qsize) 889 { 890 pThis->m_cmd_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident); 891 } 892 893 if (qsize == 0 && pThis->m_state != OMX_StatePause) 894 { 895 qsize = pThis->m_ftb_q.m_size; 896 if (qsize) 897 { 898 pThis->m_ftb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident); 899 } 900 } 901 902 if (qsize == 0 && pThis->m_state != OMX_StatePause) 903 { 904 qsize = pThis->m_ftb_q_dsp.m_size; 905 if (qsize) 906 { 907 pThis->m_ftb_q_dsp.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident); 908 } 909 } 910 911 if (qsize == 0 && pThis->m_state != OMX_StatePause) 912 { 913 qsize = pThis->m_etb_q.m_size; 914 if (qsize) 915 { 916 pThis->m_etb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident); 917 } 918 } 919 920 if (qsize == 0 && pThis->m_state != OMX_StatePause) 921 { 922 qsize = pThis->m_etb_q_swvdec.m_size; 923 if (qsize) 924 { 925 pThis->m_etb_q_swvdec.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident); 926 } 927 } 928 929 pthread_mutex_unlock(&pThis->m_lock); 930 931 /*process message if we have one*/ 932 if(qsize > 0) 933 { 934 id = ident; 935 switch (id) 936 { 937 case OMX_COMPONENT_GENERATE_EVENT: 938 if (pThis->m_cb.EventHandler) 939 { 940 switch (p1) 941 { 942 case OMX_CommandStateSet: 943 pThis->m_state = (OMX_STATETYPE) p2; 944 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d", 945 pThis->m_state); 946 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 947 OMX_EventCmdComplete, p1, p2, NULL); 948 break; 949 950 case OMX_EventError: 951 if(p2 == OMX_StateInvalid) 952 { 953 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid"); 954 pThis->m_state = (OMX_STATETYPE) p2; 955 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 956 OMX_EventError, OMX_ErrorInvalidState, p2, NULL); 957 } 958 else if (p2 == OMX_ErrorHardware) 959 { 960 pThis->omx_report_error(); 961 } 962 else 963 { 964 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 965 OMX_EventError, p2, (OMX_U32)NULL, NULL ); 966 } 967 break; 968 969 case OMX_CommandPortDisable: 970 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%d]", p2); 971 if (BITMASK_PRESENT(&pThis->m_flags, 972 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) 973 { 974 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 975 break; 976 } 977 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) 978 { 979 OMX_ERRORTYPE eRet = OMX_ErrorNone; 980 if (!pThis->m_pSwVdec || pThis->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 981 { 982 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 983 if(release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT)) 984 DEBUG_PRINT_HIGH("Failed to release output buffers"); 985 986 if (pThis->m_pSwVdec) 987 { 988 DEBUG_PRINT_HIGH("In port reconfig, SwVdec_Stop"); 989 SwVdec_Stop(pThis->m_pSwVdec); 990 } 991 } 992 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req_swvdec(); 993 pThis->in_reconfig = false; 994 if(eRet != OMX_ErrorNone) 995 { 996 DEBUG_PRINT_ERROR("get_buffer_req_swvdec failed eRet = %d",eRet); 997 pThis->omx_report_error(); 998 break; 999 } 1000 } 1001 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1002 OMX_EventCmdComplete, p1, p2, NULL ); 1003 break; 1004 case OMX_CommandPortEnable: 1005 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%d]", p2); 1006 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1007 { 1008 DEBUG_PRINT_LOW("send all interm buffers to dsp after port enabled"); 1009 pThis->fill_all_buffers_proxy_dsp(&pThis->m_cmp); 1010 } 1011 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ 1012 OMX_EventCmdComplete, p1, p2, NULL ); 1013 break; 1014 1015 default: 1016 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1017 OMX_EventCmdComplete, p1, p2, NULL ); 1018 break; 1019 1020 } 1021 } 1022 else 1023 { 1024 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1025 } 1026 break; 1027 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: 1028 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 1029 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) 1030 { 1031 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure"); 1032 pThis->omx_report_error (); 1033 } 1034 break; 1035 case OMX_COMPONENT_GENERATE_ETB: 1036 if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ 1037 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) 1038 { 1039 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); 1040 pThis->omx_report_error (); 1041 } 1042 break; 1043 1044 case OMX_COMPONENT_GENERATE_FTB: 1045 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ 1046 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) 1047 { 1048 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure"); 1049 pThis->omx_report_error (); 1050 } 1051 break; 1052 1053 case OMX_COMPONENT_GENERATE_COMMAND: 1054 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ 1055 (OMX_U32)p2,(OMX_PTR)NULL); 1056 break; 1057 1058 case OMX_COMPONENT_GENERATE_EBD: 1059 1060 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) 1061 { 1062 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure"); 1063 pThis->omx_report_error (); 1064 } 1065 else 1066 { 1067 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) 1068 { 1069 pThis->m_inp_err_count++; 1070 pThis->time_stamp_dts.remove_time_stamp( 1071 ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp, 1072 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1073 ?true:false); 1074 } 1075 else 1076 { 1077 pThis->m_inp_err_count = 0; 1078 } 1079 if ( pThis->empty_buffer_done(&pThis->m_cmp, 1080 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) 1081 { 1082 DEBUG_PRINT_ERROR("empty_buffer_done failure"); 1083 pThis->omx_report_error (); 1084 } 1085 if(pThis->m_inp_err_count >= MAX_INPUT_ERROR) 1086 { 1087 DEBUG_PRINT_ERROR("Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR); 1088 pThis->omx_report_error (); 1089 } 1090 } 1091 break; 1092 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: 1093 { 1094 int64_t *timestamp = (int64_t *)p1; 1095 if (p1) 1096 { 1097 pThis->time_stamp_dts.remove_time_stamp(*timestamp, 1098 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1099 ?true:false); 1100 free(timestamp); 1101 } 1102 } 1103 break; 1104 case OMX_COMPONENT_GENERATE_FBD: 1105 if (p2 != VDEC_S_SUCCESS) 1106 { 1107 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure"); 1108 pThis->omx_report_error (); 1109 } 1110 else if ( pThis->fill_buffer_done(&pThis->m_cmp, 1111 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) 1112 { 1113 DEBUG_PRINT_ERROR("fill_buffer_done failure"); 1114 pThis->omx_report_error (); 1115 } 1116 break; 1117 1118 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: 1119 if (!pThis->input_flush_progress) 1120 { 1121 DEBUG_PRINT_ERROR("WARNING: Unexpected INPUT_FLUSH from driver"); 1122 } 1123 else 1124 { 1125 pThis->execute_input_flush(); 1126 if (pThis->m_cb.EventHandler) 1127 { 1128 if (p2 != VDEC_S_SUCCESS) 1129 { 1130 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); 1131 pThis->omx_report_error (); 1132 } 1133 else 1134 { 1135 /*Check if we need generate event for Flush done*/ 1136 if(BITMASK_PRESENT(&pThis->m_flags, 1137 OMX_COMPONENT_INPUT_FLUSH_PENDING)) 1138 { 1139 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); 1140 DEBUG_PRINT_LOW("Input Flush completed - Notify Client"); 1141 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1142 OMX_EventCmdComplete,OMX_CommandFlush, 1143 OMX_CORE_INPUT_PORT_INDEX,NULL ); 1144 } 1145 if (BITMASK_PRESENT(&pThis->m_flags, 1146 OMX_COMPONENT_IDLE_PENDING)) 1147 { 1148 if (!pThis->m_pSwVdec || pThis->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1149 { 1150 if(pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) { 1151 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port"); 1152 pThis->omx_report_error (); 1153 } else { 1154 pThis->streaming[OUTPUT_PORT] = false; 1155 } 1156 } 1157 } 1158 } 1159 } 1160 else 1161 { 1162 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1163 } 1164 } 1165 break; 1166 1167 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: 1168 DEBUG_PRINT_HIGH("Driver flush o/p Port complete"); 1169 if (!pThis->output_flush_progress) 1170 { 1171 DEBUG_PRINT_ERROR("WARNING: Unexpected OUTPUT_FLUSH from driver"); 1172 } 1173 else 1174 { 1175 pThis->execute_output_flush(); 1176 if (pThis->m_interm_flush_dsp_progress) 1177 { 1178 pThis->execute_output_flush_dsp(); 1179 } 1180 if (pThis->m_interm_flush_swvdec_progress) 1181 { 1182 pThis->execute_input_flush_swvdec(); 1183 } 1184 if (pThis->m_cb.EventHandler) 1185 { 1186 if (p2 != VDEC_S_SUCCESS) 1187 { 1188 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); 1189 pThis->omx_report_error (); 1190 } 1191 else 1192 { 1193 /*Check if we need generate event for Flush done*/ 1194 if(BITMASK_PRESENT(&pThis->m_flags, 1195 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) 1196 { 1197 if (pThis->release_interm_done() == false) 1198 { 1199 DEBUG_PRINT_ERROR("OMX_COMPONENT_OUTPUT_FLUSH failed not all interm buffers are returned"); 1200 pThis->omx_report_error (); 1201 break; 1202 } 1203 pThis->m_fill_internal_bufers = OMX_TRUE; 1204 DEBUG_PRINT_HIGH("Notify Output Flush done"); 1205 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 1206 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1207 OMX_EventCmdComplete,OMX_CommandFlush, 1208 OMX_CORE_OUTPUT_PORT_INDEX,NULL ); 1209 } 1210 if(BITMASK_PRESENT(&pThis->m_flags, 1211 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) 1212 { 1213 DEBUG_PRINT_LOW("Internal flush complete"); 1214 BITMASK_CLEAR (&pThis->m_flags, 1215 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 1216 if (BITMASK_PRESENT(&pThis->m_flags, 1217 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) 1218 { 1219 pThis->post_event(OMX_CommandPortDisable, 1220 OMX_CORE_OUTPUT_PORT_INDEX, 1221 OMX_COMPONENT_GENERATE_EVENT); 1222 BITMASK_CLEAR (&pThis->m_flags, 1223 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 1224 BITMASK_CLEAR (&pThis->m_flags, 1225 OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 1226 1227 } 1228 } 1229 1230 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) 1231 { 1232 if (!pThis->m_pSwVdec || pThis->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1233 { 1234 if(pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) { 1235 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port"); 1236 pThis->omx_report_error (); 1237 break; 1238 } 1239 pThis->streaming[CAPTURE_PORT] = false; 1240 } 1241 if (!pThis->input_flush_progress) 1242 { 1243 DEBUG_PRINT_LOW("Output flush done hence issue stop"); 1244 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\ 1245 OMX_COMPONENT_GENERATE_STOP_DONE); 1246 } 1247 } 1248 } 1249 } 1250 else 1251 { 1252 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1253 } 1254 } 1255 break; 1256 1257 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH_DSP: 1258 DEBUG_PRINT_HIGH("Dsp Driver flush o/p Port complete"); 1259 if (!pThis->m_interm_flush_dsp_progress) 1260 { 1261 DEBUG_PRINT_ERROR("WARNING: Unexpected OUTPUT_FLUSH_DSP from driver"); 1262 } 1263 else 1264 { 1265 // check if we need to flush swvdec 1266 bool bFlushSwVdec = false; 1267 SWVDEC_BUFFER_FLUSH_TYPE aFlushType = SWVDEC_FLUSH_ALL; 1268 if (pThis->m_interm_flush_swvdec_progress) 1269 { 1270 aFlushType = SWVDEC_FLUSH_ALL; 1271 bFlushSwVdec = true; 1272 } 1273 else if (pThis->output_flush_progress) 1274 { 1275 DEBUG_PRINT_HIGH("Flush swvdec output only "); 1276 aFlushType = SWVDEC_FLUSH_OUTPUT; 1277 bFlushSwVdec = true; 1278 } 1279 1280 DEBUG_PRINT_HIGH("Flush swvdec %d, interm flush %d output flush %d swvdec flushType %d", 1281 bFlushSwVdec, pThis->m_interm_flush_swvdec_progress, pThis->output_flush_progress, aFlushType); 1282 1283 if (bFlushSwVdec) 1284 { 1285 if (SwVdec_Flush(pThis->m_pSwVdec, aFlushType) != SWVDEC_S_SUCCESS) 1286 { 1287 DEBUG_PRINT_ERROR("Flush swvdec Failed "); 1288 } 1289 } 1290 else 1291 { 1292 pThis->execute_output_flush_dsp(); 1293 } 1294 } 1295 break; 1296 1297 case OMX_COMPONENT_GENERATE_START_DONE: 1298 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE"); 1299 1300 if (pThis->m_cb.EventHandler) 1301 { 1302 if (p2 != VDEC_S_SUCCESS) 1303 { 1304 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure"); 1305 pThis->omx_report_error (); 1306 } 1307 else 1308 { 1309 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success"); 1310 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) 1311 { 1312 DEBUG_PRINT_LOW("Move to executing"); 1313 // Send the callback now 1314 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1315 pThis->m_state = OMX_StateExecuting; 1316 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1317 OMX_EventCmdComplete,OMX_CommandStateSet, 1318 OMX_StateExecuting, NULL); 1319 } 1320 else if (BITMASK_PRESENT(&pThis->m_flags, 1321 OMX_COMPONENT_PAUSE_PENDING)) 1322 { 1323 if (/*ioctl (pThis->drv_ctx.video_driver_fd, 1324 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) 1325 { 1326 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed"); 1327 pThis->omx_report_error (); 1328 } 1329 } 1330 } 1331 } 1332 else 1333 { 1334 DEBUG_PRINT_LOW("Event Handler callback is NULL"); 1335 } 1336 break; 1337 1338 case OMX_COMPONENT_GENERATE_PAUSE_DONE: 1339 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); 1340 if (pThis->m_cb.EventHandler) 1341 { 1342 if (p2 != VDEC_S_SUCCESS) 1343 { 1344 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); 1345 pThis->omx_report_error (); 1346 } 1347 else 1348 { 1349 pThis->complete_pending_buffer_done_cbs(); 1350 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) 1351 { 1352 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); 1353 //Send the callback now 1354 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); 1355 pThis->m_state = OMX_StatePause; 1356 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1357 OMX_EventCmdComplete,OMX_CommandStateSet, 1358 OMX_StatePause, NULL); 1359 } 1360 } 1361 } 1362 else 1363 { 1364 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1365 } 1366 1367 break; 1368 1369 case OMX_COMPONENT_GENERATE_RESUME_DONE: 1370 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); 1371 if (pThis->m_cb.EventHandler) 1372 { 1373 if (p2 != VDEC_S_SUCCESS) 1374 { 1375 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed"); 1376 pThis->omx_report_error (); 1377 } 1378 else 1379 { 1380 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) 1381 { 1382 DEBUG_PRINT_LOW("Moving the decoder to execute state"); 1383 // Send the callback now 1384 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1385 pThis->m_state = OMX_StateExecuting; 1386 if (pThis->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1387 { 1388 pThis->fill_all_buffers_proxy_dsp(&pThis->m_cmp); 1389 } 1390 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1391 OMX_EventCmdComplete,OMX_CommandStateSet, 1392 OMX_StateExecuting,NULL); 1393 } 1394 } 1395 } 1396 else 1397 { 1398 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1399 } 1400 1401 break; 1402 1403 case OMX_COMPONENT_GENERATE_STOP_DONE: 1404 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); 1405 if (pThis->m_cb.EventHandler) 1406 { 1407 if (p2 != VDEC_S_SUCCESS) 1408 { 1409 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); 1410 pThis->omx_report_error (); 1411 } 1412 else 1413 { 1414 pThis->complete_pending_buffer_done_cbs(); 1415 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) 1416 { 1417 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success"); 1418 // Send the callback now 1419 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); 1420 pThis->m_state = OMX_StateIdle; 1421 DEBUG_PRINT_LOW("Move to Idle State"); 1422 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, 1423 OMX_EventCmdComplete,OMX_CommandStateSet, 1424 OMX_StateIdle,NULL); 1425 } 1426 } 1427 } 1428 else 1429 { 1430 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1431 } 1432 1433 break; 1434 1435 case OMX_COMPONENT_GENERATE_PORT_RECONFIG: 1436 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG"); 1437 1438 if (p2 == OMX_IndexParamPortDefinition) { 1439 pThis->in_reconfig = true; 1440 } 1441 if (pThis->m_cb.EventHandler) { 1442 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1443 OMX_EventPortSettingsChanged, p1, p2, NULL ); 1444 } else { 1445 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1446 } 1447 1448 if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1449 { 1450 OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1; 1451 OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged; 1452 if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) 1453 format = OMX_InterlaceInterleaveFrameTopFieldFirst; 1454 else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) 1455 format = OMX_InterlaceInterleaveFrameBottomFieldFirst; 1456 else //unsupported interlace format; raise a error 1457 event = OMX_EventError; 1458 if (pThis->m_cb.EventHandler) { 1459 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1460 event, format, 0, NULL ); 1461 } else { 1462 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1463 } 1464 } 1465 break; 1466 1467 case OMX_COMPONENT_GENERATE_EOS_DONE: 1468 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); 1469 if (pThis->m_cb.EventHandler) { 1470 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, 1471 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); 1472 } else { 1473 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1474 } 1475 pThis->prev_ts = LLONG_MAX; 1476 pThis->rst_prev_ts = true; 1477 break; 1478 1479 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: 1480 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); 1481 pThis->omx_report_error (); 1482 break; 1483 1484 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING: 1485 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING"); 1486 pThis->omx_report_unsupported_setting(); 1487 break; 1488 1489 case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG: 1490 { 1491 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG"); 1492 if (pThis->m_cb.EventHandler) { 1493 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1494 (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL ); 1495 } else { 1496 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1497 } 1498 } 1499 break; 1500 1501 case OMX_COMPONENT_GENERATE_ETB_SWVDEC: 1502 { 1503 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_ETB_SWVDEC"); 1504 if (pThis->empty_this_buffer_proxy_swvdec((OMX_HANDLETYPE)p1,\ 1505 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) 1506 { 1507 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_swvdec failure"); 1508 pThis->omx_report_error (); 1509 } 1510 } 1511 break; 1512 1513 case OMX_COMPONENT_GENERATE_EBD_SWVDEC: 1514 { 1515 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EBD_SWVDEC"); 1516 if (p2 != VDEC_S_SUCCESS) 1517 { 1518 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD_SWVDEC failure"); 1519 pThis->omx_report_error (); 1520 } 1521 else if ( pThis->empty_buffer_done_swvdec(&pThis->m_cmp, 1522 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) 1523 { 1524 DEBUG_PRINT_ERROR("empty_buffer_done_swvdec failure"); 1525 pThis->omx_report_error (); 1526 } 1527 } 1528 break; 1529 1530 case OMX_COMPONENT_GENERATE_FTB_DSP: 1531 { 1532 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_FTB_DSP"); 1533 if ( pThis->fill_this_buffer_proxy_dsp((OMX_HANDLETYPE)p1,\ 1534 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) 1535 { 1536 DEBUG_PRINT_ERROR("fill_this_buffer_proxy_dsp failure"); 1537 pThis->omx_report_error (); 1538 } 1539 } 1540 break; 1541 1542 case OMX_COMPONENT_GENERATE_FBD_DSP: 1543 { 1544 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_FBD_DSP"); 1545 if (p2 != VDEC_S_SUCCESS) 1546 { 1547 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD_DSP failure"); 1548 pThis->omx_report_error (); 1549 } 1550 else if ( pThis->fill_buffer_done_dsp(&pThis->m_cmp, 1551 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) 1552 { 1553 DEBUG_PRINT_ERROR("fill_buffer_done failure"); 1554 pThis->omx_report_error (); 1555 } 1556 1557 1558 } 1559 break; 1560 1561 default: 1562 break; 1563 } 1564 } 1565 pthread_mutex_lock(&pThis->m_lock); 1566 qsize = pThis->m_cmd_q.m_size; 1567 if (pThis->m_state != OMX_StatePause) 1568 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size + 1569 pThis->m_ftb_q_dsp.m_size + pThis->m_etb_q_swvdec.m_size); 1570 pthread_mutex_unlock(&pThis->m_lock); 1571 } 1572 while(qsize>0); 1573 1574 } 1575 1576 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines) 1577 { 1578 int format_changed = 0; 1579 if ((height != (int)drv_ctx.video_resolution.frame_height) || 1580 (width != (int)drv_ctx.video_resolution.frame_width)) { 1581 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)", 1582 width, drv_ctx.video_resolution.frame_width, 1583 height,drv_ctx.video_resolution.frame_height); 1584 format_changed = 1; 1585 } 1586 drv_ctx.video_resolution.frame_height = height; 1587 drv_ctx.video_resolution.frame_width = width; 1588 drv_ctx.video_resolution.scan_lines = scan_lines; 1589 drv_ctx.video_resolution.stride = stride; 1590 rectangle.nLeft = 0; 1591 rectangle.nTop = 0; 1592 rectangle.nWidth = drv_ctx.video_resolution.frame_width; 1593 rectangle.nHeight = drv_ctx.video_resolution.frame_height; 1594 return format_changed; 1595 } 1596 1597 OMX_ERRORTYPE omx_vdec::is_video_session_supported() 1598 { 1599 if ((drv_ctx.video_resolution.frame_width * drv_ctx.video_resolution.frame_height > 1600 m_decoder_capability.max_width * m_decoder_capability.max_height) || 1601 (drv_ctx.video_resolution.frame_width* drv_ctx.video_resolution.frame_height < 1602 m_decoder_capability.min_width * m_decoder_capability.min_height)) 1603 { 1604 DEBUG_PRINT_ERROR( 1605 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)", 1606 drv_ctx.video_resolution.frame_width, 1607 drv_ctx.video_resolution.frame_height, 1608 m_decoder_capability.min_width, 1609 m_decoder_capability.min_height, 1610 m_decoder_capability.max_width, 1611 m_decoder_capability.max_height); 1612 return OMX_ErrorUnsupportedSetting; 1613 } 1614 DEBUG_PRINT_HIGH("video session supported"); 1615 return OMX_ErrorNone; 1616 } 1617 1618 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) 1619 { 1620 if (m_debug.in_buffer_log && !m_debug.infile) { 1621 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE) || 1622 !strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.hevchybrid", OMX_MAX_STRINGNAME_SIZE) || 1623 !strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.hevcswvdec", OMX_MAX_STRINGNAME_SIZE)) { 1624 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.hevc", 1625 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1626 } 1627 m_debug.infile = fopen (m_debug.infile_name, "ab"); 1628 if (!m_debug.infile) { 1629 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name); 1630 m_debug.infile_name[0] = '\0'; 1631 return -1; 1632 } 1633 } 1634 if (m_debug.infile && buffer_addr && buffer_len) { 1635 fwrite(buffer_addr, buffer_len, 1, m_debug.infile); 1636 } 1637 return 0; 1638 } 1639 1640 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) 1641 { 1642 if (m_debug.out_buffer_log && !m_debug.outfile) { 1643 sprintf(m_debug.outfile_name, "%s/output_%d_%d_%p.yuv", 1644 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1645 m_debug.outfile = fopen (m_debug.outfile_name, "ab"); 1646 if (!m_debug.outfile) { 1647 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc); 1648 m_debug.outfile_name[0] = '\0'; 1649 return -1; 1650 } 1651 } 1652 if (m_debug.outfile && buffer && buffer->nFilledLen) { 1653 int buf_index = buffer - m_out_mem_ptr; 1654 int stride = drv_ctx.video_resolution.stride; 1655 int scanlines = drv_ctx.video_resolution.scan_lines; 1656 if (m_smoothstreaming_mode) { 1657 stride = drv_ctx.video_resolution.frame_width; 1658 scanlines = drv_ctx.video_resolution.frame_height; 1659 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1)); 1660 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1)); 1661 } 1662 char *temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; 1663 unsigned i; 1664 int bytes_written = 0; 1665 DEBUG_PRINT_LOW("Logging width/height(%u/%u) stride/scanlines(%u/%u)", 1666 drv_ctx.video_resolution.frame_width, 1667 drv_ctx.video_resolution.frame_height, stride, scanlines); 1668 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) { 1669 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 1670 temp += stride; 1671 } 1672 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines; 1673 int stride_c = stride; 1674 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) { 1675 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 1676 temp += stride_c; 1677 } 1678 } 1679 return 0; 1680 } 1681 1682 int omx_vdec::log_im_buffer(OMX_BUFFERHEADERTYPE * buffer) 1683 { 1684 if (m_debug.im_buffer_log && !m_debug.imbfile) { 1685 sprintf(m_debug.imbfile_name, "%s/imb_%d_%d_%p.bin", 1686 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1687 m_debug.imbfile = fopen (m_debug.imbfile_name, "ab"); 1688 if (!m_debug.imbfile) { 1689 DEBUG_PRINT_HIGH("Failed to open intermediate file: %s for logging", m_debug.log_loc); 1690 m_debug.imbfile_name[0] = '\0'; 1691 return -1; 1692 } 1693 } 1694 1695 if (buffer && buffer->nFilledLen) 1696 { 1697 fwrite(&buffer->nFilledLen, sizeof(buffer->nFilledLen), 1, m_debug.imbfile); 1698 fwrite(buffer->pBuffer, sizeof(uint8), buffer->nFilledLen, m_debug.imbfile); 1699 } 1700 return 0; 1701 } 1702 1703 /* ====================================================================== 1704 FUNCTION 1705 omx_vdec::ComponentInit 1706 1707 DESCRIPTION 1708 Initialize the component. 1709 1710 PARAMETERS 1711 ctxt -- Context information related to the self. 1712 id -- Event identifier. This could be any of the following: 1713 1. Command completion event 1714 2. Buffer done callback event 1715 3. Frame done callback event 1716 1717 RETURN VALUE 1718 None. 1719 1720 ========================================================================== */ 1721 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) 1722 { 1723 1724 OMX_ERRORTYPE eRet = OMX_ErrorNone; 1725 struct v4l2_fmtdesc fdesc; 1726 struct v4l2_format fmt; 1727 struct v4l2_requestbuffers bufreq; 1728 struct v4l2_control control; 1729 struct v4l2_frmsizeenum frmsize; 1730 unsigned int alignment = 0,buffer_size = 0; 1731 int fds[2]; 1732 int r,ret=0; 1733 bool codec_ambiguous = false; 1734 1735 m_decoder_capability.min_width = 16; 1736 m_decoder_capability.min_height = 16; 1737 m_decoder_capability.max_width = 1920; 1738 m_decoder_capability.max_height = 1080; 1739 strlcpy(drv_ctx.kind,role,128); 1740 OMX_STRING device_name = (OMX_STRING)"/dev/video/q6_dec"; 1741 if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", 1742 OMX_MAX_STRINGNAME_SIZE)) || 1743 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid", 1744 OMX_MAX_STRINGNAME_SIZE))) 1745 { 1746 drv_ctx.video_driver_fd = open(device_name, O_RDWR); 1747 if(drv_ctx.video_driver_fd == 0){ 1748 drv_ctx.video_driver_fd = open(device_name, O_RDWR); 1749 } 1750 if(drv_ctx.video_driver_fd < 0) 1751 { 1752 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno); 1753 return OMX_ErrorInsufficientResources; 1754 } 1755 DEBUG_PRINT_HIGH("omx_vdec::component_init(%s): Open device %s returned fd %d", 1756 role, device_name, drv_ctx.video_driver_fd); 1757 } 1758 else 1759 DEBUG_PRINT_HIGH("Omx_vdec::Comp Init for full SW hence skip Q6 open"); 1760 1761 // Copy the role information which provides the decoder kind 1762 strlcpy(drv_ctx.kind,role,128); 1763 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); 1764 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid", 1765 OMX_MAX_STRINGNAME_SIZE)) 1766 { 1767 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1768 fmt.fmt.pix_mp.width = 320; 1769 fmt.fmt.pix_mp.height = 240; 1770 fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_HEVC_HYBRID; 1771 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1772 if (ret) { 1773 DEBUG_PRINT_HIGH("Failed to set format(V4L2_PIX_FMT_HEVC_HYBRID)"); 1774 DEBUG_PRINT_HIGH("Switch to HEVC fullDSP as HYBRID is not supported"); 1775 strlcpy(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", 128); 1776 } 1777 else { 1778 DEBUG_PRINT_HIGH("HEVC HYBRID is supported"); 1779 } 1780 } 1781 1782 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid", 1783 OMX_MAX_STRINGNAME_SIZE)) 1784 { 1785 m_swvdec_mode = SWVDEC_MODE_DECODE_ONLY; 1786 } 1787 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevcswvdec", 1788 OMX_MAX_STRINGNAME_SIZE)) 1789 { 1790 m_swvdec_mode = SWVDEC_MODE_PARSE_DECODE; 1791 } 1792 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", 1793 OMX_MAX_STRINGNAME_SIZE)) 1794 { 1795 DEBUG_PRINT_ERROR("Full DSP mode"); 1796 maxSmoothStreamingWidth = 1280; 1797 maxSmoothStreamingHeight = 720; 1798 m_decoder_capability.max_width = 1280; 1799 m_decoder_capability.max_height = 720; 1800 m_swvdec_mode = -1; 1801 } 1802 else { 1803 DEBUG_PRINT_ERROR("ERROR:Unknown Component"); 1804 return OMX_ErrorInvalidComponentName; 1805 } 1806 1807 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC; 1808 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc; 1809 codec_type_parse = CODEC_TYPE_HEVC; 1810 m_frame_parser.init_start_codes (codec_type_parse); 1811 m_frame_parser.init_nal_length(nal_length); 1812 1813 update_resolution(1280, 720, 1280, 720); 1814 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; 1815 OMX_COLOR_FORMATTYPE dest_color_format = (OMX_COLOR_FORMATTYPE) 1816 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 1817 if (!client_buffers.set_color_format(dest_color_format)) { 1818 DEBUG_PRINT_ERROR("Setting color format failed"); 1819 eRet = OMX_ErrorInsufficientResources; 1820 } 1821 1822 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; 1823 drv_ctx.frame_rate.fps_denominator = 1; 1824 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; 1825 drv_ctx.interm_op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 1826 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 1827 if (secure_mode) { 1828 drv_ctx.interm_op_buf.alignment=SZ_1M; 1829 drv_ctx.op_buf.alignment=SZ_1M; 1830 drv_ctx.ip_buf.alignment=SZ_1M; 1831 } else { 1832 drv_ctx.op_buf.alignment=SZ_4K; 1833 drv_ctx.interm_op_buf.alignment=SZ_4K; 1834 drv_ctx.ip_buf.alignment=SZ_4K; 1835 } 1836 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 1837 drv_ctx.extradata = 0; 1838 drv_ctx.picture_order = VDEC_ORDER_DISPLAY; 1839 1840 if (m_swvdec_mode >= 0) 1841 { 1842 // Init for SWCodec 1843 DEBUG_PRINT_HIGH(":Initializing SwVdec mode %d", m_swvdec_mode); 1844 memset(&sSwVdecParameter, 0, sizeof(SWVDEC_INITPARAMS)); 1845 sSwVdecParameter.sDimensions.nWidth = 1280; 1846 sSwVdecParameter.sDimensions.nHeight = 720; 1847 sSwVdecParameter.eDecType = SWVDEC_DECODER_HEVC; 1848 sSwVdecParameter.eColorFormat = SWVDEC_FORMAT_NV12; 1849 sSwVdecParameter.uProfile.eHevcProfile = SWVDEC_HEVC_MAIN_PROFILE; 1850 sSwVdecParameter.sMode.eMode = (SWVDEC_MODE_TYPE)m_swvdec_mode; 1851 1852 //SWVDEC_CALLBACK m_callBackInfo; 1853 m_callBackInfo.FillBufferDone = swvdec_fill_buffer_done_cb; 1854 m_callBackInfo.EmptyBufferDone = swvdec_input_buffer_done_cb; 1855 m_callBackInfo.HandleEvent = swvdec_handle_event_cb; 1856 m_callBackInfo.pClientHandle = this; 1857 SWVDEC_STATUS sRet = SwVdec_Init(&sSwVdecParameter, &m_callBackInfo, &m_pSwVdec); 1858 if (sRet != SWVDEC_S_SUCCESS) 1859 { 1860 DEBUG_PRINT_ERROR("SwVdec_Init returned %d, ret insufficient resources", sRet); 1861 return OMX_ErrorInsufficientResources; 1862 } 1863 } 1864 1865 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1866 { 1867 ret = pthread_create(&async_thread_id,0,async_message_thread,this); 1868 if(ret < 0) { 1869 close(drv_ctx.video_driver_fd); 1870 DEBUG_PRINT_ERROR("Failed to create async_message_thread"); 1871 return OMX_ErrorInsufficientResources; 1872 } 1873 async_thread_created = true; 1874 1875 capture_capability= V4L2_PIX_FMT_NV12; 1876 ret = subscribe_to_events(drv_ctx.video_driver_fd); 1877 if (ret) { 1878 DEBUG_PRINT_ERROR("Subscribe Event Failed"); 1879 return OMX_ErrorInsufficientResources; 1880 } 1881 1882 struct v4l2_capability cap; 1883 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap); 1884 if (ret) { 1885 DEBUG_PRINT_ERROR("Failed to query capabilities"); 1886 /*TODO: How to handle this case */ 1887 } else { 1888 DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s," 1889 " version = %d, capabilities = %x", cap.driver, cap.card, 1890 cap.bus_info, cap.version, cap.capabilities); 1891 } 1892 ret=0; 1893 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1894 fdesc.index=0; 1895 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 1896 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 1897 fdesc.pixelformat, fdesc.flags); 1898 fdesc.index++; 1899 } 1900 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1901 fdesc.index=0; 1902 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 1903 1904 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 1905 fdesc.pixelformat, fdesc.flags); 1906 fdesc.index++; 1907 } 1908 1909 output_capability = V4L2_PIX_FMT_HEVC; 1910 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 1911 { 1912 output_capability = V4L2_PIX_FMT_HEVC_HYBRID; 1913 } 1914 DEBUG_PRINT_HIGH("output_capability %d, V4L2_PIX_FMT_HEVC_HYBRID %d", output_capability, V4L2_PIX_FMT_HEVC_HYBRID); 1915 1916 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1917 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 1918 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 1919 fmt.fmt.pix_mp.pixelformat = output_capability; 1920 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1921 if (ret) { 1922 /*TODO: How to handle this case */ 1923 DEBUG_PRINT_ERROR("Failed to set format on output port"); 1924 return OMX_ErrorInsufficientResources; 1925 } 1926 DEBUG_PRINT_HIGH("Set Format was successful"); 1927 //Get the hardware capabilities 1928 memset((void *)&frmsize,0,sizeof(frmsize)); 1929 frmsize.index = 0; 1930 frmsize.pixel_format = output_capability; 1931 ret = ioctl(drv_ctx.video_driver_fd, 1932 VIDIOC_ENUM_FRAMESIZES, &frmsize); 1933 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) { 1934 DEBUG_PRINT_ERROR("Failed to get framesizes"); 1935 return OMX_ErrorHardware; 1936 } 1937 1938 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 1939 m_decoder_capability.min_width = frmsize.stepwise.min_width; 1940 m_decoder_capability.max_width = frmsize.stepwise.max_width; 1941 m_decoder_capability.min_height = frmsize.stepwise.min_height; 1942 m_decoder_capability.max_height = frmsize.stepwise.max_height; 1943 } 1944 1945 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1946 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 1947 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 1948 fmt.fmt.pix_mp.pixelformat = capture_capability; 1949 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1950 if (ret) { 1951 /*TODO: How to handle this case */ 1952 DEBUG_PRINT_ERROR("Failed to set format on capture port"); 1953 } 1954 DEBUG_PRINT_HIGH("Set Format was successful"); 1955 if(secure_mode){ 1956 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE; 1957 control.value = 1; 1958 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret); 1959 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 1960 if (ret) { 1961 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret); 1962 close(drv_ctx.video_driver_fd); 1963 return OMX_ErrorInsufficientResources; 1964 } 1965 } 1966 1967 /*Get the Buffer requirements for input(input buffer) and output ports(intermediate buffer) from Q6*/ 1968 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 1969 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 1970 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 1971 drv_ctx.idr_only_decoding = 0; 1972 eRet=get_buffer_req(&drv_ctx.ip_buf); 1973 DEBUG_PRINT_HIGH("Input Buffer Size =%d",drv_ctx.ip_buf.buffer_size); 1974 } 1975 else if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 1976 { 1977 SWVDEC_PROP prop_dimen, prop_attr; 1978 1979 capture_capability = V4L2_PIX_FMT_NV12; 1980 output_capability = V4L2_PIX_FMT_HEVC; 1981 1982 prop_dimen.ePropId = SWVDEC_PROP_ID_DIMENSIONS; 1983 prop_dimen.uProperty.sDimensions.nWidth = drv_ctx.video_resolution.frame_width; 1984 prop_dimen.uProperty.sDimensions.nHeight = drv_ctx.video_resolution.frame_height; 1985 ret = SwVdec_SetProperty(m_pSwVdec,&prop_dimen); 1986 if (ret) { 1987 DEBUG_PRINT_ERROR("Failed to set dimensions to SwVdec in full SW"); 1988 return OMX_ErrorInsufficientResources; 1989 } 1990 DEBUG_PRINT_LOW("Set dimensions to SwVdec in full SW successful"); 1991 prop_attr.ePropId = SWVDEC_PROP_ID_FRAME_ATTR; 1992 prop_attr.uProperty.sFrameAttr.eColorFormat = SWVDEC_FORMAT_NV12; 1993 ret = SwVdec_SetProperty(m_pSwVdec,&prop_attr); 1994 if (ret) { 1995 DEBUG_PRINT_ERROR("Failed to set color fmt to SwVdec in full SW"); 1996 return OMX_ErrorInsufficientResources; 1997 } 1998 DEBUG_PRINT_HIGH("Set dimensions and color format successful"); 1999 2000 //TODO: Get the supported min/max dimensions of full SW solution 2001 2002 drv_ctx.idr_only_decoding = 0; 2003 } 2004 2005 m_state = OMX_StateLoaded; 2006 #ifdef DEFAULT_EXTRADATA 2007 if (eRet == OMX_ErrorNone && !secure_mode) 2008 enable_extradata(DEFAULT_EXTRADATA, true, true); 2009 #endif 2010 2011 get_buffer_req_swvdec(); 2012 DEBUG_PRINT_HIGH("Input Buffer Size %d Interm Buffer Size %d Output Buffer Size =%d", 2013 drv_ctx.ip_buf.buffer_size, drv_ctx.interm_op_buf.buffer_size, 2014 drv_ctx.op_buf.buffer_size); 2015 2016 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size; 2017 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size); 2018 h264_scratch.nFilledLen = 0; 2019 h264_scratch.nOffset = 0; 2020 2021 if (h264_scratch.pBuffer == NULL) 2022 { 2023 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed "); 2024 return OMX_ErrorInsufficientResources; 2025 } 2026 2027 if(pipe(fds)) 2028 { 2029 DEBUG_PRINT_ERROR("pipe creation failed"); 2030 eRet = OMX_ErrorInsufficientResources; 2031 } 2032 else 2033 { 2034 if(fds[0] == 0 || fds[1] == 0) 2035 { 2036 if (pipe (fds)) 2037 { 2038 DEBUG_PRINT_ERROR("pipe creation failed"); 2039 return OMX_ErrorInsufficientResources; 2040 } 2041 } 2042 m_pipe_in = fds[0]; 2043 m_pipe_out = fds[1]; 2044 r = pthread_create(&msg_thread_id,0,message_thread,this); 2045 2046 if(r < 0) 2047 { 2048 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed"); 2049 return OMX_ErrorInsufficientResources; 2050 } 2051 msg_thread_created = true; 2052 } 2053 2054 if (eRet != OMX_ErrorNone && ( (!m_pSwVdec) || (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) )) 2055 { 2056 DEBUG_PRINT_ERROR("Component Init Failed eRet %d m_pSwVdec %p m_swvdec_mode %d", eRet, m_pSwVdec, m_swvdec_mode); 2057 } 2058 else 2059 { 2060 DEBUG_PRINT_HIGH("omx_vdec::component_init() success"); 2061 } 2062 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); 2063 return eRet; 2064 } 2065 2066 /* ====================================================================== 2067 FUNCTION 2068 omx_vdec::GetComponentVersion 2069 2070 DESCRIPTION 2071 Returns the component version. 2072 2073 PARAMETERS 2074 TBD. 2075 2076 RETURN VALUE 2077 OMX_ErrorNone. 2078 2079 ========================================================================== */ 2080 OMX_ERRORTYPE omx_vdec::get_component_version( 2081 OMX_IN OMX_HANDLETYPE hComp, 2082 OMX_OUT OMX_STRING componentName, 2083 OMX_OUT OMX_VERSIONTYPE* componentVersion, 2084 OMX_OUT OMX_VERSIONTYPE* specVersion, 2085 OMX_OUT OMX_UUIDTYPE* componentUUID 2086 ) 2087 { 2088 if(m_state == OMX_StateInvalid) 2089 { 2090 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State"); 2091 return OMX_ErrorInvalidState; 2092 } 2093 /* TBD -- Return the proper version */ 2094 if (specVersion) 2095 { 2096 specVersion->nVersion = OMX_SPEC_VERSION; 2097 } 2098 return OMX_ErrorNone; 2099 } 2100 /* ====================================================================== 2101 FUNCTION 2102 omx_vdec::SendCommand 2103 2104 DESCRIPTION 2105 Returns zero if all the buffers released.. 2106 2107 PARAMETERS 2108 None. 2109 2110 RETURN VALUE 2111 true/false 2112 2113 ========================================================================== */ 2114 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, 2115 OMX_IN OMX_COMMANDTYPE cmd, 2116 OMX_IN OMX_U32 param1, 2117 OMX_IN OMX_PTR cmdData 2118 ) 2119 { 2120 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client"); 2121 if(m_state == OMX_StateInvalid) 2122 { 2123 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State"); 2124 return OMX_ErrorInvalidState; 2125 } 2126 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX 2127 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) 2128 { 2129 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush " 2130 "to invalid port: %lu", param1); 2131 return OMX_ErrorBadPortIndex; 2132 } 2133 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); 2134 sem_wait(&m_cmd_lock); 2135 DEBUG_PRINT_LOW("send_command: Command Processed"); 2136 return OMX_ErrorNone; 2137 } 2138 2139 /* ====================================================================== 2140 FUNCTION 2141 omx_vdec::SendCommand 2142 2143 DESCRIPTION 2144 Returns zero if all the buffers released.. 2145 2146 PARAMETERS 2147 None. 2148 2149 RETURN VALUE 2150 true/false 2151 2152 ========================================================================== */ 2153 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, 2154 OMX_IN OMX_COMMANDTYPE cmd, 2155 OMX_IN OMX_U32 param1, 2156 OMX_IN OMX_PTR cmdData 2157 ) 2158 { 2159 OMX_ERRORTYPE eRet = OMX_ErrorNone; 2160 OMX_STATETYPE eState = (OMX_STATETYPE) param1; 2161 int bFlag = 1,sem_posted = 0,ret=0; 2162 2163 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd); 2164 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d", 2165 m_state, eState); 2166 2167 if(cmd == OMX_CommandStateSet) 2168 { 2169 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued"); 2170 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState); 2171 /***************************/ 2172 /* Current State is Loaded */ 2173 /***************************/ 2174 if(m_state == OMX_StateLoaded) 2175 { 2176 if(eState == OMX_StateIdle) 2177 { 2178 //if all buffers are allocated or all ports disabled 2179 if(allocate_done() || 2180 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) 2181 { 2182 if (m_pSwVdec && SWVDEC_S_SUCCESS != SwVdec_Start(m_pSwVdec)) 2183 { 2184 DEBUG_PRINT_ERROR("SWVDEC failed to start in allocate_done"); 2185 return OMX_ErrorInvalidState; 2186 } 2187 DEBUG_PRINT_LOW("SwVdec start successful: send_command_proxy(): Loaded-->Idle"); 2188 } 2189 else 2190 { 2191 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending"); 2192 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); 2193 // Skip the event notification 2194 bFlag = 0; 2195 } 2196 } 2197 /* Requesting transition from Loaded to Loaded */ 2198 else if(eState == OMX_StateLoaded) 2199 { 2200 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded"); 2201 post_event(OMX_EventError,OMX_ErrorSameState,\ 2202 OMX_COMPONENT_GENERATE_EVENT); 2203 eRet = OMX_ErrorSameState; 2204 } 2205 /* Requesting transition from Loaded to WaitForResources */ 2206 else if(eState == OMX_StateWaitForResources) 2207 { 2208 /* Since error is None , we will post an event 2209 at the end of this function definition */ 2210 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources"); 2211 } 2212 /* Requesting transition from Loaded to Executing */ 2213 else if(eState == OMX_StateExecuting) 2214 { 2215 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing"); 2216 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2217 OMX_COMPONENT_GENERATE_EVENT); 2218 eRet = OMX_ErrorIncorrectStateTransition; 2219 } 2220 /* Requesting transition from Loaded to Pause */ 2221 else if(eState == OMX_StatePause) 2222 { 2223 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause"); 2224 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2225 OMX_COMPONENT_GENERATE_EVENT); 2226 eRet = OMX_ErrorIncorrectStateTransition; 2227 } 2228 /* Requesting transition from Loaded to Invalid */ 2229 else if(eState == OMX_StateInvalid) 2230 { 2231 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid"); 2232 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2233 eRet = OMX_ErrorInvalidState; 2234 } 2235 else 2236 { 2237 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\ 2238 eState); 2239 eRet = OMX_ErrorBadParameter; 2240 } 2241 } 2242 2243 /***************************/ 2244 /* Current State is IDLE */ 2245 /***************************/ 2246 else if(m_state == OMX_StateIdle) 2247 { 2248 if(eState == OMX_StateLoaded) 2249 { 2250 if(release_done()) 2251 { 2252 /* 2253 Since error is None , we will post an event at the end 2254 of this function definition 2255 */ 2256 if (m_pSwVdec) 2257 { 2258 SwVdec_Stop(m_pSwVdec); 2259 } 2260 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded"); 2261 } 2262 else 2263 { 2264 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending"); 2265 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); 2266 // Skip the event notification 2267 bFlag = 0; 2268 } 2269 } 2270 /* Requesting transition from Idle to Executing */ 2271 else if(eState == OMX_StateExecuting) 2272 { 2273 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2274 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); 2275 bFlag = 1; 2276 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2277 m_state=OMX_StateExecuting; 2278 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 2279 { 2280 fill_all_buffers_proxy_dsp(hComp); 2281 } 2282 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful"); 2283 } 2284 /* Requesting transition from Idle to Idle */ 2285 else if(eState == OMX_StateIdle) 2286 { 2287 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle"); 2288 post_event(OMX_EventError,OMX_ErrorSameState,\ 2289 OMX_COMPONENT_GENERATE_EVENT); 2290 eRet = OMX_ErrorSameState; 2291 } 2292 /* Requesting transition from Idle to WaitForResources */ 2293 else if(eState == OMX_StateWaitForResources) 2294 { 2295 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources"); 2296 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2297 OMX_COMPONENT_GENERATE_EVENT); 2298 eRet = OMX_ErrorIncorrectStateTransition; 2299 } 2300 /* Requesting transition from Idle to Pause */ 2301 else if(eState == OMX_StatePause) 2302 { 2303 /*To pause the Video core we need to start the driver*/ 2304 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, 2305 NULL) < */0) 2306 { 2307 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED"); 2308 omx_report_error (); 2309 eRet = OMX_ErrorHardware; 2310 } 2311 else 2312 { 2313 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); 2314 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause"); 2315 bFlag = 0; 2316 } 2317 } 2318 /* Requesting transition from Idle to Invalid */ 2319 else if(eState == OMX_StateInvalid) 2320 { 2321 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid"); 2322 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2323 eRet = OMX_ErrorInvalidState; 2324 } 2325 else 2326 { 2327 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState); 2328 eRet = OMX_ErrorBadParameter; 2329 } 2330 } 2331 2332 /******************************/ 2333 /* Current State is Executing */ 2334 /******************************/ 2335 else if(m_state == OMX_StateExecuting) 2336 { 2337 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting"); 2338 /* Requesting transition from Executing to Idle */ 2339 if(eState == OMX_StateIdle) 2340 { 2341 /* Since error is None , we will post an event 2342 at the end of this function definition 2343 */ 2344 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle"); 2345 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 2346 if(!sem_posted) 2347 { 2348 sem_posted = 1; 2349 sem_post (&m_cmd_lock); 2350 execute_omx_flush(OMX_ALL); 2351 } 2352 bFlag = 0; 2353 } 2354 /* Requesting transition from Executing to Paused */ 2355 else if(eState == OMX_StatePause) 2356 { 2357 DEBUG_PRINT_LOW("PAUSE Command Issued"); 2358 m_state = OMX_StatePause; 2359 bFlag = 1; 2360 } 2361 /* Requesting transition from Executing to Loaded */ 2362 else if(eState == OMX_StateLoaded) 2363 { 2364 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded"); 2365 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2366 OMX_COMPONENT_GENERATE_EVENT); 2367 eRet = OMX_ErrorIncorrectStateTransition; 2368 } 2369 /* Requesting transition from Executing to WaitForResources */ 2370 else if(eState == OMX_StateWaitForResources) 2371 { 2372 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources"); 2373 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2374 OMX_COMPONENT_GENERATE_EVENT); 2375 eRet = OMX_ErrorIncorrectStateTransition; 2376 } 2377 /* Requesting transition from Executing to Executing */ 2378 else if(eState == OMX_StateExecuting) 2379 { 2380 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing"); 2381 post_event(OMX_EventError,OMX_ErrorSameState,\ 2382 OMX_COMPONENT_GENERATE_EVENT); 2383 eRet = OMX_ErrorSameState; 2384 } 2385 /* Requesting transition from Executing to Invalid */ 2386 else if(eState == OMX_StateInvalid) 2387 { 2388 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid"); 2389 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2390 eRet = OMX_ErrorInvalidState; 2391 } 2392 else 2393 { 2394 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState); 2395 eRet = OMX_ErrorBadParameter; 2396 } 2397 } 2398 /***************************/ 2399 /* Current State is Pause */ 2400 /***************************/ 2401 else if(m_state == OMX_StatePause) 2402 { 2403 /* Requesting transition from Pause to Executing */ 2404 if(eState == OMX_StateExecuting) 2405 { 2406 DEBUG_PRINT_LOW("Pause --> Executing"); 2407 m_state = OMX_StateExecuting; 2408 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 2409 { 2410 fill_all_buffers_proxy_dsp(hComp); 2411 } 2412 bFlag = 1; 2413 } 2414 /* Requesting transition from Pause to Idle */ 2415 else if(eState == OMX_StateIdle) 2416 { 2417 /* Since error is None , we will post an event 2418 at the end of this function definition */ 2419 DEBUG_PRINT_LOW("Pause --> Idle"); 2420 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 2421 if(!sem_posted) 2422 { 2423 sem_posted = 1; 2424 sem_post (&m_cmd_lock); 2425 execute_omx_flush(OMX_ALL); 2426 } 2427 bFlag = 0; 2428 } 2429 /* Requesting transition from Pause to loaded */ 2430 else if(eState == OMX_StateLoaded) 2431 { 2432 DEBUG_PRINT_ERROR("Pause --> loaded"); 2433 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2434 OMX_COMPONENT_GENERATE_EVENT); 2435 eRet = OMX_ErrorIncorrectStateTransition; 2436 } 2437 /* Requesting transition from Pause to WaitForResources */ 2438 else if(eState == OMX_StateWaitForResources) 2439 { 2440 DEBUG_PRINT_ERROR("Pause --> WaitForResources"); 2441 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2442 OMX_COMPONENT_GENERATE_EVENT); 2443 eRet = OMX_ErrorIncorrectStateTransition; 2444 } 2445 /* Requesting transition from Pause to Pause */ 2446 else if(eState == OMX_StatePause) 2447 { 2448 DEBUG_PRINT_ERROR("Pause --> Pause"); 2449 post_event(OMX_EventError,OMX_ErrorSameState,\ 2450 OMX_COMPONENT_GENERATE_EVENT); 2451 eRet = OMX_ErrorSameState; 2452 } 2453 /* Requesting transition from Pause to Invalid */ 2454 else if(eState == OMX_StateInvalid) 2455 { 2456 DEBUG_PRINT_ERROR("Pause --> Invalid"); 2457 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2458 eRet = OMX_ErrorInvalidState; 2459 } 2460 else 2461 { 2462 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState); 2463 eRet = OMX_ErrorBadParameter; 2464 } 2465 } 2466 /***************************/ 2467 /* Current State is WaitForResources */ 2468 /***************************/ 2469 else if(m_state == OMX_StateWaitForResources) 2470 { 2471 /* Requesting transition from WaitForResources to Loaded */ 2472 if(eState == OMX_StateLoaded) 2473 { 2474 /* Since error is None , we will post an event 2475 at the end of this function definition */ 2476 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded"); 2477 } 2478 /* Requesting transition from WaitForResources to WaitForResources */ 2479 else if (eState == OMX_StateWaitForResources) 2480 { 2481 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources"); 2482 post_event(OMX_EventError,OMX_ErrorSameState, 2483 OMX_COMPONENT_GENERATE_EVENT); 2484 eRet = OMX_ErrorSameState; 2485 } 2486 /* Requesting transition from WaitForResources to Executing */ 2487 else if(eState == OMX_StateExecuting) 2488 { 2489 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing"); 2490 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2491 OMX_COMPONENT_GENERATE_EVENT); 2492 eRet = OMX_ErrorIncorrectStateTransition; 2493 } 2494 /* Requesting transition from WaitForResources to Pause */ 2495 else if(eState == OMX_StatePause) 2496 { 2497 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause"); 2498 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2499 OMX_COMPONENT_GENERATE_EVENT); 2500 eRet = OMX_ErrorIncorrectStateTransition; 2501 } 2502 /* Requesting transition from WaitForResources to Invalid */ 2503 else if(eState == OMX_StateInvalid) 2504 { 2505 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid"); 2506 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2507 eRet = OMX_ErrorInvalidState; 2508 } 2509 /* Requesting transition from WaitForResources to Loaded - 2510 is NOT tested by Khronos TS */ 2511 2512 } 2513 else 2514 { 2515 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState); 2516 eRet = OMX_ErrorBadParameter; 2517 } 2518 } 2519 /********************************/ 2520 /* Current State is Invalid */ 2521 /*******************************/ 2522 else if(m_state == OMX_StateInvalid) 2523 { 2524 /* State Transition from Inavlid to any state */ 2525 if(eState == (OMX_StateLoaded || OMX_StateWaitForResources 2526 || OMX_StateIdle || OMX_StateExecuting 2527 || OMX_StatePause || OMX_StateInvalid)) 2528 { 2529 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded"); 2530 post_event(OMX_EventError,OMX_ErrorInvalidState,\ 2531 OMX_COMPONENT_GENERATE_EVENT); 2532 eRet = OMX_ErrorInvalidState; 2533 } 2534 } 2535 else if (cmd == OMX_CommandFlush) 2536 { 2537 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued" 2538 "with param1: %lu", param1); 2539 if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) 2540 { 2541 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); 2542 } 2543 if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) 2544 { 2545 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 2546 } 2547 if (!sem_posted){ 2548 sem_posted = 1; 2549 DEBUG_PRINT_LOW("Set the Semaphore"); 2550 sem_post (&m_cmd_lock); 2551 execute_omx_flush(param1); 2552 } 2553 bFlag = 0; 2554 } 2555 else if ( cmd == OMX_CommandPortEnable) 2556 { 2557 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued" 2558 "with param1: %lu", param1); 2559 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) 2560 { 2561 m_inp_bEnabled = OMX_TRUE; 2562 2563 if( (m_state == OMX_StateLoaded && 2564 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 2565 || allocate_input_done()) 2566 { 2567 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, 2568 OMX_COMPONENT_GENERATE_EVENT); 2569 } 2570 else 2571 { 2572 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 2573 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); 2574 // Skip the event notification 2575 bFlag = 0; 2576 } 2577 } 2578 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) 2579 { 2580 DEBUG_PRINT_LOW("Enable output Port command recieved"); 2581 m_out_bEnabled = OMX_TRUE; 2582 if( (m_state == OMX_StateLoaded && 2583 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 2584 || (allocate_output_done())) 2585 { 2586 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, 2587 OMX_COMPONENT_GENERATE_EVENT); 2588 } 2589 else 2590 { 2591 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 2592 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 2593 // Skip the event notification 2594 bFlag = 0; 2595 } 2596 } 2597 } 2598 else if (cmd == OMX_CommandPortDisable) 2599 { 2600 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued" 2601 "with param1: %lu", param1); 2602 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) 2603 { 2604 m_inp_bEnabled = OMX_FALSE; 2605 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 2606 && release_input_done()) 2607 { 2608 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, 2609 OMX_COMPONENT_GENERATE_EVENT); 2610 } 2611 else 2612 { 2613 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); 2614 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) 2615 { 2616 if(!sem_posted) 2617 { 2618 sem_posted = 1; 2619 sem_post (&m_cmd_lock); 2620 } 2621 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); 2622 } 2623 2624 // Skip the event notification 2625 bFlag = 0; 2626 } 2627 } 2628 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) 2629 { 2630 m_out_bEnabled = OMX_FALSE; 2631 DEBUG_PRINT_LOW("Disable output Port command recieved"); 2632 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 2633 && release_output_done()) 2634 { 2635 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ 2636 OMX_COMPONENT_GENERATE_EVENT); 2637 } 2638 else 2639 { 2640 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 2641 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) 2642 { 2643 if (!sem_posted) 2644 { 2645 sem_posted = 1; 2646 sem_post (&m_cmd_lock); 2647 } 2648 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 2649 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); 2650 } 2651 // Skip the event notification 2652 bFlag = 0; 2653 2654 } 2655 } 2656 } 2657 else 2658 { 2659 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd); 2660 eRet = OMX_ErrorNotImplemented; 2661 } 2662 if(eRet == OMX_ErrorNone && bFlag) 2663 { 2664 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); 2665 } 2666 if(!sem_posted) 2667 { 2668 sem_post(&m_cmd_lock); 2669 } 2670 2671 return eRet; 2672 } 2673 2674 /* ====================================================================== 2675 FUNCTION 2676 omx_vdec::ExecuteOmxFlush 2677 2678 DESCRIPTION 2679 Executes the OMX flush. 2680 2681 PARAMETERS 2682 flushtype - input flush(1)/output flush(0)/ both. 2683 2684 RETURN VALUE 2685 true/false 2686 2687 ========================================================================== */ 2688 bool omx_vdec::execute_omx_flush(OMX_U32 flushType) 2689 { 2690 bool bRet = false; 2691 struct v4l2_plane plane; 2692 struct v4l2_buffer v4l2_buf; 2693 struct v4l2_decoder_cmd dec; 2694 DEBUG_PRINT_LOW("in %s flushType %d", __func__, (int)flushType); 2695 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 2696 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH; 2697 switch (flushType) 2698 { 2699 case OMX_CORE_INPUT_PORT_INDEX: 2700 input_flush_progress = true; 2701 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT; 2702 break; 2703 case OMX_CORE_OUTPUT_PORT_INDEX: 2704 output_flush_progress = true; 2705 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 2706 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 2707 { 2708 m_interm_flush_swvdec_progress = true; 2709 m_interm_flush_dsp_progress = true; 2710 } 2711 break; 2712 default: 2713 input_flush_progress = true; 2714 output_flush_progress = true; 2715 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 2716 { 2717 m_interm_flush_swvdec_progress = true; 2718 m_interm_flush_dsp_progress = true; 2719 } 2720 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | 2721 V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 2722 } 2723 2724 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 2725 { 2726 DEBUG_PRINT_LOW("flush dsp %d %d %d", dec.flags, V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT, V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE); 2727 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) 2728 { 2729 DEBUG_PRINT_ERROR("Flush dsp Failed "); 2730 bRet = false; 2731 } 2732 } 2733 if (flushType == OMX_CORE_INPUT_PORT_INDEX) 2734 { 2735 // no input flush independently, wait for output flush 2736 return bRet; 2737 } 2738 if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 2739 { 2740 // for hybrid mode, swvdec flush will hapeen when dsp flush done is received 2741 SWVDEC_BUFFER_FLUSH_TYPE aFlushType = SWVDEC_FLUSH_OUTPUT; 2742 if (m_interm_flush_swvdec_progress || input_flush_progress) 2743 { 2744 aFlushType = SWVDEC_FLUSH_ALL; 2745 } 2746 DEBUG_PRINT_HIGH("Flush swvdec type %d", aFlushType); 2747 if (SwVdec_Flush(m_pSwVdec, aFlushType) != SWVDEC_S_SUCCESS) 2748 { 2749 DEBUG_PRINT_ERROR("Flush swvdec Failed "); 2750 } 2751 DEBUG_PRINT_LOW("Flush swvdec type %d successful", aFlushType); 2752 } 2753 return bRet; 2754 } 2755 /*========================================================================= 2756 FUNCTION : execute_output_flush 2757 2758 DESCRIPTION 2759 Executes the OMX flush at OUTPUT PORT. 2760 2761 PARAMETERS 2762 None. 2763 2764 RETURN VALUE 2765 true/false 2766 ==========================================================================*/ 2767 bool omx_vdec::execute_output_flush() 2768 { 2769 unsigned p1 = 0; // Parameter - 1 2770 unsigned p2 = 0; // Parameter - 2 2771 unsigned ident = 0; 2772 bool bRet = true; 2773 2774 /*Generate FBD for all Buffers in the FTBq*/ 2775 pthread_mutex_lock(&m_lock); 2776 DEBUG_PRINT_LOW("Initiate Output Flush"); 2777 while (m_ftb_q.m_size) 2778 { 2779 DEBUG_PRINT_LOW("Buffer queue size %d pending buf cnt %d", 2780 m_ftb_q.m_size,pending_output_buffers); 2781 m_ftb_q.pop_entry(&p1,&p2,&ident); 2782 DEBUG_PRINT_LOW("ID(%x) P1(%x) P2(%x)", ident, p1, p2); 2783 if(ident == m_fill_output_msg ) 2784 { 2785 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 2786 } 2787 else if (ident == OMX_COMPONENT_GENERATE_FBD) 2788 { 2789 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 2790 } 2791 } 2792 pthread_mutex_unlock(&m_lock); 2793 output_flush_progress = false; 2794 2795 if (arbitrary_bytes) 2796 { 2797 prev_ts = LLONG_MAX; 2798 rst_prev_ts = true; 2799 } 2800 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); 2801 return bRet; 2802 } 2803 /*========================================================================= 2804 FUNCTION : execute_input_flush 2805 2806 DESCRIPTION 2807 Executes the OMX flush at INPUT PORT. 2808 2809 PARAMETERS 2810 None. 2811 2812 RETURN VALUE 2813 true/false 2814 ==========================================================================*/ 2815 bool omx_vdec::execute_input_flush() 2816 { 2817 unsigned i =0; 2818 unsigned p1 = 0; // Parameter - 1 2819 unsigned p2 = 0; // Parameter - 2 2820 unsigned ident = 0; 2821 bool bRet = true; 2822 2823 /*Generate EBD for all Buffers in the ETBq*/ 2824 DEBUG_PRINT_LOW("Initiate Input Flush"); 2825 2826 pthread_mutex_lock(&m_lock); 2827 DEBUG_PRINT_LOW("Check if the Queue is empty"); 2828 while (m_etb_q.m_size) 2829 { 2830 m_etb_q.pop_entry(&p1,&p2,&ident); 2831 2832 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) 2833 { 2834 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 2835 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 2836 } 2837 else if(ident == OMX_COMPONENT_GENERATE_ETB) 2838 { 2839 pending_input_buffers++; 2840 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 2841 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 2842 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 2843 } 2844 else if (ident == OMX_COMPONENT_GENERATE_EBD) 2845 { 2846 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p", 2847 (OMX_BUFFERHEADERTYPE *)p1); 2848 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 2849 } 2850 } 2851 time_stamp_dts.flush_timestamp(); 2852 /*Check if Heap Buffers are to be flushed*/ 2853 if (arbitrary_bytes && !(codec_config_flag)) 2854 { 2855 DEBUG_PRINT_LOW("Reset all the variables before flusing"); 2856 h264_scratch.nFilledLen = 0; 2857 nal_count = 0; 2858 look_ahead_nal = false; 2859 frame_count = 0; 2860 h264_last_au_ts = LLONG_MAX; 2861 h264_last_au_flags = 0; 2862 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 2863 m_demux_entries = 0; 2864 DEBUG_PRINT_LOW("Initialize parser"); 2865 if (m_frame_parser.mutils) 2866 { 2867 m_frame_parser.mutils->initialize_frame_checking_environment(); 2868 } 2869 2870 while (m_input_pending_q.m_size) 2871 { 2872 m_input_pending_q.pop_entry(&p1,&p2,&ident); 2873 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); 2874 } 2875 2876 if (psource_frame) 2877 { 2878 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); 2879 psource_frame = NULL; 2880 } 2881 2882 if (pdest_frame) 2883 { 2884 pdest_frame->nFilledLen = 0; 2885 m_input_free_q.insert_entry((unsigned) pdest_frame, (unsigned int)NULL, 2886 (unsigned int)NULL); 2887 pdest_frame = NULL; 2888 } 2889 m_frame_parser.flush(); 2890 } 2891 else if (codec_config_flag) 2892 { 2893 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer " 2894 "is not sent to the driver yet"); 2895 } 2896 pthread_mutex_unlock(&m_lock); 2897 input_flush_progress = false; 2898 if (!arbitrary_bytes) 2899 { 2900 prev_ts = LLONG_MAX; 2901 rst_prev_ts = true; 2902 } 2903 #ifdef _ANDROID_ 2904 if (m_debug_timestamp) 2905 { 2906 m_timestamp_list.reset_ts_list(); 2907 } 2908 #endif 2909 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); 2910 return bRet; 2911 } 2912 2913 2914 /* ====================================================================== 2915 FUNCTION 2916 omx_vdec::SendCommandEvent 2917 2918 DESCRIPTION 2919 Send the event to decoder pipe. This is needed to generate the callbacks 2920 in decoder thread context. 2921 2922 PARAMETERS 2923 None. 2924 2925 RETURN VALUE 2926 true/false 2927 2928 ========================================================================== */ 2929 bool omx_vdec::post_event(unsigned int p1, 2930 unsigned int p2, 2931 unsigned int id) 2932 { 2933 bool bRet = false; 2934 OMX_BUFFERHEADERTYPE* bufHdr = NULL; 2935 2936 pthread_mutex_lock(&m_lock); 2937 2938 if (id == OMX_COMPONENT_GENERATE_FTB || 2939 id == OMX_COMPONENT_GENERATE_FBD) 2940 { 2941 m_ftb_q.insert_entry(p1,p2,id); 2942 } 2943 else if (id == OMX_COMPONENT_GENERATE_ETB || 2944 id == OMX_COMPONENT_GENERATE_EBD || 2945 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) 2946 { 2947 m_etb_q.insert_entry(p1,p2,id); 2948 } 2949 else if (id == OMX_COMPONENT_GENERATE_FTB_DSP) 2950 { 2951 bufHdr = (OMX_BUFFERHEADERTYPE*)p2; 2952 m_ftb_q_dsp.insert_entry(p1,p2,id); 2953 } 2954 else if (id == OMX_COMPONENT_GENERATE_ETB_SWVDEC) 2955 { 2956 bufHdr = (OMX_BUFFERHEADERTYPE*)p2; 2957 m_etb_q_swvdec.insert_entry(p1,p2,id); 2958 } 2959 else if (id == OMX_COMPONENT_GENERATE_FBD_DSP) 2960 { 2961 bufHdr = (OMX_BUFFERHEADERTYPE*)p1; 2962 m_ftb_q_dsp.insert_entry(p1,p2,id); 2963 } 2964 else if (id == OMX_COMPONENT_GENERATE_EBD_SWVDEC) 2965 { 2966 bufHdr = (OMX_BUFFERHEADERTYPE*)p1; 2967 m_etb_q_swvdec.insert_entry(p1,p2,id); 2968 } 2969 else 2970 { 2971 m_cmd_q.insert_entry(p1,p2,id); 2972 } 2973 2974 bRet = true; 2975 post_message(this, id); 2976 pthread_mutex_unlock(&m_lock); 2977 2978 return bRet; 2979 } 2980 2981 OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) 2982 { 2983 OMX_ERRORTYPE eRet = OMX_ErrorNoMore; 2984 if(!profileLevelType) 2985 return OMX_ErrorBadParameter; 2986 2987 if(profileLevelType->nPortIndex == 0) { 2988 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid",OMX_MAX_STRINGNAME_SIZE) || 2989 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevcswvdec",OMX_MAX_STRINGNAME_SIZE) || 2990 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE) ) 2991 { 2992 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", 2993 (int)profileLevelType->nProfileIndex); 2994 eRet = OMX_ErrorNoMore; 2995 } 2996 else 2997 { 2998 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex); 2999 eRet = OMX_ErrorNoMore; 3000 } 3001 } 3002 else 3003 { 3004 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %lu", profileLevelType->nPortIndex); 3005 eRet = OMX_ErrorBadPortIndex; 3006 } 3007 return eRet; 3008 } 3009 3010 /* ====================================================================== 3011 FUNCTION 3012 omx_vdec::GetParameter 3013 3014 DESCRIPTION 3015 OMX Get Parameter method implementation 3016 3017 PARAMETERS 3018 <TBD>. 3019 3020 RETURN VALUE 3021 Error None if successful. 3022 3023 ========================================================================== */ 3024 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, 3025 OMX_IN OMX_INDEXTYPE paramIndex, 3026 OMX_INOUT OMX_PTR paramData) 3027 { 3028 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3029 3030 DEBUG_PRINT_LOW("get_parameter:"); 3031 if(m_state == OMX_StateInvalid) 3032 { 3033 DEBUG_PRINT_ERROR("Get Param in Invalid State"); 3034 return OMX_ErrorInvalidState; 3035 } 3036 if(paramData == NULL) 3037 { 3038 DEBUG_PRINT_LOW("Get Param in Invalid paramData"); 3039 return OMX_ErrorBadParameter; 3040 } 3041 switch((unsigned long)paramIndex) 3042 { 3043 case OMX_IndexParamPortDefinition: 3044 { 3045 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = 3046 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3047 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); 3048 eRet = update_portdef(portDefn); 3049 if (eRet == OMX_ErrorNone) 3050 m_port_def = *portDefn; 3051 break; 3052 } 3053 case OMX_IndexParamVideoInit: 3054 { 3055 OMX_PORT_PARAM_TYPE *portParamType = 3056 (OMX_PORT_PARAM_TYPE *) paramData; 3057 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); 3058 3059 portParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3060 portParamType->nSize = sizeof(portParamType); 3061 portParamType->nPorts = 2; 3062 portParamType->nStartPortNumber = 0; 3063 break; 3064 } 3065 case OMX_IndexParamVideoPortFormat: 3066 { 3067 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3068 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3069 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); 3070 3071 portFmt->nVersion.nVersion = OMX_SPEC_VERSION; 3072 portFmt->nSize = sizeof(portFmt); 3073 3074 if (0 == portFmt->nPortIndex) 3075 { 3076 if (0 == portFmt->nIndex) 3077 { 3078 portFmt->eColorFormat = OMX_COLOR_FormatUnused; 3079 portFmt->eCompressionFormat = eCompressionFormat; 3080 } 3081 else 3082 { 3083 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3084 " NoMore compression formats"); 3085 eRet = OMX_ErrorNoMore; 3086 } 3087 } 3088 else if (1 == portFmt->nPortIndex) 3089 { 3090 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; 3091 3092 if(0 == portFmt->nIndex) 3093 portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE) 3094 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 3095 else if (1 == portFmt->nIndex) 3096 portFmt->eColorFormat = OMX_COLOR_FormatYUV420Planar; 3097 else 3098 { 3099 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3100 " NoMore Color formats"); 3101 eRet = OMX_ErrorNoMore; 3102 } 3103 } 3104 else 3105 { 3106 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d", 3107 (int)portFmt->nPortIndex); 3108 eRet = OMX_ErrorBadPortIndex; 3109 } 3110 break; 3111 } 3112 /*Component should support this port definition*/ 3113 case OMX_IndexParamAudioInit: 3114 { 3115 OMX_PORT_PARAM_TYPE *audioPortParamType = 3116 (OMX_PORT_PARAM_TYPE *) paramData; 3117 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); 3118 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3119 audioPortParamType->nSize = sizeof(audioPortParamType); 3120 audioPortParamType->nPorts = 0; 3121 audioPortParamType->nStartPortNumber = 0; 3122 break; 3123 } 3124 /*Component should support this port definition*/ 3125 case OMX_IndexParamImageInit: 3126 { 3127 OMX_PORT_PARAM_TYPE *imagePortParamType = 3128 (OMX_PORT_PARAM_TYPE *) paramData; 3129 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); 3130 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3131 imagePortParamType->nSize = sizeof(imagePortParamType); 3132 imagePortParamType->nPorts = 0; 3133 imagePortParamType->nStartPortNumber = 0; 3134 break; 3135 3136 } 3137 /*Component should support this port definition*/ 3138 case OMX_IndexParamOtherInit: 3139 { 3140 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x", 3141 paramIndex); 3142 eRet =OMX_ErrorUnsupportedIndex; 3143 break; 3144 } 3145 case OMX_IndexParamStandardComponentRole: 3146 { 3147 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3148 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3149 comp_role->nVersion.nVersion = OMX_SPEC_VERSION; 3150 comp_role->nSize = sizeof(*comp_role); 3151 3152 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d", 3153 paramIndex); 3154 strlcpy((char*)comp_role->cRole,(const char*)m_cRole, 3155 OMX_MAX_STRINGNAME_SIZE); 3156 break; 3157 } 3158 /* Added for parameter test */ 3159 case OMX_IndexParamPriorityMgmt: 3160 { 3161 3162 OMX_PRIORITYMGMTTYPE *priorityMgmType = 3163 (OMX_PRIORITYMGMTTYPE *) paramData; 3164 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); 3165 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; 3166 priorityMgmType->nSize = sizeof(priorityMgmType); 3167 3168 break; 3169 } 3170 /* Added for parameter test */ 3171 case OMX_IndexParamCompBufferSupplier: 3172 { 3173 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = 3174 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3175 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); 3176 3177 bufferSupplierType->nSize = sizeof(bufferSupplierType); 3178 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; 3179 if(0 == bufferSupplierType->nPortIndex) 3180 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3181 else if (1 == bufferSupplierType->nPortIndex) 3182 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3183 else 3184 eRet = OMX_ErrorBadPortIndex; 3185 3186 3187 break; 3188 } 3189 case OMX_IndexParamVideoAvc: 3190 { 3191 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x", 3192 paramIndex); 3193 break; 3194 } 3195 case OMX_IndexParamVideoH263: 3196 { 3197 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x", 3198 paramIndex); 3199 break; 3200 } 3201 case OMX_IndexParamVideoMpeg4: 3202 { 3203 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x", 3204 paramIndex); 3205 break; 3206 } 3207 case OMX_IndexParamVideoMpeg2: 3208 { 3209 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x", 3210 paramIndex); 3211 break; 3212 } 3213 case OMX_IndexParamVideoProfileLevelQuerySupported: 3214 { 3215 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex); 3216 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = 3217 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; 3218 eRet = get_supported_profile_level_for_1080p(profileLevelType); 3219 break; 3220 } 3221 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3222 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: 3223 { 3224 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); 3225 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; 3226 if(nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3227 3228 if(secure_mode) { 3229 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | 3230 GRALLOC_USAGE_PRIVATE_UNCACHED); 3231 } else { 3232 if (!m_pSwVdec) { 3233 #ifdef _HEVC_USE_ADSP_HEAP_ 3234 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); 3235 #else 3236 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); 3237 #endif 3238 } 3239 else { 3240 // for swvdec use cached buffer 3241 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage using output buffer cached"); 3242 // nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); 3243 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP); 3244 } 3245 DEBUG_PRINT_HIGH("nativeBuffersUsage->nUsage %x", (unsigned int)nativeBuffersUsage->nUsage); 3246 } 3247 } else { 3248 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!"); 3249 eRet = OMX_ErrorBadParameter; 3250 } 3251 } 3252 break; 3253 #endif 3254 3255 default: 3256 { 3257 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex); 3258 eRet =OMX_ErrorUnsupportedIndex; 3259 } 3260 3261 } 3262 3263 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)", 3264 drv_ctx.video_resolution.frame_width, 3265 drv_ctx.video_resolution.frame_height, 3266 drv_ctx.video_resolution.stride, 3267 drv_ctx.video_resolution.scan_lines); 3268 3269 return eRet; 3270 } 3271 3272 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3273 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) 3274 { 3275 DEBUG_PRINT_LOW("Inside use_android_native_buffer"); 3276 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3277 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; 3278 3279 if((params == NULL) || 3280 (params->nativeBuffer == NULL) || 3281 (params->nativeBuffer->handle == NULL) || 3282 !m_enable_android_native_buffers) 3283 return OMX_ErrorBadParameter; 3284 m_use_android_native_buffers = OMX_TRUE; 3285 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 3286 private_handle_t *handle = (private_handle_t *)nBuf->handle; 3287 if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port 3288 OMX_U8 *buffer = NULL; 3289 if(!secure_mode) { 3290 buffer = (OMX_U8*)mmap(0, handle->size, 3291 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 3292 if(buffer == MAP_FAILED) { 3293 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 3294 return OMX_ErrorInsufficientResources; 3295 } 3296 } 3297 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); 3298 } else { 3299 eRet = OMX_ErrorBadParameter; 3300 } 3301 return eRet; 3302 } 3303 #endif 3304 3305 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() { 3306 struct v4l2_control control; 3307 struct v4l2_format fmt; 3308 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER; 3309 control.value = 1; 3310 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 3311 if (rc < 0) { 3312 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); 3313 return OMX_ErrorHardware; 3314 } 3315 DEBUG_PRINT_LOW("Smooth Streaming enabled."); 3316 m_smoothstreaming_mode = true; 3317 return OMX_ErrorNone; 3318 } 3319 3320 3321 /* ====================================================================== 3322 FUNCTION 3323 omx_vdec::Setparameter 3324 3325 DESCRIPTION 3326 OMX Set Parameter method implementation. 3327 3328 PARAMETERS 3329 <TBD>. 3330 3331 RETURN VALUE 3332 OMX Error None if successful. 3333 3334 ========================================================================== */ 3335 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, 3336 OMX_IN OMX_INDEXTYPE paramIndex, 3337 OMX_IN OMX_PTR paramData) 3338 { 3339 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3340 int ret=0; 3341 struct v4l2_format fmt; 3342 if(m_state == OMX_StateInvalid) 3343 { 3344 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3345 return OMX_ErrorInvalidState; 3346 } 3347 if(paramData == NULL) 3348 { 3349 DEBUG_PRINT_ERROR("Get Param in Invalid paramData"); 3350 return OMX_ErrorBadParameter; 3351 } 3352 if((m_state != OMX_StateLoaded) && 3353 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && 3354 (m_out_bEnabled == OMX_TRUE) && 3355 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && 3356 (m_inp_bEnabled == OMX_TRUE)) { 3357 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3358 return OMX_ErrorIncorrectStateOperation; 3359 } 3360 switch((unsigned long)paramIndex) 3361 { 3362 case OMX_IndexParamPortDefinition: 3363 { 3364 OMX_PARAM_PORTDEFINITIONTYPE *portDefn; 3365 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3366 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has 3367 //been called. 3368 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", 3369 (int)portDefn->format.video.nFrameHeight, 3370 (int)portDefn->format.video.nFrameWidth); 3371 3372 // for pure dsp mode, if the dimension exceeds 720p, reject it 3373 // so that the stagefright can try the hybrid component 3374 if (!m_pSwVdec && 3375 (portDefn->format.video.nFrameHeight > 720 || 3376 portDefn->format.video.nFrameWidth > 1280)) 3377 { 3378 DEBUG_PRINT_ERROR("Full DSP mode only support up to 720p"); 3379 return OMX_ErrorBadParameter; 3380 } 3381 3382 if(OMX_DirOutput == portDefn->eDir) 3383 { 3384 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); 3385 m_display_id = portDefn->format.video.pNativeWindow; 3386 unsigned int buffer_size; 3387 if (!client_buffers.get_buffer_req(buffer_size)) { 3388 DEBUG_PRINT_ERROR("Error in getting buffer requirements"); 3389 eRet = OMX_ErrorBadParameter; 3390 } else { 3391 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && 3392 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) 3393 { 3394 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; 3395 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize; 3396 eRet = set_buffer_req_swvdec(&drv_ctx.op_buf); 3397 if (eRet == OMX_ErrorNone) 3398 m_port_def = *portDefn; 3399 } 3400 else 3401 { 3402 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%lu: %lu)", 3403 drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size, 3404 portDefn->nBufferCountActual, portDefn->nBufferSize); 3405 eRet = OMX_ErrorBadParameter; 3406 } 3407 } 3408 } 3409 else if(OMX_DirInput == portDefn->eDir) 3410 { 3411 bool port_format_changed = false; 3412 if((portDefn->format.video.xFramerate >> 16) > 0 && 3413 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) 3414 { 3415 // Frame rate only should be set if this is a "known value" or to 3416 // activate ts prediction logic (arbitrary mode only) sending input 3417 // timestamps with max value (LLONG_MAX). 3418 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %lu", 3419 portDefn->format.video.xFramerate >> 16); 3420 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, 3421 drv_ctx.frame_rate.fps_denominator); 3422 if(!drv_ctx.frame_rate.fps_numerator) 3423 { 3424 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 3425 drv_ctx.frame_rate.fps_numerator = 30; 3426 } 3427 if(drv_ctx.frame_rate.fps_denominator) 3428 drv_ctx.frame_rate.fps_numerator = (int) 3429 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 3430 drv_ctx.frame_rate.fps_denominator = 1; 3431 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 3432 drv_ctx.frame_rate.fps_numerator; 3433 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", 3434 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 3435 (float)drv_ctx.frame_rate.fps_denominator); 3436 } 3437 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port"); 3438 if(drv_ctx.video_resolution.frame_height != 3439 portDefn->format.video.nFrameHeight || 3440 drv_ctx.video_resolution.frame_width != 3441 portDefn->format.video.nFrameWidth) 3442 { 3443 DEBUG_PRINT_LOW("SetParam IP: WxH(%d x %d)", 3444 (int)portDefn->format.video.nFrameWidth, 3445 (int)portDefn->format.video.nFrameHeight); 3446 port_format_changed = true; 3447 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth; 3448 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight; 3449 if (frameHeight != 0x0 && frameWidth != 0x0) 3450 { 3451 if (m_smoothstreaming_mode && 3452 ((frameWidth * frameHeight) < 3453 (m_smoothstreaming_width * m_smoothstreaming_height))) { 3454 frameWidth = m_smoothstreaming_width; 3455 frameHeight = m_smoothstreaming_height; 3456 DEBUG_PRINT_LOW("NOTE: Setting resolution %lu x %lu for adaptive-playback/smooth-streaming", 3457 frameWidth, frameHeight); 3458 } 3459 update_resolution(frameWidth, frameHeight, 3460 frameWidth, frameHeight); 3461 3462 eRet = is_video_session_supported(); 3463 if (eRet) 3464 break; 3465 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 3466 { 3467 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 3468 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3469 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3470 fmt.fmt.pix_mp.pixelformat = output_capability; 3471 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", 3472 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); 3473 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3474 if (ret) 3475 { 3476 DEBUG_PRINT_ERROR("Set Resolution failed h %d w %d", fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width); 3477 eRet = OMX_ErrorUnsupportedSetting; 3478 break; 3479 } 3480 } 3481 if (m_pSwVdec) 3482 { 3483 SWVDEC_PROP prop; 3484 prop.ePropId = SWVDEC_PROP_ID_DIMENSIONS; 3485 prop.uProperty.sDimensions.nWidth = portDefn->format.video.nFrameWidth; 3486 prop.uProperty.sDimensions.nHeight= portDefn->format.video.nFrameHeight; 3487 SwVdec_SetProperty(m_pSwVdec,&prop); 3488 prop.ePropId = SWVDEC_PROP_ID_FRAME_ATTR; 3489 prop.uProperty.sFrameAttr.eColorFormat = SWVDEC_FORMAT_NV12; 3490 ret = SwVdec_SetProperty(m_pSwVdec,&prop); 3491 if (ret) { 3492 DEBUG_PRINT_ERROR("Failed to set color fmt to SwVdec in full SW"); 3493 return OMX_ErrorInsufficientResources; 3494 } 3495 } 3496 eRet = get_buffer_req_swvdec(); 3497 } 3498 } 3499 else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount 3500 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) 3501 { 3502 port_format_changed = true; 3503 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf; 3504 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; 3505 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) & 3506 (~(buffer_prop->alignment - 1)); 3507 DEBUG_PRINT_LOW("IP Requirements(#%d: %u) Requested(#%lu: %lu)", 3508 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size, 3509 portDefn->nBufferCountActual, portDefn->nBufferSize); 3510 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 3511 eRet = set_buffer_req(buffer_prop); 3512 } 3513 if (!port_format_changed) 3514 { 3515 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%lu: %lu)", 3516 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size, 3517 portDefn->nBufferCountActual, portDefn->nBufferSize); 3518 eRet = OMX_ErrorBadParameter; 3519 } 3520 } 3521 else if (portDefn->eDir == OMX_DirMax) 3522 { 3523 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", 3524 (int)portDefn->nPortIndex); 3525 eRet = OMX_ErrorBadPortIndex; 3526 } 3527 } 3528 break; 3529 case OMX_IndexParamVideoPortFormat: 3530 { 3531 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3532 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3533 int ret=0; 3534 struct v4l2_format fmt; 3535 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d", 3536 portFmt->eColorFormat); 3537 3538 if(1 == portFmt->nPortIndex) 3539 { 3540 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3541 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3542 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3543 fmt.fmt.pix_mp.pixelformat = capture_capability; 3544 enum vdec_output_fromat op_format; 3545 if((portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 3546 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) || 3547 (portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar)) 3548 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12; 3549 else if(portFmt->eColorFormat == 3550 (OMX_COLOR_FORMATTYPE) 3551 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka) 3552 op_format = VDEC_YUV_FORMAT_TILE_4x2; 3553 else 3554 eRet = OMX_ErrorBadParameter; 3555 3556 if(eRet == OMX_ErrorNone) 3557 { 3558 drv_ctx.output_format = op_format; 3559 if (!m_pSwVdec) 3560 { 3561 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3562 } 3563 else if ((m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) || 3564 (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY)) 3565 { 3566 SWVDEC_PROP prop; 3567 prop.ePropId = SWVDEC_PROP_ID_DIMENSIONS; 3568 prop.uProperty.sDimensions.nWidth = fmt.fmt.pix_mp.width; 3569 prop.uProperty.sDimensions.nHeight= fmt.fmt.pix_mp.height; 3570 SwVdec_SetProperty(m_pSwVdec,&prop); 3571 prop.ePropId = SWVDEC_PROP_ID_FRAME_ATTR; 3572 prop.uProperty.sFrameAttr.eColorFormat = SWVDEC_FORMAT_NV12; 3573 SwVdec_SetProperty(m_pSwVdec,&prop); 3574 } 3575 // need to set output format to swvdec 3576 if(ret) 3577 { 3578 DEBUG_PRINT_ERROR("Set output format failed"); 3579 eRet = OMX_ErrorUnsupportedSetting; 3580 /*TODO: How to handle this case */ 3581 } 3582 else 3583 { 3584 eRet = get_buffer_req_swvdec(); 3585 } 3586 } 3587 if (eRet == OMX_ErrorNone){ 3588 if (!client_buffers.set_color_format(portFmt->eColorFormat)) { 3589 DEBUG_PRINT_ERROR("Set color format failed"); 3590 eRet = OMX_ErrorBadParameter; 3591 } 3592 } 3593 } 3594 } 3595 break; 3596 3597 case OMX_QcomIndexPortDefn: 3598 { 3599 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = 3600 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; 3601 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d", 3602 (int)portFmt->nFramePackingFormat); 3603 3604 /* Input port */ 3605 if (portFmt->nPortIndex == 0) 3606 { 3607 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) 3608 { 3609 if(secure_mode) { 3610 arbitrary_bytes = false; 3611 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session"); 3612 eRet = OMX_ErrorUnsupportedSetting; 3613 } else { 3614 arbitrary_bytes = true; 3615 } 3616 } 3617 else if (portFmt->nFramePackingFormat == 3618 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) 3619 { 3620 arbitrary_bytes = false; 3621 } 3622 else 3623 { 3624 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %lu", 3625 portFmt->nFramePackingFormat); 3626 eRet = OMX_ErrorUnsupportedSetting; 3627 } 3628 } 3629 else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) 3630 { 3631 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port"); 3632 if( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && 3633 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && 3634 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) 3635 { 3636 m_out_mem_region_smi = OMX_TRUE; 3637 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) 3638 { 3639 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set"); 3640 m_use_output_pmem = OMX_TRUE; 3641 } 3642 } 3643 } 3644 } 3645 break; 3646 3647 case OMX_IndexParamStandardComponentRole: 3648 { 3649 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3650 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3651 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", 3652 comp_role->cRole); 3653 3654 if((m_state == OMX_StateLoaded)&& 3655 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 3656 { 3657 DEBUG_PRINT_LOW("Set Parameter called in valid state"); 3658 } 3659 else 3660 { 3661 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 3662 return OMX_ErrorIncorrectStateOperation; 3663 } 3664 3665 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid",OMX_MAX_STRINGNAME_SIZE) || 3666 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevcswvdec",OMX_MAX_STRINGNAME_SIZE) || 3667 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) 3668 { 3669 if(!strncmp((char*)comp_role->cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) 3670 { 3671 strlcpy((char*)m_cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); 3672 } 3673 else 3674 { 3675 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3676 eRet =OMX_ErrorUnsupportedSetting; 3677 } 3678 } 3679 else 3680 { 3681 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind); 3682 eRet = OMX_ErrorInvalidComponentName; 3683 } 3684 break; 3685 } 3686 3687 case OMX_IndexParamPriorityMgmt: 3688 { 3689 if(m_state != OMX_StateLoaded) 3690 { 3691 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 3692 return OMX_ErrorIncorrectStateOperation; 3693 } 3694 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; 3695 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d", 3696 (int)priorityMgmtype->nGroupID); 3697 3698 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d", 3699 (int)priorityMgmtype->nGroupPriority); 3700 3701 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; 3702 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; 3703 3704 break; 3705 } 3706 3707 case OMX_IndexParamCompBufferSupplier: 3708 { 3709 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3710 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", 3711 bufferSupplierType->eBufferSupplier); 3712 if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) 3713 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; 3714 3715 else 3716 3717 eRet = OMX_ErrorBadPortIndex; 3718 3719 break; 3720 3721 } 3722 case OMX_IndexParamVideoAvc: 3723 case OMX_IndexParamVideoH263: 3724 case OMX_IndexParamVideoMpeg4: 3725 case OMX_IndexParamVideoMpeg2: 3726 { 3727 eRet = OMX_ErrorUnsupportedSetting; 3728 break; 3729 } 3730 case OMX_QcomIndexParamVideoDecoderPictureOrder: 3731 { 3732 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = 3733 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; 3734 struct v4l2_control control; 3735 int pic_order,rc=0; 3736 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d", 3737 pictureOrder->eOutputPictureOrder); 3738 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) { 3739 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 3740 } 3741 else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER){ 3742 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 3743 time_stamp_dts.set_timestamp_reorder_mode(false); 3744 } 3745 else 3746 eRet = OMX_ErrorBadParameter; 3747 if (eRet == OMX_ErrorNone) 3748 { 3749 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) { 3750 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 3751 control.value = pic_order; 3752 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3753 if(rc) 3754 { 3755 DEBUG_PRINT_ERROR("Set picture order failed"); 3756 eRet = OMX_ErrorUnsupportedSetting; 3757 } 3758 } 3759 // if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 3760 { 3761 // TODO 3762 } 3763 } 3764 break; 3765 } 3766 case OMX_QcomIndexParamConcealMBMapExtraData: 3767 if(!secure_mode) 3768 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false, 3769 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3770 else { 3771 DEBUG_PRINT_ERROR("secure mode setting not supported"); 3772 eRet = OMX_ErrorUnsupportedSetting; 3773 } 3774 break; 3775 case OMX_QcomIndexParamFrameInfoExtraData: 3776 { 3777 if(!secure_mode) 3778 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, 3779 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3780 else { 3781 DEBUG_PRINT_ERROR("secure mode setting not supported"); 3782 eRet = OMX_ErrorUnsupportedSetting; 3783 } 3784 break; 3785 } 3786 case OMX_QcomIndexParamInterlaceExtraData: 3787 if(!secure_mode) 3788 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false, 3789 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3790 else { 3791 DEBUG_PRINT_ERROR("secure mode setting not supported"); 3792 eRet = OMX_ErrorUnsupportedSetting; 3793 } 3794 break; 3795 case OMX_QcomIndexParamH264TimeInfo: 3796 if(!secure_mode) 3797 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false, 3798 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3799 else { 3800 DEBUG_PRINT_ERROR("secure mode setting not supported"); 3801 eRet = OMX_ErrorUnsupportedSetting; 3802 } 3803 break; 3804 case OMX_QcomIndexParamVideoDivx: 3805 { 3806 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; 3807 } 3808 break; 3809 case OMX_QcomIndexPlatformPvt: 3810 { 3811 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); 3812 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; 3813 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) 3814 { 3815 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); 3816 eRet = OMX_ErrorUnsupportedSetting; 3817 } 3818 else 3819 { 3820 m_out_pvt_entry_pmem = OMX_TRUE; 3821 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) 3822 { 3823 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set"); 3824 m_use_output_pmem = OMX_TRUE; 3825 } 3826 } 3827 3828 } 3829 break; 3830 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: 3831 { 3832 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) { 3833 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); 3834 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); 3835 struct v4l2_control control; 3836 int rc; 3837 drv_ctx.idr_only_decoding = 1; 3838 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 3839 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 3840 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3841 if(rc) 3842 { 3843 DEBUG_PRINT_ERROR("Set picture order failed"); 3844 eRet = OMX_ErrorUnsupportedSetting; 3845 } else { 3846 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE; 3847 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE; 3848 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3849 if(rc) 3850 { 3851 DEBUG_PRINT_ERROR("Sync frame setting failed"); 3852 eRet = OMX_ErrorUnsupportedSetting; 3853 } 3854 /* Setting sync frame decoding on driver might change 3855 * buffer requirements so update them here*/ 3856 if (get_buffer_req(&drv_ctx.ip_buf)) { 3857 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements"); 3858 eRet = OMX_ErrorUnsupportedSetting; 3859 } 3860 if (!m_pSwVdec) { // for full dsp mode 3861 if (get_buffer_req(&drv_ctx.op_buf)) { 3862 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements"); 3863 eRet = OMX_ErrorUnsupportedSetting; 3864 } 3865 } else if (get_buffer_req(&drv_ctx.interm_op_buf)) { // for hybrid 3866 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements"); 3867 eRet = OMX_ErrorUnsupportedSetting; 3868 } 3869 } 3870 } 3871 } 3872 break; 3873 3874 case OMX_QcomIndexParamIndexExtraDataType: 3875 { 3876 if(!secure_mode) { 3877 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; 3878 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && 3879 (extradataIndexType->bEnabled == OMX_TRUE) && 3880 (extradataIndexType->nPortIndex == 1)) 3881 { 3882 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming"); 3883 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled); 3884 3885 } 3886 } 3887 } 3888 break; 3889 case OMX_QcomIndexParamEnableSmoothStreaming: 3890 { 3891 #ifndef SMOOTH_STREAMING_DISABLED 3892 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) { 3893 eRet = enable_smoothstreaming(); 3894 } 3895 #else 3896 eRet = OMX_ErrorUnsupportedSetting; 3897 #endif 3898 } 3899 break; 3900 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3901 /* Need to allow following two set_parameters even in Idle 3902 * state. This is ANDROID architecture which is not in sync 3903 * with openmax standard. */ 3904 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: 3905 { 3906 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; 3907 if(enableNativeBuffers) { 3908 m_enable_android_native_buffers = enableNativeBuffers->enable; 3909 } 3910 } 3911 break; 3912 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: 3913 { 3914 eRet = use_android_native_buffer(hComp, paramData); 3915 } 3916 break; 3917 #endif 3918 case OMX_QcomIndexParamEnableTimeStampReorder: 3919 { 3920 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; 3921 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) { 3922 if (reorder->bEnable == OMX_TRUE) { 3923 frm_int =0; 3924 time_stamp_dts.set_timestamp_reorder_mode(true); 3925 } 3926 else 3927 time_stamp_dts.set_timestamp_reorder_mode(false); 3928 } else { 3929 time_stamp_dts.set_timestamp_reorder_mode(false); 3930 if (reorder->bEnable == OMX_TRUE) 3931 { 3932 eRet = OMX_ErrorUnsupportedSetting; 3933 } 3934 } 3935 } 3936 break; 3937 case OMX_QcomIndexParamVideoMetaBufferMode: 3938 { 3939 StoreMetaDataInBuffersParams *metabuffer = 3940 (StoreMetaDataInBuffersParams *)paramData; 3941 if (!metabuffer) { 3942 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer); 3943 eRet = OMX_ErrorBadParameter; 3944 break; 3945 } 3946 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3947 if (m_pSwVdec == NULL) { 3948 //set property dynamic buffer mode to driver. 3949 struct v4l2_control control; 3950 struct v4l2_format fmt; 3951 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT; 3952 if (metabuffer->bStoreMetaData == true) { 3953 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC; 3954 } else { 3955 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC; 3956 } 3957 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 3958 if (!rc) { 3959 DEBUG_PRINT_HIGH(" %s buffer mode", 3960 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic"); 3961 dynamic_buf_mode = metabuffer->bStoreMetaData; 3962 } else { 3963 DEBUG_PRINT_ERROR("Failed to %s buffer mode", 3964 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic"); 3965 dynamic_buf_mode = false; 3966 eRet = OMX_ErrorUnsupportedSetting; 3967 } 3968 } else { // for hybrid codec 3969 DEBUG_PRINT_HIGH(" %s buffer mode", 3970 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic"); 3971 dynamic_buf_mode = metabuffer->bStoreMetaData; 3972 if (dynamic_buf_mode) { 3973 SWVDEC_PROP prop; 3974 prop.ePropId = SWVDEC_PROP_ID_BUFFER_ALLOC_MODE; 3975 prop.uProperty.sBufAllocMode.eBufAllocMode = SWVDEC_BUF_ALLOC_MODE_DYNAMIC; 3976 SwVdec_SetProperty(m_pSwVdec, &prop); 3977 } 3978 } 3979 } else { 3980 DEBUG_PRINT_ERROR( 3981 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %lu", 3982 metabuffer->nPortIndex); 3983 eRet = OMX_ErrorUnsupportedSetting; 3984 } 3985 } 3986 break; 3987 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 3988 case OMX_QcomIndexParamVideoAdaptivePlaybackMode: 3989 { 3990 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) { 3991 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback"); 3992 PrepareForAdaptivePlaybackParams* pParams = 3993 (PrepareForAdaptivePlaybackParams *) paramData; 3994 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3995 if (!pParams->bEnable) { 3996 return OMX_ErrorNone; 3997 } 3998 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth 3999 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) { 4000 DEBUG_PRINT_ERROR( 4001 "Adaptive playback request exceeds max supported resolution : [%lu x %lu] vs [%lu x %lu]", 4002 pParams->nMaxFrameWidth, pParams->nMaxFrameHeight, 4003 maxSmoothStreamingWidth, maxSmoothStreamingHeight); 4004 eRet = OMX_ErrorBadParameter; 4005 } else { 4006 eRet = enable_smoothstreaming(); 4007 if (eRet != OMX_ErrorNone) { 4008 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver."); 4009 eRet = OMX_ErrorHardware; 4010 } else { 4011 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu", 4012 pParams->nMaxFrameWidth, pParams->nMaxFrameHeight); 4013 m_smoothstreaming_mode = true; 4014 m_smoothstreaming_width = pParams->nMaxFrameWidth; 4015 m_smoothstreaming_height = pParams->nMaxFrameHeight; 4016 } 4017 struct v4l2_format fmt; 4018 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, 4019 m_smoothstreaming_width, m_smoothstreaming_height); 4020 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4021 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 4022 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 4023 fmt.fmt.pix_mp.pixelformat = output_capability; 4024 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", 4025 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); 4026 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4027 if (ret) { 4028 DEBUG_PRINT_ERROR("Set Resolution failed"); 4029 eRet = OMX_ErrorUnsupportedSetting; 4030 } else 4031 eRet = get_buffer_req(&drv_ctx.op_buf); 4032 } 4033 } else { 4034 DEBUG_PRINT_ERROR( 4035 "Prepare for adaptive playback supported only on output port"); 4036 eRet = OMX_ErrorBadParameter; 4037 } 4038 break; 4039 } 4040 } 4041 #endif 4042 default: 4043 { 4044 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex); 4045 eRet = OMX_ErrorUnsupportedIndex; 4046 } 4047 } 4048 return eRet; 4049 } 4050 4051 /* ====================================================================== 4052 FUNCTION 4053 omx_vdec::GetConfig 4054 4055 DESCRIPTION 4056 OMX Get Config Method implementation. 4057 4058 PARAMETERS 4059 <TBD>. 4060 4061 RETURN VALUE 4062 OMX Error None if successful. 4063 4064 ========================================================================== */ 4065 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, 4066 OMX_IN OMX_INDEXTYPE configIndex, 4067 OMX_INOUT OMX_PTR configData) 4068 { 4069 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4070 4071 if (m_state == OMX_StateInvalid) 4072 { 4073 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 4074 return OMX_ErrorInvalidState; 4075 } 4076 4077 switch ((unsigned long)configIndex) 4078 { 4079 case OMX_QcomIndexConfigInterlaced: 4080 { 4081 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = 4082 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; 4083 if (configFmt->nPortIndex == 1) 4084 { 4085 if (configFmt->nIndex == 0) 4086 { 4087 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; 4088 } 4089 else if (configFmt->nIndex == 1) 4090 { 4091 configFmt->eInterlaceType = 4092 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 4093 } 4094 else if (configFmt->nIndex == 2) 4095 { 4096 configFmt->eInterlaceType = 4097 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 4098 } 4099 else 4100 { 4101 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" 4102 " NoMore Interlaced formats"); 4103 eRet = OMX_ErrorNoMore; 4104 } 4105 4106 } 4107 else 4108 { 4109 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port", 4110 (int)configFmt->nPortIndex); 4111 eRet = OMX_ErrorBadPortIndex; 4112 } 4113 break; 4114 } 4115 case OMX_QcomIndexQueryNumberOfVideoDecInstance: 4116 { 4117 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = 4118 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; 4119 decoderinstances->nNumOfInstances = 16; 4120 /*TODO: How to handle this case */ 4121 break; 4122 } 4123 case OMX_QcomIndexConfigVideoFramePackingArrangement: 4124 { 4125 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); 4126 break; 4127 } 4128 case OMX_IndexConfigCommonOutputCrop: 4129 { 4130 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData; 4131 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE)); 4132 break; 4133 } 4134 default: 4135 { 4136 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); 4137 eRet = OMX_ErrorBadParameter; 4138 } 4139 4140 } 4141 4142 return eRet; 4143 } 4144 4145 /* ====================================================================== 4146 FUNCTION 4147 omx_vdec::SetConfig 4148 4149 DESCRIPTION 4150 OMX Set Config method implementation 4151 4152 PARAMETERS 4153 <TBD>. 4154 4155 RETURN VALUE 4156 OMX Error None if successful. 4157 ========================================================================== */ 4158 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, 4159 OMX_IN OMX_INDEXTYPE configIndex, 4160 OMX_IN OMX_PTR configData) 4161 { 4162 if(m_state == OMX_StateInvalid) 4163 { 4164 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 4165 return OMX_ErrorInvalidState; 4166 } 4167 4168 OMX_ERRORTYPE ret = OMX_ErrorNone; 4169 OMX_VIDEO_CONFIG_NALSIZE *pNal; 4170 4171 DEBUG_PRINT_LOW("Set Config Called"); 4172 4173 if (m_state == OMX_StateExecuting) 4174 { 4175 DEBUG_PRINT_ERROR("set_config:Ignore in Exe state"); 4176 return ret; 4177 } 4178 4179 if (configIndex == (OMX_INDEXTYPE)OMX_IndexVendorVideoExtraData) 4180 { 4181 OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData; 4182 DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called"); 4183 return ret; 4184 } 4185 else if (configIndex == OMX_IndexConfigVideoNalSize) 4186 { 4187 4188 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); 4189 nal_length = pNal->nNaluBytes; 4190 m_frame_parser.init_nal_length(nal_length); 4191 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d",nal_length); 4192 return ret; 4193 } 4194 return OMX_ErrorNotImplemented; 4195 } 4196 4197 /* ====================================================================== 4198 FUNCTION 4199 omx_vdec::GetExtensionIndex 4200 4201 DESCRIPTION 4202 OMX GetExtensionIndex method implementaion. <TBD> 4203 4204 PARAMETERS 4205 <TBD>. 4206 4207 RETURN VALUE 4208 OMX Error None if everything successful. 4209 4210 ========================================================================== */ 4211 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, 4212 OMX_IN OMX_STRING paramName, 4213 OMX_OUT OMX_INDEXTYPE* indexType) 4214 { 4215 if(m_state == OMX_StateInvalid) 4216 { 4217 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State"); 4218 return OMX_ErrorInvalidState; 4219 } 4220 else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) { 4221 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; 4222 } 4223 else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) 4224 { 4225 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; 4226 } 4227 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 4228 else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) { 4229 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; 4230 } 4231 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) { 4232 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; 4233 } 4234 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) { 4235 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName); 4236 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; 4237 } 4238 else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) { 4239 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; 4240 } 4241 #endif 4242 else if (!strncmp(paramName, "OMX.google.android.index.storeMetaDataInBuffers", sizeof("OMX.google.android.index.storeMetaDataInBuffers") - 1)) { 4243 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; 4244 } 4245 #if ADAPTIVE_PLAYBACK_SUPPORTED 4246 else if (!strncmp(paramName, "OMX.google.android.index.prepareForAdaptivePlayback", sizeof("OMX.google.android.index.prepareForAdaptivePlayback") -1)) { 4247 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode; 4248 } 4249 #endif 4250 else { 4251 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); 4252 return OMX_ErrorNotImplemented; 4253 } 4254 return OMX_ErrorNone; 4255 } 4256 4257 /* ====================================================================== 4258 FUNCTION 4259 omx_vdec::GetState 4260 4261 DESCRIPTION 4262 Returns the state information back to the caller.<TBD> 4263 4264 PARAMETERS 4265 <TBD>. 4266 4267 RETURN VALUE 4268 Error None if everything is successful. 4269 ========================================================================== */ 4270 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, 4271 OMX_OUT OMX_STATETYPE* state) 4272 { 4273 *state = m_state; 4274 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state); 4275 return OMX_ErrorNone; 4276 } 4277 4278 /* ====================================================================== 4279 FUNCTION 4280 omx_vdec::ComponentTunnelRequest 4281 4282 DESCRIPTION 4283 OMX Component Tunnel Request method implementation. <TBD> 4284 4285 PARAMETERS 4286 None. 4287 4288 RETURN VALUE 4289 OMX Error None if everything successful. 4290 4291 ========================================================================== */ 4292 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, 4293 OMX_IN OMX_U32 port, 4294 OMX_IN OMX_HANDLETYPE peerComponent, 4295 OMX_IN OMX_U32 peerPort, 4296 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) 4297 { 4298 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented"); 4299 return OMX_ErrorNotImplemented; 4300 } 4301 4302 /* ====================================================================== 4303 FUNCTION 4304 omx_vdec::UseOutputBuffer 4305 4306 DESCRIPTION 4307 Helper function for Use buffer in the input pin 4308 4309 PARAMETERS 4310 None. 4311 4312 RETURN VALUE 4313 true/false 4314 4315 ========================================================================== */ 4316 OMX_ERRORTYPE omx_vdec::allocate_extradata() 4317 { 4318 #ifdef USE_ION 4319 if (drv_ctx.extradata_info.buffer_size) { 4320 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { 4321 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 4322 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4323 free_ion_memory(&drv_ctx.extradata_info.ion); 4324 } 4325 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); 4326 DEBUG_PRINT_HIGH("allocate extradata memory size %d", drv_ctx.extradata_info.size); 4327 int heap = 0; 4328 #ifdef _HEVC_USE_ADSP_HEAP_ 4329 heap = ION_ADSP_HEAP_ID; 4330 #endif 4331 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( 4332 drv_ctx.extradata_info.size, 4096, 4333 &drv_ctx.extradata_info.ion.ion_alloc_data, 4334 &drv_ctx.extradata_info.ion.fd_ion_data, 0, heap); 4335 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) { 4336 DEBUG_PRINT_ERROR("Failed to alloc extradata memory"); 4337 return OMX_ErrorInsufficientResources; 4338 } 4339 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL, 4340 drv_ctx.extradata_info.size, 4341 PROT_READ|PROT_WRITE, MAP_SHARED, 4342 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0); 4343 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) { 4344 DEBUG_PRINT_ERROR("Failed to map extradata memory"); 4345 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4346 free_ion_memory(&drv_ctx.extradata_info.ion); 4347 return OMX_ErrorInsufficientResources; 4348 } 4349 memset(drv_ctx.extradata_info.uaddr, 0, drv_ctx.extradata_info.size); 4350 } 4351 #endif 4352 return OMX_ErrorNone; 4353 } 4354 4355 void omx_vdec::free_extradata() { 4356 #ifdef USE_ION 4357 if (drv_ctx.extradata_info.uaddr) { 4358 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 4359 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4360 free_ion_memory(&drv_ctx.extradata_info.ion); 4361 } 4362 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 4363 #endif 4364 } 4365 4366 OMX_ERRORTYPE omx_vdec::use_output_buffer( 4367 OMX_IN OMX_HANDLETYPE hComp, 4368 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 4369 OMX_IN OMX_U32 port, 4370 OMX_IN OMX_PTR appData, 4371 OMX_IN OMX_U32 bytes, 4372 OMX_IN OMX_U8* buffer) 4373 { 4374 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4375 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 4376 unsigned i= 0; // Temporary counter 4377 struct vdec_setbuffer_cmd setbuffers; 4378 OMX_PTR privateAppData = NULL; 4379 private_handle_t *handle = NULL; 4380 OMX_U8 *buff = buffer; 4381 4382 if (!m_out_mem_ptr) { 4383 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); 4384 eRet = allocate_output_headers(); 4385 if (!m_pSwVdec && eRet == OMX_ErrorNone) 4386 eRet = allocate_extradata(); 4387 } 4388 4389 if (eRet == OMX_ErrorNone) { 4390 for(i=0; i< drv_ctx.op_buf.actualcount; i++) { 4391 if(BITMASK_ABSENT(&m_out_bm_count,i)) 4392 { 4393 break; 4394 } 4395 } 4396 } 4397 4398 if(i >= drv_ctx.op_buf.actualcount) { 4399 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount); 4400 eRet = OMX_ErrorInsufficientResources; 4401 } 4402 4403 if (dynamic_buf_mode) { 4404 if (m_pSwVdec && !m_pSwVdecOpBuffer) 4405 { 4406 SWVDEC_PROP prop; 4407 DEBUG_PRINT_HIGH("allocating m_pSwVdecOpBuffer %d", drv_ctx.op_buf.actualcount); 4408 m_pSwVdecOpBuffer = (SWVDEC_OPBUFFER*)calloc(sizeof(SWVDEC_OPBUFFER), drv_ctx.op_buf.actualcount); 4409 } 4410 4411 *bufferHdr = (m_out_mem_ptr + i ); 4412 (*bufferHdr)->pBuffer = NULL; 4413 // for full dsp mode 4414 if (!m_pSwVdec && i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 4415 enum v4l2_buf_type buf_type; 4416 int rr = 0; 4417 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4418 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 4419 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr); 4420 return OMX_ErrorInsufficientResources; 4421 } else { 4422 streaming[CAPTURE_PORT] = true; 4423 DEBUG_PRINT_LOW("STREAMON Successful"); 4424 } 4425 } 4426 BITMASK_SET(&m_out_bm_count,i); 4427 (*bufferHdr)->pAppPrivate = appData; 4428 (*bufferHdr)->pBuffer = buffer; 4429 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 4430 4431 // SWVdec memory allocation and set the output buffer 4432 if (m_pSwVdecOpBuffer) { 4433 m_pSwVdecOpBuffer[i].nSize = sizeof(struct VideoDecoderOutputMetaData); 4434 m_pSwVdecOpBuffer[i].pBuffer = buffer; 4435 m_pSwVdecOpBuffer[i].pClientBufferData = (void*)i; 4436 } 4437 4438 return eRet; 4439 } 4440 4441 if (eRet == OMX_ErrorNone) { 4442 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) 4443 if(m_enable_android_native_buffers) { 4444 if (m_use_android_native_buffers) { 4445 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; 4446 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 4447 handle = (private_handle_t *)nBuf->handle; 4448 privateAppData = params->pAppPrivate; 4449 } else { 4450 handle = (private_handle_t *)buff; 4451 privateAppData = appData; 4452 } 4453 4454 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { 4455 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," 4456 " expected %u, got %lu", 4457 drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size); 4458 return OMX_ErrorBadParameter; 4459 } 4460 4461 drv_ctx.op_buf.buffer_size = (OMX_U32)handle->size; 4462 if (!m_use_android_native_buffers) { 4463 if (!secure_mode) { 4464 buff = (OMX_U8*)mmap(0, handle->size, 4465 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 4466 if (buff == MAP_FAILED) { 4467 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 4468 return OMX_ErrorInsufficientResources; 4469 } 4470 } 4471 } 4472 #if defined(_ANDROID_ICS_) 4473 native_buffer[i].nativehandle = handle; 4474 native_buffer[i].privatehandle = handle; 4475 #endif 4476 if(!handle) { 4477 DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); 4478 return OMX_ErrorBadParameter; 4479 } 4480 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; 4481 drv_ctx.ptr_outputbuffer[i].offset = 0; 4482 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 4483 drv_ctx.ptr_outputbuffer[i].mmaped_size = 4484 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 4485 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd = handle->fd; 4486 drv_ctx.op_buf_ion_info[i].fd_ion_data.handle = (ion_user_handle_t)handle; 4487 DEBUG_PRINT_HIGH("Native Buffer vaddr %x, idx %d fd %d len %d", (unsigned int)buff,i, handle->fd , drv_ctx.op_buf.buffer_size); 4488 } else 4489 #endif 4490 4491 if (!ouput_egl_buffers && !m_use_output_pmem) { 4492 #ifdef USE_ION 4493 DEBUG_PRINT_HIGH("allocate output buffer memory size %d", drv_ctx.op_buf.buffer_size); 4494 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 4495 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, 4496 &drv_ctx.op_buf_ion_info[i].ion_alloc_data, 4497 &drv_ctx.op_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0); 4498 if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { 4499 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd); 4500 return OMX_ErrorInsufficientResources; 4501 } 4502 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4503 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 4504 #else 4505 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4506 open (MEM_DEVICE,O_RDWR); 4507 4508 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 4509 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 4510 return OMX_ErrorInsufficientResources; 4511 } 4512 4513 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */ 4514 if(drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) 4515 { 4516 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4517 open (MEM_DEVICE,O_RDWR); 4518 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 4519 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 4520 return OMX_ErrorInsufficientResources; 4521 } 4522 } 4523 4524 if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, 4525 drv_ctx.op_buf.buffer_size, 4526 drv_ctx.op_buf.alignment)) 4527 { 4528 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 4529 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 4530 return OMX_ErrorInsufficientResources; 4531 } 4532 #endif 4533 4534 if(!secure_mode) { 4535 drv_ctx.ptr_outputbuffer[i].bufferaddr = 4536 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, 4537 PROT_READ|PROT_WRITE, MAP_SHARED, 4538 drv_ctx.ptr_outputbuffer[i].pmem_fd,0); 4539 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { 4540 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 4541 #ifdef USE_ION 4542 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 4543 #endif 4544 DEBUG_PRINT_ERROR("Unable to mmap output buffer"); 4545 return OMX_ErrorInsufficientResources; 4546 } 4547 } 4548 drv_ctx.ptr_outputbuffer[i].offset = 0; 4549 privateAppData = appData; 4550 } 4551 else { 4552 4553 DEBUG_PRINT_HIGH("Use_op_buf: out_pmem=%d",m_use_output_pmem); 4554 if (!appData || !bytes ) { 4555 if(!secure_mode && !buffer) { 4556 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case"); 4557 return OMX_ErrorBadParameter; 4558 } 4559 } 4560 4561 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; 4562 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; 4563 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; 4564 if (!pmem_list->entryList || !pmem_list->entryList->entry || 4565 !pmem_list->nEntries || 4566 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 4567 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer"); 4568 return OMX_ErrorBadParameter; 4569 } 4570 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 4571 pmem_list->entryList->entry; 4572 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x", 4573 (unsigned int)pmem_info->pmem_fd); 4574 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; 4575 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; 4576 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 4577 drv_ctx.ptr_outputbuffer[i].mmaped_size = 4578 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 4579 privateAppData = appData; 4580 } 4581 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 4582 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; 4583 4584 *bufferHdr = (m_out_mem_ptr + i ); 4585 if(secure_mode) 4586 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 4587 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 4588 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], 4589 sizeof (vdec_bufferpayload)); 4590 4591 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i, 4592 drv_ctx.ptr_outputbuffer[i].bufferaddr, 4593 drv_ctx.ptr_outputbuffer[i].pmem_fd ); 4594 4595 if (m_pSwVdec) 4596 { 4597 if (m_pSwVdecOpBuffer == NULL) 4598 { 4599 DEBUG_PRINT_HIGH("allocating m_pSwVdecOpBuffer %d", drv_ctx.op_buf.actualcount); 4600 m_pSwVdecOpBuffer = (SWVDEC_OPBUFFER*)calloc(sizeof(SWVDEC_OPBUFFER), drv_ctx.op_buf.actualcount); 4601 } 4602 4603 // SWVdec memory allocation and set the output buffer 4604 m_pSwVdecOpBuffer[i].nSize = drv_ctx.ptr_outputbuffer[i].mmaped_size; 4605 m_pSwVdecOpBuffer[i].pBuffer = (uint8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 4606 m_pSwVdecOpBuffer[i].pClientBufferData = (void*)i; 4607 if (SWVDEC_S_SUCCESS !=SwVdec_SetOutputBuffer(m_pSwVdec, &m_pSwVdecOpBuffer[i])) 4608 { 4609 DEBUG_PRINT_HIGH("SwVdec_SetOutputBuffer failed in use_output_buffer"); 4610 return OMX_ErrorInsufficientResources; 4611 } 4612 } 4613 else 4614 { 4615 struct v4l2_buffer buf; 4616 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 4617 int extra_idx = 0; 4618 buf.index = i; 4619 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4620 buf.memory = V4L2_MEMORY_USERPTR; 4621 plane[0].length = drv_ctx.op_buf.buffer_size; 4622 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 4623 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 4624 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd; 4625 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 4626 plane[0].data_offset = 0; 4627 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 4628 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 4629 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 4630 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 4631 #ifdef USE_ION 4632 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 4633 #endif 4634 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 4635 plane[extra_idx].data_offset = 0; 4636 } else if (extra_idx >= VIDEO_MAX_PLANES) { 4637 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 4638 return OMX_ErrorBadParameter; 4639 } 4640 buf.m.planes = plane; 4641 buf.length = drv_ctx.num_planes; 4642 4643 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, (unsigned int)drv_ctx.ptr_outputbuffer[i].bufferaddr); 4644 4645 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) { 4646 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 4647 /*TODO: How to handle this case */ 4648 return OMX_ErrorInsufficientResources; 4649 } 4650 4651 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 4652 enum v4l2_buf_type buf_type; 4653 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4654 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 4655 return OMX_ErrorInsufficientResources; 4656 } else { 4657 streaming[CAPTURE_PORT] = true; 4658 DEBUG_PRINT_LOW("STREAMON Successful"); 4659 } 4660 } 4661 } 4662 4663 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; 4664 if (m_enable_android_native_buffers) { 4665 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle); 4666 (*bufferHdr)->pBuffer = (OMX_U8 *)handle; 4667 } else { 4668 (*bufferHdr)->pBuffer = buff; 4669 } 4670 (*bufferHdr)->pAppPrivate = privateAppData; 4671 BITMASK_SET(&m_out_bm_count,i); 4672 } 4673 return eRet; 4674 } 4675 4676 /* ====================================================================== 4677 FUNCTION 4678 omx_vdec::use_input_heap_buffers 4679 4680 DESCRIPTION 4681 OMX Use Buffer Heap allocation method implementation. 4682 4683 PARAMETERS 4684 <TBD>. 4685 4686 RETURN VALUE 4687 OMX Error None , if everything successful. 4688 4689 ========================================================================== */ 4690 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( 4691 OMX_IN OMX_HANDLETYPE hComp, 4692 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 4693 OMX_IN OMX_U32 port, 4694 OMX_IN OMX_PTR appData, 4695 OMX_IN OMX_U32 bytes, 4696 OMX_IN OMX_U8* buffer) 4697 { 4698 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer); 4699 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4700 if(!m_inp_heap_ptr) 4701 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) 4702 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 4703 drv_ctx.ip_buf.actualcount); 4704 if(!m_phdr_pmem_ptr) 4705 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) 4706 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 4707 drv_ctx.ip_buf.actualcount); 4708 if(!m_inp_heap_ptr || !m_phdr_pmem_ptr) 4709 { 4710 DEBUG_PRINT_ERROR("Insufficent memory"); 4711 eRet = OMX_ErrorInsufficientResources; 4712 } 4713 else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) 4714 { 4715 input_use_buffer = true; 4716 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); 4717 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; 4718 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; 4719 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; 4720 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; 4721 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; 4722 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; 4723 eRet = 4724 allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); 4725 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); 4726 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt], 4727 (unsigned)NULL, (unsigned)NULL)) 4728 { 4729 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 4730 return OMX_ErrorInsufficientResources; 4731 } 4732 m_in_alloc_cnt++; 4733 } 4734 else 4735 { 4736 DEBUG_PRINT_ERROR("All i/p buffers have been set!"); 4737 eRet = OMX_ErrorInsufficientResources; 4738 } 4739 return eRet; 4740 } 4741 4742 /* ====================================================================== 4743 FUNCTION 4744 omx_vdec::UseBuffer 4745 4746 DESCRIPTION 4747 OMX Use Buffer method implementation. 4748 4749 PARAMETERS 4750 <TBD>. 4751 4752 RETURN VALUE 4753 OMX Error None , if everything successful. 4754 4755 ========================================================================== */ 4756 OMX_ERRORTYPE omx_vdec::use_buffer( 4757 OMX_IN OMX_HANDLETYPE hComp, 4758 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 4759 OMX_IN OMX_U32 port, 4760 OMX_IN OMX_PTR appData, 4761 OMX_IN OMX_U32 bytes, 4762 OMX_IN OMX_U8* buffer) 4763 { 4764 OMX_ERRORTYPE error = OMX_ErrorNone; 4765 struct vdec_setbuffer_cmd setbuffers; 4766 4767 if (bufferHdr == NULL || bytes == 0) 4768 { 4769 if(!secure_mode && buffer == NULL) { 4770 DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer); 4771 return OMX_ErrorBadParameter; 4772 } 4773 } 4774 if(m_state == OMX_StateInvalid) 4775 { 4776 DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); 4777 return OMX_ErrorInvalidState; 4778 } 4779 if(port == OMX_CORE_INPUT_PORT_INDEX) 4780 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); 4781 else if(port == OMX_CORE_OUTPUT_PORT_INDEX) 4782 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested 4783 else 4784 { 4785 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 4786 error = OMX_ErrorBadPortIndex; 4787 } 4788 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error); 4789 if(error == OMX_ErrorNone) 4790 { 4791 if(allocate_done()) 4792 { 4793 DEBUG_PRINT_LOW("Use Buffer: allocate_done"); 4794 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 4795 { 4796 // Send the callback now 4797 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 4798 post_event(OMX_CommandStateSet,OMX_StateIdle, 4799 OMX_COMPONENT_GENERATE_EVENT); 4800 } 4801 if (m_pSwVdec) 4802 { 4803 DEBUG_PRINT_LOW("Use Buffer: SwVdec_Start"); 4804 SwVdec_Start(m_pSwVdec); 4805 } 4806 } 4807 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && 4808 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) 4809 { 4810 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 4811 post_event(OMX_CommandPortEnable, 4812 OMX_CORE_INPUT_PORT_INDEX, 4813 OMX_COMPONENT_GENERATE_EVENT); 4814 } 4815 else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && 4816 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) 4817 { 4818 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 4819 post_event(OMX_CommandPortEnable, 4820 OMX_CORE_OUTPUT_PORT_INDEX, 4821 OMX_COMPONENT_GENERATE_EVENT); 4822 } 4823 } 4824 return error; 4825 } 4826 4827 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, 4828 OMX_BUFFERHEADERTYPE *pmem_bufferHdr) 4829 { 4830 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) 4831 { 4832 if(m_inp_heap_ptr[bufferindex].pBuffer) 4833 free(m_inp_heap_ptr[bufferindex].pBuffer); 4834 m_inp_heap_ptr[bufferindex].pBuffer = NULL; 4835 } 4836 if (pmem_bufferHdr) 4837 free_input_buffer(pmem_bufferHdr); 4838 return OMX_ErrorNone; 4839 } 4840 4841 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 4842 { 4843 unsigned int index = 0; 4844 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) 4845 { 4846 return OMX_ErrorBadParameter; 4847 } 4848 4849 index = bufferHdr - m_inp_mem_ptr; 4850 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 4851 4852 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) 4853 { 4854 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 4855 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) 4856 { 4857 struct vdec_setbuffer_cmd setbuffers; 4858 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; 4859 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], 4860 sizeof (vdec_bufferpayload)); 4861 DEBUG_PRINT_LOW("unmap the input buffer fd=%d", 4862 drv_ctx.ptr_inputbuffer[index].pmem_fd); 4863 DEBUG_PRINT_LOW("unmap the input buffer size=%d address = %x", 4864 drv_ctx.ptr_inputbuffer[index].mmaped_size, 4865 (unsigned int)drv_ctx.ptr_inputbuffer[index].bufferaddr); 4866 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, 4867 drv_ctx.ptr_inputbuffer[index].mmaped_size); 4868 close (drv_ctx.ptr_inputbuffer[index].pmem_fd); 4869 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; 4870 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) 4871 { 4872 free(m_desc_buffer_ptr[index].buf_addr); 4873 m_desc_buffer_ptr[index].buf_addr = NULL; 4874 m_desc_buffer_ptr[index].desc_data_size = 0; 4875 } 4876 #ifdef USE_ION 4877 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); 4878 #endif 4879 } 4880 } 4881 4882 return OMX_ErrorNone; 4883 } 4884 4885 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 4886 { 4887 unsigned int index = 0; 4888 4889 if (bufferHdr == NULL || m_out_mem_ptr == NULL) 4890 { 4891 return OMX_ErrorBadParameter; 4892 } 4893 4894 index = bufferHdr - m_out_mem_ptr; 4895 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index); 4896 4897 if (index < drv_ctx.op_buf.actualcount 4898 && drv_ctx.ptr_outputbuffer) 4899 { 4900 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %x", index, 4901 (unsigned int)drv_ctx.ptr_outputbuffer[index].bufferaddr); 4902 4903 struct vdec_setbuffer_cmd setbuffers; 4904 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 4905 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], 4906 sizeof (vdec_bufferpayload)); 4907 #ifdef _ANDROID_ 4908 if(m_enable_android_native_buffers) { 4909 if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { 4910 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, 4911 drv_ctx.ptr_outputbuffer[index].mmaped_size); 4912 } 4913 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; 4914 } else { 4915 #endif 4916 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) 4917 { 4918 DEBUG_PRINT_LOW("unmap the output buffer fd = %d", 4919 drv_ctx.ptr_outputbuffer[0].pmem_fd); 4920 DEBUG_PRINT_LOW("unmap the ouput buffer size=%d address = %x", 4921 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, 4922 (unsigned int)drv_ctx.ptr_outputbuffer[0].bufferaddr); 4923 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, 4924 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); 4925 close (drv_ctx.ptr_outputbuffer[0].pmem_fd); 4926 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; 4927 #ifdef USE_ION 4928 free_ion_memory(&drv_ctx.op_buf_ion_info[0]); 4929 #endif 4930 } 4931 #ifdef _ANDROID_ 4932 } 4933 #endif 4934 if (release_output_done()) { 4935 free_extradata(); 4936 } 4937 } 4938 4939 return OMX_ErrorNone; 4940 4941 } 4942 4943 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, 4944 OMX_BUFFERHEADERTYPE **bufferHdr, 4945 OMX_U32 port, 4946 OMX_PTR appData, 4947 OMX_U32 bytes) 4948 { 4949 OMX_BUFFERHEADERTYPE *input = NULL; 4950 unsigned char *buf_addr = NULL; 4951 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4952 unsigned i = 0; 4953 4954 /* Sanity Check*/ 4955 if (bufferHdr == NULL) 4956 { 4957 return OMX_ErrorBadParameter; 4958 } 4959 4960 if (m_inp_heap_ptr == NULL) 4961 { 4962 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ 4963 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 4964 drv_ctx.ip_buf.actualcount); 4965 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ 4966 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 4967 drv_ctx.ip_buf.actualcount); 4968 4969 if (m_inp_heap_ptr == NULL) 4970 { 4971 DEBUG_PRINT_ERROR("m_inp_heap_ptr Allocation failed "); 4972 return OMX_ErrorInsufficientResources; 4973 } 4974 } 4975 4976 /*Find a Free index*/ 4977 for(i=0; i< drv_ctx.ip_buf.actualcount; i++) 4978 { 4979 if(BITMASK_ABSENT(&m_heap_inp_bm_count,i)) 4980 { 4981 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 4982 break; 4983 } 4984 } 4985 4986 if (i < drv_ctx.ip_buf.actualcount) 4987 { 4988 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); 4989 4990 if (buf_addr == NULL) 4991 { 4992 return OMX_ErrorInsufficientResources; 4993 } 4994 4995 *bufferHdr = (m_inp_heap_ptr + i); 4996 input = *bufferHdr; 4997 BITMASK_SET(&m_heap_inp_bm_count,i); 4998 4999 input->pBuffer = (OMX_U8 *)buf_addr; 5000 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5001 input->nVersion.nVersion = OMX_SPEC_VERSION; 5002 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 5003 input->pAppPrivate = appData; 5004 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 5005 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr ); 5006 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); 5007 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]); 5008 /*Add the Buffers to freeq*/ 5009 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[i], 5010 (unsigned)NULL, (unsigned)NULL)) 5011 { 5012 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 5013 return OMX_ErrorInsufficientResources; 5014 } 5015 } 5016 else 5017 { 5018 return OMX_ErrorBadParameter; 5019 } 5020 5021 return eRet; 5022 5023 } 5024 5025 5026 /* ====================================================================== 5027 FUNCTION 5028 omx_vdec::AllocateInputBuffer 5029 5030 DESCRIPTION 5031 Helper function for allocate buffer in the input pin 5032 5033 PARAMETERS 5034 None. 5035 5036 RETURN VALUE 5037 true/false 5038 5039 ========================================================================== */ 5040 OMX_ERRORTYPE omx_vdec::allocate_input_buffer( 5041 OMX_IN OMX_HANDLETYPE hComp, 5042 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5043 OMX_IN OMX_U32 port, 5044 OMX_IN OMX_PTR appData, 5045 OMX_IN OMX_U32 bytes) 5046 { 5047 5048 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5049 struct vdec_setbuffer_cmd setbuffers; 5050 OMX_BUFFERHEADERTYPE *input = NULL; 5051 unsigned i = 0; 5052 unsigned char *buf_addr = NULL; 5053 int pmem_fd = -1; 5054 5055 if(bytes != drv_ctx.ip_buf.buffer_size) 5056 { 5057 DEBUG_PRINT_LOW("Requested Size is wrong %d epected is %d", 5058 (int)bytes, drv_ctx.ip_buf.buffer_size); 5059 return OMX_ErrorBadParameter; 5060 } 5061 5062 if(!m_inp_mem_ptr) 5063 { 5064 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%d)", 5065 drv_ctx.ip_buf.actualcount, 5066 drv_ctx.ip_buf.buffer_size); 5067 5068 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ 5069 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); 5070 5071 if (m_inp_mem_ptr == NULL) 5072 { 5073 return OMX_ErrorInsufficientResources; 5074 } 5075 5076 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ 5077 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); 5078 5079 if (drv_ctx.ptr_inputbuffer == NULL) 5080 { 5081 return OMX_ErrorInsufficientResources; 5082 } 5083 #ifdef USE_ION 5084 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ 5085 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); 5086 5087 if (drv_ctx.ip_buf_ion_info == NULL) 5088 { 5089 return OMX_ErrorInsufficientResources; 5090 } 5091 #endif 5092 5093 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) 5094 { 5095 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; 5096 #ifdef USE_ION 5097 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; 5098 #endif 5099 } 5100 5101 if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 5102 { 5103 // allocate swvdec input buffers 5104 m_pSwVdecIpBuffer = (SWVDEC_IPBUFFER *)calloc(sizeof(SWVDEC_IPBUFFER), drv_ctx.ip_buf.actualcount); 5105 if (m_pSwVdecIpBuffer == NULL) { 5106 eRet = OMX_ErrorInsufficientResources; 5107 } 5108 } 5109 } 5110 5111 for(i=0; i< drv_ctx.ip_buf.actualcount; i++) 5112 { 5113 if(BITMASK_ABSENT(&m_inp_bm_count,i)) 5114 { 5115 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 5116 break; 5117 } 5118 } 5119 5120 if(i < drv_ctx.ip_buf.actualcount) 5121 { 5122 #ifdef USE_ION 5123 int heap = 0; 5124 #ifdef _HEVC_USE_ADSP_HEAP_ 5125 heap = ION_ADSP_HEAP_ID; 5126 #endif 5127 DEBUG_PRINT_HIGH("Allocate ion input Buffer size %d", drv_ctx.ip_buf.buffer_size); 5128 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 5129 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, 5130 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, 5131 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0, heap); 5132 if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { 5133 return OMX_ErrorInsufficientResources; 5134 } 5135 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; 5136 #else 5137 pmem_fd = open (MEM_DEVICE,O_RDWR); 5138 5139 if (pmem_fd < 0) 5140 { 5141 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 5142 return OMX_ErrorInsufficientResources; 5143 } 5144 5145 if (pmem_fd == 0) 5146 { 5147 pmem_fd = open (MEM_DEVICE,O_RDWR); 5148 5149 if (pmem_fd < 0) 5150 { 5151 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 5152 return OMX_ErrorInsufficientResources; 5153 } 5154 } 5155 5156 if(!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, 5157 drv_ctx.ip_buf.alignment)) 5158 { 5159 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 5160 close(pmem_fd); 5161 return OMX_ErrorInsufficientResources; 5162 } 5163 #endif 5164 if (!secure_mode) { 5165 buf_addr = (unsigned char *)mmap(NULL, 5166 drv_ctx.ip_buf.buffer_size, 5167 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); 5168 5169 if (buf_addr == MAP_FAILED) 5170 { 5171 close(pmem_fd); 5172 #ifdef USE_ION 5173 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); 5174 #endif 5175 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer"); 5176 return OMX_ErrorInsufficientResources; 5177 } 5178 } 5179 *bufferHdr = (m_inp_mem_ptr + i); 5180 if (secure_mode) 5181 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; 5182 else 5183 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; 5184 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; 5185 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; 5186 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; 5187 drv_ctx.ptr_inputbuffer [i].offset = 0; 5188 5189 if (!m_pSwVdec || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 5190 { 5191 struct v4l2_buffer buf; 5192 struct v4l2_plane plane; 5193 int rc; 5194 buf.index = i; 5195 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 5196 buf.memory = V4L2_MEMORY_USERPTR; 5197 plane.bytesused = 0; 5198 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size; 5199 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr; 5200 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd; 5201 plane.reserved[1] = 0; 5202 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset; 5203 buf.m.planes = &plane; 5204 buf.length = 1; 5205 5206 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %x", i, (unsigned int)drv_ctx.ptr_inputbuffer[i].bufferaddr); 5207 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 5208 if (rc) { 5209 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 5210 /*TODO: How to handle this case */ 5211 return OMX_ErrorInsufficientResources; 5212 } 5213 } 5214 else if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 5215 { 5216 m_pSwVdecIpBuffer[i].pBuffer = buf_addr; 5217 m_pSwVdecIpBuffer[i].pClientBufferData = (void*)i; 5218 } 5219 5220 input = *bufferHdr; 5221 BITMASK_SET(&m_inp_bm_count,i); 5222 DEBUG_PRINT_LOW("Buffer address %p of pmem idx %d",*bufferHdr, i); 5223 if (secure_mode) 5224 input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd; 5225 else 5226 input->pBuffer = (OMX_U8 *)buf_addr; 5227 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5228 input->nVersion.nVersion = OMX_SPEC_VERSION; 5229 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 5230 input->pAppPrivate = appData; 5231 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 5232 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; 5233 5234 if (drv_ctx.disable_dmx) 5235 { 5236 eRet = allocate_desc_buffer(i); 5237 } 5238 } 5239 else 5240 { 5241 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found"); 5242 eRet = OMX_ErrorInsufficientResources; 5243 } 5244 return eRet; 5245 } 5246 5247 5248 /* ====================================================================== 5249 FUNCTION 5250 omx_vdec::AllocateOutputBuffer 5251 5252 DESCRIPTION 5253 Helper fn for AllocateBuffer in the output pin 5254 5255 PARAMETERS 5256 <TBD>. 5257 5258 RETURN VALUE 5259 OMX Error None if everything went well. 5260 5261 ========================================================================== */ 5262 OMX_ERRORTYPE omx_vdec::allocate_output_buffer( 5263 OMX_IN OMX_HANDLETYPE hComp, 5264 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5265 OMX_IN OMX_U32 port, 5266 OMX_IN OMX_PTR appData, 5267 OMX_IN OMX_U32 bytes) 5268 { 5269 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5270 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 5271 unsigned i= 0; // Temporary counter 5272 struct vdec_setbuffer_cmd setbuffers; 5273 int extra_idx = 0; 5274 #ifdef USE_ION 5275 int ion_device_fd =-1; 5276 struct ion_allocation_data ion_alloc_data; 5277 struct ion_fd_data fd_ion_data; 5278 #endif 5279 if(!m_out_mem_ptr) 5280 { 5281 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%d)", 5282 drv_ctx.op_buf.actualcount, 5283 drv_ctx.op_buf.buffer_size); 5284 int nBufHdrSize = 0; 5285 int nPlatformEntrySize = 0; 5286 int nPlatformListSize = 0; 5287 int nPMEMInfoSize = 0; 5288 int pmem_fd = -1; 5289 unsigned char *pmem_baseaddress = NULL; 5290 5291 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 5292 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 5293 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 5294 5295 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)", 5296 drv_ctx.op_buf.actualcount); 5297 nBufHdrSize = drv_ctx.op_buf.actualcount * 5298 sizeof(OMX_BUFFERHEADERTYPE); 5299 5300 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 5301 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 5302 nPlatformListSize = drv_ctx.op_buf.actualcount * 5303 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 5304 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 5305 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 5306 5307 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, 5308 sizeof(OMX_BUFFERHEADERTYPE), 5309 nPMEMInfoSize, 5310 nPlatformListSize); 5311 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, 5312 drv_ctx.op_buf.actualcount); 5313 #ifdef USE_ION 5314 DEBUG_PRINT_HIGH("allocate outputBuffer size %d",drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount); 5315 int heap_id = 0; 5316 int flags = secure_mode ? ION_SECURE : 0; 5317 if (!m_pSwVdec) { 5318 #ifdef _HEVC_USE_ADSP_HEAP_ 5319 heap_id = ION_ADSP_HEAP_ID; 5320 #endif 5321 } 5322 ion_device_fd = alloc_map_ion_memory( 5323 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount, 5324 drv_ctx.op_buf.alignment, 5325 &ion_alloc_data, &fd_ion_data,flags, heap_id); 5326 if (ion_device_fd < 0) { 5327 return OMX_ErrorInsufficientResources; 5328 } 5329 pmem_fd = fd_ion_data.fd; 5330 #else 5331 pmem_fd = open (MEM_DEVICE,O_RDWR); 5332 5333 if (pmem_fd < 0) 5334 { 5335 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 5336 drv_ctx.op_buf.buffer_size); 5337 return OMX_ErrorInsufficientResources; 5338 } 5339 5340 if(pmem_fd == 0) 5341 { 5342 pmem_fd = open (MEM_DEVICE,O_RDWR); 5343 5344 if (pmem_fd < 0) 5345 { 5346 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 5347 drv_ctx.op_buf.buffer_size); 5348 return OMX_ErrorInsufficientResources; 5349 } 5350 } 5351 5352 if(!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size * 5353 drv_ctx.op_buf.actualcount, 5354 drv_ctx.op_buf.alignment)) 5355 { 5356 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 5357 close(pmem_fd); 5358 return OMX_ErrorInsufficientResources; 5359 } 5360 #endif 5361 if (!secure_mode) { 5362 pmem_baseaddress = (unsigned char *)mmap(NULL, 5363 (drv_ctx.op_buf.buffer_size * 5364 drv_ctx.op_buf.actualcount), 5365 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); 5366 if (pmem_baseaddress == MAP_FAILED) 5367 { 5368 DEBUG_PRINT_ERROR("MMAP failed for Size %d", 5369 drv_ctx.op_buf.buffer_size); 5370 close(pmem_fd); 5371 #ifdef USE_ION 5372 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 5373 #endif 5374 return OMX_ErrorInsufficientResources; 5375 } 5376 } 5377 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 5378 // Alloc mem for platform specific info 5379 char *pPtr=NULL; 5380 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 5381 nPMEMInfoSize,1); 5382 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ 5383 calloc (sizeof(struct vdec_bufferpayload), 5384 drv_ctx.op_buf.actualcount); 5385 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 5386 calloc (sizeof (struct vdec_output_frameinfo), 5387 drv_ctx.op_buf.actualcount); 5388 #ifdef USE_ION 5389 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ 5390 calloc (sizeof(struct vdec_ion), 5391 drv_ctx.op_buf.actualcount); 5392 #endif 5393 5394 if (m_pSwVdec && m_pSwVdecOpBuffer == NULL) 5395 { 5396 m_pSwVdecOpBuffer = (SWVDEC_OPBUFFER*)calloc(sizeof(SWVDEC_OPBUFFER), drv_ctx.op_buf.actualcount); 5397 } 5398 if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer && drv_ctx.ptr_respbuffer 5399 && ((m_pSwVdec && m_pSwVdecOpBuffer) || (!m_pSwVdec)) ) 5400 { 5401 drv_ctx.ptr_outputbuffer[0].mmaped_size = 5402 (drv_ctx.op_buf.buffer_size * 5403 drv_ctx.op_buf.actualcount); 5404 bufHdr = m_out_mem_ptr; 5405 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 5406 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 5407 (((char *) m_platform_list) + nPlatformListSize); 5408 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 5409 (((char *) m_platform_entry) + nPlatformEntrySize); 5410 pPlatformList = m_platform_list; 5411 pPlatformEntry = m_platform_entry; 5412 pPMEMInfo = m_pmem_info; 5413 5414 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 5415 5416 // Settting the entire storage nicely 5417 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry); 5418 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 5419 for(i=0; i < drv_ctx.op_buf.actualcount ; i++) 5420 { 5421 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5422 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 5423 // Set the values when we determine the right HxW param 5424 bufHdr->nAllocLen = bytes; 5425 bufHdr->nFilledLen = 0; 5426 bufHdr->pAppPrivate = appData; 5427 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 5428 // Platform specific PMEM Information 5429 // Initialize the Platform Entry 5430 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i); 5431 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 5432 pPlatformEntry->entry = pPMEMInfo; 5433 // Initialize the Platform List 5434 pPlatformList->nEntries = 1; 5435 pPlatformList->entryList = pPlatformEntry; 5436 // Keep pBuffer NULL till vdec is opened 5437 bufHdr->pBuffer = NULL; 5438 bufHdr->nOffset = 0; 5439 5440 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i; 5441 pPMEMInfo->pmem_fd = 0; 5442 bufHdr->pPlatformPrivate = pPlatformList; 5443 5444 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd; 5445 m_pmem_info[i].pmem_fd = pmem_fd; 5446 #ifdef USE_ION 5447 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd; 5448 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data; 5449 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data; 5450 #endif 5451 5452 /*Create a mapping between buffers*/ 5453 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 5454 drv_ctx.ptr_respbuffer[i].client_data = (void *)\ 5455 &drv_ctx.ptr_outputbuffer[i]; 5456 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i; 5457 drv_ctx.ptr_outputbuffer[i].bufferaddr = 5458 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i); 5459 5460 DEBUG_PRINT_LOW("pmem_fd = %d offset = %d address = %p", 5461 pmem_fd, drv_ctx.ptr_outputbuffer[i].offset, 5462 drv_ctx.ptr_outputbuffer[i].bufferaddr); 5463 // Move the buffer and buffer header pointers 5464 bufHdr++; 5465 pPMEMInfo++; 5466 pPlatformEntry++; 5467 pPlatformList++; 5468 } 5469 } 5470 else 5471 { 5472 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 5473 m_out_mem_ptr, pPtr); 5474 if(m_out_mem_ptr) 5475 { 5476 free(m_out_mem_ptr); 5477 m_out_mem_ptr = NULL; 5478 } 5479 if(pPtr) 5480 { 5481 free(pPtr); 5482 pPtr = NULL; 5483 } 5484 if(drv_ctx.ptr_outputbuffer) 5485 { 5486 free(drv_ctx.ptr_outputbuffer); 5487 drv_ctx.ptr_outputbuffer = NULL; 5488 } 5489 if(drv_ctx.ptr_respbuffer) 5490 { 5491 free(drv_ctx.ptr_respbuffer); 5492 drv_ctx.ptr_respbuffer = NULL; 5493 } 5494 #ifdef USE_ION 5495 if (drv_ctx.op_buf_ion_info) { 5496 DEBUG_PRINT_LOW("Free o/p ion context"); 5497 free(drv_ctx.op_buf_ion_info); 5498 drv_ctx.op_buf_ion_info = NULL; 5499 } 5500 #endif 5501 eRet = OMX_ErrorInsufficientResources; 5502 } 5503 if ( (!m_pSwVdec) && (eRet == OMX_ErrorNone) ) 5504 eRet = allocate_extradata(); 5505 } 5506 5507 for(i=0; i< drv_ctx.op_buf.actualcount; i++) 5508 { 5509 if(BITMASK_ABSENT(&m_out_bm_count,i)) 5510 { 5511 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i); 5512 break; 5513 } 5514 } 5515 5516 if (eRet == OMX_ErrorNone) 5517 { 5518 if(i < drv_ctx.op_buf.actualcount) 5519 { 5520 int rc; 5521 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 5522 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 5523 5524 *bufferHdr = (m_out_mem_ptr + i ); 5525 if (secure_mode) { 5526 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 5527 } 5528 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; 5529 5530 if (m_pSwVdec) 5531 { 5532 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 5533 (*bufferHdr)->pAppPrivate = appData; 5534 m_pSwVdecOpBuffer[i].nSize = drv_ctx.ptr_outputbuffer[i].mmaped_size; 5535 m_pSwVdecOpBuffer[i].pBuffer = (*bufferHdr)->pBuffer; 5536 m_pSwVdecOpBuffer[i].pClientBufferData = (void*)i; 5537 SwVdec_SetOutputBuffer(m_pSwVdec, &m_pSwVdecOpBuffer[i]); 5538 } 5539 else 5540 { 5541 struct v4l2_buffer buf; 5542 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 5543 buf.index = i; 5544 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5545 buf.memory = V4L2_MEMORY_USERPTR; 5546 plane[0].length = drv_ctx.op_buf.buffer_size; 5547 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 5548 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 5549 #ifdef USE_ION 5550 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 5551 #endif 5552 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 5553 plane[0].data_offset = 0; 5554 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 5555 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 5556 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 5557 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 5558 #ifdef USE_ION 5559 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 5560 #endif 5561 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 5562 plane[extra_idx].data_offset = 0; 5563 } else if (extra_idx >= VIDEO_MAX_PLANES) { 5564 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx); 5565 return OMX_ErrorBadParameter; 5566 } 5567 buf.m.planes = plane; 5568 buf.length = drv_ctx.num_planes; 5569 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, (unsigned int)drv_ctx.ptr_outputbuffer[i].bufferaddr); 5570 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 5571 if (rc) { 5572 /*TODO: How to handle this case */ 5573 return OMX_ErrorInsufficientResources; 5574 } 5575 5576 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { 5577 enum v4l2_buf_type buf_type; 5578 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5579 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 5580 if (rc) { 5581 return OMX_ErrorInsufficientResources; 5582 } else { 5583 streaming[CAPTURE_PORT] = true; 5584 DEBUG_PRINT_LOW("STREAMON Successful"); 5585 } 5586 } 5587 } 5588 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 5589 (*bufferHdr)->pAppPrivate = appData; 5590 BITMASK_SET(&m_out_bm_count,i); 5591 } 5592 else 5593 { 5594 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient"); 5595 eRet = OMX_ErrorInsufficientResources; 5596 } 5597 } 5598 5599 return eRet; 5600 } 5601 5602 5603 // AllocateBuffer -- API Call 5604 /* ====================================================================== 5605 FUNCTION 5606 omx_vdec::AllocateBuffer 5607 5608 DESCRIPTION 5609 Returns zero if all the buffers released.. 5610 5611 PARAMETERS 5612 None. 5613 5614 RETURN VALUE 5615 true/false 5616 5617 ========================================================================== */ 5618 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, 5619 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5620 OMX_IN OMX_U32 port, 5621 OMX_IN OMX_PTR appData, 5622 OMX_IN OMX_U32 bytes) 5623 { 5624 unsigned i = 0; 5625 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type 5626 5627 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port); 5628 if(m_state == OMX_StateInvalid) 5629 { 5630 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State"); 5631 return OMX_ErrorInvalidState; 5632 } 5633 5634 if(port == OMX_CORE_INPUT_PORT_INDEX) 5635 { 5636 if (arbitrary_bytes) 5637 { 5638 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); 5639 } 5640 else 5641 { 5642 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); 5643 } 5644 } 5645 else if(port == OMX_CORE_OUTPUT_PORT_INDEX) 5646 { 5647 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port, 5648 appData,bytes); 5649 } 5650 else 5651 { 5652 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 5653 eRet = OMX_ErrorBadPortIndex; 5654 } 5655 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); 5656 if(eRet == OMX_ErrorNone) 5657 { 5658 if(allocate_done()) 5659 { 5660 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 5661 { 5662 // Send the callback now 5663 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 5664 post_event(OMX_CommandStateSet,OMX_StateIdle, 5665 OMX_COMPONENT_GENERATE_EVENT); 5666 } 5667 if (m_pSwVdec) 5668 { 5669 DEBUG_PRINT_LOW("allocate_buffer: SwVdec_Start"); 5670 SwVdec_Start(m_pSwVdec); 5671 } 5672 } 5673 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) 5674 { 5675 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) 5676 { 5677 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 5678 post_event(OMX_CommandPortEnable, 5679 OMX_CORE_INPUT_PORT_INDEX, 5680 OMX_COMPONENT_GENERATE_EVENT); 5681 } 5682 } 5683 if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) 5684 { 5685 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) 5686 { 5687 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 5688 post_event(OMX_CommandPortEnable, 5689 OMX_CORE_OUTPUT_PORT_INDEX, 5690 OMX_COMPONENT_GENERATE_EVENT); 5691 } 5692 } 5693 } 5694 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet); 5695 return eRet; 5696 } 5697 5698 // Free Buffer - API call 5699 /* ====================================================================== 5700 FUNCTION 5701 omx_vdec::FreeBuffer 5702 5703 DESCRIPTION 5704 5705 PARAMETERS 5706 None. 5707 5708 RETURN VALUE 5709 true/false 5710 5711 ========================================================================== */ 5712 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, 5713 OMX_IN OMX_U32 port, 5714 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 5715 { 5716 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5717 unsigned int nPortIndex; 5718 5719 if(m_state == OMX_StateIdle && 5720 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) 5721 { 5722 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); 5723 } 5724 else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| 5725 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) 5726 { 5727 DEBUG_PRINT_LOW("Free Buffer while port %d disabled", (int)port); 5728 } 5729 else if ((port == OMX_CORE_INPUT_PORT_INDEX && 5730 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) || 5731 (port == OMX_CORE_OUTPUT_PORT_INDEX && 5732 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) 5733 { 5734 DEBUG_PRINT_LOW("Free Buffer while port %d enable pending", (int)port); 5735 } 5736 else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) 5737 { 5738 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled"); 5739 post_event(OMX_EventError, 5740 OMX_ErrorPortUnpopulated, 5741 OMX_COMPONENT_GENERATE_EVENT); 5742 5743 return OMX_ErrorIncorrectStateOperation; 5744 } 5745 else if (m_state != OMX_StateInvalid) 5746 { 5747 DEBUG_PRINT_ERROR("Invalid state %d to free buffer,port %d lost Buffers", m_state, (int)port); 5748 post_event(OMX_EventError, 5749 OMX_ErrorPortUnpopulated, 5750 OMX_COMPONENT_GENERATE_EVENT); 5751 } 5752 5753 if(port == OMX_CORE_INPUT_PORT_INDEX) 5754 { 5755 /*Check if arbitrary bytes*/ 5756 if(!arbitrary_bytes && !input_use_buffer) 5757 nPortIndex = buffer - m_inp_mem_ptr; 5758 else 5759 nPortIndex = buffer - m_inp_heap_ptr; 5760 5761 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); 5762 if(nPortIndex < drv_ctx.ip_buf.actualcount) 5763 { 5764 // Clear the bit associated with it. 5765 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); 5766 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); 5767 if (input_use_buffer == true) 5768 { 5769 5770 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex); 5771 if(m_phdr_pmem_ptr) 5772 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); 5773 } 5774 else 5775 { 5776 if (arbitrary_bytes) 5777 { 5778 if(m_phdr_pmem_ptr) 5779 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); 5780 else 5781 free_input_buffer(nPortIndex,NULL); 5782 } 5783 else 5784 free_input_buffer(buffer); 5785 } 5786 m_inp_bPopulated = OMX_FALSE; 5787 /*Free the Buffer Header*/ 5788 if (release_input_done()) 5789 { 5790 DEBUG_PRINT_HIGH("ALL input buffers are freed/released"); 5791 free_input_buffer_header(); 5792 } 5793 } 5794 else 5795 { 5796 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid"); 5797 eRet = OMX_ErrorBadPortIndex; 5798 } 5799 5800 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) 5801 && release_input_done()) 5802 { 5803 DEBUG_PRINT_LOW("MOVING TO INPUT DISABLED STATE"); 5804 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); 5805 post_event(OMX_CommandPortDisable, 5806 OMX_CORE_INPUT_PORT_INDEX, 5807 OMX_COMPONENT_GENERATE_EVENT); 5808 } 5809 } 5810 else if(port == OMX_CORE_OUTPUT_PORT_INDEX) 5811 { 5812 // check if the buffer is valid 5813 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 5814 if(nPortIndex < drv_ctx.op_buf.actualcount) 5815 { 5816 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); 5817 // Clear the bit associated with it. 5818 BITMASK_CLEAR(&m_out_bm_count,nPortIndex); 5819 m_out_bPopulated = OMX_FALSE; 5820 client_buffers.free_output_buffer (buffer); 5821 5822 if (release_output_done()) 5823 { 5824 free_output_buffer_header(); 5825 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 5826 { 5827 DEBUG_PRINT_LOW("release_output_done: start free_interm_buffers"); 5828 free_interm_buffers(); 5829 } 5830 } 5831 } 5832 else 5833 { 5834 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid"); 5835 eRet = OMX_ErrorBadPortIndex; 5836 } 5837 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) 5838 && release_output_done()) 5839 { 5840 DEBUG_PRINT_LOW("MOVING TO OUTPUT DISABLED STATE"); 5841 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 5842 #ifdef _ANDROID_ICS_ 5843 if (m_enable_android_native_buffers) 5844 { 5845 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); 5846 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 5847 } 5848 #endif 5849 5850 post_event(OMX_CommandPortDisable, 5851 OMX_CORE_OUTPUT_PORT_INDEX, 5852 OMX_COMPONENT_GENERATE_EVENT); 5853 } 5854 } 5855 else 5856 { 5857 eRet = OMX_ErrorBadPortIndex; 5858 } 5859 if((eRet == OMX_ErrorNone) && 5860 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) 5861 { 5862 if(release_done()) 5863 { 5864 // Send the callback now 5865 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); 5866 if (m_pSwVdec) 5867 { 5868 SwVdec_Stop(m_pSwVdec); 5869 } 5870 post_event(OMX_CommandStateSet, OMX_StateLoaded, 5871 OMX_COMPONENT_GENERATE_EVENT); 5872 } 5873 } 5874 return eRet; 5875 } 5876 5877 5878 /* ====================================================================== 5879 FUNCTION 5880 omx_vdec::EmptyThisBuffer 5881 5882 DESCRIPTION 5883 This routine is used to push the encoded video frames to 5884 the video decoder. 5885 5886 PARAMETERS 5887 None. 5888 5889 RETURN VALUE 5890 OMX Error None if everything went successful. 5891 5892 ========================================================================== */ 5893 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 5894 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 5895 { 5896 OMX_ERRORTYPE ret1 = OMX_ErrorNone; 5897 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; 5898 5899 if(m_state == OMX_StateInvalid) 5900 { 5901 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State"); 5902 return OMX_ErrorInvalidState; 5903 } 5904 5905 if (buffer == NULL) 5906 { 5907 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL"); 5908 return OMX_ErrorBadParameter; 5909 } 5910 5911 if (!m_inp_bEnabled) 5912 { 5913 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled."); 5914 return OMX_ErrorIncorrectStateOperation; 5915 } 5916 5917 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) 5918 { 5919 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %lu", buffer->nInputPortIndex); 5920 return OMX_ErrorBadPortIndex; 5921 } 5922 5923 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) 5924 { 5925 codec_config_flag = true; 5926 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); 5927 } 5928 5929 #ifdef _ANDROID_ 5930 if(iDivXDrmDecrypt) 5931 { 5932 OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer); 5933 if(drmErr != OMX_ErrorNone) { 5934 // this error can be ignored 5935 DEBUG_PRINT_LOW("ERROR:iDivXDrmDecrypt->Decrypt %d", drmErr); 5936 } 5937 } 5938 #endif //_ANDROID_ 5939 if (perf_flag) 5940 { 5941 if (!latency) 5942 { 5943 dec_time.stop(); 5944 latency = dec_time.processing_time_us(); 5945 dec_time.start(); 5946 } 5947 } 5948 5949 if (arbitrary_bytes) 5950 { 5951 nBufferIndex = buffer - m_inp_heap_ptr; 5952 } 5953 else 5954 { 5955 if (input_use_buffer == true) 5956 { 5957 nBufferIndex = buffer - m_inp_heap_ptr; 5958 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; 5959 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; 5960 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; 5961 buffer = &m_inp_mem_ptr[nBufferIndex]; 5962 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %lu", 5963 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen); 5964 } 5965 else{ 5966 nBufferIndex = buffer - m_inp_mem_ptr; 5967 } 5968 } 5969 5970 if (nBufferIndex > drv_ctx.ip_buf.actualcount ) 5971 { 5972 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); 5973 return OMX_ErrorBadParameter; 5974 } 5975 5976 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu) nFlags(%lu)", 5977 buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen, buffer->nFlags); 5978 if (arbitrary_bytes) 5979 { 5980 post_event ((unsigned)hComp,(unsigned)buffer, 5981 OMX_COMPONENT_GENERATE_ETB_ARBITRARY); 5982 } 5983 else 5984 { 5985 if (!(client_extradata & OMX_TIMEINFO_EXTRADATA)) 5986 set_frame_rate(buffer->nTimeStamp); 5987 post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB); 5988 } 5989 return OMX_ErrorNone; 5990 } 5991 5992 /* ====================================================================== 5993 FUNCTION 5994 omx_vdec::empty_this_buffer_proxy 5995 5996 DESCRIPTION 5997 This routine is used to push the encoded video frames to 5998 the video decoder. 5999 6000 PARAMETERS 6001 None. 6002 6003 RETURN VALUE 6004 OMX Error None if everything went successful. 6005 6006 ========================================================================== */ 6007 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, 6008 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6009 { 6010 int push_cnt = 0,i=0; 6011 unsigned nPortIndex = 0; 6012 OMX_ERRORTYPE ret = OMX_ErrorNone; 6013 struct vdec_input_frameinfo frameinfo; 6014 struct vdec_bufferpayload *temp_buffer; 6015 struct vdec_seqheader seq_header; 6016 bool port_setting_changed = true; 6017 bool not_coded_vop = false; 6018 6019 /*Should we generate a Aync error event*/ 6020 if (buffer == NULL || buffer->pInputPortPrivate == NULL) 6021 { 6022 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid"); 6023 return OMX_ErrorBadParameter; 6024 } 6025 6026 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 6027 6028 if (nPortIndex > drv_ctx.ip_buf.actualcount) 6029 { 6030 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", 6031 nPortIndex); 6032 return OMX_ErrorBadParameter; 6033 } 6034 6035 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY && m_fill_internal_bufers) 6036 { 6037 fill_all_buffers_proxy_dsp(hComp); 6038 } 6039 6040 pending_input_buffers++; 6041 6042 /* return zero length and not an EOS buffer */ 6043 if (!arbitrary_bytes && (buffer->nFilledLen == 0) && 6044 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) 6045 { 6046 DEBUG_PRINT_HIGH("return zero legth buffer"); 6047 post_event ((unsigned int)buffer,VDEC_S_SUCCESS, 6048 OMX_COMPONENT_GENERATE_EBD); 6049 return OMX_ErrorNone; 6050 } 6051 6052 if(input_flush_progress == true 6053 6054 || not_coded_vop 6055 6056 ) 6057 { 6058 DEBUG_PRINT_LOW("Flush in progress return buffer "); 6059 post_event ((unsigned int)buffer,VDEC_S_SUCCESS, 6060 OMX_COMPONENT_GENERATE_EBD); 6061 return OMX_ErrorNone; 6062 } 6063 6064 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; 6065 6066 if ((temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) 6067 { 6068 return OMX_ErrorBadParameter; 6069 } 6070 6071 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 6072 /*for use buffer we need to memcpy the data*/ 6073 temp_buffer->buffer_len = buffer->nFilledLen; 6074 6075 if (input_use_buffer) 6076 { 6077 if (buffer->nFilledLen <= temp_buffer->buffer_len) 6078 { 6079 if(arbitrary_bytes) 6080 { 6081 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); 6082 } 6083 else 6084 { 6085 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), 6086 buffer->nFilledLen); 6087 } 6088 } 6089 else 6090 { 6091 return OMX_ErrorBadParameter; 6092 } 6093 6094 } 6095 6096 frameinfo.bufferaddr = temp_buffer->bufferaddr; 6097 frameinfo.client_data = (void *) buffer; 6098 frameinfo.datalen = temp_buffer->buffer_len; 6099 frameinfo.flags = 0; 6100 frameinfo.offset = buffer->nOffset; 6101 frameinfo.pmem_fd = temp_buffer->pmem_fd; 6102 frameinfo.pmem_offset = temp_buffer->offset; 6103 frameinfo.timestamp = buffer->nTimeStamp; 6104 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) 6105 { 6106 DEBUG_PRINT_LOW("ETB: dmx enabled"); 6107 if (m_demux_entries == 0) 6108 { 6109 extract_demux_addr_offsets(buffer); 6110 } 6111 6112 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d", (int)m_demux_entries); 6113 handle_demux_data(buffer); 6114 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; 6115 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; 6116 } 6117 else 6118 { 6119 frameinfo.desc_addr = NULL; 6120 frameinfo.desc_size = 0; 6121 } 6122 if(!arbitrary_bytes) 6123 { 6124 frameinfo.flags |= buffer->nFlags; 6125 } 6126 6127 #ifdef _ANDROID_ 6128 if (m_debug_timestamp) 6129 { 6130 if(arbitrary_bytes) 6131 { 6132 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 6133 m_timestamp_list.insert_ts(buffer->nTimeStamp); 6134 } 6135 else if(!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) 6136 { 6137 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 6138 m_timestamp_list.insert_ts(buffer->nTimeStamp); 6139 } 6140 } 6141 #endif 6142 6143 if (m_debug.in_buffer_log) 6144 { 6145 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); 6146 } 6147 6148 if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) 6149 { 6150 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 6151 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 6152 } 6153 6154 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) 6155 { 6156 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached"); 6157 frameinfo.flags |= VDEC_BUFFERFLAG_EOS; 6158 h264_scratch.nFilledLen = 0; 6159 nal_count = 0; 6160 look_ahead_nal = false; 6161 frame_count = 0; 6162 if (m_frame_parser.mutils) 6163 m_frame_parser.mutils->initialize_frame_checking_environment(); 6164 m_frame_parser.flush(); 6165 h264_last_au_ts = LLONG_MAX; 6166 h264_last_au_flags = 0; 6167 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 6168 m_demux_entries = 0; 6169 } 6170 6171 if ( (!m_pSwVdec) || (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) ) 6172 { 6173 struct v4l2_buffer buf; 6174 struct v4l2_plane plane; 6175 memset( (void *)&buf, 0, sizeof(buf)); 6176 memset( (void *)&plane, 0, sizeof(plane)); 6177 int rc; 6178 unsigned long print_count; 6179 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) 6180 { 6181 buf.flags = V4L2_QCOM_BUF_FLAG_EOS; 6182 DEBUG_PRINT_HIGH("INPUT EOS reached") ; 6183 } 6184 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6185 buf.index = nPortIndex; 6186 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6187 buf.memory = V4L2_MEMORY_USERPTR; 6188 plane.bytesused = temp_buffer->buffer_len; 6189 plane.length = drv_ctx.ip_buf.buffer_size; 6190 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr - 6191 (unsigned long)temp_buffer->offset; 6192 plane.reserved[0] = temp_buffer->pmem_fd; 6193 plane.reserved[1] = temp_buffer->offset; 6194 plane.data_offset = 0; 6195 buf.m.planes = &plane; 6196 buf.length = 1; 6197 if (frameinfo.timestamp >= LLONG_MAX) { 6198 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID; 6199 } 6200 //assumption is that timestamp is in milliseconds 6201 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000; 6202 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000); 6203 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0; 6204 6205 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 6206 if(rc) 6207 { 6208 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver"); 6209 return OMX_ErrorHardware; 6210 } 6211 codec_config_flag = false; 6212 DEBUG_PRINT_LOW("%s: codec_config cleared", __FUNCTION__); 6213 if(!streaming[OUTPUT_PORT]) 6214 { 6215 enum v4l2_buf_type buf_type; 6216 int ret,r; 6217 6218 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6219 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 6220 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 6221 if(!ret) { 6222 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful"); 6223 streaming[OUTPUT_PORT] = true; 6224 } else { 6225 /*TODO: How to handle this case */ 6226 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT"); 6227 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued"); 6228 post_event ((unsigned int)buffer,VDEC_S_SUCCESS, 6229 OMX_COMPONENT_GENERATE_EBD); 6230 return OMX_ErrorBadParameter; 6231 } 6232 } 6233 } 6234 else if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 6235 { 6236 // send this to the swvdec 6237 DEBUG_PRINT_HIGH("empty_this_buffer_proxy bufHdr %p pBuffer %p nFilledLen %lu m_pSwVdecIpBuffer %p, idx %d", 6238 buffer, buffer->pBuffer, buffer->nFilledLen, m_pSwVdecIpBuffer, nPortIndex); 6239 m_pSwVdecIpBuffer[nPortIndex].nFlags = buffer->nFlags; 6240 m_pSwVdecIpBuffer[nPortIndex].nFilledLen = buffer->nFilledLen; 6241 m_pSwVdecIpBuffer[nPortIndex].nIpTimestamp = buffer->nTimeStamp; 6242 6243 if (SwVdec_EmptyThisBuffer(m_pSwVdec, &m_pSwVdecIpBuffer[nPortIndex]) != SWVDEC_S_SUCCESS) { 6244 ret = OMX_ErrorBadParameter; 6245 } 6246 } 6247 6248 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)", 6249 frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen); 6250 time_stamp_dts.insert_timestamp(buffer); 6251 return ret; 6252 } 6253 6254 /* ====================================================================== 6255 FUNCTION 6256 omx_vdec::FillThisBuffer 6257 6258 DESCRIPTION 6259 IL client uses this method to release the frame buffer 6260 after displaying them. 6261 6262 PARAMETERS 6263 None. 6264 6265 RETURN VALUE 6266 true/false 6267 6268 ========================================================================== */ 6269 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 6270 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6271 { 6272 if(m_state == OMX_StateInvalid) 6273 { 6274 DEBUG_PRINT_ERROR("FTB in Invalid State"); 6275 return OMX_ErrorInvalidState; 6276 } 6277 6278 if (!m_out_bEnabled) 6279 { 6280 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); 6281 return OMX_ErrorIncorrectStateOperation; 6282 } 6283 6284 unsigned int nPortIndex = (unsigned int)(buffer - client_buffers.get_il_buf_hdr()); 6285 if (!buffer || !buffer->pBuffer || nPortIndex >= drv_ctx.op_buf.actualcount) 6286 { 6287 DEBUG_PRINT_ERROR("ERROR:FTB invalid bufHdr %p, nPortIndex %u", buffer, nPortIndex); 6288 return OMX_ErrorBadParameter; 6289 } 6290 6291 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) 6292 { 6293 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %lu", buffer->nOutputPortIndex); 6294 return OMX_ErrorBadPortIndex; 6295 } 6296 6297 if (dynamic_buf_mode) { 6298 private_handle_t *handle = NULL; 6299 struct VideoDecoderOutputMetaData *meta; 6300 OMX_U8 *buff = NULL; 6301 6302 //get the buffer type and fd info 6303 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer; 6304 handle = (private_handle_t *)meta->pHandle; 6305 DEBUG_PRINT_LOW("FTB: buftype: %d bufhndl: %p", meta->eType, meta->pHandle); 6306 6307 pthread_mutex_lock(&m_lock); 6308 if (out_dynamic_list[nPortIndex].ref_count == 0) { 6309 6310 //map the buffer handle based on the size set on output port definition. 6311 if (!secure_mode) { 6312 buff = (OMX_U8*)mmap(0, drv_ctx.op_buf.buffer_size, 6313 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 6314 } else { 6315 buff = (OMX_U8*) buffer; 6316 } 6317 6318 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd; 6319 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0; 6320 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = buff; 6321 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = drv_ctx.op_buf.buffer_size; 6322 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = drv_ctx.op_buf.buffer_size; 6323 DEBUG_PRINT_LOW("fill_this_buffer: bufHdr %p idx %d mapped pBuffer %p size %u", buffer, nPortIndex, buff, drv_ctx.op_buf.buffer_size); 6324 if (m_pSwVdecOpBuffer) { 6325 m_pSwVdecOpBuffer[nPortIndex].nSize = drv_ctx.op_buf.buffer_size; 6326 m_pSwVdecOpBuffer[nPortIndex].pBuffer = buff; 6327 } 6328 } 6329 pthread_mutex_unlock(&m_lock); 6330 buf_ref_add(nPortIndex, drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 6331 drv_ctx.ptr_outputbuffer[nPortIndex].offset); 6332 } 6333 6334 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 6335 post_event((unsigned) hComp, (unsigned)buffer, m_fill_output_msg); 6336 return OMX_ErrorNone; 6337 } 6338 /* ====================================================================== 6339 FUNCTION 6340 omx_vdec::fill_this_buffer_proxy 6341 6342 DESCRIPTION 6343 IL client uses this method to release the frame buffer 6344 after displaying them. 6345 6346 PARAMETERS 6347 None. 6348 6349 RETURN VALUE 6350 true/false 6351 6352 ========================================================================== */ 6353 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( 6354 OMX_IN OMX_HANDLETYPE hComp, 6355 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) 6356 { 6357 OMX_ERRORTYPE nRet = OMX_ErrorNone; 6358 OMX_BUFFERHEADERTYPE *buffer = bufferAdd; 6359 unsigned nPortIndex = 0; 6360 struct vdec_fillbuffer_cmd fillbuffer; 6361 struct vdec_bufferpayload *ptr_outputbuffer = NULL; 6362 struct vdec_output_frameinfo *ptr_respbuffer = NULL; 6363 6364 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 6365 6366 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) 6367 { 6368 DEBUG_PRINT_ERROR("FTBProxy: bufhdr = %p, nPortIndex %u bufCount %u", 6369 bufferAdd, nPortIndex, drv_ctx.op_buf.actualcount); 6370 return OMX_ErrorBadParameter; 6371 } 6372 6373 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", 6374 bufferAdd, bufferAdd->pBuffer); 6375 /*Return back the output buffer to client*/ 6376 if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true) 6377 { 6378 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition"); 6379 buffer->nFilledLen = 0; 6380 m_cb.FillBufferDone (hComp,m_app_data,buffer); 6381 return OMX_ErrorNone; 6382 } 6383 pending_output_buffers++; 6384 buffer = client_buffers.get_dr_buf_hdr(bufferAdd); 6385 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; 6386 if (ptr_respbuffer) 6387 { 6388 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; 6389 } 6390 6391 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) 6392 { 6393 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); 6394 buffer->nFilledLen = 0; 6395 m_cb.FillBufferDone (hComp,m_app_data,buffer); 6396 pending_output_buffers--; 6397 return OMX_ErrorBadParameter; 6398 } 6399 6400 if (m_pSwVdec) 6401 { 6402 DEBUG_PRINT_HIGH("SwVdec_FillThisBuffer idx %d, bufHdr %p pBuffer %p", nPortIndex, 6403 bufferAdd, m_pSwVdecOpBuffer[nPortIndex].pBuffer); 6404 if (SWVDEC_S_SUCCESS != SwVdec_FillThisBuffer(m_pSwVdec, &m_pSwVdecOpBuffer[nPortIndex])) 6405 { 6406 DEBUG_PRINT_ERROR("SwVdec_FillThisBuffer failed"); 6407 } 6408 } 6409 else 6410 { 6411 int rc = 0; 6412 struct v4l2_buffer buf; 6413 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 6414 memset( (void *)&buf, 0, sizeof(buf)); 6415 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); 6416 int extra_idx = 0; 6417 6418 buf.index = nPortIndex; 6419 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6420 buf.memory = V4L2_MEMORY_USERPTR; 6421 plane[0].bytesused = buffer->nFilledLen; 6422 plane[0].length = drv_ctx.op_buf.buffer_size; 6423 plane[0].m.userptr = 6424 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr - 6425 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset; 6426 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 6427 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 6428 plane[0].data_offset = 0; 6429 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 6430 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 6431 plane[extra_idx].bytesused = 0; 6432 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 6433 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size); 6434 #ifdef USE_ION 6435 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 6436 #endif 6437 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; 6438 plane[extra_idx].data_offset = 0; 6439 } else if (extra_idx >= VIDEO_MAX_PLANES) { 6440 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx); 6441 return OMX_ErrorBadParameter; 6442 } 6443 buf.m.planes = plane; 6444 buf.length = drv_ctx.num_planes; 6445 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 6446 if (rc) { 6447 /*TODO: How to handle this case */ 6448 DEBUG_PRINT_ERROR("Failed to qbuf to driver"); 6449 } 6450 } 6451 return OMX_ErrorNone; 6452 } 6453 6454 /* ====================================================================== 6455 FUNCTION 6456 omx_vdec::SetCallbacks 6457 6458 DESCRIPTION 6459 Set the callbacks. 6460 6461 PARAMETERS 6462 None. 6463 6464 RETURN VALUE 6465 OMX Error None if everything successful. 6466 6467 ========================================================================== */ 6468 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, 6469 OMX_IN OMX_CALLBACKTYPE* callbacks, 6470 OMX_IN OMX_PTR appData) 6471 { 6472 6473 m_cb = *callbacks; 6474 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ 6475 m_cb.EventHandler,m_cb.FillBufferDone); 6476 m_app_data = appData; 6477 return OMX_ErrorNotImplemented; 6478 } 6479 6480 /* ====================================================================== 6481 FUNCTION 6482 omx_vdec::ComponentDeInit 6483 6484 DESCRIPTION 6485 Destroys the component and release memory allocated to the heap. 6486 6487 PARAMETERS 6488 <TBD>. 6489 6490 RETURN VALUE 6491 OMX Error None if everything successful. 6492 6493 ========================================================================== */ 6494 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) 6495 { 6496 #ifdef _ANDROID_ 6497 if(iDivXDrmDecrypt) 6498 { 6499 delete iDivXDrmDecrypt; 6500 iDivXDrmDecrypt=NULL; 6501 } 6502 #endif //_ANDROID_ 6503 6504 unsigned i = 0; 6505 if (OMX_StateLoaded != m_state) 6506 { 6507 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\ 6508 m_state); 6509 DEBUG_PRINT_ERROR("Playback Ended - FAILED"); 6510 } 6511 else 6512 { 6513 DEBUG_PRINT_HIGH("Playback Ended - PASSED"); 6514 } 6515 6516 /*Check if the output buffers have to be cleaned up*/ 6517 if(m_out_mem_ptr) 6518 { 6519 DEBUG_PRINT_LOW("Freeing the Output Memory"); 6520 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) 6521 { 6522 free_output_buffer (&m_out_mem_ptr[i]); 6523 } 6524 #ifdef _ANDROID_ICS_ 6525 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 6526 #endif 6527 } 6528 6529 /*Check if the input buffers have to be cleaned up*/ 6530 if(m_inp_mem_ptr || m_inp_heap_ptr) 6531 { 6532 DEBUG_PRINT_LOW("Freeing the Input Memory"); 6533 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) 6534 { 6535 if (m_inp_mem_ptr) 6536 free_input_buffer (i,&m_inp_mem_ptr[i]); 6537 else 6538 free_input_buffer (i,NULL); 6539 } 6540 } 6541 free_input_buffer_header(); 6542 free_output_buffer_header(); 6543 if(h264_scratch.pBuffer) 6544 { 6545 free(h264_scratch.pBuffer); 6546 h264_scratch.pBuffer = NULL; 6547 } 6548 6549 if (h264_parser) 6550 { 6551 delete h264_parser; 6552 h264_parser = NULL; 6553 } 6554 6555 if(m_platform_list) 6556 { 6557 free(m_platform_list); 6558 m_platform_list = NULL; 6559 } 6560 if(m_vendor_config.pData) 6561 { 6562 free(m_vendor_config.pData); 6563 m_vendor_config.pData = NULL; 6564 } 6565 6566 // Reset counters in mesg queues 6567 m_ftb_q.m_size=0; 6568 m_cmd_q.m_size=0; 6569 m_etb_q.m_size=0; 6570 m_ftb_q.m_read = m_ftb_q.m_write =0; 6571 m_cmd_q.m_read = m_cmd_q.m_write =0; 6572 m_etb_q.m_read = m_etb_q.m_write =0; 6573 m_ftb_q_dsp.m_size=0; 6574 m_etb_q_swvdec.m_size=0; 6575 m_ftb_q_dsp.m_read = m_ftb_q_dsp.m_write =0; 6576 m_etb_q_swvdec.m_read = m_etb_q_swvdec.m_write =0; 6577 #ifdef _ANDROID_ 6578 if (m_debug_timestamp) 6579 { 6580 m_timestamp_list.reset_ts_list(); 6581 } 6582 #endif 6583 6584 if (m_debug.infile) { 6585 fclose(m_debug.infile); 6586 m_debug.infile = NULL; 6587 } 6588 if (m_debug.outfile) { 6589 fclose(m_debug.outfile); 6590 m_debug.outfile = NULL; 6591 } 6592 if (m_debug.imbfile) { 6593 fclose(m_debug.imbfile); 6594 m_debug.imbfile = NULL; 6595 } 6596 6597 if (m_pSwVdec) 6598 { 6599 SwVdec_DeInit(m_pSwVdec); 6600 m_pSwVdec = NULL; 6601 } 6602 DEBUG_PRINT_HIGH("omx_vdec::component_deinit() complete"); 6603 return OMX_ErrorNone; 6604 } 6605 6606 /* ====================================================================== 6607 FUNCTION 6608 omx_vdec::UseEGLImage 6609 6610 DESCRIPTION 6611 OMX Use EGL Image method implementation <TBD>. 6612 6613 PARAMETERS 6614 <TBD>. 6615 6616 RETURN VALUE 6617 Not Implemented error. 6618 6619 ========================================================================== */ 6620 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, 6621 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6622 OMX_IN OMX_U32 port, 6623 OMX_IN OMX_PTR appData, 6624 OMX_IN void* eglImage) 6625 { 6626 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; 6627 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; 6628 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; 6629 6630 #ifdef USE_EGL_IMAGE_GPU 6631 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; 6632 EGLint fd = -1, offset = 0,pmemPtr = 0; 6633 #else 6634 int fd = -1, offset = 0; 6635 #endif 6636 DEBUG_PRINT_HIGH("use EGL image support for decoder"); 6637 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { 6638 DEBUG_PRINT_ERROR("use_EGL_image: Invalid param"); 6639 } 6640 #ifdef USE_EGL_IMAGE_GPU 6641 if(m_display_id == NULL) { 6642 DEBUG_PRINT_ERROR("Display ID is not set by IL client"); 6643 return OMX_ErrorInsufficientResources; 6644 } 6645 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) 6646 eglGetProcAddress("eglQueryImageKHR"); 6647 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd); 6648 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset); 6649 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr); 6650 #else //with OMX test app 6651 struct temp_egl { 6652 int pmem_fd; 6653 int offset; 6654 }; 6655 struct temp_egl *temp_egl_id = NULL; 6656 void * pmemPtr = (void *) eglImage; 6657 temp_egl_id = (struct temp_egl *)eglImage; 6658 if (temp_egl_id != NULL) 6659 { 6660 fd = temp_egl_id->pmem_fd; 6661 offset = temp_egl_id->offset; 6662 } 6663 #endif 6664 if (fd < 0) { 6665 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd); 6666 return OMX_ErrorInsufficientResources; 6667 } 6668 pmem_info.pmem_fd = (OMX_U32) fd; 6669 pmem_info.offset = (OMX_U32) offset; 6670 pmem_entry.entry = (void *) &pmem_info; 6671 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 6672 pmem_list.entryList = &pmem_entry; 6673 pmem_list.nEntries = 1; 6674 ouput_egl_buffers = true; 6675 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, 6676 (void *)&pmem_list, drv_ctx.op_buf.buffer_size, 6677 (OMX_U8 *)pmemPtr)) { 6678 DEBUG_PRINT_ERROR("use buffer call failed for egl image"); 6679 return OMX_ErrorInsufficientResources; 6680 } 6681 return OMX_ErrorNone; 6682 } 6683 6684 /* ====================================================================== 6685 FUNCTION 6686 omx_vdec::ComponentRoleEnum 6687 6688 DESCRIPTION 6689 OMX Component Role Enum method implementation. 6690 6691 PARAMETERS 6692 <TBD>. 6693 6694 RETURN VALUE 6695 OMX Error None if everything is successful. 6696 ========================================================================== */ 6697 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, 6698 OMX_OUT OMX_U8* role, 6699 OMX_IN OMX_U32 index) 6700 { 6701 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6702 6703 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevchybrid",OMX_MAX_STRINGNAME_SIZE) || 6704 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevcswvdec",OMX_MAX_STRINGNAME_SIZE) || 6705 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) 6706 { 6707 if((0 == index) && role) 6708 { 6709 strlcpy((char *)role, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); 6710 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6711 } 6712 else 6713 { 6714 DEBUG_PRINT_LOW("No more roles"); 6715 eRet = OMX_ErrorNoMore; 6716 } 6717 } 6718 else 6719 { 6720 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component"); 6721 eRet = OMX_ErrorInvalidComponentName; 6722 } 6723 return eRet; 6724 } 6725 6726 6727 6728 6729 /* ====================================================================== 6730 FUNCTION 6731 omx_vdec::AllocateDone 6732 6733 DESCRIPTION 6734 Checks if entire buffer pool is allocated by IL Client or not. 6735 Need this to move to IDLE state. 6736 6737 PARAMETERS 6738 None. 6739 6740 RETURN VALUE 6741 true/false. 6742 6743 ========================================================================== */ 6744 bool omx_vdec::allocate_done(void) 6745 { 6746 bool bRet = false; 6747 bool bRet_In = false; 6748 bool bRet_Out = false; 6749 6750 bRet_In = allocate_input_done(); 6751 bRet_Out = allocate_output_done(); 6752 6753 if(bRet_In && bRet_Out) 6754 { 6755 bRet = true; 6756 if (m_pSwVdec && m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 6757 { 6758 if (allocate_interm_buffer(drv_ctx.interm_op_buf.buffer_size) != OMX_ErrorNone) 6759 { 6760 omx_report_error(); 6761 bRet = false; 6762 } 6763 } 6764 } 6765 6766 return bRet; 6767 } 6768 /* ====================================================================== 6769 FUNCTION 6770 omx_vdec::AllocateInputDone 6771 6772 DESCRIPTION 6773 Checks if I/P buffer pool is allocated by IL Client or not. 6774 6775 PARAMETERS 6776 None. 6777 6778 RETURN VALUE 6779 true/false. 6780 6781 ========================================================================== */ 6782 bool omx_vdec::allocate_input_done(void) 6783 { 6784 bool bRet = false; 6785 unsigned i=0; 6786 6787 if (m_inp_mem_ptr == NULL) 6788 { 6789 return bRet; 6790 } 6791 if(m_inp_mem_ptr ) 6792 { 6793 for(;i<drv_ctx.ip_buf.actualcount;i++) 6794 { 6795 if(BITMASK_ABSENT(&m_inp_bm_count,i)) 6796 { 6797 break; 6798 } 6799 } 6800 } 6801 if(i == drv_ctx.ip_buf.actualcount) 6802 { 6803 bRet = true; 6804 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers"); 6805 } 6806 if(i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) 6807 { 6808 m_inp_bPopulated = OMX_TRUE; 6809 } 6810 return bRet; 6811 } 6812 /* ====================================================================== 6813 FUNCTION 6814 omx_vdec::AllocateOutputDone 6815 6816 DESCRIPTION 6817 Checks if entire O/P buffer pool is allocated by IL Client or not. 6818 6819 PARAMETERS 6820 None. 6821 6822 RETURN VALUE 6823 true/false. 6824 6825 ========================================================================== */ 6826 bool omx_vdec::allocate_output_done(void) 6827 { 6828 bool bRet = false; 6829 unsigned j=0; 6830 6831 if (m_out_mem_ptr == NULL) 6832 { 6833 return bRet; 6834 } 6835 6836 if (m_out_mem_ptr) 6837 { 6838 for(;j < drv_ctx.op_buf.actualcount;j++) 6839 { 6840 if(BITMASK_ABSENT(&m_out_bm_count,j)) 6841 { 6842 break; 6843 } 6844 } 6845 } 6846 6847 if(j == drv_ctx.op_buf.actualcount) 6848 { 6849 bRet = true; 6850 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers"); 6851 if(m_out_bEnabled) 6852 m_out_bPopulated = OMX_TRUE; 6853 } 6854 6855 return bRet; 6856 } 6857 6858 /* ====================================================================== 6859 FUNCTION 6860 omx_vdec::ReleaseDone 6861 6862 DESCRIPTION 6863 Checks if IL client has released all the buffers. 6864 6865 PARAMETERS 6866 None. 6867 6868 RETURN VALUE 6869 true/false 6870 6871 ========================================================================== */ 6872 bool omx_vdec::release_done(void) 6873 { 6874 bool bRet = false; 6875 6876 if(release_input_done()) 6877 { 6878 if(release_output_done()) 6879 { 6880 bRet = true; 6881 } 6882 } 6883 6884 if (bRet && m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 6885 { 6886 bRet = release_interm_done(); 6887 } 6888 return bRet; 6889 } 6890 6891 bool omx_vdec::release_interm_done(void) 6892 { 6893 bool bRet = true; 6894 unsigned int i=0; 6895 6896 if (!drv_ctx.ptr_interm_outputbuffer) return bRet; 6897 6898 pthread_mutex_lock(&m_lock); 6899 for(; (i<drv_ctx.interm_op_buf.actualcount) && drv_ctx.ptr_interm_outputbuffer[i].pmem_fd ; i++) 6900 { 6901 if(m_interm_buf_state[i] != WITH_COMPONENT) 6902 { 6903 bRet = false; 6904 DEBUG_PRINT_ERROR("interm buffer i %d state %d",i, m_interm_buf_state[i]); 6905 break; 6906 } 6907 } 6908 pthread_mutex_unlock(&m_lock); 6909 6910 DEBUG_PRINT_LOW("release_interm_done %d",bRet); 6911 return bRet; 6912 } 6913 6914 6915 /* ====================================================================== 6916 FUNCTION 6917 omx_vdec::ReleaseOutputDone 6918 6919 DESCRIPTION 6920 Checks if IL client has released all the buffers. 6921 6922 PARAMETERS 6923 None. 6924 6925 RETURN VALUE 6926 true/false 6927 6928 ========================================================================== */ 6929 bool omx_vdec::release_output_done(void) 6930 { 6931 bool bRet = false; 6932 unsigned i=0,j=0; 6933 6934 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_out_mem_ptr); 6935 if(m_out_mem_ptr) 6936 { 6937 for(;j < drv_ctx.op_buf.actualcount ; j++) 6938 { 6939 if(BITMASK_PRESENT(&m_out_bm_count,j)) 6940 { 6941 break; 6942 } 6943 } 6944 if(j == drv_ctx.op_buf.actualcount) 6945 { 6946 m_out_bm_count = 0; 6947 bRet = true; 6948 } 6949 } 6950 else 6951 { 6952 m_out_bm_count = 0; 6953 bRet = true; 6954 } 6955 return bRet; 6956 } 6957 /* ====================================================================== 6958 FUNCTION 6959 omx_vdec::ReleaseInputDone 6960 6961 DESCRIPTION 6962 Checks if IL client has released all the buffers. 6963 6964 PARAMETERS 6965 None. 6966 6967 RETURN VALUE 6968 true/false 6969 6970 ========================================================================== */ 6971 bool omx_vdec::release_input_done(void) 6972 { 6973 bool bRet = false; 6974 unsigned i=0,j=0; 6975 6976 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr); 6977 if(m_inp_mem_ptr) 6978 { 6979 for(;j<drv_ctx.ip_buf.actualcount;j++) 6980 { 6981 if( BITMASK_PRESENT(&m_inp_bm_count,j)) 6982 { 6983 break; 6984 } 6985 } 6986 if(j==drv_ctx.ip_buf.actualcount) 6987 { 6988 bRet = true; 6989 } 6990 } 6991 else 6992 { 6993 bRet = true; 6994 } 6995 return bRet; 6996 } 6997 6998 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, 6999 OMX_BUFFERHEADERTYPE * buffer) 7000 { 7001 unsigned long nPortIndex = buffer - m_out_mem_ptr; 7002 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; 7003 if (!buffer || nPortIndex >= drv_ctx.op_buf.actualcount) 7004 { 7005 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer); 7006 return OMX_ErrorBadParameter; 7007 } 7008 else if (output_flush_progress) 7009 { 7010 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); 7011 buffer->nFilledLen = 0; 7012 buffer->nTimeStamp = 0; 7013 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 7014 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7015 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 7016 } 7017 7018 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p idx %d, TS %lld nFlags %lu", 7019 buffer, buffer->pBuffer, buffer - m_out_mem_ptr, buffer->nTimeStamp, buffer->nFlags ); 7020 pending_output_buffers --; 7021 7022 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 7023 { 7024 DEBUG_PRINT_HIGH("Output EOS has been reached"); 7025 if (!output_flush_progress) 7026 post_event((unsigned)NULL, (unsigned)NULL, 7027 OMX_COMPONENT_GENERATE_EOS_DONE); 7028 7029 if (psource_frame) 7030 { 7031 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); 7032 psource_frame = NULL; 7033 } 7034 if (pdest_frame) 7035 { 7036 pdest_frame->nFilledLen = 0; 7037 m_input_free_q.insert_entry((unsigned) pdest_frame,(unsigned)NULL, 7038 (unsigned)NULL); 7039 pdest_frame = NULL; 7040 } 7041 } 7042 7043 if (m_debug.out_buffer_log) 7044 { 7045 log_output_buffers(buffer); 7046 } 7047 7048 /* For use buffer we need to copy the data */ 7049 if (!output_flush_progress) 7050 { 7051 time_stamp_dts.get_next_timestamp(buffer, 7052 (drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 7053 ?true:false); 7054 if (m_debug_timestamp) 7055 { 7056 { 7057 OMX_TICKS expected_ts = 0; 7058 m_timestamp_list.pop_min_ts(expected_ts); 7059 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", 7060 buffer->nTimeStamp, expected_ts); 7061 7062 if (buffer->nTimeStamp != expected_ts) 7063 { 7064 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check"); 7065 } 7066 } 7067 } 7068 } 7069 if (m_cb.FillBufferDone) 7070 { 7071 if (buffer->nFilledLen > 0) 7072 { 7073 handle_extradata(buffer); 7074 if (client_extradata & OMX_TIMEINFO_EXTRADATA) 7075 // Keep min timestamp interval to handle corrupted bit stream scenario 7076 set_frame_rate(buffer->nTimeStamp); 7077 else if (arbitrary_bytes) 7078 adjust_timestamp(buffer->nTimeStamp); 7079 if (perf_flag) 7080 { 7081 if (!proc_frms) 7082 { 7083 dec_time.stop(); 7084 latency = dec_time.processing_time_us() - latency; 7085 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); 7086 dec_time.start(); 7087 fps_metrics.start(); 7088 } 7089 proc_frms++; 7090 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 7091 { 7092 OMX_U64 proc_time = 0; 7093 fps_metrics.stop(); 7094 proc_time = fps_metrics.processing_time_us(); 7095 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)", 7096 proc_frms, (float)proc_time / 1e6, 7097 (float)(1e6 * proc_frms) / proc_time); 7098 proc_frms = 0; 7099 } 7100 } 7101 7102 #ifdef OUTPUT_EXTRADATA_LOG 7103 if (outputExtradataFile) 7104 { 7105 7106 OMX_OTHER_EXTRADATATYPE *p_extra = NULL; 7107 p_extra = (OMX_OTHER_EXTRADATATYPE *) 7108 ((unsigned)(buffer->pBuffer + buffer->nOffset + 7109 buffer->nFilledLen + 3)&(~3)); 7110 while(p_extra && 7111 (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) ) 7112 { 7113 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType); 7114 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); 7115 if (p_extra->eType == OMX_ExtraDataNone) 7116 { 7117 break; 7118 } 7119 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 7120 } 7121 } 7122 #endif 7123 } 7124 if (buffer->nFlags & OMX_BUFFERFLAG_EOS){ 7125 prev_ts = LLONG_MAX; 7126 rst_prev_ts = true; 7127 } 7128 7129 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 7130 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) 7131 buffer->pPlatformPrivate)->entryList->entry; 7132 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu", pPMEMInfo->pmem_fd); 7133 OMX_BUFFERHEADERTYPE *il_buffer; 7134 il_buffer = client_buffers.get_il_buf_hdr(buffer); 7135 7136 if (dynamic_buf_mode && !secure_mode && 7137 !(buffer->nFlags & OMX_BUFFERFLAG_READONLY)) 7138 { 7139 DEBUG_PRINT_LOW("swvdec_fill_buffer_done rmd ref frame"); 7140 buf_ref_remove(drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 7141 drv_ctx.ptr_outputbuffer[nPortIndex].offset); 7142 } 7143 if (il_buffer) 7144 m_cb.FillBufferDone (hComp,m_app_data,il_buffer); 7145 else { 7146 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr"); 7147 return OMX_ErrorBadParameter; 7148 } 7149 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd); 7150 } 7151 else 7152 { 7153 return OMX_ErrorBadParameter; 7154 } 7155 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 7156 if (m_smoothstreaming_mode && m_out_mem_ptr) { 7157 OMX_U32 buf_index = buffer - m_out_mem_ptr; 7158 BufferDim_t dim; 7159 private_handle_t *private_handle = NULL; 7160 dim.sliceWidth = drv_ctx.video_resolution.frame_width; 7161 dim.sliceHeight = drv_ctx.video_resolution.frame_height; 7162 if (native_buffer[buf_index].privatehandle) 7163 private_handle = native_buffer[buf_index].privatehandle; 7164 if (private_handle) { 7165 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d", 7166 dim.sliceWidth, dim.sliceHeight); 7167 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim); 7168 } 7169 } 7170 #endif 7171 7172 return OMX_ErrorNone; 7173 } 7174 7175 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, 7176 OMX_BUFFERHEADERTYPE* buffer) 7177 { 7178 7179 if (buffer == NULL || ((buffer - m_inp_mem_ptr) > (int)drv_ctx.ip_buf.actualcount)) 7180 { 7181 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); 7182 return OMX_ErrorBadParameter; 7183 } 7184 7185 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", 7186 buffer, buffer->pBuffer); 7187 pending_input_buffers--; 7188 7189 if (arbitrary_bytes) 7190 { 7191 if (pdest_frame == NULL && input_flush_progress == false) 7192 { 7193 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer); 7194 pdest_frame = buffer; 7195 buffer->nFilledLen = 0; 7196 buffer->nTimeStamp = LLONG_MAX; 7197 push_input_buffer (hComp); 7198 } 7199 else 7200 { 7201 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer); 7202 buffer->nFilledLen = 0; 7203 if (!m_input_free_q.insert_entry((unsigned)buffer, 7204 (unsigned)NULL, (unsigned)NULL)) 7205 { 7206 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error"); 7207 } 7208 } 7209 } 7210 else if(m_cb.EmptyBufferDone) 7211 { 7212 buffer->nFilledLen = 0; 7213 if (input_use_buffer == true){ 7214 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; 7215 } 7216 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); 7217 } 7218 return OMX_ErrorNone; 7219 } 7220 7221 7222 void dump_buffer(FILE* pFile, char* buffer, int stride, int scanlines, int width, int height) 7223 { 7224 if (buffer) 7225 { 7226 char *temp = (char *)buffer; 7227 int i; 7228 int bytes_written = 0; 7229 int bytes = 0; 7230 7231 for (i = 0; i < height; i++) { 7232 bytes_written = fwrite(temp, width, 1, pFile); 7233 temp += stride; 7234 if (bytes_written >0) 7235 bytes += bytes_written * width; 7236 } 7237 temp = (char *)buffer + stride * scanlines; 7238 int stride_c = stride; 7239 for(i = 0; i < height/2; i++) { 7240 bytes_written = fwrite(temp, width, 1, pFile); 7241 temp += stride_c; 7242 if (bytes_written >0) 7243 bytes += bytes_written * width; 7244 } 7245 7246 DEBUG_PRINT_ERROR("stride %d, scanlines %d, frame_height %d bytes_written %d", 7247 stride, scanlines, height, bytes); 7248 } 7249 } 7250 7251 int omx_vdec::async_message_process (void *context, void* message) 7252 { 7253 omx_vdec* omx = NULL; 7254 struct vdec_msginfo *vdec_msg = NULL; 7255 OMX_BUFFERHEADERTYPE* omxhdr = NULL; 7256 struct v4l2_buffer *v4l2_buf_ptr = NULL; 7257 struct vdec_output_frameinfo *output_respbuf = NULL; 7258 int rc=1; 7259 if (context == NULL || message == NULL) 7260 { 7261 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check"); 7262 return -1; 7263 } 7264 vdec_msg = (struct vdec_msginfo *)message; 7265 7266 omx = reinterpret_cast<omx_vdec*>(context); 7267 7268 switch (vdec_msg->msgcode) 7269 { 7270 7271 case VDEC_MSG_EVT_HW_ERROR: 7272 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7273 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 7274 break; 7275 7276 case VDEC_MSG_RESP_START_DONE: 7277 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7278 OMX_COMPONENT_GENERATE_START_DONE); 7279 break; 7280 7281 case VDEC_MSG_RESP_STOP_DONE: 7282 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7283 OMX_COMPONENT_GENERATE_STOP_DONE); 7284 break; 7285 7286 case VDEC_MSG_RESP_RESUME_DONE: 7287 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7288 OMX_COMPONENT_GENERATE_RESUME_DONE); 7289 break; 7290 7291 case VDEC_MSG_RESP_PAUSE_DONE: 7292 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7293 OMX_COMPONENT_GENERATE_PAUSE_DONE); 7294 break; 7295 7296 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 7297 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7298 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); 7299 break; 7300 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 7301 if (!omx->m_pSwVdec) 7302 { 7303 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7304 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); 7305 } 7306 else 7307 { 7308 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7309 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH_DSP); 7310 } 7311 break; 7312 case VDEC_MSG_RESP_INPUT_FLUSHED: 7313 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 7314 7315 /* omxhdr = (OMX_BUFFERHEADERTYPE* ) 7316 vdec_msg->msgdata.input_frame_clientdata; */ 7317 7318 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata; 7319 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index; 7320 if (omxhdr == NULL || 7321 ((omxhdr - omx->m_inp_mem_ptr) > (int)omx->drv_ctx.ip_buf.actualcount) ) 7322 { 7323 omxhdr = NULL; 7324 vdec_msg->status_code = VDEC_S_EFATAL; 7325 } 7326 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) { 7327 DEBUG_PRINT_HIGH("Unsupported input"); 7328 omx->omx_report_error (); 7329 } 7330 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 7331 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR; 7332 } 7333 omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, 7334 OMX_COMPONENT_GENERATE_EBD); 7335 break; 7336 case VDEC_MSG_EVT_INFO_FIELD_DROPPED: 7337 int64_t *timestamp; 7338 timestamp = (int64_t *) malloc(sizeof(int64_t)); 7339 if (timestamp) { 7340 *timestamp = vdec_msg->msgdata.output_frame.time_stamp; 7341 omx->post_event ((unsigned int)timestamp, vdec_msg->status_code, 7342 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); 7343 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", 7344 vdec_msg->msgdata.output_frame.time_stamp); 7345 } 7346 break; 7347 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 7348 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 7349 { 7350 int actualcount = omx->drv_ctx.op_buf.actualcount; 7351 OMX_BUFFERHEADERTYPE* p_mem_ptr = omx->m_out_mem_ptr; 7352 vdec_output_frameinfo* ptr_respbuffer = omx->drv_ctx.ptr_respbuffer; 7353 if (omx->m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 7354 { 7355 actualcount = omx->drv_ctx.interm_op_buf.actualcount; 7356 p_mem_ptr = omx->m_interm_mem_ptr; 7357 ptr_respbuffer = omx->drv_ctx.ptr_interm_respbuffer; 7358 } 7359 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; 7360 omxhdr=p_mem_ptr+v4l2_buf_ptr->index; 7361 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) pBuffer (%p) idx %d Ts(%lld) Pic_type(%u) frame.len(%d)", 7362 omxhdr, omxhdr->pBuffer, v4l2_buf_ptr->index, vdec_msg->msgdata.output_frame.time_stamp, 7363 vdec_msg->msgdata.output_frame.pic_type, vdec_msg->msgdata.output_frame.len); 7364 7365 if (omxhdr && omxhdr->pOutputPortPrivate && 7366 ((omxhdr - p_mem_ptr) < actualcount) && 7367 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate 7368 - ptr_respbuffer) < actualcount)) 7369 { 7370 if ((omx->m_pSwVdec == NULL) && 7371 omx->dynamic_buf_mode && 7372 vdec_msg->msgdata.output_frame.len) 7373 { 7374 vdec_msg->msgdata.output_frame.len = omxhdr->nAllocLen; 7375 } 7376 if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) 7377 { 7378 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; 7379 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; 7380 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp; 7381 omxhdr->nFlags = 0; 7382 7383 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) { 7384 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS; 7385 //rc = -1; 7386 } 7387 if (omxhdr->nFilledLen) { 7388 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 7389 } 7390 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 7391 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 7392 } else { 7393 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME; 7394 } 7395 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) { 7396 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7397 } 7398 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) { 7399 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY; 7400 } 7401 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) 7402 { 7403 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY; 7404 } 7405 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) && 7406 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) && 7407 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) { 7408 omx->time_stamp_dts.remove_time_stamp( 7409 omxhdr->nTimeStamp, 7410 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 7411 ?true:false); 7412 omx->post_event ((unsigned)NULL,(unsigned int)omxhdr, 7413 OMX_COMPONENT_GENERATE_FTB); 7414 break; 7415 } 7416 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 7417 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 7418 } 7419 vdec_msg->msgdata.output_frame.bufferaddr = 7420 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; 7421 int format_notably_changed = 0; 7422 if (omxhdr->nFilledLen && 7423 (omxhdr->nFilledLen != (unsigned)omx->prev_n_filled_len)) { 7424 if ((vdec_msg->msgdata.output_frame.framesize.bottom != omx->drv_ctx.video_resolution.frame_height) || 7425 (vdec_msg->msgdata.output_frame.framesize.right != omx->drv_ctx.video_resolution.frame_width)) { 7426 DEBUG_PRINT_HIGH("Height/Width information has changed"); 7427 omx->drv_ctx.video_resolution.frame_height = vdec_msg->msgdata.output_frame.framesize.bottom; 7428 omx->drv_ctx.video_resolution.frame_width = vdec_msg->msgdata.output_frame.framesize.right; 7429 format_notably_changed = 1; 7430 } 7431 } 7432 if (omxhdr->nFilledLen && (((unsigned)omx->rectangle.nLeft != 7433 vdec_msg->msgdata.output_frame.framesize.left) 7434 || ((unsigned)omx->rectangle.nTop != vdec_msg->msgdata.output_frame.framesize.top) 7435 || (omx->rectangle.nWidth != vdec_msg->msgdata.output_frame.framesize.right) 7436 || (omx->rectangle.nHeight != vdec_msg->msgdata.output_frame.framesize.bottom))) { 7437 if ((vdec_msg->msgdata.output_frame.framesize.bottom != omx->drv_ctx.video_resolution.frame_height) || 7438 (vdec_msg->msgdata.output_frame.framesize.right != omx->drv_ctx.video_resolution.frame_width)) { 7439 omx->drv_ctx.video_resolution.frame_height = vdec_msg->msgdata.output_frame.framesize.bottom; 7440 omx->drv_ctx.video_resolution.frame_width = vdec_msg->msgdata.output_frame.framesize.right; 7441 DEBUG_PRINT_HIGH("Height/Width information has changed. W: %d --> %d, H: %d --> %d", 7442 omx->drv_ctx.video_resolution.frame_width, vdec_msg->msgdata.output_frame.framesize.right, 7443 omx->drv_ctx.video_resolution.frame_height, vdec_msg->msgdata.output_frame.framesize.bottom); 7444 } 7445 DEBUG_PRINT_HIGH("Crop information changed. W: %lu --> %d, H: %lu -> %d", 7446 omx->rectangle.nWidth, vdec_msg->msgdata.output_frame.framesize.right, 7447 omx->rectangle.nHeight, vdec_msg->msgdata.output_frame.framesize.bottom); 7448 if (vdec_msg->msgdata.output_frame.framesize.left + vdec_msg->msgdata.output_frame.framesize.right >= 7449 omx->drv_ctx.video_resolution.frame_width) { 7450 vdec_msg->msgdata.output_frame.framesize.left = 0; 7451 if (vdec_msg->msgdata.output_frame.framesize.right > omx->drv_ctx.video_resolution.frame_width) { 7452 vdec_msg->msgdata.output_frame.framesize.right = omx->drv_ctx.video_resolution.frame_width; 7453 } 7454 } 7455 if (vdec_msg->msgdata.output_frame.framesize.top + vdec_msg->msgdata.output_frame.framesize.bottom >= 7456 omx->drv_ctx.video_resolution.frame_height) { 7457 vdec_msg->msgdata.output_frame.framesize.top = 0; 7458 if (vdec_msg->msgdata.output_frame.framesize.bottom > omx->drv_ctx.video_resolution.frame_height) { 7459 vdec_msg->msgdata.output_frame.framesize.bottom = omx->drv_ctx.video_resolution.frame_height; 7460 } 7461 } 7462 DEBUG_PRINT_LOW("omx_vdec: Adjusted Dim L: %d, T: %d, R: %d, B: %d, W: %d, H: %d", 7463 vdec_msg->msgdata.output_frame.framesize.left, 7464 vdec_msg->msgdata.output_frame.framesize.top, 7465 vdec_msg->msgdata.output_frame.framesize.right, 7466 vdec_msg->msgdata.output_frame.framesize.bottom, 7467 omx->drv_ctx.video_resolution.frame_width, 7468 omx->drv_ctx.video_resolution.frame_height); 7469 omx->rectangle.nLeft = vdec_msg->msgdata.output_frame.framesize.left; 7470 omx->rectangle.nTop = vdec_msg->msgdata.output_frame.framesize.top; 7471 omx->rectangle.nWidth = vdec_msg->msgdata.output_frame.framesize.right; 7472 omx->rectangle.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom; 7473 format_notably_changed = 1; 7474 } 7475 DEBUG_PRINT_HIGH("Left: %d, Right: %d, top: %d, Bottom: %d", 7476 vdec_msg->msgdata.output_frame.framesize.left,vdec_msg->msgdata.output_frame.framesize.right, 7477 vdec_msg->msgdata.output_frame.framesize.top, vdec_msg->msgdata.output_frame.framesize.bottom); 7478 if (format_notably_changed) { 7479 if (omx->is_video_session_supported()) { 7480 omx->post_event (0, vdec_msg->status_code, 7481 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); 7482 } else { 7483 if (!omx->client_buffers.update_buffer_req()) { 7484 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); 7485 } 7486 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexConfigCommonOutputCrop, 7487 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 7488 } 7489 } 7490 if (omxhdr->nFilledLen) 7491 omx->prev_n_filled_len = omxhdr->nFilledLen; 7492 7493 output_respbuf = (struct vdec_output_frameinfo *)\ 7494 omxhdr->pOutputPortPrivate; 7495 output_respbuf->len = vdec_msg->msgdata.output_frame.len; 7496 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; 7497 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) { 7498 output_respbuf->pic_type = PICTURE_TYPE_I; 7499 } 7500 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) { 7501 output_respbuf->pic_type = PICTURE_TYPE_P; 7502 } 7503 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) { 7504 output_respbuf->pic_type = PICTURE_TYPE_B; 7505 } 7506 7507 if (omx->output_use_buffer) 7508 memcpy ( omxhdr->pBuffer, (void *) 7509 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr + 7510 (unsigned long)vdec_msg->msgdata.output_frame.offset), 7511 vdec_msg->msgdata.output_frame.len); 7512 } else 7513 omxhdr->nFilledLen = 0; 7514 if (!omx->m_pSwVdec) 7515 { 7516 omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code, 7517 OMX_COMPONENT_GENERATE_FBD); 7518 } 7519 else 7520 { 7521 omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code, 7522 OMX_COMPONENT_GENERATE_FBD_DSP); 7523 } 7524 } 7525 else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) 7526 omx->post_event ((unsigned int)NULL, vdec_msg->status_code, 7527 OMX_COMPONENT_GENERATE_EOS_DONE); 7528 else 7529 omx->post_event ((unsigned int)NULL, vdec_msg->status_code, 7530 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 7531 } 7532 break; 7533 case VDEC_MSG_EVT_CONFIG_CHANGED: 7534 if (!omx->m_pSwVdec) 7535 { 7536 DEBUG_PRINT_HIGH("Port settings changed"); 7537 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition, 7538 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 7539 } 7540 break; 7541 default: 7542 break; 7543 } 7544 return rc; 7545 } 7546 7547 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( 7548 OMX_HANDLETYPE hComp, 7549 OMX_BUFFERHEADERTYPE *buffer 7550 ) 7551 { 7552 unsigned address,p2,id; 7553 DEBUG_PRINT_LOW("Empty this arbitrary"); 7554 7555 if (buffer == NULL) 7556 { 7557 return OMX_ErrorBadParameter; 7558 } 7559 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7560 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %lu, flags %lu, timestamp %u", 7561 buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp); 7562 7563 /* return zero length and not an EOS buffer */ 7564 /* return buffer if input flush in progress */ 7565 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && 7566 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) 7567 { 7568 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress"); 7569 m_cb.EmptyBufferDone (hComp,m_app_data,buffer); 7570 return OMX_ErrorNone; 7571 } 7572 7573 if (psource_frame == NULL) 7574 { 7575 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp); 7576 psource_frame = buffer; 7577 DEBUG_PRINT_LOW("Try to Push One Input Buffer "); 7578 push_input_buffer (hComp); 7579 } 7580 else 7581 { 7582 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer); 7583 if (!m_input_pending_q.insert_entry((unsigned)buffer, (unsigned)NULL, 7584 (unsigned)NULL)) 7585 { 7586 return OMX_ErrorBadParameter; 7587 } 7588 } 7589 7590 7591 return OMX_ErrorNone; 7592 } 7593 7594 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) 7595 { 7596 unsigned address,p2,id; 7597 OMX_ERRORTYPE ret = OMX_ErrorNone; 7598 7599 if (pdest_frame == NULL || psource_frame == NULL) 7600 { 7601 /*Check if we have a destination buffer*/ 7602 if (pdest_frame == NULL) 7603 { 7604 DEBUG_PRINT_LOW("Get a Destination buffer from the queue"); 7605 if (m_input_free_q.m_size) 7606 { 7607 m_input_free_q.pop_entry(&address,&p2,&id); 7608 pdest_frame = (OMX_BUFFERHEADERTYPE *)address; 7609 pdest_frame->nFilledLen = 0; 7610 pdest_frame->nTimeStamp = LLONG_MAX; 7611 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame); 7612 } 7613 } 7614 7615 /*Check if we have a destination buffer*/ 7616 if (psource_frame == NULL) 7617 { 7618 DEBUG_PRINT_LOW("Get a source buffer from the queue"); 7619 if (m_input_pending_q.m_size) 7620 { 7621 m_input_pending_q.pop_entry(&address,&p2,&id); 7622 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 7623 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 7624 psource_frame->nTimeStamp); 7625 DEBUG_PRINT_LOW("Next source Buffer flag %lu length %lu", 7626 psource_frame->nFlags,psource_frame->nFilledLen); 7627 7628 } 7629 } 7630 7631 } 7632 7633 while ((pdest_frame != NULL) && (psource_frame != NULL)) 7634 { 7635 switch (codec_type_parse) 7636 { 7637 case CODEC_TYPE_HEVC: 7638 ret = push_input_hevc(hComp); 7639 break; 7640 default: 7641 break; 7642 } 7643 if (ret != OMX_ErrorNone) 7644 { 7645 DEBUG_PRINT_ERROR("Pushing input Buffer Failed"); 7646 omx_report_error (); 7647 break; 7648 } 7649 } 7650 7651 return ret; 7652 } 7653 7654 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc) 7655 { 7656 OMX_ERRORTYPE rc = OMX_ErrorNone; 7657 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) 7658 { 7659 memcpy ((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen); 7660 if (pDst->nTimeStamp == LLONG_MAX) 7661 { 7662 pDst->nTimeStamp = pSrc->nTimeStamp; 7663 DEBUG_PRINT_LOW("Assign Dst nTimeStamp=%lld", pDst->nTimeStamp); 7664 } 7665 pDst->nFilledLen += pSrc->nFilledLen; 7666 pSrc->nFilledLen = 0; 7667 } 7668 else 7669 { 7670 DEBUG_PRINT_ERROR("Error: Destination buffer overflow"); 7671 rc = OMX_ErrorBadParameter; 7672 } 7673 return rc; 7674 } 7675 7676 OMX_ERRORTYPE omx_vdec::push_input_hevc (OMX_HANDLETYPE hComp) 7677 { 7678 OMX_U32 partial_frame = 1; 7679 unsigned address,p2,id; 7680 OMX_BOOL isNewFrame = OMX_FALSE; 7681 OMX_BOOL generate_ebd = OMX_TRUE; 7682 OMX_ERRORTYPE rc = OMX_ErrorNone; 7683 7684 if (h264_scratch.pBuffer == NULL) 7685 { 7686 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated"); 7687 return OMX_ErrorBadParameter; 7688 } 7689 7690 7691 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %lu has look_ahead_nal %d pdest_frame nFilledLen %lu nTimeStamp %lld", 7692 h264_scratch.nFilledLen, look_ahead_nal, pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 7693 7694 if (h264_scratch.nFilledLen && look_ahead_nal) 7695 { 7696 look_ahead_nal = false; 7697 7698 // copy the lookahead buffer in the scratch 7699 rc = copy_buffer(pdest_frame, &h264_scratch); 7700 if (rc != OMX_ErrorNone) 7701 { 7702 return rc; 7703 } 7704 } 7705 if (nal_length == 0) 7706 { 7707 if (m_frame_parser.parse_sc_frame(psource_frame, 7708 &h264_scratch,&partial_frame) == -1) 7709 { 7710 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 7711 return OMX_ErrorBadParameter; 7712 } 7713 } 7714 else 7715 { 7716 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length); 7717 if (m_frame_parser.parse_h264_nallength(psource_frame, 7718 &h264_scratch,&partial_frame) == -1) 7719 { 7720 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 7721 return OMX_ErrorBadParameter; 7722 } 7723 } 7724 7725 if (partial_frame == 0) 7726 { 7727 if (nal_count == 0 && h264_scratch.nFilledLen == 0) 7728 { 7729 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 7730 nal_count++; 7731 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 7732 h264_scratch.nFlags = psource_frame->nFlags; 7733 } 7734 else 7735 { 7736 DEBUG_PRINT_LOW("Parsed New NAL Length = %lu",h264_scratch.nFilledLen); 7737 if(h264_scratch.nFilledLen) 7738 { 7739 mHEVCutils.isNewFrame(&h264_scratch, 0, isNewFrame); 7740 nal_count++; 7741 } 7742 7743 if (!isNewFrame) 7744 { 7745 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %lu nTimestamp %lld, pdest_frame nFilledLen %lu nTimestamp %lld", 7746 h264_scratch.nFilledLen, h264_scratch.nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 7747 rc = copy_buffer(pdest_frame, &h264_scratch); 7748 if ( rc != OMX_ErrorNone) 7749 { 7750 return rc; 7751 } 7752 } 7753 else 7754 { 7755 look_ahead_nal = true; 7756 if (pdest_frame->nFilledLen == 0) 7757 { 7758 look_ahead_nal = false; 7759 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer"); 7760 rc = copy_buffer(pdest_frame, &h264_scratch); 7761 if ( rc != OMX_ErrorNone ) 7762 { 7763 return OMX_ErrorBadParameter; 7764 } 7765 } 7766 else 7767 { 7768 if(psource_frame->nFilledLen || h264_scratch.nFilledLen) 7769 { 7770 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 7771 } 7772 7773 DEBUG_PRINT_LOW("FrameDetecetd # %d pdest_frame nFilledLen %lu nTimeStamp %lld, look_ahead_nal in h264_scratch nFilledLen %lu nTimeStamp %lld", 7774 frame_count++, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp); 7775 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) 7776 { 7777 return OMX_ErrorBadParameter; 7778 } 7779 pdest_frame = NULL; 7780 if (m_input_free_q.m_size) 7781 { 7782 m_input_free_q.pop_entry(&address,&p2,&id); 7783 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 7784 DEBUG_PRINT_LOW("pop the next pdest_buffer %p",pdest_frame); 7785 pdest_frame->nFilledLen = 0; 7786 pdest_frame->nFlags = 0; 7787 pdest_frame->nTimeStamp = LLONG_MAX; 7788 } 7789 } 7790 } 7791 } 7792 } 7793 else 7794 { 7795 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %lu nTimeStamp %lld, pdest_frame nFilledLen %lu nTimeStamp %lld, h264_scratch nFilledLen %lu nTimeStamp %lld", 7796 psource_frame->nFilledLen, psource_frame->nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp); 7797 7798 /*Check if Destination Buffer is full*/ 7799 if (h264_scratch.nAllocLen == 7800 h264_scratch.nFilledLen + h264_scratch.nOffset) 7801 { 7802 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 7803 return OMX_ErrorStreamCorrupt; 7804 } 7805 } 7806 7807 if (!psource_frame->nFilledLen) 7808 { 7809 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame); 7810 7811 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) 7812 { 7813 if (pdest_frame) 7814 { 7815 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 7816 rc = copy_buffer(pdest_frame, &h264_scratch); 7817 if ( rc != OMX_ErrorNone ) 7818 { 7819 return rc; 7820 } 7821 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 7822 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 7823 7824 7825 DEBUG_PRINT_ERROR("Push EOS frame number:%d nFilledLen =%lu TimeStamp = %lld nFlags %lu", 7826 frame_count++, pdest_frame->nFilledLen,pdest_frame->nTimeStamp, pdest_frame->nFlags); 7827 7828 /*Push the frame to the Decoder*/ 7829 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) 7830 { 7831 return OMX_ErrorBadParameter; 7832 } 7833 pdest_frame = NULL; 7834 } 7835 else 7836 { 7837 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %lu frame_count %d", 7838 pdest_frame,h264_scratch.nFilledLen, frame_count); 7839 generate_ebd = OMX_FALSE; 7840 } 7841 } 7842 } 7843 if(generate_ebd && !psource_frame->nFilledLen) 7844 { 7845 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 7846 psource_frame = NULL; 7847 if (m_input_pending_q.m_size) 7848 { 7849 m_input_pending_q.pop_entry(&address,&p2,&id); 7850 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 7851 DEBUG_PRINT_LOW("Next source Buffer flag %lu nFilledLen %lu, nTimeStamp %lld", 7852 psource_frame->nFlags,psource_frame->nFilledLen, psource_frame->nTimeStamp); 7853 } 7854 } 7855 return OMX_ErrorNone; 7856 } 7857 7858 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, 7859 OMX_U32 alignment) 7860 { 7861 struct pmem_allocation allocation; 7862 allocation.size = buffer_size; 7863 allocation.align = clip2(alignment); 7864 if (allocation.align < 4096) 7865 { 7866 allocation.align = 4096; 7867 } 7868 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) 7869 { 7870 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)", 7871 allocation.align, allocation.size); 7872 return false; 7873 } 7874 return true; 7875 } 7876 #ifdef USE_ION 7877 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, 7878 OMX_U32 alignment, struct ion_allocation_data *alloc_data, 7879 struct ion_fd_data *fd_data, int flag, int heap_id) 7880 { 7881 int fd = -EINVAL; 7882 int rc = -EINVAL; 7883 int ion_dev_flag; 7884 struct vdec_ion ion_buf_info; 7885 if (!alloc_data || buffer_size <= 0 || !fd_data) { 7886 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory"); 7887 return -EINVAL; 7888 } 7889 ion_dev_flag = O_RDONLY; 7890 fd = open (MEM_DEVICE, ion_dev_flag); 7891 if (fd < 0) { 7892 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd); 7893 return fd; 7894 } 7895 alloc_data->flags = 0; 7896 if(!secure_mode && (flag & ION_FLAG_CACHED)) 7897 { 7898 alloc_data->flags |= ION_FLAG_CACHED; 7899 } 7900 alloc_data->len = buffer_size; 7901 alloc_data->align = clip2(alignment); 7902 if (alloc_data->align < 4096) 7903 { 7904 alloc_data->align = 4096; 7905 } 7906 if ((secure_mode) && (flag & ION_SECURE)) 7907 alloc_data->flags |= ION_SECURE; 7908 7909 alloc_data->heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID); 7910 if (!secure_mode && heap_id) 7911 alloc_data->heap_mask = ION_HEAP(heap_id); 7912 7913 DEBUG_PRINT_LOW("ION ALLOC memory heap_id %d mask %0xx size %d align %d", 7914 heap_id, (unsigned int)alloc_data->heap_mask, alloc_data->len, alloc_data->align); 7915 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); 7916 if (rc || !alloc_data->handle) { 7917 DEBUG_PRINT_ERROR("ION ALLOC memory failed "); 7918 alloc_data->handle = 0; 7919 close(fd); 7920 fd = -ENOMEM; 7921 return fd; 7922 } 7923 fd_data->handle = alloc_data->handle; 7924 rc = ioctl(fd,ION_IOC_MAP,fd_data); 7925 if (rc) { 7926 DEBUG_PRINT_ERROR("ION MAP failed "); 7927 ion_buf_info.ion_alloc_data = *alloc_data; 7928 ion_buf_info.ion_device_fd = fd; 7929 ion_buf_info.fd_ion_data = *fd_data; 7930 free_ion_memory(&ion_buf_info); 7931 fd_data->fd =-1; 7932 close(fd); 7933 fd = -ENOMEM; 7934 } 7935 7936 return fd; 7937 } 7938 7939 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) { 7940 7941 if(!buf_ion_info) { 7942 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata"); 7943 return; 7944 } 7945 if(ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, 7946 &buf_ion_info->ion_alloc_data.handle)) { 7947 DEBUG_PRINT_ERROR("ION: free failed" ); 7948 } 7949 7950 close(buf_ion_info->ion_device_fd); 7951 buf_ion_info->ion_device_fd = -1; 7952 buf_ion_info->ion_alloc_data.handle = 0; 7953 buf_ion_info->fd_ion_data.fd = -1; 7954 } 7955 #endif 7956 void omx_vdec::free_output_buffer_header() 7957 { 7958 DEBUG_PRINT_HIGH("ALL output buffers are freed/released"); 7959 output_use_buffer = false; 7960 ouput_egl_buffers = false; 7961 7962 if (m_out_mem_ptr) 7963 { 7964 free (m_out_mem_ptr); 7965 m_out_mem_ptr = NULL; 7966 } 7967 7968 if(m_platform_list) 7969 { 7970 free(m_platform_list); 7971 m_platform_list = NULL; 7972 } 7973 7974 if (drv_ctx.ptr_respbuffer) 7975 { 7976 free (drv_ctx.ptr_respbuffer); 7977 drv_ctx.ptr_respbuffer = NULL; 7978 } 7979 if (drv_ctx.ptr_outputbuffer) 7980 { 7981 free (drv_ctx.ptr_outputbuffer); 7982 drv_ctx.ptr_outputbuffer = NULL; 7983 } 7984 #ifdef USE_ION 7985 if (drv_ctx.op_buf_ion_info) { 7986 DEBUG_PRINT_LOW("Free o/p ion context"); 7987 free(drv_ctx.op_buf_ion_info); 7988 drv_ctx.op_buf_ion_info = NULL; 7989 } 7990 #endif 7991 if (out_dynamic_list) { 7992 free(out_dynamic_list); 7993 out_dynamic_list = NULL; 7994 } 7995 } 7996 7997 void omx_vdec::free_input_buffer_header() 7998 { 7999 input_use_buffer = false; 8000 if (arbitrary_bytes) 8001 { 8002 if (m_frame_parser.mutils) 8003 { 8004 DEBUG_PRINT_LOW("Free utils parser"); 8005 delete (m_frame_parser.mutils); 8006 m_frame_parser.mutils = NULL; 8007 } 8008 8009 if (m_inp_heap_ptr) 8010 { 8011 DEBUG_PRINT_LOW("Free input Heap Pointer"); 8012 free (m_inp_heap_ptr); 8013 m_inp_heap_ptr = NULL; 8014 } 8015 8016 if (m_phdr_pmem_ptr) 8017 { 8018 DEBUG_PRINT_LOW("Free input pmem header Pointer"); 8019 free (m_phdr_pmem_ptr); 8020 m_phdr_pmem_ptr = NULL; 8021 } 8022 } 8023 if (m_inp_mem_ptr) 8024 { 8025 DEBUG_PRINT_LOW("Free input pmem Pointer area"); 8026 free (m_inp_mem_ptr); 8027 m_inp_mem_ptr = NULL; 8028 } 8029 while (m_input_free_q.m_size) { 8030 unsigned address, p2, id; 8031 m_input_free_q.pop_entry(&address, &p2, &id); 8032 } 8033 if (drv_ctx.ptr_inputbuffer) 8034 { 8035 DEBUG_PRINT_LOW("Free Driver Context pointer"); 8036 free (drv_ctx.ptr_inputbuffer); 8037 drv_ctx.ptr_inputbuffer = NULL; 8038 } 8039 #ifdef USE_ION 8040 if (drv_ctx.ip_buf_ion_info) { 8041 DEBUG_PRINT_LOW("Free ion context"); 8042 free(drv_ctx.ip_buf_ion_info); 8043 drv_ctx.ip_buf_ion_info = NULL; 8044 } 8045 #endif 8046 } 8047 8048 int omx_vdec::stream_off(OMX_U32 port) 8049 { 8050 enum v4l2_buf_type btype; 8051 int rc = 0; 8052 enum v4l2_ports v4l2_port = OUTPUT_PORT; 8053 8054 if (port == OMX_CORE_INPUT_PORT_INDEX) { 8055 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8056 v4l2_port = OUTPUT_PORT; 8057 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 8058 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8059 v4l2_port = CAPTURE_PORT; 8060 } else if (port == OMX_ALL) { 8061 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX); 8062 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 8063 8064 if (!rc_input) 8065 return rc_input; 8066 else 8067 return rc_output; 8068 } 8069 8070 if (!streaming[v4l2_port]) { 8071 // already streamed off, warn and move on 8072 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port," 8073 " which is already streamed off", v4l2_port); 8074 return 0; 8075 } 8076 8077 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port); 8078 8079 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); 8080 if (rc) { 8081 /*TODO: How to handle this case */ 8082 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port); 8083 } else { 8084 streaming[v4l2_port] = false; 8085 } 8086 8087 return rc; 8088 } 8089 8090 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) 8091 { 8092 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8093 struct v4l2_requestbuffers bufreq; 8094 unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0; 8095 struct v4l2_format fmt; 8096 int ret = 0; 8097 8098 bufreq.memory = V4L2_MEMORY_USERPTR; 8099 bufreq.count = 1; 8100 if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){ 8101 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8102 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8103 fmt.fmt.pix_mp.pixelformat = output_capability; 8104 }else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT){ 8105 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8106 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8107 fmt.fmt.pix_mp.pixelformat = capture_capability; 8108 }else {eRet = OMX_ErrorBadParameter;} 8109 if(eRet==OMX_ErrorNone){ 8110 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 8111 } 8112 if(ret) 8113 { 8114 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 8115 /*TODO: How to handle this case */ 8116 eRet = OMX_ErrorInsufficientResources; 8117 return eRet; 8118 } 8119 else 8120 { 8121 buffer_prop->actualcount = bufreq.count; 8122 buffer_prop->mincount = bufreq.count; 8123 DEBUG_PRINT_HIGH("Count = %d",bufreq.count); 8124 } 8125 DEBUG_PRINT_HIGH("GetBufReq: ActCnt(%d) Size(%d), BufType(%d)", 8126 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type); 8127 8128 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 8129 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 8130 8131 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 8132 8133 update_resolution(fmt.fmt.pix_mp.width, 8134 fmt.fmt.pix_mp.height, 8135 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, 8136 fmt.fmt.pix_mp.plane_fmt[0].reserved[0]); 8137 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 8138 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes; 8139 DEBUG_PRINT_HIGH("Buffer Size (plane[0].sizeimage) = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage); 8140 8141 if(ret) 8142 { 8143 /*TODO: How to handle this case */ 8144 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 8145 eRet = OMX_ErrorInsufficientResources; 8146 } 8147 else 8148 { 8149 int extra_idx = 0; 8150 8151 eRet = is_video_session_supported(); 8152 if (eRet) 8153 return eRet; 8154 8155 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; 8156 buf_size = buffer_prop->buffer_size; 8157 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 8158 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 8159 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage; 8160 } else if (extra_idx >= VIDEO_MAX_PLANES) { 8161 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 8162 return OMX_ErrorBadParameter; 8163 } 8164 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 8165 { 8166 DEBUG_PRINT_HIGH("Frame info extra data enabled!"); 8167 client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE; 8168 } 8169 if (client_extradata & OMX_INTERLACE_EXTRADATA) 8170 { 8171 client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE; 8172 } 8173 if (client_extradata & OMX_PORTDEF_EXTRADATA) 8174 { 8175 client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE; 8176 DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d", 8177 client_extra_data_size); 8178 } 8179 if (client_extra_data_size) 8180 { 8181 client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator 8182 buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit 8183 } 8184 drv_ctx.extradata_info.size = buffer_prop->actualcount * extra_data_size; 8185 drv_ctx.extradata_info.count = buffer_prop->actualcount; 8186 drv_ctx.extradata_info.buffer_size = extra_data_size; 8187 buf_size += client_extra_data_size; 8188 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 8189 DEBUG_PRINT_HIGH("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d) BufType(%d), extradata size %d", 8190 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size, buffer_prop->buffer_type, client_extra_data_size); 8191 if (in_reconfig) // BufReq will be set to driver when port is disabled 8192 buffer_prop->buffer_size = buf_size; 8193 else if (buf_size != buffer_prop->buffer_size) 8194 { 8195 buffer_prop->buffer_size = buf_size; 8196 eRet = set_buffer_req(buffer_prop); 8197 } 8198 } 8199 DEBUG_PRINT_HIGH("GetBufReq OUT: ActCnt(%d) Size(%d), BufType(%d)", 8200 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type); 8201 return eRet; 8202 } 8203 8204 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) 8205 { 8206 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8207 unsigned buf_size = 0; 8208 struct v4l2_format fmt; 8209 struct v4l2_requestbuffers bufreq; 8210 int ret; 8211 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)", 8212 buffer_prop->actualcount, buffer_prop->buffer_size); 8213 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 8214 if (buf_size != buffer_prop->buffer_size) 8215 { 8216 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)", 8217 buffer_prop->buffer_size, buf_size); 8218 eRet = OMX_ErrorBadParameter; 8219 } 8220 else 8221 { 8222 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 8223 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 8224 8225 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){ 8226 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8227 fmt.fmt.pix_mp.pixelformat = output_capability; 8228 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8229 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8230 fmt.fmt.pix_mp.pixelformat = capture_capability; 8231 } else { 8232 eRet = OMX_ErrorBadParameter; 8233 } 8234 8235 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 8236 if (ret) 8237 { 8238 /*TODO: How to handle this case */ 8239 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret); 8240 eRet = OMX_ErrorInsufficientResources; 8241 } 8242 8243 bufreq.memory = V4L2_MEMORY_USERPTR; 8244 bufreq.count = buffer_prop->actualcount; 8245 if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 8246 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8247 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8248 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8249 } else { 8250 eRet = OMX_ErrorBadParameter; 8251 } 8252 8253 if (eRet==OMX_ErrorNone) { 8254 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 8255 } 8256 8257 if (ret) 8258 { 8259 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret); 8260 /*TODO: How to handle this case */ 8261 eRet = OMX_ErrorInsufficientResources; 8262 } else if (bufreq.count < buffer_prop->actualcount) { 8263 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers" 8264 " on v4l2 port %d to %d (prefers %d)", bufreq.type, 8265 buffer_prop->actualcount, bufreq.count); 8266 eRet = OMX_ErrorInsufficientResources; 8267 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8268 if (!client_buffers.update_buffer_req()) { 8269 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); 8270 eRet = OMX_ErrorInsufficientResources; 8271 } 8272 } 8273 } 8274 if (!eRet && !m_pSwVdec && buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) 8275 { 8276 // need to update extradata buffers also in pure dsp mode 8277 drv_ctx.extradata_info.size = buffer_prop->actualcount * drv_ctx.extradata_info.buffer_size; 8278 drv_ctx.extradata_info.count = buffer_prop->actualcount; 8279 } 8280 return eRet; 8281 } 8282 8283 OMX_ERRORTYPE omx_vdec::update_picture_resolution() 8284 { 8285 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8286 return eRet; 8287 } 8288 8289 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) 8290 { 8291 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8292 if (!portDefn) 8293 { 8294 return OMX_ErrorBadParameter; 8295 } 8296 DEBUG_PRINT_LOW("omx_vdec::update_portdef"); 8297 portDefn->nVersion.nVersion = OMX_SPEC_VERSION; 8298 portDefn->nSize = sizeof(portDefn); 8299 portDefn->eDomain = OMX_PortDomainVideo; 8300 if (drv_ctx.frame_rate.fps_denominator > 0) 8301 portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator / 8302 drv_ctx.frame_rate.fps_denominator; 8303 else { 8304 DEBUG_PRINT_ERROR("Error: Divide by zero"); 8305 return OMX_ErrorBadParameter; 8306 } 8307 if (0 == portDefn->nPortIndex) 8308 { 8309 portDefn->eDir = OMX_DirInput; 8310 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; 8311 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; 8312 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size; 8313 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; 8314 portDefn->format.video.eCompressionFormat = eCompressionFormat; 8315 portDefn->bEnabled = m_inp_bEnabled; 8316 portDefn->bPopulated = m_inp_bPopulated; 8317 } 8318 else if (1 == portDefn->nPortIndex) 8319 { 8320 unsigned int buf_size = 0; 8321 if (!client_buffers.update_buffer_req()) { 8322 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed"); 8323 return OMX_ErrorHardware; 8324 } 8325 if (!client_buffers.get_buffer_req(buf_size)) { 8326 DEBUG_PRINT_ERROR("update buffer requirements"); 8327 return OMX_ErrorHardware; 8328 } 8329 portDefn->nBufferSize = buf_size; 8330 portDefn->eDir = OMX_DirOutput; 8331 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; 8332 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; 8333 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 8334 portDefn->bEnabled = m_out_bEnabled; 8335 portDefn->bPopulated = m_out_bPopulated; 8336 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) { 8337 DEBUG_PRINT_ERROR("Error in getting color format"); 8338 return OMX_ErrorHardware; 8339 } 8340 } 8341 else 8342 { 8343 portDefn->eDir = OMX_DirMax; 8344 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", 8345 (int)portDefn->nPortIndex); 8346 eRet = OMX_ErrorBadPortIndex; 8347 } 8348 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; 8349 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; 8350 portDefn->format.video.nStride = drv_ctx.video_resolution.stride; 8351 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; 8352 DEBUG_PRINT_HIGH("update_portdef Width = %lu Height = %lu Stride = %ld" 8353 " SliceHeight = %lu", portDefn->format.video.nFrameWidth, 8354 portDefn->format.video.nFrameHeight, 8355 portDefn->format.video.nStride, 8356 portDefn->format.video.nSliceHeight); 8357 return eRet; 8358 8359 } 8360 8361 OMX_ERRORTYPE omx_vdec::allocate_output_headers() 8362 { 8363 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8364 OMX_BUFFERHEADERTYPE *bufHdr = NULL; 8365 unsigned i= 0; 8366 8367 if(!m_out_mem_ptr) { 8368 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation"); 8369 int nBufHdrSize = 0; 8370 int nPlatformEntrySize = 0; 8371 int nPlatformListSize = 0; 8372 int nPMEMInfoSize = 0; 8373 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 8374 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 8375 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 8376 8377 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)", 8378 drv_ctx.op_buf.actualcount); 8379 nBufHdrSize = drv_ctx.op_buf.actualcount * 8380 sizeof(OMX_BUFFERHEADERTYPE); 8381 8382 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 8383 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 8384 nPlatformListSize = drv_ctx.op_buf.actualcount * 8385 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 8386 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 8387 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 8388 8389 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, 8390 sizeof(OMX_BUFFERHEADERTYPE), 8391 nPMEMInfoSize, 8392 nPlatformListSize); 8393 DEBUG_PRINT_LOW("PE %d bmSize %d",nPlatformEntrySize, 8394 m_out_bm_count); 8395 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 8396 // Alloc mem for platform specific info 8397 char *pPtr=NULL; 8398 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 8399 nPMEMInfoSize,1); 8400 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ 8401 calloc (sizeof(struct vdec_bufferpayload), 8402 drv_ctx.op_buf.actualcount); 8403 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 8404 calloc (sizeof (struct vdec_output_frameinfo), 8405 drv_ctx.op_buf.actualcount); 8406 #ifdef USE_ION 8407 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ 8408 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); 8409 #endif 8410 if (dynamic_buf_mode) { 8411 out_dynamic_list = (struct dynamic_buf_list *) \ 8412 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount); 8413 } 8414 if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 8415 && drv_ctx.ptr_respbuffer) 8416 { 8417 bufHdr = m_out_mem_ptr; 8418 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 8419 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 8420 (((char *) m_platform_list) + nPlatformListSize); 8421 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 8422 (((char *) m_platform_entry) + nPlatformEntrySize); 8423 pPlatformList = m_platform_list; 8424 pPlatformEntry = m_platform_entry; 8425 pPMEMInfo = m_pmem_info; 8426 8427 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 8428 8429 // Settting the entire storage nicely 8430 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, 8431 m_out_mem_ptr,pPlatformEntry); 8432 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 8433 for(i=0; i < drv_ctx.op_buf.actualcount ; i++) 8434 { 8435 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 8436 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 8437 // Set the values when we determine the right HxW param 8438 bufHdr->nAllocLen = 0; 8439 bufHdr->nFilledLen = 0; 8440 bufHdr->pAppPrivate = NULL; 8441 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 8442 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 8443 pPlatformEntry->entry = pPMEMInfo; 8444 // Initialize the Platform List 8445 pPlatformList->nEntries = 1; 8446 pPlatformList->entryList = pPlatformEntry; 8447 // Keep pBuffer NULL till vdec is opened 8448 bufHdr->pBuffer = NULL; 8449 pPMEMInfo->offset = 0; 8450 pPMEMInfo->pmem_fd = 0; 8451 bufHdr->pPlatformPrivate = pPlatformList; 8452 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; 8453 #ifdef USE_ION 8454 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; 8455 #endif 8456 /*Create a mapping between buffers*/ 8457 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 8458 drv_ctx.ptr_respbuffer[i].client_data = (void *) \ 8459 &drv_ctx.ptr_outputbuffer[i]; 8460 // Move the buffer and buffer header pointers 8461 bufHdr++; 8462 pPMEMInfo++; 8463 pPlatformEntry++; 8464 pPlatformList++; 8465 } 8466 } 8467 else 8468 { 8469 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 8470 m_out_mem_ptr, pPtr); 8471 if(m_out_mem_ptr) 8472 { 8473 free(m_out_mem_ptr); 8474 m_out_mem_ptr = NULL; 8475 } 8476 if(pPtr) 8477 { 8478 free(pPtr); 8479 pPtr = NULL; 8480 } 8481 if(drv_ctx.ptr_outputbuffer) 8482 { 8483 free(drv_ctx.ptr_outputbuffer); 8484 drv_ctx.ptr_outputbuffer = NULL; 8485 } 8486 if(drv_ctx.ptr_respbuffer) 8487 { 8488 free(drv_ctx.ptr_respbuffer); 8489 drv_ctx.ptr_respbuffer = NULL; 8490 } 8491 #ifdef USE_ION 8492 if (drv_ctx.op_buf_ion_info) { 8493 DEBUG_PRINT_LOW("Free o/p ion context"); 8494 free(drv_ctx.op_buf_ion_info); 8495 drv_ctx.op_buf_ion_info = NULL; 8496 } 8497 #endif 8498 eRet = OMX_ErrorInsufficientResources; 8499 } 8500 } else { 8501 eRet = OMX_ErrorInsufficientResources; 8502 } 8503 return eRet; 8504 } 8505 8506 void omx_vdec::complete_pending_buffer_done_cbs() 8507 { 8508 unsigned p1; 8509 unsigned p2; 8510 unsigned ident; 8511 omx_cmd_queue tmp_q, pending_bd_q; 8512 pthread_mutex_lock(&m_lock); 8513 // pop all pending GENERATE FDB from ftb queue 8514 while (m_ftb_q.m_size) 8515 { 8516 m_ftb_q.pop_entry(&p1,&p2,&ident); 8517 if(ident == OMX_COMPONENT_GENERATE_FBD) 8518 { 8519 pending_bd_q.insert_entry(p1,p2,ident); 8520 } 8521 else 8522 { 8523 tmp_q.insert_entry(p1,p2,ident); 8524 } 8525 } 8526 //return all non GENERATE FDB to ftb queue 8527 while(tmp_q.m_size) 8528 { 8529 tmp_q.pop_entry(&p1,&p2,&ident); 8530 m_ftb_q.insert_entry(p1,p2,ident); 8531 } 8532 // pop all pending GENERATE EDB from etb queue 8533 while (m_etb_q.m_size) 8534 { 8535 m_etb_q.pop_entry(&p1,&p2,&ident); 8536 if(ident == OMX_COMPONENT_GENERATE_EBD) 8537 { 8538 pending_bd_q.insert_entry(p1,p2,ident); 8539 } 8540 else 8541 { 8542 tmp_q.insert_entry(p1,p2,ident); 8543 } 8544 } 8545 //return all non GENERATE FDB to etb queue 8546 while(tmp_q.m_size) 8547 { 8548 tmp_q.pop_entry(&p1,&p2,&ident); 8549 m_etb_q.insert_entry(p1,p2,ident); 8550 } 8551 pthread_mutex_unlock(&m_lock); 8552 // process all pending buffer dones 8553 while(pending_bd_q.m_size) 8554 { 8555 pending_bd_q.pop_entry(&p1,&p2,&ident); 8556 switch(ident) 8557 { 8558 case OMX_COMPONENT_GENERATE_EBD: 8559 if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) 8560 { 8561 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!"); 8562 omx_report_error (); 8563 } 8564 break; 8565 8566 case OMX_COMPONENT_GENERATE_FBD: 8567 if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) 8568 { 8569 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!"); 8570 omx_report_error (); 8571 } 8572 break; 8573 } 8574 } 8575 } 8576 8577 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) 8578 { 8579 OMX_U32 new_frame_interval = 0; 8580 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts 8581 && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000)) 8582 { 8583 new_frame_interval = (act_timestamp > prev_ts)? 8584 act_timestamp - prev_ts : 8585 prev_ts - act_timestamp; 8586 if (new_frame_interval < frm_int || frm_int == 0) 8587 { 8588 frm_int = new_frame_interval; 8589 if(frm_int) 8590 { 8591 drv_ctx.frame_rate.fps_numerator = 1e6; 8592 drv_ctx.frame_rate.fps_denominator = frm_int; 8593 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%lu) fps(%f)", 8594 frm_int, drv_ctx.frame_rate.fps_numerator / 8595 (float)drv_ctx.frame_rate.fps_denominator); 8596 } 8597 } 8598 } 8599 prev_ts = act_timestamp; 8600 } 8601 8602 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) 8603 { 8604 if (rst_prev_ts && VALID_TS(act_timestamp)) 8605 { 8606 prev_ts = act_timestamp; 8607 rst_prev_ts = false; 8608 } 8609 else if (VALID_TS(prev_ts)) 8610 { 8611 bool codec_cond = (drv_ctx.timestamp_adjust)? 8612 (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)? 8613 (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)): 8614 (!VALID_TS(act_timestamp) || act_timestamp == prev_ts); 8615 if(frm_int > 0 && codec_cond) 8616 { 8617 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); 8618 act_timestamp = prev_ts + frm_int; 8619 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); 8620 prev_ts = act_timestamp; 8621 } 8622 else 8623 set_frame_rate(act_timestamp); 8624 } 8625 else if (frm_int > 0) // In this case the frame rate was set along 8626 { // with the port definition, start ts with 0 8627 act_timestamp = prev_ts = 0; // and correct if a valid ts is received. 8628 rst_prev_ts = true; 8629 } 8630 } 8631 8632 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) 8633 { 8634 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; 8635 OMX_U32 num_conceal_MB = 0; 8636 OMX_U32 frame_rate = 0; 8637 int consumed_len = 0; 8638 OMX_U32 num_MB_in_frame; 8639 OMX_U32 recovery_sei_flags = 1; 8640 int buf_index = p_buf_hdr - m_out_mem_ptr; 8641 struct msm_vidc_panscan_window_payload *panscan_payload = NULL; 8642 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) + 8643 p_buf_hdr->nOffset; 8644 if (!drv_ctx.extradata_info.uaddr) { 8645 return; 8646 } 8647 p_extra = (OMX_OTHER_EXTRADATATYPE *) 8648 ((unsigned)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3)); 8649 if (!client_extradata) 8650 p_extra = NULL; 8651 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size; 8652 if ((OMX_U8*)p_extra >= (pBuffer + p_buf_hdr->nAllocLen)) 8653 p_extra = NULL; 8654 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; 8655 if (data) { 8656 while((consumed_len < drv_ctx.extradata_info.buffer_size) 8657 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) { 8658 if ((consumed_len + data->nSize) > (OMX_U32)drv_ctx.extradata_info.buffer_size) { 8659 DEBUG_PRINT_LOW("Invalid extra data size"); 8660 break; 8661 } 8662 switch((unsigned long)data->eType) { 8663 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO: 8664 struct msm_vidc_interlace_payload *payload; 8665 payload = (struct msm_vidc_interlace_payload *)data->data; 8666 if (payload->format != MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) { 8667 int enable = 1; 8668 OMX_U32 mbaff = 0; 8669 mbaff = (h264_parser)? (h264_parser->is_mbaff()): false; 8670 if ((payload->format == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !mbaff) 8671 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 8672 else 8673 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 8674 if(m_enable_android_native_buffers) 8675 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 8676 PP_PARAM_INTERLACED, (void*)&enable); 8677 } 8678 if (!secure_mode && (client_extradata & OMX_INTERLACE_EXTRADATA)) { 8679 append_interlace_extradata(p_extra, payload->format); 8680 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 8681 } 8682 break; 8683 case MSM_VIDC_EXTRADATA_FRAME_RATE: 8684 struct msm_vidc_framerate_payload *frame_rate_payload; 8685 frame_rate_payload = (struct msm_vidc_framerate_payload *)data->data; 8686 frame_rate = frame_rate_payload->frame_rate; 8687 break; 8688 case MSM_VIDC_EXTRADATA_TIMESTAMP: 8689 struct msm_vidc_ts_payload *time_stamp_payload; 8690 time_stamp_payload = (struct msm_vidc_ts_payload *)data->data; 8691 p_buf_hdr->nTimeStamp = time_stamp_payload->timestamp_lo; 8692 p_buf_hdr->nTimeStamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32); 8693 break; 8694 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB: 8695 struct msm_vidc_concealmb_payload *conceal_mb_payload; 8696 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)data->data; 8697 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 8698 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 8699 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0); 8700 break; 8701 case MSM_VIDC_EXTRADATA_ASPECT_RATIO: 8702 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload; 8703 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)data->data; 8704 ((struct vdec_output_frameinfo *) 8705 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width; 8706 ((struct vdec_output_frameinfo *) 8707 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height; 8708 break; 8709 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI: 8710 struct msm_vidc_recoverysei_payload *recovery_sei_payload; 8711 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)data->data; 8712 recovery_sei_flags = recovery_sei_payload->flags; 8713 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) { 8714 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 8715 DEBUG_PRINT_HIGH("Extradata: OMX_BUFFERFLAG_DATACORRUPT Received"); 8716 } 8717 break; 8718 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW: 8719 panscan_payload = (struct msm_vidc_panscan_window_payload *)data->data; 8720 break; 8721 default: 8722 goto unrecognized_extradata; 8723 } 8724 consumed_len += data->nSize; 8725 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); 8726 } 8727 if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) { 8728 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 8729 append_frame_info_extradata(p_extra, 8730 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate, 8731 panscan_payload,&((struct vdec_output_frameinfo *) 8732 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);} 8733 } 8734 unrecognized_extradata: 8735 if(!secure_mode && client_extradata) 8736 append_terminator_extradata(p_extra); 8737 return; 8738 } 8739 8740 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, 8741 bool is_internal, bool enable) 8742 { 8743 OMX_ERRORTYPE ret = OMX_ErrorNone; 8744 struct v4l2_control control; 8745 if(m_state != OMX_StateLoaded) 8746 { 8747 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); 8748 return OMX_ErrorIncorrectStateOperation; 8749 } 8750 DEBUG_PRINT_ERROR("NOTE: enable_extradata: actual[%lx] requested[%lx] enable[%d], is_internal: %d swvdec mode %d", 8751 client_extradata, requested_extradata, enable, is_internal, m_swvdec_mode); 8752 8753 if (!is_internal) { 8754 if (enable) 8755 client_extradata |= requested_extradata; 8756 else 8757 client_extradata = client_extradata & ~requested_extradata; 8758 } 8759 8760 if (enable) { 8761 if (m_pSwVdec == NULL || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) { 8762 if (requested_extradata & OMX_INTERLACE_EXTRADATA) { 8763 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8764 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO; 8765 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8766 DEBUG_PRINT_HIGH("Failed to set interlaced extradata." 8767 " Quality of interlaced clips might be impacted."); 8768 } 8769 } else if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) 8770 { 8771 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8772 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE; 8773 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8774 DEBUG_PRINT_HIGH("Failed to set framerate extradata"); 8775 } 8776 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8777 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB; 8778 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8779 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata"); 8780 } 8781 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8782 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI; 8783 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8784 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata"); 8785 } 8786 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8787 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW; 8788 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8789 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 8790 } 8791 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8792 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO; 8793 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8794 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 8795 } 8796 } else if (requested_extradata & OMX_TIMEINFO_EXTRADATA){ 8797 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 8798 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP; 8799 if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 8800 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata"); 8801 } 8802 } 8803 } 8804 } 8805 return ret; 8806 } 8807 8808 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) 8809 { 8810 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; 8811 OMX_U8 *data_ptr = extra->data, data = 0; 8812 while (byte_count < extra->nDataSize) 8813 { 8814 data = *data_ptr; 8815 while (data) 8816 { 8817 num_MB += (data&0x01); 8818 data >>= 1; 8819 } 8820 data_ptr++; 8821 byte_count++; 8822 } 8823 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 8824 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 8825 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); 8826 } 8827 8828 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) 8829 { 8830 if (!m_debug_extradata) 8831 return; 8832 8833 DEBUG_PRINT_HIGH( 8834 "============== Extra Data ==============\n" 8835 " Size: %lu\n" 8836 " Version: %lu\n" 8837 " PortIndex: %lu\n" 8838 " Type: %x\n" 8839 " DataSize: %lu", 8840 extra->nSize, extra->nVersion.nVersion, 8841 extra->nPortIndex, extra->eType, extra->nDataSize); 8842 8843 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) 8844 { 8845 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data; 8846 DEBUG_PRINT_HIGH( 8847 "------ Interlace Format ------\n" 8848 " Size: %lu\n" 8849 " Version: %lu\n" 8850 " PortIndex: %lu\n" 8851 " Is Interlace Format: %d\n" 8852 " Interlace Formats: %lu\n" 8853 "=========== End of Interlace ===========", 8854 intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex, 8855 intfmt->bInterlaceFormat, intfmt->nInterlaceFormats); 8856 } 8857 else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) 8858 { 8859 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; 8860 8861 DEBUG_PRINT_HIGH( 8862 "-------- Frame Format --------\n" 8863 " Picture Type: %d\n" 8864 " Interlace Type: %d\n" 8865 " Pan Scan Total Frame Num: %lu\n" 8866 " Concealed Macro Blocks: %lu\n" 8867 " frame rate: %lu\n" 8868 " Aspect Ratio X: %lu\n" 8869 " Aspect Ratio Y: %lu", 8870 fminfo->ePicType, 8871 fminfo->interlaceType, 8872 fminfo->panScan.numWindows, 8873 fminfo->nConcealedMacroblocks, 8874 fminfo->nFrameRate, 8875 fminfo->aspectRatio.aspectRatioX, 8876 fminfo->aspectRatio.aspectRatioY); 8877 8878 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) 8879 { 8880 DEBUG_PRINT_HIGH( 8881 "------------------------------\n" 8882 " Pan Scan Frame Num: %lu\n" 8883 " Rectangle x: %ld\n" 8884 " Rectangle y: %ld\n" 8885 " Rectangle dx: %ld\n" 8886 " Rectangle dy: %ld", 8887 i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y, 8888 fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy); 8889 } 8890 8891 DEBUG_PRINT_HIGH("========= End of Frame Format =========="); 8892 } 8893 else if (extra->eType == OMX_ExtraDataNone) 8894 { 8895 DEBUG_PRINT_HIGH("========== End of Terminator ==========="); 8896 } 8897 else 8898 { 8899 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); 8900 } 8901 } 8902 8903 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, 8904 OMX_U32 interlaced_format_type) 8905 { 8906 OMX_STREAMINTERLACEFORMAT *interlace_format; 8907 OMX_U32 mbaff = 0; 8908 if (!(client_extradata & OMX_INTERLACE_EXTRADATA) || !extra) { 8909 return; 8910 } 8911 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; 8912 extra->nVersion.nVersion = OMX_SPEC_VERSION; 8913 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 8914 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; 8915 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); 8916 interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data; 8917 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); 8918 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; 8919 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 8920 mbaff = (h264_parser)? (h264_parser->is_mbaff()): false; 8921 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !mbaff) 8922 { 8923 interlace_format->bInterlaceFormat = OMX_FALSE; 8924 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; 8925 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 8926 } 8927 else 8928 { 8929 interlace_format->bInterlaceFormat = OMX_TRUE; 8930 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 8931 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 8932 } 8933 print_debug_extradata(extra); 8934 } 8935 8936 void omx_vdec::fill_aspect_ratio_info( 8937 struct vdec_aspectratioinfo *aspect_ratio_info, 8938 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info) 8939 { 8940 m_extradata = frame_info; 8941 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width; 8942 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height; 8943 DEBUG_PRINT_LOW("aspectRatioX %lu aspectRatioX %lu", m_extradata->aspectRatio.aspectRatioX, 8944 m_extradata->aspectRatio.aspectRatioY); 8945 } 8946 8947 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, 8948 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate, 8949 struct msm_vidc_panscan_window_payload *panscan_payload, 8950 struct vdec_aspectratioinfo *aspect_ratio_info) 8951 { 8952 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; 8953 struct msm_vidc_panscan_window *panscan_window; 8954 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA) || !extra) { 8955 return; 8956 } 8957 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; 8958 extra->nVersion.nVersion = OMX_SPEC_VERSION; 8959 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 8960 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; 8961 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); 8962 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; 8963 switch (picture_type) 8964 { 8965 case PICTURE_TYPE_I: 8966 frame_info->ePicType = OMX_VIDEO_PictureTypeI; 8967 break; 8968 case PICTURE_TYPE_P: 8969 frame_info->ePicType = OMX_VIDEO_PictureTypeP; 8970 break; 8971 case PICTURE_TYPE_B: 8972 frame_info->ePicType = OMX_VIDEO_PictureTypeB; 8973 break; 8974 default: 8975 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; 8976 } 8977 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) 8978 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 8979 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) 8980 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 8981 else 8982 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; 8983 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); 8984 frame_info->nConcealedMacroblocks = num_conceal_mb; 8985 frame_info->nFrameRate = frame_rate; 8986 frame_info->panScan.numWindows = 0; 8987 if(panscan_payload) { 8988 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows; 8989 panscan_window = &panscan_payload->wnd[0]; 8990 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) 8991 { 8992 frame_info->panScan.window[i].x = panscan_window->panscan_window_width; 8993 frame_info->panScan.window[i].y = panscan_window->panscan_window_height; 8994 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset; 8995 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset; 8996 panscan_window++; 8997 } 8998 } 8999 fill_aspect_ratio_info(aspect_ratio_info, frame_info); 9000 print_debug_extradata(extra); 9001 } 9002 9003 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9004 { 9005 if (!client_extradata || !extra) { 9006 return; 9007 } 9008 9009 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; 9010 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; 9011 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9012 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9013 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; 9014 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 9015 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data; 9016 *portDefn = m_port_def; 9017 DEBUG_PRINT_LOW("append_portdef_extradata height = %lu width = %lu stride = %lu" 9018 "sliceheight = %lu",portDefn->format.video.nFrameHeight, 9019 portDefn->format.video.nFrameWidth, 9020 portDefn->format.video.nStride, 9021 portDefn->format.video.nSliceHeight); 9022 } 9023 9024 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9025 { 9026 if (!client_extradata || !extra) { 9027 return; 9028 } 9029 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); 9030 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9031 extra->eType = OMX_ExtraDataNone; 9032 extra->nDataSize = 0; 9033 extra->data[0] = 0; 9034 9035 print_debug_extradata(extra); 9036 } 9037 9038 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) 9039 { 9040 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9041 if (index >= drv_ctx.ip_buf.actualcount) 9042 { 9043 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found"); 9044 return OMX_ErrorInsufficientResources; 9045 } 9046 if (m_desc_buffer_ptr == NULL) 9047 { 9048 m_desc_buffer_ptr = (desc_buffer_hdr*) \ 9049 calloc( (sizeof(desc_buffer_hdr)), 9050 drv_ctx.ip_buf.actualcount); 9051 if (m_desc_buffer_ptr == NULL) 9052 { 9053 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed "); 9054 return OMX_ErrorInsufficientResources; 9055 } 9056 } 9057 9058 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); 9059 if (m_desc_buffer_ptr[index].buf_addr == NULL) 9060 { 9061 DEBUG_PRINT_ERROR("desc buffer Allocation failed "); 9062 return OMX_ErrorInsufficientResources; 9063 } 9064 9065 return eRet; 9066 } 9067 9068 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) 9069 { 9070 DEBUG_PRINT_LOW("Inserting address offset (%lu) at idx (%lu)", address_offset,m_demux_entries); 9071 if (m_demux_entries < 8192) 9072 { 9073 m_demux_offsets[m_demux_entries++] = address_offset; 9074 } 9075 return; 9076 } 9077 9078 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) 9079 { 9080 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; 9081 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; 9082 OMX_U32 index = 0; 9083 9084 m_demux_entries = 0; 9085 9086 while (index < bytes_to_parse) 9087 { 9088 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 9089 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || 9090 ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 9091 (buf[index+2] == 0x01)) ) 9092 { 9093 //Found start code, insert address offset 9094 insert_demux_addr_offset(index); 9095 if (buf[index+2] == 0x01) // 3 byte start code 9096 index += 3; 9097 else //4 byte start code 9098 index += 4; 9099 } 9100 else 9101 index++; 9102 } 9103 DEBUG_PRINT_LOW("Extracted (%lu) demux entry offsets",m_demux_entries); 9104 return; 9105 } 9106 9107 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) 9108 { 9109 //fix this, handle 3 byte start code, vc1 terminator entry 9110 OMX_U8 *p_demux_data = NULL; 9111 OMX_U32 desc_data = 0; 9112 OMX_U32 start_addr = 0; 9113 OMX_U32 nal_size = 0; 9114 OMX_U32 suffix_byte = 0; 9115 OMX_U32 demux_index = 0; 9116 OMX_U32 buffer_index = 0; 9117 9118 if (m_desc_buffer_ptr == NULL) 9119 { 9120 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); 9121 return OMX_ErrorBadParameter; 9122 } 9123 9124 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 9125 if (buffer_index > drv_ctx.ip_buf.actualcount) 9126 { 9127 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%lu)", buffer_index); 9128 return OMX_ErrorBadParameter; 9129 } 9130 9131 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; 9132 9133 if ( ((OMX_U8*)p_demux_data == NULL) || 9134 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) 9135 { 9136 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); 9137 return OMX_ErrorBadParameter; 9138 } 9139 else 9140 { 9141 for (; demux_index < m_demux_entries; demux_index++) 9142 { 9143 desc_data = 0; 9144 start_addr = m_demux_offsets[demux_index]; 9145 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) 9146 { 9147 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; 9148 } 9149 else 9150 { 9151 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; 9152 } 9153 if (demux_index < (m_demux_entries - 1)) 9154 { 9155 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; 9156 } 9157 else 9158 { 9159 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; 9160 } 9161 DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%lu),demux_index(%lu)", 9162 (void*)start_addr, 9163 (unsigned int)suffix_byte, 9164 nal_size, 9165 demux_index); 9166 desc_data = (start_addr >> 3) << 1; 9167 desc_data |= (start_addr & 7) << 21; 9168 desc_data |= suffix_byte << 24; 9169 9170 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 9171 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); 9172 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 9173 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 9174 9175 p_demux_data += 16; 9176 } 9177 if (codec_type_parse == CODEC_TYPE_VC1) 9178 { 9179 DEBUG_PRINT_LOW("VC1 terminator entry"); 9180 desc_data = 0; 9181 desc_data = 0x82 << 24; 9182 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 9183 memset(p_demux_data + 4, 0, sizeof(OMX_U32)); 9184 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 9185 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 9186 p_demux_data += 16; 9187 m_demux_entries++; 9188 } 9189 //Add zero word to indicate end of descriptors 9190 memset(p_demux_data, 0, sizeof(OMX_U32)); 9191 9192 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); 9193 DEBUG_PRINT_LOW("desc table data size=%lu", m_desc_buffer_ptr[buffer_index].desc_data_size); 9194 } 9195 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 9196 m_demux_entries = 0; 9197 DEBUG_PRINT_LOW("Demux table complete!"); 9198 return OMX_ErrorNone; 9199 } 9200 9201 OMX_ERRORTYPE omx_vdec::createDivxDrmContext() 9202 { 9203 OMX_ERRORTYPE err = OMX_ErrorNone; 9204 iDivXDrmDecrypt = DivXDrmDecrypt::Create(); 9205 if (iDivXDrmDecrypt) { 9206 OMX_ERRORTYPE err = iDivXDrmDecrypt->Init(); 9207 if(err!=OMX_ErrorNone) { 9208 DEBUG_PRINT_ERROR("ERROR :iDivXDrmDecrypt->Init %d", err); 9209 delete iDivXDrmDecrypt; 9210 iDivXDrmDecrypt = NULL; 9211 } 9212 } 9213 else { 9214 DEBUG_PRINT_ERROR("Unable to Create DIVX DRM"); 9215 err = OMX_ErrorUndefined; 9216 } 9217 return err; 9218 } 9219 9220 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf() 9221 { 9222 enabled = false; 9223 omx = NULL; 9224 init_members(); 9225 ColorFormat = OMX_COLOR_FormatMax; 9226 } 9227 9228 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client) 9229 { 9230 omx = reinterpret_cast<omx_vdec*>(client); 9231 } 9232 9233 void omx_vdec::allocate_color_convert_buf::init_members() { 9234 allocated_count = 0; 9235 buffer_size_req = 0; 9236 buffer_alignment_req = 0; 9237 memset(m_platform_list_client,0,sizeof(m_platform_list_client)); 9238 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client)); 9239 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client)); 9240 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client)); 9241 #ifdef USE_ION 9242 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client)); 9243 #endif 9244 for (int i = 0; i < MAX_COUNT;i++) 9245 pmem_fd[i] = -1; 9246 } 9247 9248 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf() { 9249 c2d.destroy(); 9250 } 9251 9252 bool omx_vdec::allocate_color_convert_buf::update_buffer_req() 9253 { 9254 bool status = true; 9255 unsigned int src_size = 0, destination_size = 0; 9256 OMX_COLOR_FORMATTYPE drv_color_format; 9257 if (!omx){ 9258 DEBUG_PRINT_ERROR("Invalid client in color convert"); 9259 return false; 9260 } 9261 if (!enabled){ 9262 DEBUG_PRINT_ERROR("No color conversion required"); 9263 return status; 9264 } 9265 pthread_mutex_lock(&omx->c_lock); 9266 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 && 9267 ColorFormat != OMX_COLOR_FormatYUV420Planar) { 9268 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion"); 9269 status = false; 9270 goto fail_update_buf_req; 9271 } 9272 c2d.close(); 9273 status = c2d.open(omx->drv_ctx.video_resolution.frame_height, 9274 omx->drv_ctx.video_resolution.frame_width, 9275 NV12_128m,YCbCr420P); 9276 if (status) { 9277 status = c2d.get_buffer_size(C2D_INPUT,src_size); 9278 if (status) 9279 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size); 9280 } 9281 if (status) { 9282 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size || 9283 !destination_size) { 9284 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d" 9285 "driver size %d destination size %d", 9286 src_size,omx->drv_ctx.op_buf.buffer_size,destination_size); 9287 status = false; 9288 c2d.close(); 9289 buffer_size_req = 0; 9290 } else { 9291 buffer_size_req = destination_size; 9292 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size) 9293 buffer_size_req = omx->drv_ctx.op_buf.buffer_size; 9294 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 9295 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 9296 } 9297 } 9298 fail_update_buf_req: 9299 pthread_mutex_unlock(&omx->c_lock); 9300 return status; 9301 } 9302 9303 bool omx_vdec::allocate_color_convert_buf::set_color_format( 9304 OMX_COLOR_FORMATTYPE dest_color_format) 9305 { 9306 bool status = true; 9307 OMX_COLOR_FORMATTYPE drv_color_format; 9308 if (!omx){ 9309 DEBUG_PRINT_ERROR("Invalid client in color convert"); 9310 return false; 9311 } 9312 pthread_mutex_lock(&omx->c_lock); 9313 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 9314 drv_color_format = (OMX_COLOR_FORMATTYPE) 9315 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 9316 else { 9317 DEBUG_PRINT_ERROR("Incorrect color format"); 9318 status = false; 9319 } 9320 if (status && (drv_color_format != dest_color_format)) { 9321 DEBUG_PRINT_LOW("Enabling C2D"); 9322 if (dest_color_format != OMX_COLOR_FormatYUV420Planar) { 9323 DEBUG_PRINT_ERROR("Unsupported color format for c2d"); 9324 status = false; 9325 } else { 9326 ColorFormat = OMX_COLOR_FormatYUV420Planar; 9327 if (enabled) 9328 c2d.destroy(); 9329 enabled = false; 9330 if (!c2d.init()) { 9331 DEBUG_PRINT_ERROR("open failed for c2d"); 9332 status = false; 9333 } else 9334 enabled = true; 9335 } 9336 } else { 9337 if (enabled) 9338 c2d.destroy(); 9339 enabled = false; 9340 } 9341 pthread_mutex_unlock(&omx->c_lock); 9342 return status; 9343 } 9344 9345 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() 9346 { 9347 if (!omx){ 9348 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 9349 return NULL; 9350 } 9351 if (!enabled) 9352 return omx->m_out_mem_ptr; 9353 return m_out_mem_ptr_client; 9354 } 9355 9356 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr 9357 (OMX_BUFFERHEADERTYPE *bufadd) 9358 { 9359 if (!omx){ 9360 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 9361 return NULL; 9362 } 9363 if (!enabled) 9364 return bufadd; 9365 9366 unsigned index = 0; 9367 index = bufadd - omx->m_out_mem_ptr; 9368 if (index < omx->drv_ctx.op_buf.actualcount) { 9369 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS); 9370 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp; 9371 bool status; 9372 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) { 9373 pthread_mutex_lock(&omx->c_lock); 9374 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd, 9375 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer,pmem_fd[index], 9376 pmem_baseaddress[index], pmem_baseaddress[index]); 9377 pthread_mutex_unlock(&omx->c_lock); 9378 m_out_mem_ptr_client[index].nFilledLen = buffer_size_req; 9379 if (!status){ 9380 DEBUG_PRINT_ERROR("Failed color conversion %d", status); 9381 m_out_mem_ptr_client[index].nFilledLen = 0; 9382 return &m_out_mem_ptr_client[index]; 9383 } 9384 } else 9385 m_out_mem_ptr_client[index].nFilledLen = 0; 9386 return &m_out_mem_ptr_client[index]; 9387 } 9388 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr"); 9389 return NULL; 9390 } 9391 9392 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr 9393 (OMX_BUFFERHEADERTYPE *bufadd) 9394 { 9395 if (!omx){ 9396 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 9397 return NULL; 9398 } 9399 if (!enabled) 9400 return bufadd; 9401 unsigned index = 0; 9402 index = bufadd - m_out_mem_ptr_client; 9403 if (index < omx->drv_ctx.op_buf.actualcount) { 9404 return &omx->m_out_mem_ptr[index]; 9405 } 9406 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr"); 9407 return NULL; 9408 } 9409 bool omx_vdec::allocate_color_convert_buf::get_buffer_req(unsigned int &buffer_size) 9410 { 9411 bool status = true; 9412 pthread_mutex_lock(&omx->c_lock); 9413 if (!enabled) 9414 buffer_size = omx->drv_ctx.op_buf.buffer_size; 9415 else { 9416 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) { 9417 DEBUG_PRINT_ERROR("Get buffer size failed"); 9418 status = false; 9419 goto fail_get_buffer_size; 9420 } 9421 } 9422 if (buffer_size < omx->drv_ctx.op_buf.buffer_size) 9423 buffer_size = omx->drv_ctx.op_buf.buffer_size; 9424 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 9425 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 9426 fail_get_buffer_size: 9427 pthread_mutex_unlock(&omx->c_lock); 9428 return status; 9429 } 9430 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer( 9431 OMX_BUFFERHEADERTYPE *bufhdr) 9432 { 9433 unsigned int index = 0; 9434 9435 if (!enabled) 9436 return omx->free_output_buffer(bufhdr); 9437 if (enabled && omx->is_component_secure()) 9438 return OMX_ErrorNone; 9439 if (!allocated_count || !bufhdr) { 9440 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr); 9441 return OMX_ErrorBadParameter; 9442 } 9443 index = bufhdr - m_out_mem_ptr_client; 9444 if (index >= omx->drv_ctx.op_buf.actualcount){ 9445 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer"); 9446 return OMX_ErrorBadParameter; 9447 } 9448 if (pmem_fd[index] > 0) { 9449 munmap(pmem_baseaddress[index], buffer_size_req); 9450 close(pmem_fd[index]); 9451 } 9452 pmem_fd[index] = -1; 9453 #ifdef USE_ION 9454 omx->free_ion_memory(&op_buf_ion_info[index]); 9455 #endif 9456 m_heap_ptr[index].video_heap_ptr = NULL; 9457 if (allocated_count > 0) 9458 allocated_count--; 9459 else 9460 allocated_count = 0; 9461 if (!allocated_count) { 9462 pthread_mutex_lock(&omx->c_lock); 9463 c2d.close(); 9464 init_members(); 9465 pthread_mutex_unlock(&omx->c_lock); 9466 } 9467 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]); 9468 } 9469 9470 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp, 9471 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes) 9472 { 9473 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9474 if (!enabled){ 9475 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); 9476 return eRet; 9477 } 9478 if (enabled && omx->is_component_secure()) { 9479 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d", 9480 omx->is_component_secure()); 9481 return OMX_ErrorUnsupportedSetting; 9482 } 9483 if (!bufferHdr || bytes > buffer_size_req) { 9484 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr); 9485 DEBUG_PRINT_ERROR("color_convert buffer_size_req %d bytes %lu", 9486 buffer_size_req,bytes); 9487 return OMX_ErrorBadParameter; 9488 } 9489 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) { 9490 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert"); 9491 return OMX_ErrorInsufficientResources; 9492 } 9493 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL; 9494 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr, 9495 port,appData,omx->drv_ctx.op_buf.buffer_size); 9496 if (eRet != OMX_ErrorNone || !temp_bufferHdr){ 9497 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert"); 9498 return eRet; 9499 } 9500 if ((temp_bufferHdr - omx->m_out_mem_ptr) >= 9501 (int)omx->drv_ctx.op_buf.actualcount) { 9502 DEBUG_PRINT_ERROR("Invalid header index %d", 9503 (temp_bufferHdr - omx->m_out_mem_ptr)); 9504 return OMX_ErrorUndefined; 9505 } 9506 unsigned int i = allocated_count; 9507 #ifdef USE_ION 9508 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory( 9509 buffer_size_req,buffer_alignment_req, 9510 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data, 9511 0); 9512 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd; 9513 if (op_buf_ion_info[i].ion_device_fd < 0) { 9514 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert"); 9515 return OMX_ErrorInsufficientResources; 9516 } 9517 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req, 9518 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0); 9519 9520 if (pmem_baseaddress[i] == MAP_FAILED) { 9521 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req); 9522 close(pmem_fd[i]); 9523 omx->free_ion_memory(&op_buf_ion_info[i]); 9524 return OMX_ErrorInsufficientResources; 9525 } 9526 m_heap_ptr[i].video_heap_ptr = new VideoHeap ( 9527 op_buf_ion_info[i].ion_device_fd,buffer_size_req, 9528 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]); 9529 #endif 9530 m_pmem_info_client[i].pmem_fd = (OMX_U32)m_heap_ptr[i].video_heap_ptr.get(); 9531 m_pmem_info_client[i].offset = 0; 9532 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i]; 9533 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 9534 m_platform_list_client[i].nEntries = 1; 9535 m_platform_list_client[i].entryList = &m_platform_entry_client[i]; 9536 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL; 9537 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req; 9538 m_out_mem_ptr_client[i].nFilledLen = 0; 9539 m_out_mem_ptr_client[i].nFlags = 0; 9540 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9541 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE); 9542 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION; 9543 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i]; 9544 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i]; 9545 m_out_mem_ptr_client[i].pAppPrivate = appData; 9546 *bufferHdr = &m_out_mem_ptr_client[i]; 9547 DEBUG_PRINT_ERROR("IL client buffer header %p", *bufferHdr); 9548 allocated_count++; 9549 return eRet; 9550 } 9551 9552 bool omx_vdec::is_component_secure() 9553 { 9554 return secure_mode; 9555 } 9556 9557 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format) 9558 { 9559 bool status = true; 9560 if (!enabled) { 9561 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 9562 dest_color_format = (OMX_COLOR_FORMATTYPE) 9563 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 9564 else 9565 status = false; 9566 } else { 9567 if (ColorFormat != OMX_COLOR_FormatYUV420Planar) { 9568 status = false; 9569 } else 9570 dest_color_format = OMX_COLOR_FormatYUV420Planar; 9571 } 9572 return status; 9573 } 9574 9575 void omx_vdec::buf_ref_add(int index, OMX_U32 fd, OMX_U32 offset) 9576 { 9577 int i = 0; 9578 bool buf_present = false; 9579 9580 pthread_mutex_lock(&m_lock); 9581 if (out_dynamic_list[index].dup_fd && 9582 (out_dynamic_list[index].fd != fd) && 9583 (out_dynamic_list[index].offset != offset)) 9584 { 9585 DEBUG_PRINT_LOW("buf_ref_add error: index %d taken by fd = %lu offset = %lu, new fd %lu offset %lu", 9586 index, out_dynamic_list[index].fd, out_dynamic_list[index].offset, fd, offset); 9587 pthread_mutex_unlock(&m_lock); 9588 return; 9589 } 9590 9591 if (out_dynamic_list[index].dup_fd == 0) 9592 { 9593 out_dynamic_list[index].fd = fd; 9594 out_dynamic_list[index].offset = offset; 9595 out_dynamic_list[index].dup_fd = dup(fd); 9596 } 9597 out_dynamic_list[index].ref_count++; 9598 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %lu ref_count = %lu", 9599 out_dynamic_list[index].fd, out_dynamic_list[index].ref_count); 9600 pthread_mutex_unlock(&m_lock); 9601 } 9602 9603 void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset) 9604 { 9605 unsigned long i = 0; 9606 pthread_mutex_lock(&m_lock); 9607 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 9608 //check the buffer fd, offset, uv addr with list contents 9609 //If present decrement reference. 9610 if ((out_dynamic_list[i].fd == fd) && 9611 (out_dynamic_list[i].offset == offset)) { 9612 out_dynamic_list[i].ref_count--; 9613 if (out_dynamic_list[i].ref_count == 0) { 9614 close(out_dynamic_list[i].dup_fd); 9615 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %lu ref_count = %lu", 9616 out_dynamic_list[i].fd, out_dynamic_list[i].ref_count); 9617 out_dynamic_list[i].dup_fd = 0; 9618 out_dynamic_list[i].fd = 0; 9619 out_dynamic_list[i].offset = 0; 9620 9621 munmap(drv_ctx.ptr_outputbuffer[i].bufferaddr, 9622 drv_ctx.ptr_outputbuffer[i].mmaped_size); 9623 DEBUG_PRINT_LOW("unmapped dynamic buffer idx %lu pBuffer %p", 9624 i, drv_ctx.ptr_outputbuffer[i].bufferaddr); 9625 9626 drv_ctx.ptr_outputbuffer[i].bufferaddr = NULL; 9627 drv_ctx.ptr_outputbuffer[i].offset = 0; 9628 drv_ctx.ptr_outputbuffer[i].mmaped_size = 0; 9629 if (m_pSwVdecOpBuffer) 9630 { 9631 m_pSwVdecOpBuffer[i].pBuffer = NULL; 9632 m_pSwVdecOpBuffer[i].nSize = 0; 9633 } 9634 } 9635 break; 9636 } 9637 } 9638 if (i >= drv_ctx.op_buf.actualcount) { 9639 DEBUG_PRINT_ERROR("Error - could not remove ref, no match with any entry in list"); 9640 } 9641 pthread_mutex_unlock(&m_lock); 9642 } 9643 9644 OMX_ERRORTYPE omx_vdec::get_buffer_req_swvdec() 9645 { 9646 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9647 9648 if (!m_pSwVdec) 9649 { 9650 eRet=get_buffer_req(&drv_ctx.ip_buf); 9651 eRet=get_buffer_req(&drv_ctx.op_buf); 9652 return eRet; 9653 } 9654 9655 SWVDEC_PROP property; 9656 if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 9657 { 9658 property.ePropId = SWVDEC_PROP_ID_IPBUFFREQ; 9659 SWVDEC_STATUS sRet = SwVdec_GetProperty(m_pSwVdec, &property); 9660 if (sRet != SWVDEC_S_SUCCESS) 9661 { 9662 return OMX_ErrorUndefined; 9663 } 9664 else 9665 { 9666 drv_ctx.ip_buf.buffer_size = property.uProperty.sIpBuffReq.nSize; 9667 drv_ctx.ip_buf.mincount = property.uProperty.sIpBuffReq.nMinCount; 9668 drv_ctx.ip_buf.actualcount = property.uProperty.sIpBuffReq.nMinCount; 9669 DEBUG_PRINT_ERROR("swvdec input buf size %d count %d",drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.actualcount); 9670 } 9671 } 9672 9673 property.ePropId = SWVDEC_PROP_ID_OPBUFFREQ; 9674 SWVDEC_STATUS sRet = SwVdec_GetProperty(m_pSwVdec, &property); 9675 if (sRet != SWVDEC_S_SUCCESS) 9676 { 9677 return OMX_ErrorUndefined; 9678 } 9679 else 9680 { 9681 int client_extra_data_size = 0; 9682 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 9683 { 9684 DEBUG_PRINT_HIGH("Frame info extra data enabled!"); 9685 client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE; 9686 } 9687 if (client_extradata & OMX_INTERLACE_EXTRADATA) 9688 { 9689 DEBUG_PRINT_HIGH("OMX_INTERLACE_EXTRADATA!"); 9690 client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE; 9691 } 9692 if (client_extradata & OMX_PORTDEF_EXTRADATA) 9693 { 9694 client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE; 9695 DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d", 9696 client_extra_data_size); 9697 } 9698 if (client_extra_data_size) 9699 { 9700 client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator 9701 } 9702 drv_ctx.op_buf.buffer_size = property.uProperty.sOpBuffReq.nSize + client_extra_data_size; 9703 drv_ctx.op_buf.mincount = property.uProperty.sOpBuffReq.nMinCount; 9704 drv_ctx.op_buf.actualcount = property.uProperty.sOpBuffReq.nMinCount; 9705 DEBUG_PRINT_HIGH("swvdec opbuf size %lu extradata size %d total size %d count %d", 9706 property.uProperty.sOpBuffReq.nSize, client_extra_data_size, 9707 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.actualcount); 9708 } 9709 9710 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 9711 { 9712 return get_buffer_req(&drv_ctx.interm_op_buf); 9713 } 9714 return OMX_ErrorNone; 9715 } 9716 9717 OMX_ERRORTYPE omx_vdec::set_buffer_req_swvdec(vdec_allocatorproperty *buffer_prop) 9718 { 9719 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9720 9721 if (!m_pSwVdec) 9722 { 9723 eRet = set_buffer_req(buffer_prop); 9724 return eRet; 9725 } 9726 9727 unsigned buf_size = 0; 9728 SWVDEC_PROP property; 9729 SWVDEC_STATUS sRet = SWVDEC_S_SUCCESS; 9730 9731 DEBUG_PRINT_HIGH("set_buffer_req_swvdec IN: ActCnt(%d) Size(%d), buffer type %d", 9732 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type); 9733 9734 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 9735 if (buf_size != buffer_prop->buffer_size) 9736 { 9737 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)", 9738 buffer_prop->buffer_size, buf_size); 9739 eRet = OMX_ErrorBadParameter; 9740 } 9741 else 9742 { 9743 property.uProperty.sIpBuffReq.nSize = buffer_prop->buffer_size; 9744 property.uProperty.sIpBuffReq.nMaxCount = buffer_prop->actualcount; 9745 property.uProperty.sIpBuffReq.nMinCount = buffer_prop->actualcount; 9746 9747 if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) 9748 { 9749 property.ePropId = SWVDEC_PROP_ID_IPBUFFREQ; 9750 DEBUG_PRINT_HIGH("swvdec input Buffer Size = %lu Count = %d",property.uProperty.sIpBuffReq.nSize, buffer_prop->mincount); 9751 } 9752 else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) 9753 { 9754 property.ePropId = SWVDEC_PROP_ID_OPBUFFREQ; 9755 DEBUG_PRINT_HIGH("swvdec output Buffer Size = %lu and Count = %d",property.uProperty.sOpBuffReq.nSize, buffer_prop->actualcount); 9756 } 9757 else 9758 { 9759 eRet = OMX_ErrorBadParameter; 9760 } 9761 9762 if(eRet==OMX_ErrorNone) 9763 { 9764 sRet = SwVdec_SetProperty(m_pSwVdec, &property); 9765 } 9766 9767 if (sRet != SWVDEC_S_SUCCESS) 9768 { 9769 DEBUG_PRINT_ERROR("Set buffer requirements from ARM codec failed"); 9770 return OMX_ErrorInsufficientResources; 9771 } 9772 } 9773 9774 if ((m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) && 9775 (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT)) 9776 { 9777 // need to update extradata buffers also 9778 drv_ctx.extradata_info.size = buffer_prop->actualcount * drv_ctx.extradata_info.buffer_size; 9779 drv_ctx.extradata_info.count = buffer_prop->actualcount; 9780 eRet = set_buffer_req(&drv_ctx.interm_op_buf); 9781 } 9782 9783 return eRet; 9784 } 9785 9786 /* ====================================================================== 9787 FUNCTION 9788 omx_vdec::empty_this_buffer_proxy 9789 9790 DESCRIPTION 9791 This routine is used to push the encoded video frames to 9792 the video decoder. 9793 9794 PARAMETERS 9795 None. 9796 9797 RETURN VALUE 9798 OMX Error None if everything went successful. 9799 9800 ========================================================================== */ 9801 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_swvdec(OMX_IN OMX_HANDLETYPE hComp, 9802 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 9803 { 9804 int push_cnt = 0,i=0; 9805 unsigned nPortIndex = 0; 9806 OMX_ERRORTYPE ret = OMX_ErrorNone; 9807 struct vdec_input_frameinfo frameinfo; 9808 struct vdec_bufferpayload *temp_buffer; 9809 struct vdec_seqheader seq_header; 9810 bool port_setting_changed = true; 9811 bool not_coded_vop = false; 9812 9813 /*Should we generate a Aync error event*/ 9814 if (buffer == NULL) 9815 { 9816 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid"); 9817 return OMX_ErrorBadParameter; 9818 } 9819 9820 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_interm_mem_ptr); 9821 9822 if (nPortIndex > drv_ctx.interm_op_buf.actualcount) 9823 { 9824 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy_swvdec invalid nPortIndex[%u]", 9825 nPortIndex); 9826 return OMX_ErrorBadParameter; 9827 } 9828 9829 /* return zero length and not an EOS buffer */ 9830 if ( (buffer->nFilledLen == 0) && 9831 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) 9832 { 9833 DEBUG_PRINT_HIGH("return zero legth buffer"); 9834 pthread_mutex_lock(&m_lock); 9835 m_interm_buf_state[nPortIndex] = WITH_SWVDEC; 9836 pthread_mutex_unlock(&m_lock); 9837 post_event ((unsigned int)buffer,VDEC_S_SUCCESS, 9838 OMX_COMPONENT_GENERATE_EBD_SWVDEC); 9839 return OMX_ErrorNone; 9840 } 9841 9842 if(m_interm_bEnabled != OMX_TRUE || m_interm_flush_swvdec_progress == true) 9843 { 9844 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_swvdec called when swvdec flush is in progress"); 9845 return OMX_ErrorNone; 9846 } 9847 9848 // send this buffer to swvdec 9849 DEBUG_PRINT_LOW("empty_this_buffer_proxy_swvdec bufHdr %p pBuffer %p nFilledLen %lu m_pSwVdecIpBuffer %p, idx %d nFlags %x", 9850 buffer, buffer->pBuffer, buffer->nFilledLen, m_pSwVdecIpBuffer, nPortIndex, (unsigned int)buffer->nFlags); 9851 m_pSwVdecIpBuffer[nPortIndex].nFlags = buffer->nFlags; 9852 m_pSwVdecIpBuffer[nPortIndex].nFilledLen = buffer->nFilledLen; 9853 m_pSwVdecIpBuffer[nPortIndex].nIpTimestamp = buffer->nTimeStamp; 9854 if (SwVdec_EmptyThisBuffer(m_pSwVdec, &m_pSwVdecIpBuffer[nPortIndex]) != SWVDEC_S_SUCCESS) { 9855 ret = OMX_ErrorBadParameter; 9856 } 9857 pthread_mutex_lock(&m_lock); 9858 m_interm_buf_state[nPortIndex] = WITH_SWVDEC; 9859 pthread_mutex_unlock(&m_lock); 9860 return ret; 9861 } 9862 9863 OMX_ERRORTYPE omx_vdec::empty_buffer_done_swvdec(OMX_HANDLETYPE hComp, 9864 OMX_BUFFERHEADERTYPE* buffer) 9865 { 9866 int idx = buffer - m_interm_mem_ptr; 9867 if (buffer == NULL || idx > (int)drv_ctx.interm_op_buf.actualcount) 9868 { 9869 DEBUG_PRINT_ERROR("empty_buffer_done_swvdec: ERROR bufhdr = %p", buffer); 9870 return OMX_ErrorBadParameter; 9871 } 9872 9873 DEBUG_PRINT_LOW("empty_buffer_done_swvdec: bufhdr = %p, bufhdr->pBuffer = %p idx %d", 9874 buffer, buffer->pBuffer, idx); 9875 9876 buffer->nFilledLen = 0; 9877 pthread_mutex_lock(&m_lock); 9878 if (m_interm_buf_state[idx] != WITH_SWVDEC) 9879 { 9880 DEBUG_PRINT_ERROR("empty_buffer_done_swvdec error: bufhdr = %p, idx %d, buffer not with swvdec ",buffer, idx); 9881 pthread_mutex_unlock(&m_lock); 9882 return OMX_ErrorBadParameter; 9883 } 9884 m_interm_buf_state[idx] = WITH_COMPONENT; 9885 pthread_mutex_unlock(&m_lock); 9886 9887 if(m_interm_bEnabled != OMX_TRUE || 9888 output_flush_progress == true || 9889 m_interm_flush_dsp_progress == true || 9890 m_interm_flush_swvdec_progress == true) 9891 { 9892 DEBUG_PRINT_HIGH("empty_buffer_done_swvdec: Buffer (%p) flushed idx %d", buffer, idx); 9893 buffer->nFilledLen = 0; 9894 buffer->nTimeStamp = 0; 9895 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 9896 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 9897 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 9898 return OMX_ErrorNone; 9899 } 9900 9901 // call DSP FTB for the intermediate buffer. post event to the command queue do it asynchrounously 9902 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY && in_reconfig != true) 9903 { 9904 post_event((unsigned int)&m_cmp, (unsigned int)buffer, OMX_COMPONENT_GENERATE_FTB_DSP); 9905 } 9906 else if (m_swvdec_mode == SWVDEC_MODE_PARSE_DECODE) 9907 { 9908 post_event((unsigned int)&m_cmp, (unsigned int)buffer, OMX_COMPONENT_GENERATE_EBD); 9909 } 9910 9911 return OMX_ErrorNone; 9912 } 9913 9914 OMX_ERRORTYPE omx_vdec::fill_all_buffers_proxy_dsp(OMX_HANDLETYPE hComp) 9915 { 9916 int idx = 0; 9917 OMX_ERRORTYPE nRet = OMX_ErrorNone; 9918 if (m_fill_internal_bufers == OMX_FALSE) 9919 { 9920 return nRet; 9921 } 9922 9923 if (m_interm_mem_ptr == NULL) 9924 { 9925 DEBUG_PRINT_ERROR("fill_all_buffers_proxy_dsp called in bad state"); 9926 return nRet; 9927 } 9928 m_fill_internal_bufers = OMX_FALSE; 9929 9930 for (idx=0; idx < (int)drv_ctx.interm_op_buf.actualcount; idx++) 9931 { 9932 pthread_mutex_lock(&m_lock); 9933 if (m_interm_buf_state[idx] == WITH_COMPONENT) 9934 { 9935 OMX_BUFFERHEADERTYPE* bufHdr = m_interm_mem_ptr + idx; 9936 nRet = fill_this_buffer_proxy_dsp(hComp, bufHdr); 9937 if (nRet != OMX_ErrorNone) 9938 { 9939 DEBUG_PRINT_ERROR("fill_this_buffer_proxy_dsp failed for buff %d bufHdr %p pBuffer %p", 9940 idx, bufHdr, bufHdr->pBuffer); 9941 break; 9942 } 9943 } 9944 pthread_mutex_unlock(&m_lock); 9945 } 9946 return nRet; 9947 } 9948 9949 9950 /* ====================================================================== 9951 FUNCTION 9952 omx_vdec::fill_this_buffer_proxy_dsp 9953 9954 DESCRIPTION 9955 IL client uses this method to release the frame buffer 9956 after displaying them. 9957 9958 PARAMETERS 9959 None. 9960 9961 RETURN VALUE 9962 true/false 9963 9964 ========================================================================== */ 9965 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy_dsp( 9966 OMX_IN OMX_HANDLETYPE hComp, 9967 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) 9968 { 9969 OMX_ERRORTYPE nRet = OMX_ErrorNone; 9970 OMX_BUFFERHEADERTYPE *buffer = bufferAdd; 9971 unsigned nPortIndex = 0; 9972 struct vdec_fillbuffer_cmd fillbuffer; 9973 struct vdec_bufferpayload *ptr_outputbuffer = NULL; 9974 struct vdec_output_frameinfo *ptr_respbuffer = NULL; 9975 int rc = 0; 9976 9977 if(m_state == OMX_StateInvalid) 9978 { 9979 DEBUG_PRINT_ERROR("FTB in Invalid State"); 9980 return OMX_ErrorInvalidState; 9981 } 9982 9983 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_interm_mem_ptr); 9984 9985 if (bufferAdd == NULL || nPortIndex > drv_ctx.interm_op_buf.actualcount) 9986 return OMX_ErrorBadParameter; 9987 9988 DEBUG_PRINT_LOW("fill_this_buffer_proxy_dsp: bufhdr = %p,pBuffer = %p, idx %d, state %d", 9989 bufferAdd, bufferAdd->pBuffer, nPortIndex, m_interm_buf_state[nPortIndex]); 9990 9991 pthread_mutex_lock(&m_lock); 9992 if (m_interm_buf_state[nPortIndex] == WITH_DSP) 9993 { 9994 DEBUG_PRINT_HIGH("fill_this_buffer_proxy_dsp: buffer is with dsp"); 9995 pthread_mutex_unlock(&m_lock); 9996 return OMX_ErrorNone; 9997 } 9998 pthread_mutex_unlock(&m_lock); 9999 10000 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; 10001 if (ptr_respbuffer) 10002 { 10003 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; 10004 } 10005 10006 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) 10007 { 10008 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); 10009 buffer->nFilledLen = 0; 10010 return OMX_ErrorBadParameter; 10011 } 10012 10013 if(m_interm_bEnabled != OMX_TRUE || m_interm_flush_dsp_progress == true) 10014 { 10015 DEBUG_PRINT_ERROR("fill_this_buffer_proxy_dsp called when dsp flush in progress"); 10016 buffer->nFilledLen = 0; 10017 return OMX_ErrorNone; 10018 } 10019 10020 memcpy (&fillbuffer.buffer,ptr_outputbuffer, 10021 sizeof(struct vdec_bufferpayload)); 10022 fillbuffer.client_data = bufferAdd; 10023 10024 struct v4l2_buffer buf; 10025 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 10026 memset( (void *)&buf, 0, sizeof(buf)); 10027 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); 10028 int extra_idx = 0; 10029 10030 buf.index = nPortIndex; 10031 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10032 buf.memory = V4L2_MEMORY_USERPTR; 10033 plane[0].bytesused = buffer->nFilledLen; 10034 plane[0].length = drv_ctx.interm_op_buf.buffer_size; 10035 plane[0].m.userptr = 10036 (unsigned long)drv_ctx.ptr_interm_outputbuffer[nPortIndex].bufferaddr - 10037 (unsigned long)drv_ctx.ptr_interm_outputbuffer[nPortIndex].offset; 10038 10039 plane[0].reserved[0] = drv_ctx.ptr_interm_outputbuffer[nPortIndex].pmem_fd; 10040 plane[0].reserved[1] = drv_ctx.ptr_interm_outputbuffer[nPortIndex].offset; 10041 plane[0].data_offset = 0; 10042 10043 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 10044 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 10045 plane[extra_idx].bytesused = 0; 10046 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 10047 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size); 10048 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 10049 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; 10050 plane[extra_idx].data_offset = 0; 10051 } else if (extra_idx >= VIDEO_MAX_PLANES) { 10052 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx); 10053 return OMX_ErrorBadParameter; 10054 } 10055 10056 buf.m.planes = plane; 10057 buf.length = drv_ctx.num_planes; 10058 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 10059 if (rc) { 10060 DEBUG_PRINT_ERROR("Failed to qbuf to driver"); 10061 return OMX_ErrorBadParameter; 10062 } 10063 10064 pthread_mutex_lock(&m_lock); 10065 m_interm_buf_state[nPortIndex] = WITH_DSP; 10066 pthread_mutex_unlock(&m_lock); 10067 10068 return OMX_ErrorNone; 10069 } 10070 10071 OMX_ERRORTYPE omx_vdec::fill_buffer_done_dsp(OMX_HANDLETYPE hComp, 10072 OMX_BUFFERHEADERTYPE * buffer) 10073 { 10074 int idx = buffer - m_interm_mem_ptr; 10075 if (!buffer || idx >= (int)drv_ctx.interm_op_buf.actualcount) 10076 { 10077 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p), m_interm_mem_ptr(%p) idx %d", buffer, m_interm_mem_ptr, idx); 10078 return OMX_ErrorBadParameter; 10079 } 10080 10081 DEBUG_PRINT_LOW("fill_buffer_done_dsp: bufhdr = %p, bufhdr->pBuffer = %p, idx %d nFilledLen %lu nFlags %x", 10082 buffer, buffer->pBuffer, idx, buffer->nFilledLen, (unsigned int)buffer->nFlags); 10083 10084 pthread_mutex_lock(&m_lock); 10085 if (m_interm_buf_state[idx] != WITH_DSP) 10086 { 10087 DEBUG_PRINT_ERROR("fill_buffer_done_dsp error: bufhdr = %p, idx %d, buffer not with dsp", buffer, idx); 10088 pthread_mutex_unlock(&m_lock); 10089 return OMX_ErrorBadParameter; 10090 } 10091 m_interm_buf_state[idx] = WITH_COMPONENT; 10092 pthread_mutex_unlock(&m_lock); 10093 10094 if (m_interm_bEnabled != OMX_TRUE || 10095 output_flush_progress == true || 10096 m_interm_flush_dsp_progress == true || 10097 m_interm_flush_swvdec_progress == true) 10098 { 10099 DEBUG_PRINT_HIGH("fill_buffer_done_dsp: Buffer (%p) flushed idx %d", buffer, idx); 10100 buffer->nFilledLen = 0; 10101 buffer->nTimeStamp = 0; 10102 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 10103 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 10104 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 10105 return OMX_ErrorNone; 10106 } 10107 10108 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 10109 { 10110 DEBUG_PRINT_HIGH("interm EOS has been reached"); 10111 10112 if (psource_frame) 10113 { 10114 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); 10115 psource_frame = NULL; 10116 } 10117 if (pdest_frame) 10118 { 10119 pdest_frame->nFilledLen = 0; 10120 m_input_free_q.insert_entry((unsigned) pdest_frame,(unsigned)NULL, 10121 (unsigned)NULL); 10122 pdest_frame = NULL; 10123 } 10124 } 10125 10126 if (m_debug.im_buffer_log) 10127 { 10128 log_im_buffer(buffer); 10129 } 10130 10131 post_event((unsigned int)&m_cmp, (unsigned int)buffer, OMX_COMPONENT_GENERATE_ETB_SWVDEC); 10132 return OMX_ErrorNone; 10133 } 10134 10135 OMX_ERRORTYPE omx_vdec::allocate_interm_buffer(OMX_U32 bytes) 10136 { 10137 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10138 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 10139 unsigned i= 0; // Temporary counter 10140 struct vdec_setbuffer_cmd setbuffers; 10141 int extra_idx = 0; 10142 10143 int ion_device_fd =-1; 10144 struct ion_allocation_data ion_alloc_data; 10145 struct ion_fd_data fd_ion_data; 10146 10147 if(!m_interm_mem_ptr) 10148 { 10149 DEBUG_PRINT_HIGH("Allocate interm buffer Header: Cnt(%d) Sz(%d)", 10150 drv_ctx.interm_op_buf.actualcount, drv_ctx.interm_op_buf.buffer_size); 10151 10152 int nBufHdrSize = drv_ctx.interm_op_buf.actualcount * sizeof(OMX_BUFFERHEADERTYPE); 10153 m_interm_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 10154 10155 drv_ctx.ptr_interm_outputbuffer = (struct vdec_bufferpayload *) 10156 calloc (sizeof(struct vdec_bufferpayload), drv_ctx.interm_op_buf.actualcount); 10157 drv_ctx.ptr_interm_respbuffer = (struct vdec_output_frameinfo *) 10158 calloc (sizeof (struct vdec_output_frameinfo), drv_ctx.interm_op_buf.actualcount); 10159 drv_ctx.interm_op_buf_ion_info = (struct vdec_ion *) 10160 calloc (sizeof(struct vdec_ion), drv_ctx.interm_op_buf.actualcount); 10161 m_pSwVdecIpBuffer = (SWVDEC_IPBUFFER *)calloc(sizeof(SWVDEC_IPBUFFER), drv_ctx.interm_op_buf.actualcount); 10162 10163 if (m_interm_mem_ptr == NULL || 10164 drv_ctx.ptr_interm_outputbuffer == NULL || 10165 drv_ctx.ptr_interm_respbuffer == NULL || 10166 drv_ctx.interm_op_buf_ion_info == NULL || 10167 m_pSwVdecIpBuffer == NULL) 10168 { 10169 goto clean_up; 10170 } 10171 } 10172 10173 bufHdr = m_interm_mem_ptr; 10174 for (unsigned long i = 0; i < drv_ctx.interm_op_buf.actualcount; i++) 10175 { 10176 int pmem_fd = -1; 10177 unsigned char *pmem_baseaddress = NULL; 10178 int flags = secure_mode ? ION_SECURE : 0; 10179 if (m_pSwVdec) 10180 { 10181 DEBUG_PRINT_HIGH("Allocate cached interm buffers"); 10182 flags = ION_FLAG_CACHED; 10183 } 10184 10185 DEBUG_PRINT_HIGH("allocate interm output buffer size %d idx %lu", 10186 drv_ctx.interm_op_buf.buffer_size, i); 10187 ion_device_fd = alloc_map_ion_memory( 10188 drv_ctx.interm_op_buf.buffer_size, 10189 drv_ctx.interm_op_buf.alignment, 10190 &ion_alloc_data, &fd_ion_data, flags, ION_ADSP_HEAP_ID); 10191 if (ion_device_fd < 0) { 10192 eRet = OMX_ErrorInsufficientResources; 10193 goto clean_up; 10194 } 10195 pmem_fd = fd_ion_data.fd; 10196 10197 drv_ctx.ptr_interm_outputbuffer[i].pmem_fd = pmem_fd; 10198 drv_ctx.interm_op_buf_ion_info[i].ion_device_fd = ion_device_fd; 10199 drv_ctx.interm_op_buf_ion_info[i].ion_alloc_data = ion_alloc_data; 10200 drv_ctx.interm_op_buf_ion_info[i].fd_ion_data = fd_ion_data; 10201 10202 if (!secure_mode) { 10203 pmem_baseaddress = (unsigned char *)mmap(NULL, 10204 drv_ctx.interm_op_buf.buffer_size, 10205 PROT_READ|PROT_WRITE,MAP_SHARED, pmem_fd, 0); 10206 if (pmem_baseaddress == MAP_FAILED) 10207 { 10208 DEBUG_PRINT_ERROR("MMAP failed for Size %d", 10209 drv_ctx.interm_op_buf.buffer_size); 10210 eRet = OMX_ErrorInsufficientResources; 10211 goto clean_up; 10212 } 10213 } 10214 10215 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 10216 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 10217 bufHdr->nAllocLen = bytes; 10218 bufHdr->nFilledLen = 0; 10219 bufHdr->pAppPrivate = this; 10220 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 10221 bufHdr->pBuffer = pmem_baseaddress; 10222 bufHdr->nOffset = 0; 10223 10224 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_interm_respbuffer[i]; 10225 drv_ctx.ptr_interm_respbuffer[i].client_data = (void *)&drv_ctx.ptr_interm_outputbuffer[i]; 10226 drv_ctx.ptr_interm_outputbuffer[i].offset = 0; 10227 drv_ctx.ptr_interm_outputbuffer[i].bufferaddr = pmem_baseaddress; 10228 drv_ctx.ptr_interm_outputbuffer[i].mmaped_size = drv_ctx.interm_op_buf.buffer_size; 10229 drv_ctx.ptr_interm_outputbuffer[i].buffer_len = drv_ctx.interm_op_buf.buffer_size; 10230 10231 DEBUG_PRINT_LOW("interm pmem_fd = %d offset = %d address = %p, bufHdr %p", 10232 pmem_fd, drv_ctx.ptr_interm_outputbuffer[i].offset, 10233 drv_ctx.ptr_interm_outputbuffer[i].bufferaddr, bufHdr); 10234 10235 m_interm_buf_state[i] = WITH_COMPONENT; 10236 m_pSwVdecIpBuffer[i].pBuffer = bufHdr->pBuffer; 10237 m_pSwVdecIpBuffer[i].pClientBufferData = (void*)i; 10238 10239 // Move the buffer and buffer header pointers 10240 bufHdr++; 10241 } 10242 10243 eRet = allocate_extradata(); 10244 if (eRet != OMX_ErrorNone) 10245 { 10246 goto clean_up; 10247 } 10248 10249 for(i=0; i<drv_ctx.interm_op_buf.actualcount; i++) 10250 { 10251 struct v4l2_buffer buf; 10252 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 10253 int rc; 10254 10255 bufHdr = (m_interm_mem_ptr + i ); 10256 if (secure_mode) { 10257 drv_ctx.ptr_interm_outputbuffer[i].bufferaddr = bufHdr; 10258 } 10259 10260 buf.index = i; 10261 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10262 buf.memory = V4L2_MEMORY_USERPTR; 10263 plane[0].length = drv_ctx.interm_op_buf.buffer_size; 10264 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_interm_outputbuffer[i].bufferaddr - 10265 (unsigned long)drv_ctx.ptr_interm_outputbuffer[i].offset; 10266 plane[0].reserved[0] = drv_ctx.interm_op_buf_ion_info[i].fd_ion_data.fd; 10267 plane[0].reserved[1] = drv_ctx.ptr_interm_outputbuffer[i].offset; 10268 plane[0].data_offset = 0; 10269 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 10270 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 10271 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 10272 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr 10273 + i * drv_ctx.extradata_info.buffer_size); 10274 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 10275 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 10276 plane[extra_idx].data_offset = 0; 10277 } else if (extra_idx >= VIDEO_MAX_PLANES) { 10278 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx); 10279 goto clean_up; 10280 } 10281 buf.m.planes = plane; 10282 buf.length = drv_ctx.num_planes; 10283 DEBUG_PRINT_LOW("Set interm Output Buffer Idx: %d Addr: %x", i, (unsigned int)drv_ctx.ptr_interm_outputbuffer[i].bufferaddr); 10284 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 10285 if (rc) { 10286 DEBUG_PRINT_ERROR("VIDIOC_PREPARE_BUF failed"); 10287 goto clean_up; 10288 } 10289 10290 if (i == (drv_ctx.interm_op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { 10291 enum v4l2_buf_type buf_type; 10292 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10293 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 10294 if (rc) { 10295 return OMX_ErrorInsufficientResources; 10296 } else { 10297 streaming[CAPTURE_PORT] = true; 10298 DEBUG_PRINT_LOW("STREAMON Successful"); 10299 } 10300 } 10301 10302 bufHdr->pAppPrivate = this; 10303 } 10304 10305 m_interm_bEnabled = OMX_TRUE; 10306 m_interm_bPopulated = OMX_TRUE; 10307 10308 return OMX_ErrorNone; 10309 10310 clean_up: 10311 10312 if (drv_ctx.interm_op_buf_ion_info) 10313 { 10314 for(i=0; i< drv_ctx.interm_op_buf.actualcount; i++) 10315 { 10316 if(drv_ctx.ptr_interm_outputbuffer) 10317 { 10318 close(drv_ctx.ptr_interm_outputbuffer[i].pmem_fd); 10319 drv_ctx.ptr_interm_outputbuffer[i].pmem_fd = 0; 10320 } 10321 free_ion_memory(&drv_ctx.interm_op_buf_ion_info[i]); 10322 } 10323 } 10324 10325 if(m_interm_mem_ptr) 10326 { 10327 free(m_interm_mem_ptr); 10328 m_interm_mem_ptr = NULL; 10329 } 10330 if(drv_ctx.ptr_interm_outputbuffer) 10331 { 10332 free(drv_ctx.ptr_interm_outputbuffer); 10333 drv_ctx.ptr_interm_outputbuffer = NULL; 10334 } 10335 if(drv_ctx.ptr_interm_respbuffer) 10336 { 10337 free(drv_ctx.ptr_interm_respbuffer); 10338 drv_ctx.ptr_interm_respbuffer = NULL; 10339 } 10340 if (drv_ctx.interm_op_buf_ion_info) { 10341 DEBUG_PRINT_LOW("Free o/p ion context"); 10342 free(drv_ctx.interm_op_buf_ion_info); 10343 drv_ctx.interm_op_buf_ion_info = NULL; 10344 } 10345 return OMX_ErrorInsufficientResources; 10346 } 10347 10348 //callback function used by SWVdec 10349 10350 SWVDEC_STATUS omx_vdec::swvdec_input_buffer_done_cb 10351 ( 10352 SWVDEC_HANDLE pSwDec, 10353 SWVDEC_IPBUFFER *m_pSwVdecIpBuffer, 10354 void *pClientHandle 10355 ) 10356 { 10357 SWVDEC_STATUS eRet = SWVDEC_S_SUCCESS; 10358 omx_vdec *omx = reinterpret_cast<omx_vdec*>(pClientHandle); 10359 10360 if (m_pSwVdecIpBuffer == NULL) 10361 { 10362 eRet = SWVDEC_S_EFAIL; 10363 } 10364 else 10365 { 10366 DEBUG_PRINT_LOW("%s invoked", __func__); 10367 omx->swvdec_input_buffer_done(m_pSwVdecIpBuffer); 10368 } 10369 10370 return eRet; 10371 } 10372 10373 void omx_vdec::swvdec_input_buffer_done(SWVDEC_IPBUFFER *m_pSwVdecIpBuffer) 10374 { 10375 int index = (int)m_pSwVdecIpBuffer->pClientBufferData; 10376 10377 if (m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 10378 { 10379 post_event((unsigned int)(m_interm_mem_ptr + index), 10380 VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_EBD_SWVDEC); 10381 } 10382 else 10383 { 10384 post_event((unsigned int)(m_inp_mem_ptr + index), 10385 VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_EBD); 10386 } 10387 } 10388 10389 SWVDEC_STATUS omx_vdec::swvdec_fill_buffer_done_cb 10390 ( 10391 SWVDEC_HANDLE pSwDec, 10392 SWVDEC_OPBUFFER *m_pSwVdecOpBuffer, 10393 void *pClientHandle 10394 ) 10395 { 10396 SWVDEC_STATUS eRet = SWVDEC_S_SUCCESS; 10397 omx_vdec *omx = reinterpret_cast<omx_vdec*>(pClientHandle); 10398 10399 if (m_pSwVdecOpBuffer == NULL) 10400 { 10401 eRet = SWVDEC_S_EFAIL; 10402 } 10403 else 10404 { 10405 omx->swvdec_fill_buffer_done(m_pSwVdecOpBuffer); 10406 } 10407 return eRet; 10408 } 10409 10410 void omx_vdec::swvdec_fill_buffer_done(SWVDEC_OPBUFFER *m_pSwVdecOpBuffer) 10411 { 10412 int index = (int)m_pSwVdecOpBuffer->pClientBufferData; 10413 OMX_BUFFERHEADERTYPE *bufHdr = m_out_mem_ptr + index; 10414 bufHdr->nFilledLen = m_pSwVdecOpBuffer->nFilledLen; 10415 bufHdr->nFlags = m_pSwVdecOpBuffer->nFlags; 10416 bufHdr->nTimeStamp = m_pSwVdecOpBuffer->nOpTimestamp; 10417 10418 if (dynamic_buf_mode && m_pSwVdecOpBuffer->nFilledLen) 10419 { 10420 bufHdr->nFilledLen = bufHdr->nAllocLen; 10421 } 10422 if (bufHdr->nFlags & OMX_BUFFERFLAG_EOS) 10423 { 10424 DEBUG_PRINT_HIGH("swvdec output EOS reached"); 10425 } 10426 DEBUG_PRINT_LOW("swvdec_fill_buffer_done bufHdr %p pBuffer %p SwvdecOpBuffer %p idx %d nFilledLen %lu nAllocLen %lu nFlags %lx", 10427 bufHdr, bufHdr->pBuffer, m_pSwVdecOpBuffer->pBuffer, index, m_pSwVdecOpBuffer->nFilledLen, bufHdr->nAllocLen, m_pSwVdecOpBuffer->nFlags); 10428 post_event((unsigned int)bufHdr, VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_FBD); 10429 } 10430 10431 SWVDEC_STATUS omx_vdec::swvdec_handle_event_cb 10432 ( 10433 SWVDEC_HANDLE pSwDec, 10434 SWVDEC_EVENTHANDLER* pEventHandler, 10435 void *pClientHandle 10436 ) 10437 { 10438 omx_vdec *omx = reinterpret_cast<omx_vdec*>(pClientHandle); 10439 omx->swvdec_handle_event(pEventHandler); 10440 return SWVDEC_S_SUCCESS; 10441 } 10442 10443 void omx_vdec::swvdec_handle_event(SWVDEC_EVENTHANDLER *pEvent) 10444 { 10445 switch(pEvent->eEvent) 10446 { 10447 case SWVDEC_FLUSH_DONE: 10448 DEBUG_PRINT_ERROR("SWVDEC_FLUSH_DONE input_flush_progress %d output_flush_progress %d", 10449 input_flush_progress, output_flush_progress); 10450 if (input_flush_progress) 10451 { 10452 post_event ((unsigned)NULL, VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); 10453 } 10454 if (output_flush_progress) 10455 { 10456 post_event ((unsigned)NULL, VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); 10457 } 10458 break; 10459 10460 case SWVDEC_RECONFIG_SUFFICIENT_RESOURCES: 10461 { 10462 DEBUG_PRINT_HIGH("swvdec port settings changed info"); 10463 10464 // get_buffer_req and populate port defn structure 10465 SWVDEC_PROP prop; 10466 prop.ePropId = SWVDEC_PROP_ID_DIMENSIONS; 10467 SwVdec_GetProperty(m_pSwVdec, &prop); 10468 10469 update_resolution(prop.uProperty.sDimensions.nWidth, 10470 prop.uProperty.sDimensions.nHeight, 10471 prop.uProperty.sDimensions.nWidth, 10472 prop.uProperty.sDimensions.nHeight); 10473 drv_ctx.video_resolution.stride = (prop.uProperty.sDimensions.nWidth + 127) & (~127); 10474 drv_ctx.video_resolution.scan_lines = (prop.uProperty.sDimensions.nHeight + 31) & (~31); 10475 10476 m_port_def.nPortIndex = 1; 10477 update_portdef(&m_port_def); 10478 post_event ((unsigned)NULL, VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG); 10479 } 10480 break; 10481 10482 case SWVDEC_RECONFIG_INSUFFICIENT_RESOURCES: 10483 DEBUG_PRINT_HIGH("swvdec port settings changed"); 10484 in_reconfig = true; 10485 post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition, 10486 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 10487 break; 10488 10489 case SWVDEC_ERROR: 10490 break; 10491 10492 case SWVDEC_RELEASE_BUFFER_REFERENCE: 10493 { 10494 SWVDEC_OPBUFFER* pOpBuffer = (SWVDEC_OPBUFFER *)pEvent->pEventData; 10495 if (pOpBuffer == NULL) 10496 { 10497 DEBUG_PRINT_ERROR("swvdec release buffer reference for null buffer"); 10498 } 10499 unsigned long idx = (unsigned long)pOpBuffer->pClientBufferData; 10500 DEBUG_PRINT_HIGH("swvdec release buffer reference idx %lu", idx); 10501 10502 if (idx >= 0 && idx < drv_ctx.op_buf.actualcount) 10503 { 10504 DEBUG_PRINT_LOW("swvdec REFERENCE RELEASE EVENT fd = %d offset = %u buf idx %lu pBuffer %p", 10505 drv_ctx.ptr_outputbuffer[idx].pmem_fd, drv_ctx.ptr_outputbuffer[idx].offset, 10506 idx, drv_ctx.ptr_outputbuffer[idx].bufferaddr); 10507 buf_ref_remove(drv_ctx.ptr_outputbuffer[idx].pmem_fd, 10508 drv_ctx.ptr_outputbuffer[idx].offset); 10509 } 10510 } 10511 break; 10512 default: 10513 break; 10514 } 10515 10516 // put into the event command q 10517 // m_cmd_q.insert_entry((unsigned int)NULL, 10518 // SWVDEC_S_SUCCESS, 10519 // OMX_COMPONENT_GENERATE_STOP_DONE_SWVDEC); 10520 // post_message(this, OMX_COMPONENT_GENERATE_STOP_DONE_SWVDEC); 10521 } 10522 10523 bool omx_vdec::execute_input_flush_swvdec() 10524 { 10525 int idx =0; 10526 unsigned int p1 = 0; // Parameter - 1 10527 unsigned int p2 = 0; // Parameter - 2 10528 unsigned int ident = 0; 10529 bool bRet = true; 10530 10531 DEBUG_PRINT_LOW("execute_input_flush_swvdec qsize %d, actual %d", 10532 m_etb_q_swvdec.m_size, drv_ctx.interm_op_buf.actualcount); 10533 10534 pthread_mutex_lock(&m_lock); 10535 while (m_etb_q_swvdec.m_size) 10536 { 10537 OMX_BUFFERHEADERTYPE* bufHdr = NULL; 10538 m_etb_q_swvdec.pop_entry(&p1,&p2,&ident); 10539 if (ident == OMX_COMPONENT_GENERATE_ETB_SWVDEC) 10540 { 10541 bufHdr = (OMX_BUFFERHEADERTYPE*)p2; 10542 } 10543 else if (ident == OMX_COMPONENT_GENERATE_EBD_SWVDEC) 10544 { 10545 bufHdr = (OMX_BUFFERHEADERTYPE*)p1; 10546 } 10547 idx = (bufHdr - m_interm_mem_ptr); 10548 if (idx >= 0 && idx < (int)drv_ctx.interm_op_buf.actualcount) 10549 { 10550 DEBUG_PRINT_ERROR("execute_input_flush_swvdec flushed buffer idx %d", idx); 10551 m_interm_buf_state[idx] = WITH_COMPONENT; 10552 } 10553 else 10554 { 10555 DEBUG_PRINT_ERROR("execute_input_flush_swvdec issue: invalid idx %d", idx); 10556 } 10557 } 10558 m_interm_flush_swvdec_progress = false; 10559 pthread_mutex_unlock(&m_lock); 10560 10561 for (idx = 0; idx < (int)drv_ctx.interm_op_buf.actualcount; idx++) 10562 { 10563 DEBUG_PRINT_LOW("Flush swvdec interm bufq idx %d, state %d", idx, m_interm_buf_state[idx]); 10564 // m_interm_buf_state[idx] = WITH_COMPONENT; 10565 } 10566 10567 return true; 10568 } 10569 10570 10571 bool omx_vdec::execute_output_flush_dsp() 10572 { 10573 int idx =0; 10574 unsigned int p1 = 0; // Parameter - 1 10575 unsigned int p2 = 0; // Parameter - 2 10576 unsigned int ident = 0; 10577 bool bRet = true; 10578 10579 DEBUG_PRINT_LOW("execute_output_flush_dsp qsize %d, actual %d", 10580 m_ftb_q_dsp.m_size, drv_ctx.interm_op_buf.actualcount); 10581 10582 pthread_mutex_lock(&m_lock); 10583 while (m_ftb_q_dsp.m_size) 10584 { 10585 OMX_BUFFERHEADERTYPE* bufHdr = NULL; 10586 m_ftb_q_dsp.pop_entry(&p1,&p2,&ident); 10587 if (ident == OMX_COMPONENT_GENERATE_FTB_DSP) 10588 { 10589 bufHdr = (OMX_BUFFERHEADERTYPE*)p2; 10590 } 10591 else if (ident == OMX_COMPONENT_GENERATE_FBD_DSP) 10592 { 10593 bufHdr = (OMX_BUFFERHEADERTYPE*)p1; 10594 } 10595 idx = (bufHdr - m_interm_mem_ptr); 10596 if (idx >= 0 && idx < (int)drv_ctx.interm_op_buf.actualcount) 10597 { 10598 DEBUG_PRINT_ERROR("execute_output_flush_dsp flushed buffer idx %d", idx); 10599 m_interm_buf_state[idx] = WITH_COMPONENT; 10600 } 10601 else 10602 { 10603 DEBUG_PRINT_ERROR("execute_output_flush_dsp issue: invalid idx %d", idx); 10604 } 10605 } 10606 m_interm_flush_dsp_progress = false; 10607 m_fill_internal_bufers = OMX_TRUE; 10608 pthread_mutex_unlock(&m_lock); 10609 10610 for (idx = 0; idx < (int)drv_ctx.interm_op_buf.actualcount; idx++) 10611 { 10612 DEBUG_PRINT_LOW("Flush dsp interm bufq idx %d, state %d", idx, m_interm_buf_state[idx]); 10613 // m_interm_buf_state[idx] = WITH_COMPONENT; 10614 } 10615 return true; 10616 } 10617 10618 OMX_ERRORTYPE omx_vdec::free_interm_buffers() 10619 { 10620 free_extradata(); 10621 10622 if (drv_ctx.ptr_interm_outputbuffer) 10623 { 10624 for(unsigned long i=0; i< drv_ctx.interm_op_buf.actualcount; i++) 10625 { 10626 if (drv_ctx.ptr_interm_outputbuffer[i].pmem_fd > 0) 10627 { 10628 DEBUG_PRINT_LOW("Free interm ouput Buffer index = %lu addr = %x", i, 10629 (unsigned int)drv_ctx.ptr_interm_outputbuffer[i].bufferaddr); 10630 10631 munmap (drv_ctx.ptr_interm_outputbuffer[i].bufferaddr, 10632 drv_ctx.ptr_interm_outputbuffer[i].mmaped_size); 10633 close(drv_ctx.ptr_interm_outputbuffer[i].pmem_fd); 10634 drv_ctx.ptr_interm_outputbuffer[i].pmem_fd = 0; 10635 free_ion_memory(&drv_ctx.interm_op_buf_ion_info[i]); 10636 } 10637 } 10638 } 10639 10640 if (m_interm_mem_ptr) 10641 { 10642 free(m_interm_mem_ptr); 10643 m_interm_mem_ptr = NULL; 10644 } 10645 10646 if (drv_ctx.ptr_interm_respbuffer) 10647 { 10648 free (drv_ctx.ptr_interm_respbuffer); 10649 drv_ctx.ptr_interm_respbuffer = NULL; 10650 } 10651 10652 if (drv_ctx.ptr_interm_outputbuffer) 10653 { 10654 free (drv_ctx.ptr_interm_outputbuffer); 10655 drv_ctx.ptr_interm_outputbuffer = NULL; 10656 } 10657 10658 if (drv_ctx.interm_op_buf_ion_info) { 10659 free(drv_ctx.interm_op_buf_ion_info); 10660 drv_ctx.interm_op_buf_ion_info = NULL; 10661 } 10662 10663 if (!in_reconfig || m_swvdec_mode == SWVDEC_MODE_DECODE_ONLY) 10664 { 10665 if (m_pSwVdecIpBuffer) 10666 { 10667 free(m_pSwVdecIpBuffer); 10668 m_pSwVdecIpBuffer = NULL; 10669 } 10670 } 10671 10672 if (m_pSwVdecOpBuffer) 10673 { 10674 free(m_pSwVdecOpBuffer); 10675 m_pSwVdecOpBuffer = NULL; 10676 } 10677 10678 m_interm_bEnabled = OMX_FALSE; 10679 m_interm_bPopulated = OMX_FALSE; 10680 return OMX_ErrorNone; 10681 } 10682 10683