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