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