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