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