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