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