1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010 - 2017, 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 This module contains the implementation of the OpenMAX core & component. 34 35 *//*========================================================================*/ 36 37 ////////////////////////////////////////////////////////////////////////////// 38 // Include Files 39 ////////////////////////////////////////////////////////////////////////////// 40 41 #define __STDC_FORMAT_MACROS 42 #include <inttypes.h> 43 44 #include <string.h> 45 #include <pthread.h> 46 #include <sys/prctl.h> 47 #include <stdlib.h> 48 #include <unistd.h> 49 #include <errno.h> 50 #include "omx_vdec.h" 51 #include <fcntl.h> 52 #include <limits.h> 53 #include <stdlib.h> 54 #include <media/hardware/HardwareAPI.h> 55 #include <sys/eventfd.h> 56 #include <nativebase/nativebase.h> 57 58 #if !defined(_ANDROID_) || defined(SYS_IOCTL) 59 #include <sys/ioctl.h> 60 #include <sys/mman.h> 61 #endif 62 63 #ifdef _ANDROID_ 64 #include <cutils/properties.h> 65 #undef USE_EGL_IMAGE_GPU 66 67 #ifdef _QUERY_DISP_RES_ 68 #include "display_config.h" 69 #endif 70 #endif 71 72 #ifdef _USE_GLIB_ 73 #include <glib.h> 74 #define strlcpy g_strlcpy 75 #endif 76 77 #include <qdMetaData.h> 78 #include <gralloc_priv.h> 79 80 #ifdef ANDROID_JELLYBEAN_MR2 81 #include "QComOMXMetadata.h" 82 #endif 83 84 #ifdef USE_EGL_IMAGE_GPU 85 #include <EGL/egl.h> 86 #include <EGL/eglQCOM.h> 87 #define EGL_BUFFER_HANDLE 0x4F00 88 #define EGL_BUFFER_OFFSET 0x4F01 89 #endif 90 91 #define BUFFER_LOG_LOC "/data/vendor/media" 92 93 #ifdef OUTPUT_EXTRADATA_LOG 94 FILE *outputExtradataFile; 95 char output_extradata_filename [] = "/data/vendor/media/extradata"; 96 #endif 97 98 #define DEFAULT_FPS 30 99 #define MAX_SUPPORTED_FPS 240 100 #define DEFAULT_WIDTH_ALIGNMENT 128 101 #define DEFAULT_HEIGHT_ALIGNMENT 32 102 103 #define VC1_SP_MP_START_CODE 0xC5000000 104 #define VC1_SP_MP_START_CODE_MASK 0xFF000000 105 #define VC1_AP_SEQ_START_CODE 0x0F010000 106 #define VC1_STRUCT_C_PROFILE_MASK 0xF0 107 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 108 #define VC1_SIMPLE_PROFILE 0 109 #define VC1_MAIN_PROFILE 1 110 #define VC1_ADVANCE_PROFILE 3 111 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 112 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2 113 #define VC1_STRUCT_C_LEN 4 114 #define VC1_STRUCT_C_POS 8 115 #define VC1_STRUCT_A_POS 12 116 #define VC1_STRUCT_B_POS 24 117 #define VC1_SEQ_LAYER_SIZE 36 118 #define POLL_TIMEOUT 0x7fffffff 119 120 #define MEM_DEVICE "/dev/ion" 121 122 #ifdef _ANDROID_ 123 extern "C" { 124 #include<utils/Log.h> 125 } 126 #endif//_ANDROID_ 127 128 #define SZ_4K 0x1000 129 #define SZ_1M 0x100000 130 131 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } 132 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } 133 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0) 134 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1)) 135 136 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \ 137 | OMX_DISPLAY_INFO_EXTRADATA | OMX_HDR_COLOR_INFO_EXTRADATA) 138 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default 139 140 #ifndef ION_FLAG_CP_BITSTREAM 141 #define ION_FLAG_CP_BITSTREAM 0 142 #endif 143 144 #ifndef ION_FLAG_CP_PIXEL 145 #define ION_FLAG_CP_PIXEL 0 146 #endif 147 148 #ifdef MASTER_SIDE_CP 149 #define MEM_HEAP_ID ION_SECURE_HEAP_ID 150 #define SECURE_ALIGN SZ_4K 151 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM) 152 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL) 153 #else //SLAVE_SIDE_CP 154 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID 155 #define SECURE_ALIGN SZ_1M 156 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE 157 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE 158 #endif 159 160 #define LUMINANCE_DIV_FACTOR 10000.0 161 162 #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 163 #define MAX(x,y) (((x) > (y)) ? (x) : (y)) 164 165 static OMX_U32 maxSmoothStreamingWidth = 1920; 166 static OMX_U32 maxSmoothStreamingHeight = 1088; 167 168 void* async_message_thread (void *input) 169 { 170 OMX_BUFFERHEADERTYPE *buffer; 171 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 172 struct pollfd pfds[2]; 173 struct v4l2_buffer v4l2_buf; 174 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 175 struct v4l2_event dqevent; 176 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input); 177 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI; 178 pfds[1].events = POLLIN | POLLERR; 179 pfds[0].fd = omx->drv_ctx.video_driver_fd; 180 pfds[1].fd = omx->m_poll_efd; 181 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0; 182 DEBUG_PRINT_HIGH("omx_vdec: Async thread start"); 183 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); 184 while (!omx->async_thread_force_stop) { 185 rc = poll(pfds, 2, POLL_TIMEOUT); 186 if (!rc) { 187 DEBUG_PRINT_ERROR("Poll timedout"); 188 break; 189 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) { 190 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno); 191 break; 192 } 193 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) { 194 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited"); 195 break; 196 } 197 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) { 198 struct vdec_msginfo vdec_msg; 199 memset(&vdec_msg, 0, sizeof(vdec_msg)); 200 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 201 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 202 v4l2_buf.length = omx->drv_ctx.num_planes; 203 v4l2_buf.m.planes = plane; 204 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) { 205 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 206 vdec_msg.status_code=VDEC_S_SUCCESS; 207 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf; 208 vdec_msg.msgdata.output_frame.len=plane[0].bytesused; 209 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr; 210 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) + 211 (uint64_t)v4l2_buf.timestamp.tv_usec; 212 213 if (omx->async_message_process(input,&vdec_msg) < 0) { 214 DEBUG_PRINT_HIGH("async_message_thread Exited"); 215 break; 216 } 217 } 218 } 219 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) { 220 struct vdec_msginfo vdec_msg; 221 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 222 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 223 v4l2_buf.length = 1; 224 v4l2_buf.m.planes = plane; 225 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) { 226 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE; 227 vdec_msg.status_code=VDEC_S_SUCCESS; 228 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf; 229 if (omx->async_message_process(input,&vdec_msg) < 0) { 230 DEBUG_PRINT_HIGH("async_message_thread Exited"); 231 break; 232 } 233 } 234 } 235 if (pfds[0].revents & POLLPRI) { 236 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent); 237 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) { 238 struct vdec_msginfo vdec_msg; 239 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 240 241 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED; 242 vdec_msg.status_code=VDEC_S_SUCCESS; 243 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0]; 244 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1]; 245 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient"); 246 if(ptr[2] & V4L2_EVENT_BITDEPTH_FLAG) { 247 omx->dpb_bit_depth = ptr[3]; 248 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", ptr[3]); 249 } 250 if(ptr[2] & V4L2_EVENT_PICSTRUCT_FLAG) { 251 omx->m_progressive = ptr[4]; 252 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct change - %d", ptr[4]); 253 } 254 if(ptr[2] & V4L2_EVENT_COLOUR_SPACE_FLAG) { 255 if (ptr[5] == MSM_VIDC_BT2020) { 256 omx->m_color_space = omx_vdec::BT2020; 257 } else { 258 omx->m_color_space = omx_vdec::EXCEPT_BT2020; 259 } 260 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace change - %d", omx->m_color_space); 261 } 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_FLUSH_DONE) { 267 struct vdec_msginfo vdec_msg; 268 uint32_t flush_type = *(uint32_t *)dqevent.u.data; 269 // Old driver doesn't send flushType information. 270 // To make this backward compatible fallback to old approach 271 // if the flush_type is not present. 272 vdec_msg.status_code=VDEC_S_SUCCESS; 273 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) { 274 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE; 275 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved"); 276 if (omx->async_message_process(input,&vdec_msg) < 0) { 277 DEBUG_PRINT_HIGH("async_message_thread Exited"); 278 break; 279 } 280 } 281 282 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) { 283 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE; 284 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved"); 285 if (omx->async_message_process(input,&vdec_msg) < 0) { 286 DEBUG_PRINT_HIGH("async_message_thread Exited"); 287 break; 288 } 289 } 290 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) { 291 struct vdec_msginfo vdec_msg; 292 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD; 293 vdec_msg.status_code=VDEC_S_SUCCESS; 294 DEBUG_PRINT_ERROR("HW Overload received"); 295 if (omx->async_message_process(input,&vdec_msg) < 0) { 296 DEBUG_PRINT_HIGH("async_message_thread Exited"); 297 break; 298 } 299 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) { 300 struct vdec_msginfo vdec_msg; 301 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED; 302 vdec_msg.status_code=VDEC_S_SUCCESS; 303 DEBUG_PRINT_ERROR("HW Unsupported received"); 304 if (omx->async_message_process(input,&vdec_msg) < 0) { 305 DEBUG_PRINT_HIGH("async_message_thread Exited"); 306 break; 307 } 308 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) { 309 struct vdec_msginfo vdec_msg; 310 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR; 311 vdec_msg.status_code = VDEC_S_SUCCESS; 312 DEBUG_PRINT_HIGH("SYS Error Recieved"); 313 if (omx->async_message_process(input,&vdec_msg) < 0) { 314 DEBUG_PRINT_HIGH("async_message_thread Exited"); 315 break; 316 } 317 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) { 318 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 319 320 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]); 321 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) { 322 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 323 struct vdec_msginfo vdec_msg; 324 325 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]); 326 327 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 328 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 329 v4l2_buf.length = omx->drv_ctx.num_planes; 330 v4l2_buf.m.planes = plane; 331 v4l2_buf.index = ptr[5]; 332 v4l2_buf.flags = 0; 333 334 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 335 vdec_msg.status_code = VDEC_S_SUCCESS; 336 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf; 337 vdec_msg.msgdata.output_frame.len = 0; 338 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2]; 339 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) + 340 (uint64_t)ptr[4]; 341 if (omx->async_message_process(input,&vdec_msg) < 0) { 342 DEBUG_PRINT_HIGH("async_message_thread Exitedn"); 343 break; 344 } 345 } else { 346 DEBUG_PRINT_HIGH("VIDC Some Event recieved"); 347 continue; 348 } 349 } 350 } 351 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop"); 352 return NULL; 353 } 354 355 void* message_thread_dec(void *input) 356 { 357 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input); 358 unsigned char id; 359 int n; 360 361 fd_set readFds; 362 int res = 0; 363 struct timeval tv; 364 365 DEBUG_PRINT_HIGH("omx_vdec: message thread start"); 366 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); 367 while (!omx->message_thread_stop) { 368 369 tv.tv_sec = 2; 370 tv.tv_usec = 0; 371 372 FD_ZERO(&readFds); 373 FD_SET(omx->m_pipe_in, &readFds); 374 375 res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv); 376 if (res < 0) { 377 DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno)); 378 continue; 379 } else if (res == 0 /*timeout*/ || omx->message_thread_stop) { 380 continue; 381 } 382 383 n = read(omx->m_pipe_in, &id, 1); 384 385 if (0 == n) { 386 break; 387 } 388 389 if (1 == n) { 390 omx->process_event_cb(omx, id); 391 } 392 393 if ((n < 0) && (errno != EINTR)) { 394 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno); 395 break; 396 } 397 } 398 DEBUG_PRINT_HIGH("omx_vdec: message thread stop"); 399 return 0; 400 } 401 402 void post_message(omx_vdec *omx, unsigned char id) 403 { 404 int ret_value; 405 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out); 406 ret_value = write(omx->m_pipe_out, &id, 1); 407 if (ret_value <= 0) { 408 DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno)); 409 } else { 410 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value); 411 } 412 } 413 414 // omx_cmd_queue destructor 415 omx_vdec::omx_cmd_queue::~omx_cmd_queue() 416 { 417 // Nothing to do 418 } 419 420 // omx cmd queue constructor 421 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) 422 { 423 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); 424 } 425 426 // omx cmd queue insert 427 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id) 428 { 429 bool ret = true; 430 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) { 431 m_q[m_write].id = id; 432 m_q[m_write].param1 = p1; 433 m_q[m_write].param2 = p2; 434 m_write++; 435 m_size ++; 436 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) { 437 m_write = 0; 438 } 439 } else { 440 ret = false; 441 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__); 442 } 443 return ret; 444 } 445 446 // omx cmd queue pop 447 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id) 448 { 449 bool ret = true; 450 if (m_size > 0) { 451 *id = m_q[m_read].id; 452 *p1 = m_q[m_read].param1; 453 *p2 = m_q[m_read].param2; 454 // Move the read pointer ahead 455 ++m_read; 456 --m_size; 457 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) { 458 m_read = 0; 459 } 460 } else { 461 ret = false; 462 } 463 return ret; 464 } 465 466 // Retrieve the first mesg type in the queue 467 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() 468 { 469 return m_q[m_read].id; 470 } 471 472 #ifdef _ANDROID_ 473 omx_vdec::ts_arr_list::ts_arr_list() 474 { 475 //initialize timestamps array 476 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) ); 477 } 478 omx_vdec::ts_arr_list::~ts_arr_list() 479 { 480 //free m_ts_arr_list? 481 } 482 483 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) 484 { 485 bool ret = true; 486 bool duplicate_ts = false; 487 int idx = 0; 488 489 //insert at the first available empty location 490 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 491 if (!m_ts_arr_list[idx].valid) { 492 //found invalid or empty entry, save timestamp 493 m_ts_arr_list[idx].valid = true; 494 m_ts_arr_list[idx].timestamp = ts; 495 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", 496 ts, idx); 497 break; 498 } 499 } 500 501 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) { 502 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); 503 ret = false; 504 } 505 return ret; 506 } 507 508 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) 509 { 510 bool ret = true; 511 int min_idx = -1; 512 OMX_TICKS min_ts = 0; 513 int idx = 0; 514 515 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 516 517 if (m_ts_arr_list[idx].valid) { 518 //found valid entry, save index 519 if (min_idx < 0) { 520 //first valid entry 521 min_ts = m_ts_arr_list[idx].timestamp; 522 min_idx = idx; 523 } else if (m_ts_arr_list[idx].timestamp < min_ts) { 524 min_ts = m_ts_arr_list[idx].timestamp; 525 min_idx = idx; 526 } 527 } 528 529 } 530 531 if (min_idx < 0) { 532 //no valid entries found 533 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); 534 ts = 0; 535 ret = false; 536 } else { 537 ts = m_ts_arr_list[min_idx].timestamp; 538 m_ts_arr_list[min_idx].valid = false; 539 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", 540 ts, min_idx); 541 } 542 543 return ret; 544 545 } 546 547 548 bool omx_vdec::ts_arr_list::reset_ts_list() 549 { 550 bool ret = true; 551 int idx = 0; 552 553 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); 554 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 555 m_ts_arr_list[idx].valid = false; 556 } 557 return ret; 558 } 559 #endif 560 561 // factory function executed by the core to create instances 562 void *get_omx_component_factory_fn(void) 563 { 564 return (new omx_vdec); 565 } 566 567 bool is_platform_tp10capture_supported() 568 { 569 char platform_name[PROPERTY_VALUE_MAX] = {0}; 570 property_get("ro.board.platform", platform_name, "0"); 571 if (!strncmp(platform_name, "msm8998", 7)) { 572 DEBUG_PRINT_HIGH("TP10 on capture port is supported"); 573 return true; 574 } 575 DEBUG_PRINT_HIGH("TP10 on capture port is not supported"); 576 return false; 577 } 578 579 /* ====================================================================== 580 FUNCTION 581 omx_vdec::omx_vdec 582 583 DESCRIPTION 584 Constructor 585 586 PARAMETERS 587 None 588 589 RETURN VALUE 590 None. 591 ========================================================================== */ 592 omx_vdec::omx_vdec(): m_error_propogated(false), 593 m_state(OMX_StateInvalid), 594 m_app_data(NULL), 595 m_inp_mem_ptr(NULL), 596 m_out_mem_ptr(NULL), 597 m_client_output_extradata_mem_ptr(NULL), 598 input_flush_progress (false), 599 output_flush_progress (false), 600 input_use_buffer (false), 601 output_use_buffer (false), 602 ouput_egl_buffers(false), 603 m_use_output_pmem(OMX_FALSE), 604 m_out_mem_region_smi(OMX_FALSE), 605 m_out_pvt_entry_pmem(OMX_FALSE), 606 pending_input_buffers(0), 607 pending_output_buffers(0), 608 m_out_bm_count(0), 609 m_inp_bm_count(0), 610 m_out_extradata_bm_count(0), 611 m_inp_bPopulated(OMX_FALSE), 612 m_out_bPopulated(OMX_FALSE), 613 m_flags(0), 614 m_inp_bEnabled(OMX_TRUE), 615 m_out_bEnabled(OMX_TRUE), 616 m_in_alloc_cnt(0), 617 m_platform_list(NULL), 618 m_platform_entry(NULL), 619 m_pmem_info(NULL), 620 h264_parser(NULL), 621 arbitrary_bytes (true), 622 psource_frame (NULL), 623 pdest_frame (NULL), 624 m_inp_heap_ptr (NULL), 625 m_phdr_pmem_ptr(NULL), 626 m_heap_inp_bm_count (0), 627 codec_type_parse ((codec_type)0), 628 first_frame_meta (true), 629 frame_count (0), 630 nal_count (0), 631 nal_length(0), 632 look_ahead_nal (false), 633 first_frame(0), 634 first_buffer(NULL), 635 first_frame_size (0), 636 m_device_file_ptr(NULL), 637 m_vc1_profile((vc1_profile_type)0), 638 h264_last_au_ts(LLONG_MAX), 639 h264_last_au_flags(0), 640 m_disp_hor_size(0), 641 m_disp_vert_size(0), 642 prev_ts(LLONG_MAX), 643 prev_ts_actual(LLONG_MAX), 644 rst_prev_ts(true), 645 frm_int(0), 646 m_fps_received(0), 647 m_fps_prev(0), 648 m_drc_enable(0), 649 in_reconfig(false), 650 m_display_id(NULL), 651 client_extradata(0), 652 m_reject_avc_1080p_mp (0), 653 #ifdef _ANDROID_ 654 m_enable_android_native_buffers(OMX_FALSE), 655 m_use_android_native_buffers(OMX_FALSE), 656 #endif 657 m_desc_buffer_ptr(NULL), 658 secure_mode(false), 659 allocate_native_handle(false), 660 m_other_extradata(NULL), 661 m_profile(0), 662 m_need_turbo(0), 663 client_set_fps(false), 664 stereo_output_mode(HAL_NO_3D), 665 m_last_rendered_TS(-1), 666 m_queued_codec_config_count(0), 667 current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL), 668 secure_scaling_to_non_secure_opb(false), 669 m_force_compressed_for_dpb(true), 670 m_is_display_session(false) 671 { 672 m_pipe_in = -1; 673 m_pipe_out = -1; 674 m_poll_efd = -1; 675 drv_ctx.video_driver_fd = -1; 676 drv_ctx.extradata_info.ion.fd_ion_data.fd = -1; 677 /* Assumption is that , to begin with , we have all the frames with decoder */ 678 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8); 679 memset(&m_debug,0,sizeof(m_debug)); 680 #ifdef _ANDROID_ 681 char property_value[PROPERTY_VALUE_MAX] = {0}; 682 property_get("vendor.vidc.debug.level", property_value, "1"); 683 debug_level = strtoul(property_value, NULL, 16); 684 property_value[0] = '\0'; 685 686 DEBUG_PRINT_HIGH("In OMX vdec Constructor"); 687 688 property_get("vendor.vidc.dec.debug.perf", property_value, "0"); 689 perf_flag = atoi(property_value); 690 if (perf_flag) { 691 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); 692 dec_time.start(); 693 } 694 proc_frms = latency = 0; 695 prev_n_filled_len = 0; 696 property_value[0] = '\0'; 697 property_get("vendor.vidc.dec.debug.ts", property_value, "0"); 698 m_debug_timestamp = atoi(property_value); 699 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); 700 if (m_debug_timestamp) { 701 time_stamp_dts.set_timestamp_reorder_mode(true); 702 time_stamp_dts.enable_debug_print(true); 703 } 704 705 property_value[0] = '\0'; 706 property_get("vendor.vidc.dec.debug.concealedmb", property_value, "0"); 707 m_debug_concealedmb = atoi(property_value); 708 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); 709 710 property_value[0] = '\0'; 711 property_get("vendor.vidc.dec.profile.check", property_value, "0"); 712 m_reject_avc_1080p_mp = atoi(property_value); 713 DEBUG_PRINT_HIGH("vendor.vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp); 714 715 property_value[0] = '\0'; 716 property_get("vendor.vidc.dec.log.in", property_value, "0"); 717 m_debug.in_buffer_log = atoi(property_value); 718 719 property_value[0] = '\0'; 720 property_get("vendor.vidc.dec.log.out", property_value, "0"); 721 m_debug.out_buffer_log = atoi(property_value); 722 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC); 723 724 property_value[0] = '\0'; 725 property_get("vendor.vidc.dec.meta.log.out", property_value, "0"); 726 m_debug.out_meta_buffer_log = atoi(property_value); 727 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC); 728 729 property_value[0] = '\0'; 730 property_get("vendor.vidc.log.loc", property_value, ""); 731 if (*property_value) 732 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX); 733 734 property_value[0] = '\0'; 735 property_get("vendor.vidc.dec.120fps.enabled", property_value, "0"); 736 737 //if this feature is not enabled then reset this value -ve 738 if(atoi(property_value)) { 739 DEBUG_PRINT_LOW("feature 120 FPS decode enabled"); 740 m_last_rendered_TS = 0; 741 } 742 743 property_value[0] = '\0'; 744 property_get("vendor.vidc.dec.debug.dyn.disabled", property_value, "0"); 745 m_disable_dynamic_buf_mode = atoi(property_value); 746 DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode); 747 748 property_value[0] = '\0'; 749 property_get("vendor.vidc.dec.drc.enable", property_value, "0"); 750 if (atoi(property_value)) { 751 m_drc_enable = true; 752 DEBUG_PRINT_HIGH("DRC enabled"); 753 } 754 755 #ifdef _UBWC_ 756 property_value[0] = '\0'; 757 property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0"); 758 m_disable_ubwc_mode = atoi(property_value); 759 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled"); 760 #else 761 m_disable_ubwc_mode = true; 762 #endif 763 #endif 764 memset(&m_cmp,0,sizeof(m_cmp)); 765 memset(&m_cb,0,sizeof(m_cb)); 766 memset (&drv_ctx,0,sizeof(drv_ctx)); 767 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); 768 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); 769 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 770 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize)); 771 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams)); 772 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams)); 773 memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams)); 774 memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams)); 775 memset(&m_color_mdata, 0, sizeof(ColorMetaData)); 776 m_demux_entries = 0; 777 msg_thread_id = 0; 778 async_thread_id = 0; 779 msg_thread_created = false; 780 async_thread_created = false; 781 async_thread_force_stop = false; 782 message_thread_stop = false; 783 #ifdef _ANDROID_ICS_ 784 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 785 #endif 786 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 787 788 /* invalidate m_frame_pack_arrangement */ 789 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 790 m_frame_pack_arrangement.cancel_flag = 1; 791 792 drv_ctx.timestamp_adjust = false; 793 m_vendor_config.pData = NULL; 794 pthread_mutex_init(&m_lock, NULL); 795 pthread_mutex_init(&c_lock, NULL); 796 pthread_mutex_init(&buf_lock, NULL); 797 sem_init(&m_cmd_lock,0,0); 798 sem_init(&m_safe_flush, 0, 0); 799 streaming[CAPTURE_PORT] = 800 streaming[OUTPUT_PORT] = false; 801 #ifdef _ANDROID_ 802 char extradata_value[PROPERTY_VALUE_MAX] = {0}; 803 property_get("vendor.vidc.dec.debug.extradata", extradata_value, "0"); 804 m_debug_extradata = atoi(extradata_value); 805 DEBUG_PRINT_HIGH("vendor.vidc.dec.debug.extradata value is %d",m_debug_extradata); 806 #endif 807 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB; 808 client_buffers.set_vdec_client(this); 809 dynamic_buf_mode = false; 810 out_dynamic_list = NULL; 811 is_down_scalar_enabled = false; 812 m_enable_downscalar = 0; 813 m_downscalar_width = 0; 814 m_downscalar_height = 0; 815 m_force_down_scalar = 0; 816 m_reconfig_height = 0; 817 m_reconfig_width = 0; 818 m_smoothstreaming_mode = false; 819 m_smoothstreaming_width = 0; 820 m_smoothstreaming_height = 0; 821 m_decode_order_mode = false; 822 is_q6_platform = false; 823 m_perf_control.send_hint_to_mpctl(true); 824 m_input_pass_buffer_fd = false; 825 memset(&m_extradata_info, 0, sizeof(m_extradata_info)); 826 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX; 827 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; 828 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; 829 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; 830 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; 831 832 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; 833 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; 834 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; 835 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; 836 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; 837 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams); 838 839 m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX; 840 m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; 841 m_change_client_hdr_info = false; 842 pthread_mutex_init(&m_hdr_info_client_lock, NULL); 843 844 char dither_value[PROPERTY_VALUE_MAX] = {0}; 845 property_get("vendor.vidc.dec.dither", dither_value, "0"); 846 if ((atoi(dither_value) > DITHER_ALL_COLORSPACE) || 847 (atoi(dither_value) < DITHER_DISABLE)) { 848 m_dither_config = DITHER_ALL_COLORSPACE; 849 } else { 850 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)atoi(dither_value) : DITHER_ALL_COLORSPACE; 851 } 852 853 DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config); 854 m_color_space = EXCEPT_BT2020; 855 } 856 857 static const int event_type[] = { 858 V4L2_EVENT_MSM_VIDC_FLUSH_DONE, 859 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT, 860 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT, 861 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT, 862 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE, 863 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER, 864 V4L2_EVENT_MSM_VIDC_SYS_ERROR, 865 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD, 866 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED 867 }; 868 869 static OMX_ERRORTYPE subscribe_to_events(int fd) 870 { 871 OMX_ERRORTYPE eRet = OMX_ErrorNone; 872 struct v4l2_event_subscription sub; 873 int array_sz = sizeof(event_type)/sizeof(int); 874 int i,rc; 875 if (fd < 0) { 876 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 877 return OMX_ErrorBadParameter; 878 } 879 880 for (i = 0; i < array_sz; ++i) { 881 memset(&sub, 0, sizeof(sub)); 882 sub.type = event_type[i]; 883 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); 884 if (rc) { 885 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type); 886 break; 887 } 888 } 889 if (i < array_sz) { 890 for (--i; i >=0 ; i--) { 891 memset(&sub, 0, sizeof(sub)); 892 sub.type = event_type[i]; 893 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 894 if (rc) 895 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 896 } 897 eRet = OMX_ErrorNotImplemented; 898 } 899 return eRet; 900 } 901 902 903 static OMX_ERRORTYPE unsubscribe_to_events(int fd) 904 { 905 OMX_ERRORTYPE eRet = OMX_ErrorNone; 906 struct v4l2_event_subscription sub; 907 int array_sz = sizeof(event_type)/sizeof(int); 908 int i,rc; 909 if (fd < 0) { 910 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 911 return OMX_ErrorBadParameter; 912 } 913 914 for (i = 0; i < array_sz; ++i) { 915 memset(&sub, 0, sizeof(sub)); 916 sub.type = event_type[i]; 917 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 918 if (rc) { 919 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 920 break; 921 } 922 } 923 return eRet; 924 } 925 926 /* ====================================================================== 927 FUNCTION 928 omx_vdec::~omx_vdec 929 930 DESCRIPTION 931 Destructor 932 933 PARAMETERS 934 None 935 936 RETURN VALUE 937 None. 938 ========================================================================== */ 939 omx_vdec::~omx_vdec() 940 { 941 m_pmem_info = NULL; 942 DEBUG_PRINT_HIGH("In OMX vdec Destructor"); 943 if (msg_thread_created) { 944 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread"); 945 message_thread_stop = true; 946 post_message(this, OMX_COMPONENT_CLOSE_MSG); 947 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); 948 pthread_join(msg_thread_id,NULL); 949 } 950 close(m_pipe_in); 951 close(m_pipe_out); 952 m_pipe_in = -1; 953 m_pipe_out = -1; 954 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); 955 if(eventfd_write(m_poll_efd, 1)) { 956 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno); 957 async_thread_force_stop = true; 958 } 959 960 if (async_thread_created) 961 pthread_join(async_thread_id,NULL); 962 unsubscribe_to_events(drv_ctx.video_driver_fd); 963 close(m_poll_efd); 964 close(drv_ctx.video_driver_fd); 965 pthread_mutex_destroy(&m_lock); 966 pthread_mutex_destroy(&c_lock); 967 pthread_mutex_destroy(&buf_lock); 968 sem_destroy(&m_cmd_lock); 969 pthread_mutex_destroy(&m_hdr_info_client_lock); 970 if (perf_flag) { 971 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); 972 dec_time.end(); 973 } 974 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd); 975 m_perf_control.send_hint_to_mpctl(false); 976 } 977 978 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type) 979 { 980 struct v4l2_requestbuffers bufreq; 981 int rc = 0; 982 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 983 bufreq.memory = V4L2_MEMORY_USERPTR; 984 bufreq.count = 0; 985 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 986 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 987 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) { 988 bufreq.memory = V4L2_MEMORY_USERPTR; 989 bufreq.count = 0; 990 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 991 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 992 } 993 return rc; 994 } 995 996 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format) 997 { 998 int rc = 0; 999 struct v4l2_ext_control ctrl[2]; 1000 struct v4l2_ext_controls controls; 1001 1002 DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s", 1003 is_split_mode ? "split" : "combined", 1004 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc": 1005 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc": 1006 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb": 1007 "unknown", 1008 capture_capability == V4L2_PIX_FMT_NV12 ? "nv12": 1009 capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc": 1010 capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC ? "nv12_10bit_ubwc": 1011 "unknown"); 1012 1013 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE; 1014 if (is_split_mode) { 1015 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY; 1016 } else { 1017 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY; 1018 } 1019 1020 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT; 1021 ctrl[1].value = dpb_color_format; 1022 1023 controls.count = 2; 1024 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 1025 controls.controls = ctrl; 1026 1027 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls); 1028 if (rc) { 1029 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc); 1030 return OMX_ErrorUnsupportedSetting; 1031 } 1032 return OMX_ErrorNone; 1033 } 1034 1035 1036 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt) 1037 { 1038 OMX_ERRORTYPE eRet = OMX_ErrorNone; 1039 struct v4l2_format fmt; 1040 int rc = 0; 1041 bool cpu_access = (capture_capability != V4L2_PIX_FMT_NV12_UBWC) && 1042 capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC; 1043 bool tp10_enable = !drv_ctx.idr_only_decoding && 1044 dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10; 1045 bool dither_enable = true; 1046 1047 switch (m_dither_config) { 1048 case DITHER_DISABLE: 1049 dither_enable = false; 1050 break; 1051 case DITHER_COLORSPACE_EXCEPTBT2020: 1052 dither_enable = (m_color_space == EXCEPT_BT2020); 1053 break; 1054 case DITHER_ALL_COLORSPACE: 1055 dither_enable = true; 1056 break; 1057 default: 1058 DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config); 1059 } 1060 1061 if (tp10_enable && !dither_enable) { 1062 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC; 1063 capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC; 1064 cpu_access = false; 1065 1066 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1067 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1068 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 1069 if (rc) { 1070 DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__); 1071 return OMX_ErrorUnsupportedSetting; 1072 } 1073 fmt.fmt.pix_mp.pixelformat = capture_capability; 1074 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1075 if (rc) { 1076 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__); 1077 return OMX_ErrorUnsupportedSetting; 1078 } 1079 } 1080 1081 1082 if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) && 1083 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 1084 DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split"); 1085 return eRet; 1086 } 1087 1088 1089 if (cpu_access) { 1090 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) { 1091 /* Disabled split mode for VP9. In split mode the DPB buffers are part of the internal 1092 * scratch buffers and the driver does not does the reference buffer management for 1093 * scratch buffers. In case of VP9 with spatial scalability, when a sequence changed 1094 * event is received with the new resolution, and when a flush is sent by the driver, it 1095 * releases all the references of internal scratch buffers. However as per the VP9 1096 * spatial scalability, even after the flush, the buffers which have not yet received 1097 * release reference event should not be unmapped and freed. Currently in driver, 1098 * reference buffer management of the internal scratch buffer is not implemented 1099 * and hence the DPB buffers get unmapped. For other codecs it does not matter 1100 * as with the new SPS/PPS, the DPB is flushed. 1101 */ 1102 bool is_not_vp9 = eCompressionFormat != OMX_VIDEO_CodingVP9; 1103 bool eligible_for_split_dpb_ubwc = 1104 m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE && //@ Due to Venus limitation for Interlaced, Split mode enabled only for Progressive. 1105 is_not_vp9 && //@ Split mode disabled for VP9. 1106 !drv_ctx.idr_only_decoding && //@ Split mode disabled for Thumbnail usecase. 1107 !m_disable_split_mode; //@ Set prop to disable split mode 1108 1109 //Since opb is linear, dpb should also be linear. 1110 if (split_opb_dpb_with_same_color_fmt) { 1111 eligible_for_split_dpb_ubwc = false; 1112 } 1113 1114 if (eligible_for_split_dpb_ubwc) { 1115 //split DPB-OPB 1116 //DPB -> UBWC , OPB -> Linear 1117 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC); 1118 } else if (split_opb_dpb_with_same_color_fmt) { 1119 //DPB -> Linear, OPB -> Linear 1120 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1121 } else { 1122 //DPB-OPB combined linear 1123 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1124 } 1125 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) { 1126 //split DPB-OPB 1127 //DPB -> UBWC, OPB -> Linear 1128 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC); 1129 } 1130 } else { //no cpu access 1131 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) { 1132 if (split_opb_dpb_with_same_color_fmt) { 1133 //split DPB-OPB 1134 //DPB -> UBWC, OPB -> UBWC 1135 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC); 1136 } else { 1137 //DPB-OPB combined UBWC 1138 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1139 } 1140 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) { 1141 if (dither_enable) { 1142 //split DPB-OPB 1143 //DPB -> TP10UBWC, OPB -> UBWC 1144 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC); 1145 } else { 1146 //combined DPB-OPB 1147 //DPB -> TP10UBWC, OPB -> TP10UBWC 1148 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC); 1149 } 1150 } 1151 } 1152 if (eRet) { 1153 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet); 1154 } 1155 1156 1157 1158 return eRet; 1159 } 1160 1161 int omx_vdec::enable_downscalar() 1162 { 1163 int rc = 0; 1164 struct v4l2_control control; 1165 struct v4l2_format fmt; 1166 1167 if (is_down_scalar_enabled) { 1168 DEBUG_PRINT_LOW("%s: already enabled", __func__); 1169 return 0; 1170 } 1171 1172 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar"); 1173 rc = decide_dpb_buffer_mode(true); 1174 if (rc) { 1175 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__); 1176 return rc; 1177 } 1178 is_down_scalar_enabled = true; 1179 1180 memset(&control, 0x0, sizeof(struct v4l2_control)); 1181 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO; 1182 control.value = 1; 1183 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 1184 if (rc) { 1185 DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__); 1186 return rc; 1187 } 1188 1189 return 0; 1190 } 1191 1192 int omx_vdec::disable_downscalar() 1193 { 1194 int rc = 0; 1195 struct v4l2_control control; 1196 1197 if (!is_down_scalar_enabled) { 1198 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled"); 1199 return 0; 1200 } 1201 1202 rc = decide_dpb_buffer_mode(false); 1203 if (rc < 0) { 1204 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__); 1205 return rc; 1206 } 1207 is_down_scalar_enabled = false; 1208 1209 return rc; 1210 } 1211 1212 int omx_vdec::decide_downscalar() 1213 { 1214 int rc = 0; 1215 struct v4l2_format fmt; 1216 enum color_fmts color_format; 1217 OMX_U32 width, height; 1218 OMX_BOOL isPortraitVideo = OMX_FALSE; 1219 1220 if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) { 1221 rc = disable_downscalar(); 1222 if (rc) { 1223 DEBUG_PRINT_ERROR("Disable downscalar failed!"); 1224 return rc; 1225 } 1226 return 0; 1227 } 1228 1229 if (!m_enable_downscalar) { 1230 DEBUG_PRINT_LOW("%s: downscalar not supported", __func__); 1231 return 0; 1232 } 1233 1234 #ifdef _QUERY_DISP_RES_ 1235 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1236 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1237 fmt.fmt.pix_mp.pixelformat = capture_capability; 1238 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 1239 if (rc < 0) { 1240 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__); 1241 return rc; 1242 } 1243 isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE; 1244 if (!m_downscalar_width || !m_downscalar_height) { 1245 qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {}; 1246 int prim_config, ext_config, virt_config; 1247 1248 prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY); 1249 dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY); 1250 DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d dpa.yres=%d dpa.xdpi = %f dpa.ydpi = %f ", 1251 __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi); 1252 1253 ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL); 1254 dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL); 1255 DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d dsa.yres = %d dsa.xdpi = %f dsa.ydpi = %f ", 1256 __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi); 1257 1258 virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL); 1259 dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL); 1260 DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d dva.yres = %d dva.xdpi = %f dva.ydpi = %f ", 1261 __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi); 1262 1263 /* Below logic takes care of following conditions: 1264 * 1. Choose display resolution as maximum resolution of all the connected 1265 * displays (secondary, primary, virtual), so that we do not downscale 1266 * unnecessarily which might be supported on one of the display losing quality. 1267 * 2. Displays connected might be in landscape or portrait mode, so the xres might 1268 * be smaller or greater than the yres. So we first take the max of the two 1269 * in width and min of two in height and then rotate it if below point is true. 1270 * 3. Video might also be in portrait mode, so invert the downscalar width and 1271 * height for such cases. 1272 */ 1273 if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) { 1274 m_downscalar_width = MAX(dsa.xres, dsa.yres); 1275 m_downscalar_height = MIN(dsa.xres, dsa.yres); 1276 } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) { 1277 m_downscalar_width = MAX(dva.xres, dva.yres); 1278 m_downscalar_height = MIN(dva.xres, dva.yres); 1279 1280 } else { 1281 m_downscalar_width = MAX(dpa.xres, dpa.yres); 1282 m_downscalar_height = MIN(dpa.xres, dpa.yres); 1283 } 1284 if (isPortraitVideo) { 1285 // Swap width and height 1286 m_downscalar_width = m_downscalar_width ^ m_downscalar_height; 1287 m_downscalar_height = m_downscalar_width ^ m_downscalar_height; 1288 m_downscalar_width = m_downscalar_width ^ m_downscalar_height; 1289 } 1290 } 1291 m_downscalar_width = ALIGN(m_downscalar_width, 128); 1292 m_downscalar_height = ALIGN(m_downscalar_height, 32); 1293 #endif 1294 1295 if (!m_downscalar_width || !m_downscalar_height) { 1296 DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__); 1297 return 0; 1298 } 1299 1300 if (m_force_down_scalar) { 1301 DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar); 1302 return 0; 1303 } 1304 1305 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1306 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1307 fmt.fmt.pix_mp.pixelformat = capture_capability; 1308 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 1309 if (rc < 0) { 1310 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__); 1311 return rc; 1312 } 1313 1314 height = fmt.fmt.pix_mp.height; 1315 width = fmt.fmt.pix_mp.width; 1316 1317 DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__, 1318 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session); 1319 1320 if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) && 1321 m_is_display_session) { 1322 rc = enable_downscalar(); 1323 if (rc < 0) { 1324 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__); 1325 return rc; 1326 } 1327 1328 width = m_downscalar_width > fmt.fmt.pix_mp.width ? 1329 fmt.fmt.pix_mp.width : m_downscalar_width; 1330 height = m_downscalar_height > fmt.fmt.pix_mp.height ? 1331 fmt.fmt.pix_mp.height : m_downscalar_height; 1332 switch (capture_capability) { 1333 case V4L2_PIX_FMT_NV12: 1334 color_format = COLOR_FMT_NV12; 1335 break; 1336 case V4L2_PIX_FMT_NV12_UBWC: 1337 color_format = COLOR_FMT_NV12_UBWC; 1338 break; 1339 case V4L2_PIX_FMT_NV12_TP10_UBWC: 1340 color_format = COLOR_FMT_NV12_BPP10_UBWC; 1341 break; 1342 default: 1343 DEBUG_PRINT_ERROR("Color format not recognized\n"); 1344 rc = OMX_ErrorUndefined; 1345 return rc; 1346 } 1347 } else { 1348 1349 rc = disable_downscalar(); 1350 if (rc < 0) { 1351 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__); 1352 return rc; 1353 } 1354 } 1355 1356 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1357 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1358 fmt.fmt.pix_mp.height = height; 1359 fmt.fmt.pix_mp.width = width; 1360 fmt.fmt.pix_mp.pixelformat = capture_capability; 1361 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1362 if (rc) { 1363 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__); 1364 return rc; 1365 } 1366 1367 rc = get_buffer_req(&drv_ctx.op_buf); 1368 if (rc) { 1369 DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__); 1370 return rc; 1371 } 1372 1373 return rc; 1374 } 1375 1376 /* ====================================================================== 1377 FUNCTION 1378 omx_vdec::OMXCntrlProcessMsgCb 1379 1380 DESCRIPTION 1381 IL Client callbacks are generated through this routine. The decoder 1382 provides the thread context for this routine. 1383 1384 PARAMETERS 1385 ctxt -- Context information related to the self. 1386 id -- Event identifier. This could be any of the following: 1387 1. Command completion event 1388 2. Buffer done callback event 1389 3. Frame done callback event 1390 1391 RETURN VALUE 1392 None. 1393 1394 ========================================================================== */ 1395 void omx_vdec::process_event_cb(void *ctxt, unsigned char id) 1396 { 1397 unsigned long p1; // Parameter - 1 1398 unsigned long p2; // Parameter - 2 1399 unsigned long ident; 1400 unsigned qsize=0; // qsize 1401 omx_vdec *pThis = (omx_vdec *) ctxt; 1402 1403 if (!pThis) { 1404 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out", 1405 __func__); 1406 return; 1407 } 1408 1409 // Protect the shared queue data structure 1410 do { 1411 /*Read the message id's from the queue*/ 1412 pthread_mutex_lock(&pThis->m_lock); 1413 qsize = pThis->m_cmd_q.m_size; 1414 if (qsize) { 1415 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident); 1416 } 1417 1418 if (qsize == 0 && pThis->m_state != OMX_StatePause) { 1419 qsize = pThis->m_ftb_q.m_size; 1420 if (qsize) { 1421 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident); 1422 } 1423 } 1424 1425 if (qsize == 0 && pThis->m_state != OMX_StatePause) { 1426 qsize = pThis->m_etb_q.m_size; 1427 if (qsize) { 1428 pThis->m_etb_q.pop_entry(&p1, &p2, &ident); 1429 } 1430 } 1431 pthread_mutex_unlock(&pThis->m_lock); 1432 1433 /*process message if we have one*/ 1434 if (qsize > 0) { 1435 id = ident; 1436 switch (id) { 1437 case OMX_COMPONENT_GENERATE_EVENT: 1438 if (pThis->m_cb.EventHandler) { 1439 switch (p1) { 1440 case OMX_CommandStateSet: 1441 pThis->m_state = (OMX_STATETYPE) p2; 1442 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d", 1443 pThis->m_state); 1444 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1445 OMX_EventCmdComplete, p1, p2, NULL); 1446 break; 1447 1448 case OMX_EventError: 1449 if (p2 == OMX_StateInvalid) { 1450 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid"); 1451 pThis->m_state = (OMX_STATETYPE) p2; 1452 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1453 OMX_EventError, OMX_ErrorInvalidState, p2, NULL); 1454 } else if (p2 == (unsigned long)OMX_ErrorHardware) { 1455 pThis->omx_report_error(); 1456 } else { 1457 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1458 OMX_EventError, p2, (OMX_U32)NULL, NULL ); 1459 } 1460 break; 1461 1462 case OMX_CommandPortDisable: 1463 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2); 1464 if (BITMASK_PRESENT(&pThis->m_flags, 1465 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) { 1466 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 1467 break; 1468 } 1469 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) { 1470 OMX_ERRORTYPE eRet = OMX_ErrorNone; 1471 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 1472 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT)) 1473 DEBUG_PRINT_HIGH("Failed to release output buffers"); 1474 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf); 1475 if (eRet != OMX_ErrorNone) { 1476 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet); 1477 pThis->omx_report_error(); 1478 break; 1479 } 1480 } 1481 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1482 OMX_EventCmdComplete, p1, p2, NULL ); 1483 break; 1484 case OMX_CommandPortEnable: 1485 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2); 1486 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ 1487 OMX_EventCmdComplete, p1, p2, NULL ); 1488 pThis->in_reconfig = false; 1489 break; 1490 1491 default: 1492 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1493 OMX_EventCmdComplete, p1, p2, NULL ); 1494 break; 1495 1496 } 1497 } else { 1498 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1499 } 1500 break; 1501 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: 1502 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 1503 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) { 1504 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure"); 1505 pThis->omx_report_error (); 1506 } 1507 break; 1508 case OMX_COMPONENT_GENERATE_ETB: { 1509 OMX_ERRORTYPE iret; 1510 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2); 1511 if (iret == OMX_ErrorInsufficientResources) { 1512 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload"); 1513 pThis->omx_report_hw_overload (); 1514 } else if (iret != OMX_ErrorNone) { 1515 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); 1516 pThis->omx_report_error (); 1517 } 1518 } 1519 break; 1520 1521 case OMX_COMPONENT_GENERATE_FTB: 1522 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\ 1523 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) { 1524 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure"); 1525 pThis->omx_report_error (); 1526 } 1527 break; 1528 1529 case OMX_COMPONENT_GENERATE_COMMAND: 1530 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ 1531 (OMX_U32)p2,(OMX_PTR)NULL); 1532 break; 1533 1534 case OMX_COMPONENT_GENERATE_EBD: 1535 1536 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) { 1537 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure"); 1538 pThis->omx_report_error (); 1539 } else { 1540 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) { 1541 pThis->time_stamp_dts.remove_time_stamp( 1542 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp, 1543 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1544 ?true:false); 1545 } 1546 1547 if ( pThis->empty_buffer_done(&pThis->m_cmp, 1548 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) { 1549 DEBUG_PRINT_ERROR("empty_buffer_done failure"); 1550 pThis->omx_report_error (); 1551 } 1552 } 1553 break; 1554 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: { 1555 int64_t *timestamp = (int64_t *)(intptr_t)p1; 1556 if (p1) { 1557 pThis->time_stamp_dts.remove_time_stamp(*timestamp, 1558 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1559 ?true:false); 1560 free(timestamp); 1561 } 1562 } 1563 break; 1564 case OMX_COMPONENT_GENERATE_FBD: 1565 if (p2 != VDEC_S_SUCCESS) { 1566 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure"); 1567 pThis->omx_report_error (); 1568 } else if ( pThis->fill_buffer_done(&pThis->m_cmp, 1569 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) { 1570 DEBUG_PRINT_ERROR("fill_buffer_done failure"); 1571 pThis->omx_report_error (); 1572 } 1573 break; 1574 1575 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: 1576 DEBUG_PRINT_HIGH("Driver flush i/p Port complete"); 1577 if (!pThis->input_flush_progress) { 1578 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver"); 1579 } else { 1580 pThis->execute_input_flush(); 1581 if (pThis->m_cb.EventHandler) { 1582 if (p2 != VDEC_S_SUCCESS) { 1583 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); 1584 pThis->omx_report_error (); 1585 } else { 1586 /*Check if we need generate event for Flush done*/ 1587 pThis->notify_flush_done(ctxt); 1588 1589 if (BITMASK_PRESENT(&pThis->m_flags, 1590 OMX_COMPONENT_IDLE_PENDING)) { 1591 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) { 1592 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port"); 1593 pThis->omx_report_error (); 1594 } else { 1595 pThis->streaming[OUTPUT_PORT] = false; 1596 } 1597 if (!pThis->output_flush_progress) { 1598 DEBUG_PRINT_LOW("Input flush done hence issue stop"); 1599 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\ 1600 OMX_COMPONENT_GENERATE_STOP_DONE); 1601 } 1602 } 1603 } 1604 } else { 1605 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1606 } 1607 } 1608 break; 1609 1610 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: 1611 DEBUG_PRINT_HIGH("Driver flush o/p Port complete"); 1612 if (!pThis->output_flush_progress) { 1613 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver"); 1614 } else { 1615 pThis->execute_output_flush(); 1616 if (pThis->m_cb.EventHandler) { 1617 if (p2 != VDEC_S_SUCCESS) { 1618 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); 1619 pThis->omx_report_error (); 1620 } else { 1621 /*Check if we need generate event for Flush done*/ 1622 pThis->notify_flush_done(ctxt); 1623 1624 if (BITMASK_PRESENT(&pThis->m_flags, 1625 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) { 1626 DEBUG_PRINT_LOW("Internal flush complete"); 1627 BITMASK_CLEAR (&pThis->m_flags, 1628 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 1629 if (BITMASK_PRESENT(&pThis->m_flags, 1630 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) { 1631 pThis->post_event(OMX_CommandPortDisable, 1632 OMX_CORE_OUTPUT_PORT_INDEX, 1633 OMX_COMPONENT_GENERATE_EVENT); 1634 BITMASK_CLEAR (&pThis->m_flags, 1635 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 1636 BITMASK_CLEAR (&pThis->m_flags, 1637 OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 1638 1639 } 1640 } 1641 1642 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) { 1643 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) { 1644 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port"); 1645 pThis->omx_report_error (); 1646 break; 1647 } 1648 pThis->streaming[CAPTURE_PORT] = false; 1649 if (!pThis->input_flush_progress) { 1650 DEBUG_PRINT_LOW("Output flush done hence issue stop"); 1651 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\ 1652 OMX_COMPONENT_GENERATE_STOP_DONE); 1653 } 1654 } 1655 } 1656 } else { 1657 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1658 } 1659 } 1660 break; 1661 1662 case OMX_COMPONENT_GENERATE_START_DONE: 1663 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE"); 1664 1665 if (pThis->m_cb.EventHandler) { 1666 if (p2 != VDEC_S_SUCCESS) { 1667 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure"); 1668 pThis->omx_report_error (); 1669 } else { 1670 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success"); 1671 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) { 1672 DEBUG_PRINT_LOW("Move to executing"); 1673 // Send the callback now 1674 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1675 pThis->m_state = OMX_StateExecuting; 1676 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1677 OMX_EventCmdComplete,OMX_CommandStateSet, 1678 OMX_StateExecuting, NULL); 1679 } else if (BITMASK_PRESENT(&pThis->m_flags, 1680 OMX_COMPONENT_PAUSE_PENDING)) { 1681 if (/*ioctl (pThis->drv_ctx.video_driver_fd, 1682 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) { 1683 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed"); 1684 pThis->omx_report_error (); 1685 } 1686 } 1687 } 1688 } else { 1689 DEBUG_PRINT_LOW("Event Handler callback is NULL"); 1690 } 1691 break; 1692 1693 case OMX_COMPONENT_GENERATE_PAUSE_DONE: 1694 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); 1695 if (pThis->m_cb.EventHandler) { 1696 if (p2 != VDEC_S_SUCCESS) { 1697 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); 1698 pThis->omx_report_error (); 1699 } else { 1700 pThis->complete_pending_buffer_done_cbs(); 1701 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) { 1702 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); 1703 //Send the callback now 1704 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); 1705 pThis->m_state = OMX_StatePause; 1706 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1707 OMX_EventCmdComplete,OMX_CommandStateSet, 1708 OMX_StatePause, NULL); 1709 } 1710 } 1711 } else { 1712 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1713 } 1714 1715 break; 1716 1717 case OMX_COMPONENT_GENERATE_RESUME_DONE: 1718 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); 1719 if (pThis->m_cb.EventHandler) { 1720 if (p2 != VDEC_S_SUCCESS) { 1721 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed"); 1722 pThis->omx_report_error (); 1723 } else { 1724 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) { 1725 DEBUG_PRINT_LOW("Moving the decoder to execute state"); 1726 // Send the callback now 1727 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1728 pThis->m_state = OMX_StateExecuting; 1729 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1730 OMX_EventCmdComplete,OMX_CommandStateSet, 1731 OMX_StateExecuting,NULL); 1732 } 1733 } 1734 } else { 1735 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1736 } 1737 1738 break; 1739 1740 case OMX_COMPONENT_GENERATE_STOP_DONE: 1741 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); 1742 if (pThis->m_cb.EventHandler) { 1743 if (p2 != VDEC_S_SUCCESS) { 1744 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); 1745 pThis->omx_report_error (); 1746 } else { 1747 pThis->complete_pending_buffer_done_cbs(); 1748 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) { 1749 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success"); 1750 // Send the callback now 1751 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); 1752 pThis->m_state = OMX_StateIdle; 1753 DEBUG_PRINT_LOW("Move to Idle State"); 1754 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, 1755 OMX_EventCmdComplete,OMX_CommandStateSet, 1756 OMX_StateIdle,NULL); 1757 } 1758 } 1759 } else { 1760 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1761 } 1762 1763 break; 1764 1765 case OMX_COMPONENT_GENERATE_PORT_RECONFIG: 1766 if (p2 == OMX_IndexParamPortDefinition) { 1767 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition"); 1768 pThis->in_reconfig = true; 1769 pThis->m_need_turbo &= ~TURBO_MODE_HIGH_FPS; 1770 } else if (p2 == OMX_IndexConfigCommonOutputCrop) { 1771 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop"); 1772 1773 /* Check if resolution is changed in smooth streaming mode */ 1774 if (pThis->m_smoothstreaming_mode && 1775 (pThis->framesize.nWidth != 1776 pThis->drv_ctx.video_resolution.frame_width) || 1777 (pThis->framesize.nHeight != 1778 pThis->drv_ctx.video_resolution.frame_height)) { 1779 1780 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d", 1781 pThis->framesize.nWidth, 1782 pThis->framesize.nHeight, 1783 pThis->drv_ctx.video_resolution.frame_width, 1784 pThis->drv_ctx.video_resolution.frame_height); 1785 1786 /* Update new resolution */ 1787 pThis->framesize.nWidth = 1788 pThis->drv_ctx.video_resolution.frame_width; 1789 pThis->framesize.nHeight = 1790 pThis->drv_ctx.video_resolution.frame_height; 1791 1792 /* Update C2D with new resolution */ 1793 if (!pThis->client_buffers.update_buffer_req()) { 1794 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed"); 1795 } 1796 } 1797 1798 /* Update new crop information */ 1799 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left; 1800 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top; 1801 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right; 1802 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom; 1803 1804 /* Validate the new crop information */ 1805 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth > 1806 pThis->drv_ctx.video_resolution.frame_width) { 1807 1808 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]", 1809 pThis->rectangle.nLeft, pThis->rectangle.nWidth, 1810 pThis->drv_ctx.video_resolution.frame_width); 1811 pThis->rectangle.nLeft = 0; 1812 1813 if (pThis->rectangle.nWidth > 1814 pThis->drv_ctx.video_resolution.frame_width) { 1815 1816 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]", 1817 pThis->rectangle.nWidth, 1818 pThis->drv_ctx.video_resolution.frame_width); 1819 pThis->rectangle.nWidth = 1820 pThis->drv_ctx.video_resolution.frame_width; 1821 } 1822 } 1823 if (pThis->rectangle.nTop + pThis->rectangle.nHeight > 1824 pThis->drv_ctx.video_resolution.frame_height) { 1825 1826 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]", 1827 pThis->rectangle.nTop, pThis->rectangle.nHeight, 1828 pThis->drv_ctx.video_resolution.frame_height); 1829 pThis->rectangle.nTop = 0; 1830 1831 if (pThis->rectangle.nHeight > 1832 pThis->drv_ctx.video_resolution.frame_height) { 1833 1834 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]", 1835 pThis->rectangle.nHeight, 1836 pThis->drv_ctx.video_resolution.frame_height); 1837 pThis->rectangle.nHeight = 1838 pThis->drv_ctx.video_resolution.frame_height; 1839 } 1840 } 1841 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u", 1842 pThis->rectangle.nLeft, pThis->rectangle.nTop, 1843 pThis->rectangle.nWidth, pThis->rectangle.nHeight); 1844 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) { 1845 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects"); 1846 } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) { 1847 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo"); 1848 } else { 1849 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2); 1850 break; 1851 } 1852 if (pThis->m_debug.outfile) { 1853 fclose(pThis->m_debug.outfile); 1854 pThis->m_debug.outfile = NULL; 1855 } 1856 if (pThis->m_debug.out_ymeta_file) { 1857 fclose(pThis->m_debug.out_ymeta_file); 1858 pThis->m_debug.out_ymeta_file = NULL; 1859 } 1860 if (pThis->m_debug.out_uvmeta_file) { 1861 fclose(pThis->m_debug.out_uvmeta_file); 1862 pThis->m_debug.out_uvmeta_file = NULL; 1863 } 1864 1865 if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) { 1866 pThis->prefetchNewBuffers(); 1867 } 1868 1869 if (pThis->m_cb.EventHandler) { 1870 uint32_t frame_data[7]; 1871 frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ? 1872 pThis->m_reconfig_height : pThis->rectangle.nHeight; 1873 frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ? 1874 pThis->m_reconfig_width : pThis->rectangle.nWidth; 1875 1876 frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ? 1877 frame_data[0] : pThis->drv_ctx.video_resolution.frame_height; 1878 1879 frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ? 1880 frame_data[1] : pThis->drv_ctx.video_resolution.frame_width; 1881 frame_data[4] = pThis->dpb_bit_depth; 1882 frame_data[5] = pThis->m_color_space; 1883 frame_data[6] = pThis->m_dither_config; 1884 1885 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1886 OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data ); 1887 } else { 1888 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1889 } 1890 break; 1891 1892 case OMX_COMPONENT_GENERATE_EOS_DONE: 1893 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); 1894 if (pThis->m_cb.EventHandler) { 1895 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, 1896 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); 1897 } else { 1898 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1899 } 1900 pThis->prev_ts = LLONG_MAX; 1901 pThis->rst_prev_ts = true; 1902 break; 1903 1904 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: 1905 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); 1906 pThis->omx_report_error(); 1907 break; 1908 1909 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING: 1910 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING"); 1911 pThis->omx_report_unsupported_setting(); 1912 break; 1913 1914 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD: 1915 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD"); 1916 pThis->omx_report_hw_overload(); 1917 break; 1918 1919 default: 1920 break; 1921 } 1922 } 1923 pthread_mutex_lock(&pThis->m_lock); 1924 qsize = pThis->m_cmd_q.m_size; 1925 if (pThis->m_state != OMX_StatePause) 1926 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size); 1927 pthread_mutex_unlock(&pThis->m_lock); 1928 } while (qsize>0); 1929 1930 } 1931 1932 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines) 1933 { 1934 int format_changed = 0; 1935 if ((height != (int)drv_ctx.video_resolution.frame_height) || 1936 (width != (int)drv_ctx.video_resolution.frame_width)) { 1937 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)", 1938 width, drv_ctx.video_resolution.frame_width, 1939 height,drv_ctx.video_resolution.frame_height); 1940 format_changed = 1; 1941 } 1942 drv_ctx.video_resolution.frame_height = height; 1943 drv_ctx.video_resolution.frame_width = width; 1944 drv_ctx.video_resolution.scan_lines = scan_lines; 1945 drv_ctx.video_resolution.stride = stride; 1946 1947 if (!is_down_scalar_enabled) { 1948 rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft; 1949 rectangle.nTop = m_extradata_info.output_crop_rect.nTop; 1950 rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth; 1951 rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight; 1952 } 1953 return format_changed; 1954 } 1955 1956 OMX_ERRORTYPE omx_vdec::is_video_session_supported() 1957 { 1958 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", 1959 OMX_MAX_STRINGNAME_SIZE) && 1960 (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) { 1961 m_decoder_capability.max_width = 1280; 1962 m_decoder_capability.max_height = 720; 1963 DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP"); 1964 } 1965 1966 if ((drv_ctx.video_resolution.frame_width * 1967 drv_ctx.video_resolution.frame_height > 1968 m_decoder_capability.max_width * 1969 m_decoder_capability.max_height) || 1970 (drv_ctx.video_resolution.frame_width* 1971 drv_ctx.video_resolution.frame_height < 1972 m_decoder_capability.min_width * 1973 m_decoder_capability.min_height)) { 1974 DEBUG_PRINT_ERROR( 1975 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)", 1976 drv_ctx.video_resolution.frame_width, 1977 drv_ctx.video_resolution.frame_height, 1978 m_decoder_capability.min_width, 1979 m_decoder_capability.min_height, 1980 m_decoder_capability.max_width, 1981 m_decoder_capability.max_height); 1982 return OMX_ErrorUnsupportedSetting; 1983 } 1984 DEBUG_PRINT_HIGH("video session supported"); 1985 return OMX_ErrorNone; 1986 } 1987 1988 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) 1989 { 1990 if (m_debug.in_buffer_log && !m_debug.infile) { 1991 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 1992 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v", 1993 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1994 } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 1995 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc, 1996 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1997 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 1998 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263", 1999 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2000 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) || 2001 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 2002 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264", 2003 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2004 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 2005 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265", 2006 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2007 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) { 2008 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1", 2009 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2010 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) { 2011 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1", 2012 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2013 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) { 2014 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf", 2015 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2016 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 2017 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf", 2018 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2019 } else { 2020 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx", 2021 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2022 } 2023 m_debug.infile = fopen (m_debug.infile_name, "ab"); 2024 if (!m_debug.infile) { 2025 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name); 2026 m_debug.infile_name[0] = '\0'; 2027 return -1; 2028 } 2029 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 2030 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 2031 struct ivf_file_header { 2032 OMX_U8 signature[4]; //='DKIF'; 2033 OMX_U8 version ; //= 0; 2034 OMX_U8 headersize ; //= 32; 2035 OMX_U32 FourCC; 2036 OMX_U8 width; 2037 OMX_U8 height; 2038 OMX_U32 rate; 2039 OMX_U32 scale; 2040 OMX_U32 length; 2041 OMX_U8 unused[4]; 2042 } file_header; 2043 2044 memset((void *)&file_header,0,sizeof(file_header)); 2045 file_header.signature[0] = 'D'; 2046 file_header.signature[1] = 'K'; 2047 file_header.signature[2] = 'I'; 2048 file_header.signature[3] = 'F'; 2049 file_header.version = 0; 2050 file_header.headersize = 32; 2051 switch (drv_ctx.decoder_format) { 2052 case VDEC_CODECTYPE_VP8: 2053 file_header.FourCC = 0x30385056; 2054 break; 2055 case VDEC_CODECTYPE_VP9: 2056 file_header.FourCC = 0x30395056; 2057 break; 2058 default: 2059 DEBUG_PRINT_ERROR("unsupported format for VP8/VP9"); 2060 break; 2061 } 2062 fwrite((const char *)&file_header, 2063 sizeof(file_header),1,m_debug.infile); 2064 } 2065 } 2066 if (m_debug.infile && buffer_addr && buffer_len) { 2067 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 2068 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 2069 struct vpx_ivf_frame_header { 2070 OMX_U32 framesize; 2071 OMX_U32 timestamp_lo; 2072 OMX_U32 timestamp_hi; 2073 } vpx_frame_header; 2074 vpx_frame_header.framesize = buffer_len; 2075 /* Currently FW doesn't use timestamp values */ 2076 vpx_frame_header.timestamp_lo = 0; 2077 vpx_frame_header.timestamp_hi = 0; 2078 fwrite((const char *)&vpx_frame_header, 2079 sizeof(vpx_frame_header),1,m_debug.infile); 2080 } 2081 fwrite(buffer_addr, buffer_len, 1, m_debug.infile); 2082 } 2083 return 0; 2084 } 2085 2086 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) { 2087 int buf_index = 0; 2088 char *temp = NULL; 2089 2090 if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen) 2091 return 0; 2092 2093 if (m_debug.out_buffer_log && !m_debug.outfile) { 2094 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv", 2095 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2096 m_debug.outfile = fopen (m_debug.outfile_name, "ab"); 2097 if (!m_debug.outfile) { 2098 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc); 2099 m_debug.outfile_name[0] = '\0'; 2100 return -1; 2101 } 2102 } 2103 2104 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) { 2105 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta", 2106 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2107 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta", 2108 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 2109 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab"); 2110 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab"); 2111 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) { 2112 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc); 2113 m_debug.out_ymetafile_name[0] = '\0'; 2114 m_debug.out_uvmetafile_name[0] = '\0'; 2115 return -1; 2116 } 2117 } 2118 2119 buf_index = buffer - m_out_mem_ptr; 2120 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; 2121 2122 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC || 2123 drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) { 2124 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)", 2125 drv_ctx.video_resolution.frame_width, 2126 drv_ctx.video_resolution.frame_height); 2127 2128 if (m_debug.outfile) 2129 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile); 2130 2131 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) { 2132 unsigned int width = 0, height = 0; 2133 unsigned int y_plane, y_meta_plane; 2134 int y_stride = 0, y_sclines = 0; 2135 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0; 2136 int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC; 2137 int i; 2138 int bytes_written = 0; 2139 2140 width = drv_ctx.video_resolution.frame_width; 2141 height = drv_ctx.video_resolution.frame_height; 2142 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width); 2143 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height); 2144 y_stride = VENUS_Y_STRIDE(color_fmt, width); 2145 y_sclines = VENUS_Y_SCANLINES(color_fmt, height); 2146 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width); 2147 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height); 2148 2149 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096); 2150 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096); 2151 2152 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; 2153 for (i = 0; i < y_meta_scanlines; i++) { 2154 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file); 2155 temp += y_meta_stride; 2156 } 2157 2158 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane; 2159 for(i = 0; i < uv_meta_scanlines; i++) { 2160 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file); 2161 temp += uv_meta_stride; 2162 } 2163 } 2164 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 2165 int stride = drv_ctx.video_resolution.stride; 2166 int scanlines = drv_ctx.video_resolution.scan_lines; 2167 if (m_smoothstreaming_mode) { 2168 stride = drv_ctx.video_resolution.frame_width; 2169 scanlines = drv_ctx.video_resolution.frame_height; 2170 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1)); 2171 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1)); 2172 } 2173 unsigned i; 2174 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)", 2175 drv_ctx.video_resolution.frame_width, 2176 drv_ctx.video_resolution.frame_height, stride, scanlines); 2177 int bytes_written = 0; 2178 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) { 2179 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 2180 temp += stride; 2181 } 2182 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines; 2183 int stride_c = stride; 2184 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) { 2185 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 2186 temp += stride_c; 2187 } 2188 } 2189 return 0; 2190 } 2191 2192 /* ====================================================================== 2193 FUNCTION 2194 omx_vdec::ComponentInit 2195 2196 DESCRIPTION 2197 Initialize the component. 2198 2199 PARAMETERS 2200 ctxt -- Context information related to the self. 2201 id -- Event identifier. This could be any of the following: 2202 1. Command completion event 2203 2. Buffer done callback event 2204 3. Frame done callback event 2205 2206 RETURN VALUE 2207 None. 2208 2209 ========================================================================== */ 2210 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) 2211 { 2212 2213 OMX_ERRORTYPE eRet = OMX_ErrorNone; 2214 struct v4l2_fmtdesc fdesc; 2215 struct v4l2_format fmt; 2216 struct v4l2_requestbuffers bufreq; 2217 struct v4l2_control control; 2218 struct v4l2_frmsizeenum frmsize; 2219 unsigned int alignment = 0,buffer_size = 0; 2220 int fds[2]; 2221 int r,ret=0; 2222 bool codec_ambiguous = false; 2223 OMX_STRING device_name = (OMX_STRING)"/dev/video32"; 2224 char property_value[PROPERTY_VALUE_MAX] = {0}; 2225 FILE *soc_file = NULL; 2226 char buffer[10]; 2227 2228 #ifdef _ANDROID_ 2229 char platform_name[PROPERTY_VALUE_MAX]; 2230 property_get("ro.board.platform", platform_name, "0"); 2231 if (!strncmp(platform_name, "msm8610", 7)) { 2232 device_name = (OMX_STRING)"/dev/video/q6_dec"; 2233 is_q6_platform = true; 2234 maxSmoothStreamingWidth = 1280; 2235 maxSmoothStreamingHeight = 720; 2236 } 2237 #endif 2238 2239 is_thulium_v1 = false; 2240 soc_file = fopen("/sys/devices/soc0/soc_id", "r"); 2241 if (soc_file) { 2242 fread(buffer, 1, 4, soc_file); 2243 fclose(soc_file); 2244 if (atoi(buffer) == 246) { 2245 soc_file = fopen("/sys/devices/soc0/revision", "r"); 2246 if (soc_file) { 2247 fread(buffer, 1, 4, soc_file); 2248 fclose(soc_file); 2249 if (atoi(buffer) == 1) { 2250 is_thulium_v1 = true; 2251 DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE"); 2252 } 2253 } 2254 } 2255 } 2256 2257 #ifdef _ANDROID_ 2258 /* 2259 * turn off frame parsing for Android by default. 2260 * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode 2261 */ 2262 arbitrary_bytes = false; 2263 property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); 2264 if (atoi(property_value)) { 2265 DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command"); 2266 arbitrary_bytes = true; 2267 } 2268 #endif 2269 2270 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure", 2271 OMX_MAX_STRINGNAME_SIZE)) { 2272 secure_mode = true; 2273 arbitrary_bytes = false; 2274 role = (OMX_STRING)"OMX.qcom.video.decoder.avc"; 2275 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure", 2276 OMX_MAX_STRINGNAME_SIZE)) { 2277 secure_mode = true; 2278 arbitrary_bytes = false; 2279 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2"; 2280 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure", 2281 OMX_MAX_STRINGNAME_SIZE)) { 2282 secure_mode = true; 2283 arbitrary_bytes = false; 2284 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc"; 2285 } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure", 2286 OMX_MAX_STRINGNAME_SIZE)) { 2287 secure_mode = true; 2288 arbitrary_bytes = false; 2289 role = (OMX_STRING)"OMX.qcom.video.decoder.vc1"; 2290 } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure", 2291 OMX_MAX_STRINGNAME_SIZE)) { 2292 secure_mode = true; 2293 arbitrary_bytes = false; 2294 role = (OMX_STRING)"OMX.qcom.video.decoder.wmv"; 2295 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure", 2296 OMX_MAX_STRINGNAME_SIZE)) { 2297 secure_mode = true; 2298 arbitrary_bytes = false; 2299 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4"; 2300 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure", 2301 OMX_MAX_STRINGNAME_SIZE)) { 2302 secure_mode = true; 2303 arbitrary_bytes = false; 2304 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9"; 2305 } 2306 else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure", 2307 OMX_MAX_STRINGNAME_SIZE)) { 2308 secure_mode = true; 2309 arbitrary_bytes = false; 2310 role = (OMX_STRING)"OMX.qcom.video.decoder.vp8"; 2311 } 2312 2313 drv_ctx.video_driver_fd = open(device_name, O_RDWR); 2314 2315 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd); 2316 2317 if (drv_ctx.video_driver_fd < 0) { 2318 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno); 2319 return OMX_ErrorInsufficientResources; 2320 } 2321 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; 2322 drv_ctx.frame_rate.fps_denominator = 1; 2323 operating_frame_rate = DEFAULT_FPS; 2324 m_poll_efd = eventfd(0, 0); 2325 if (m_poll_efd < 0) { 2326 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno)); 2327 return OMX_ErrorInsufficientResources; 2328 } 2329 ret = subscribe_to_events(drv_ctx.video_driver_fd); 2330 if (!ret) { 2331 async_thread_created = true; 2332 ret = pthread_create(&async_thread_id,0,async_message_thread,this); 2333 } 2334 if (ret) { 2335 DEBUG_PRINT_ERROR("Failed to create async_message_thread"); 2336 async_thread_created = false; 2337 return OMX_ErrorInsufficientResources; 2338 } 2339 2340 #ifdef OUTPUT_EXTRADATA_LOG 2341 outputExtradataFile = fopen (output_extradata_filename, "ab"); 2342 #endif 2343 2344 // Copy the role information which provides the decoder kind 2345 strlcpy(drv_ctx.kind,role,128); 2346 2347 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\ 2348 OMX_MAX_STRINGNAME_SIZE)) { 2349 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\ 2350 OMX_MAX_STRINGNAME_SIZE); 2351 drv_ctx.timestamp_adjust = true; 2352 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4; 2353 eCompressionFormat = OMX_VIDEO_CodingMPEG4; 2354 output_capability=V4L2_PIX_FMT_MPEG4; 2355 /*Initialize Start Code for MPEG4*/ 2356 codec_type_parse = CODEC_TYPE_MPEG4; 2357 m_frame_parser.init_start_codes(codec_type_parse); 2358 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\ 2359 OMX_MAX_STRINGNAME_SIZE)) { 2360 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\ 2361 OMX_MAX_STRINGNAME_SIZE); 2362 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2; 2363 output_capability = V4L2_PIX_FMT_MPEG2; 2364 eCompressionFormat = OMX_VIDEO_CodingMPEG2; 2365 /*Initialize Start Code for MPEG2*/ 2366 codec_type_parse = CODEC_TYPE_MPEG2; 2367 m_frame_parser.init_start_codes(codec_type_parse); 2368 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\ 2369 OMX_MAX_STRINGNAME_SIZE)) { 2370 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 2371 DEBUG_PRINT_LOW("H263 Decoder selected"); 2372 drv_ctx.decoder_format = VDEC_CODECTYPE_H263; 2373 eCompressionFormat = OMX_VIDEO_CodingH263; 2374 output_capability = V4L2_PIX_FMT_H263; 2375 codec_type_parse = CODEC_TYPE_H263; 2376 m_frame_parser.init_start_codes(codec_type_parse); 2377 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\ 2378 OMX_MAX_STRINGNAME_SIZE)) { 2379 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2380 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected"); 2381 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3; 2382 output_capability = V4L2_PIX_FMT_DIVX_311; 2383 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2384 codec_type_parse = CODEC_TYPE_DIVX; 2385 m_frame_parser.init_start_codes(codec_type_parse); 2386 2387 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ 2388 OMX_MAX_STRINGNAME_SIZE)) { 2389 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2390 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected"); 2391 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4; 2392 output_capability = V4L2_PIX_FMT_DIVX; 2393 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2394 codec_type_parse = CODEC_TYPE_DIVX; 2395 codec_ambiguous = true; 2396 m_frame_parser.init_start_codes(codec_type_parse); 2397 2398 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\ 2399 OMX_MAX_STRINGNAME_SIZE)) { 2400 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2401 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected"); 2402 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6; 2403 output_capability = V4L2_PIX_FMT_DIVX; 2404 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2405 codec_type_parse = CODEC_TYPE_DIVX; 2406 codec_ambiguous = true; 2407 m_frame_parser.init_start_codes(codec_type_parse); 2408 2409 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\ 2410 OMX_MAX_STRINGNAME_SIZE)) { 2411 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 2412 drv_ctx.decoder_format = VDEC_CODECTYPE_H264; 2413 output_capability=V4L2_PIX_FMT_H264; 2414 eCompressionFormat = OMX_VIDEO_CodingAVC; 2415 codec_type_parse = CODEC_TYPE_H264; 2416 m_frame_parser.init_start_codes(codec_type_parse); 2417 m_frame_parser.init_nal_length(nal_length); 2418 if (is_thulium_v1) { 2419 arbitrary_bytes = true; 2420 DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264"); 2421 } 2422 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\ 2423 OMX_MAX_STRINGNAME_SIZE)) { 2424 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 2425 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC; 2426 output_capability = V4L2_PIX_FMT_H264_MVC; 2427 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC; 2428 codec_type_parse = CODEC_TYPE_H264; 2429 m_frame_parser.init_start_codes(codec_type_parse); 2430 m_frame_parser.init_nal_length(nal_length); 2431 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\ 2432 OMX_MAX_STRINGNAME_SIZE)) { 2433 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); 2434 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC; 2435 output_capability = V4L2_PIX_FMT_HEVC; 2436 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc; 2437 codec_type_parse = CODEC_TYPE_HEVC; 2438 m_frame_parser.init_start_codes(codec_type_parse); 2439 m_frame_parser.init_nal_length(nal_length); 2440 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\ 2441 OMX_MAX_STRINGNAME_SIZE)) { 2442 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 2443 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1; 2444 eCompressionFormat = OMX_VIDEO_CodingWMV; 2445 codec_type_parse = CODEC_TYPE_VC1; 2446 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G; 2447 m_frame_parser.init_start_codes(codec_type_parse); 2448 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\ 2449 OMX_MAX_STRINGNAME_SIZE)) { 2450 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 2451 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV; 2452 eCompressionFormat = OMX_VIDEO_CodingWMV; 2453 codec_type_parse = CODEC_TYPE_VC1; 2454 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L; 2455 m_frame_parser.init_start_codes(codec_type_parse); 2456 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \ 2457 OMX_MAX_STRINGNAME_SIZE)) { 2458 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 2459 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8; 2460 output_capability = V4L2_PIX_FMT_VP8; 2461 eCompressionFormat = OMX_VIDEO_CodingVP8; 2462 codec_type_parse = CODEC_TYPE_VP8; 2463 arbitrary_bytes = false; 2464 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \ 2465 OMX_MAX_STRINGNAME_SIZE)) { 2466 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE); 2467 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9; 2468 output_capability = V4L2_PIX_FMT_VP9; 2469 eCompressionFormat = OMX_VIDEO_CodingVP9; 2470 codec_type_parse = CODEC_TYPE_VP9; 2471 arbitrary_bytes = false; 2472 } else { 2473 DEBUG_PRINT_ERROR("ERROR:Unknown Component"); 2474 eRet = OMX_ErrorInvalidComponentName; 2475 } 2476 2477 if (eRet == OMX_ErrorNone) { 2478 OMX_COLOR_FORMATTYPE dest_color_format; 2479 if (m_disable_ubwc_mode) { 2480 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; 2481 } else { 2482 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC; 2483 } 2484 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC) 2485 dest_color_format = (OMX_COLOR_FORMATTYPE) 2486 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 2487 else 2488 dest_color_format = (OMX_COLOR_FORMATTYPE) 2489 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 2490 if (!client_buffers.set_color_format(dest_color_format)) { 2491 DEBUG_PRINT_ERROR("Setting color format failed"); 2492 eRet = OMX_ErrorInsufficientResources; 2493 } 2494 2495 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8; 2496 m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE; 2497 2498 if (m_disable_ubwc_mode) { 2499 capture_capability = V4L2_PIX_FMT_NV12; 2500 } else { 2501 capture_capability = V4L2_PIX_FMT_NV12_UBWC; 2502 } 2503 2504 struct v4l2_capability cap; 2505 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap); 2506 if (ret) { 2507 DEBUG_PRINT_ERROR("Failed to query capabilities"); 2508 /*TODO: How to handle this case */ 2509 } else { 2510 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s," 2511 " version = %d, capabilities = %x", cap.driver, cap.card, 2512 cap.bus_info, cap.version, cap.capabilities); 2513 } 2514 ret=0; 2515 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2516 fdesc.index=0; 2517 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 2518 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 2519 fdesc.pixelformat, fdesc.flags); 2520 fdesc.index++; 2521 } 2522 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2523 fdesc.index=0; 2524 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 2525 2526 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 2527 fdesc.pixelformat, fdesc.flags); 2528 fdesc.index++; 2529 } 2530 m_extradata_info.output_crop_rect.nLeft = 0; 2531 m_extradata_info.output_crop_rect.nTop = 0; 2532 m_extradata_info.output_crop_rect.nWidth = 320; 2533 m_extradata_info.output_crop_rect.nHeight = 240; 2534 update_resolution(320, 240, 320, 240); 2535 2536 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2537 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 2538 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 2539 fmt.fmt.pix_mp.pixelformat = output_capability; 2540 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 2541 if (ret) { 2542 /*TODO: How to handle this case */ 2543 DEBUG_PRINT_ERROR("Failed to set format on output port"); 2544 return OMX_ErrorInsufficientResources; 2545 } 2546 DEBUG_PRINT_HIGH("Set Format was successful"); 2547 if (codec_ambiguous) { 2548 if (output_capability == V4L2_PIX_FMT_DIVX) { 2549 struct v4l2_control divx_ctrl; 2550 2551 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) { 2552 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4; 2553 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) { 2554 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5; 2555 } else { 2556 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6; 2557 } 2558 2559 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT; 2560 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl); 2561 if (ret) { 2562 DEBUG_PRINT_ERROR("Failed to set divx version"); 2563 } 2564 } else { 2565 DEBUG_PRINT_ERROR("Codec should not be ambiguous"); 2566 } 2567 } 2568 2569 property_get("persist.vendor.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR); 2570 m_conceal_color= atoi(property_value); 2571 DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color); 2572 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR; 2573 control.value = m_conceal_color; 2574 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2575 if (ret) { 2576 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret); 2577 } 2578 2579 //Get the hardware capabilities 2580 memset((void *)&frmsize,0,sizeof(frmsize)); 2581 frmsize.index = 0; 2582 frmsize.pixel_format = output_capability; 2583 ret = ioctl(drv_ctx.video_driver_fd, 2584 VIDIOC_ENUM_FRAMESIZES, &frmsize); 2585 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) { 2586 DEBUG_PRINT_ERROR("Failed to get framesizes"); 2587 return OMX_ErrorHardware; 2588 } 2589 2590 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 2591 m_decoder_capability.min_width = frmsize.stepwise.min_width; 2592 m_decoder_capability.max_width = frmsize.stepwise.max_width; 2593 m_decoder_capability.min_height = frmsize.stepwise.min_height; 2594 m_decoder_capability.max_height = frmsize.stepwise.max_height; 2595 } 2596 2597 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 2598 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2599 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 2600 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 2601 fmt.fmt.pix_mp.pixelformat = capture_capability; 2602 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 2603 if (ret) { 2604 /*TODO: How to handle this case */ 2605 DEBUG_PRINT_ERROR("Failed to set format on capture port"); 2606 } 2607 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE)); 2608 framesize.nWidth = drv_ctx.video_resolution.frame_width; 2609 framesize.nHeight = drv_ctx.video_resolution.frame_height; 2610 2611 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE)); 2612 rectangle.nWidth = drv_ctx.video_resolution.frame_width; 2613 rectangle.nHeight = drv_ctx.video_resolution.frame_height; 2614 2615 DEBUG_PRINT_HIGH("Set Format was successful"); 2616 if (secure_mode) { 2617 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE; 2618 control.value = 1; 2619 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret); 2620 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 2621 if (ret) { 2622 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret); 2623 return OMX_ErrorInsufficientResources; 2624 } 2625 } 2626 if (output_capability == V4L2_PIX_FMT_H264_MVC) { 2627 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT; 2628 control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM; 2629 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2630 if (ret) { 2631 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout"); 2632 return OMX_ErrorInsufficientResources; 2633 } 2634 } 2635 2636 if (is_thulium_v1) { 2637 eRet = enable_smoothstreaming(); 2638 if (eRet != OMX_ErrorNone) { 2639 DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver"); 2640 return eRet; 2641 } 2642 } 2643 2644 /*Get the Buffer requirements for input and output ports*/ 2645 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; 2646 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 2647 2648 if (secure_mode) { 2649 drv_ctx.op_buf.alignment = SECURE_ALIGN; 2650 drv_ctx.ip_buf.alignment = SECURE_ALIGN; 2651 } else { 2652 drv_ctx.op_buf.alignment = SZ_4K; 2653 drv_ctx.ip_buf.alignment = SZ_4K; 2654 } 2655 2656 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 2657 drv_ctx.extradata = 0; 2658 drv_ctx.picture_order = VDEC_ORDER_DISPLAY; 2659 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 2660 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 2661 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2662 drv_ctx.idr_only_decoding = 0; 2663 2664 #ifdef _ANDROID_ 2665 property_get("vendor.vidc.dec.enable.downscalar",property_value,"0"); 2666 if (atoi(property_value)) { 2667 m_enable_downscalar = atoi(property_value); 2668 property_get("vendor.vidc.dec.downscalar_width",property_value,"0"); 2669 if (atoi(property_value)) { 2670 m_downscalar_width = atoi(property_value); 2671 } 2672 property_get("vendor.vidc.dec.downscalar_height",property_value,"0"); 2673 if (atoi(property_value)) { 2674 m_downscalar_height = atoi(property_value); 2675 } 2676 2677 if (m_downscalar_width < m_decoder_capability.min_width || 2678 m_downscalar_height < m_decoder_capability.min_height) { 2679 m_downscalar_width = 0; 2680 m_downscalar_height = 0; 2681 } 2682 2683 DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n", 2684 m_downscalar_width, m_downscalar_height); 2685 } 2686 property_get("vendor.vidc.disable.split.mode",property_value,"0"); 2687 m_disable_split_mode = atoi(property_value); 2688 DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled"); 2689 #endif 2690 m_state = OMX_StateLoaded; 2691 #ifdef DEFAULT_EXTRADATA 2692 enable_extradata(DEFAULT_EXTRADATA, true, true); 2693 #endif 2694 eRet = get_buffer_req(&drv_ctx.ip_buf); 2695 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size); 2696 get_buffer_req(&drv_ctx.op_buf); 2697 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 || 2698 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC || 2699 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) { 2700 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size; 2701 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size); 2702 h264_scratch.nFilledLen = 0; 2703 h264_scratch.nOffset = 0; 2704 2705 if (h264_scratch.pBuffer == NULL) { 2706 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed "); 2707 return OMX_ErrorInsufficientResources; 2708 } 2709 } 2710 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 || 2711 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) { 2712 if (m_frame_parser.mutils == NULL) { 2713 m_frame_parser.mutils = new H264_Utils(); 2714 if (m_frame_parser.mutils == NULL) { 2715 DEBUG_PRINT_ERROR("parser utils Allocation failed "); 2716 eRet = OMX_ErrorInsufficientResources; 2717 } else { 2718 m_frame_parser.mutils->initialize_frame_checking_environment(); 2719 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size); 2720 } 2721 } 2722 2723 h264_parser = new h264_stream_parser(); 2724 if (!h264_parser) { 2725 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!"); 2726 eRet = OMX_ErrorInsufficientResources; 2727 } 2728 } 2729 2730 if (pipe(fds)) { 2731 DEBUG_PRINT_ERROR("pipe creation failed"); 2732 eRet = OMX_ErrorInsufficientResources; 2733 } else { 2734 m_pipe_in = fds[0]; 2735 m_pipe_out = fds[1]; 2736 msg_thread_created = true; 2737 r = pthread_create(&msg_thread_id,0,message_thread_dec,this); 2738 2739 if (r < 0) { 2740 DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed"); 2741 msg_thread_created = false; 2742 eRet = OMX_ErrorInsufficientResources; 2743 } 2744 } 2745 } 2746 2747 { 2748 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore); 2749 init_vendor_extensions(*extStore); 2750 mVendorExtensionStore.dumpExtensions((const char *)role); 2751 } 2752 2753 if (eRet != OMX_ErrorNone) { 2754 DEBUG_PRINT_ERROR("Component Init Failed"); 2755 } else { 2756 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d", 2757 drv_ctx.video_driver_fd); 2758 } 2759 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); 2760 return eRet; 2761 } 2762 2763 /* ====================================================================== 2764 FUNCTION 2765 omx_vdec::GetComponentVersion 2766 2767 DESCRIPTION 2768 Returns the component version. 2769 2770 PARAMETERS 2771 TBD. 2772 2773 RETURN VALUE 2774 OMX_ErrorNone. 2775 2776 ========================================================================== */ 2777 OMX_ERRORTYPE omx_vdec::get_component_version 2778 ( 2779 OMX_IN OMX_HANDLETYPE hComp, 2780 OMX_OUT OMX_STRING componentName, 2781 OMX_OUT OMX_VERSIONTYPE* componentVersion, 2782 OMX_OUT OMX_VERSIONTYPE* specVersion, 2783 OMX_OUT OMX_UUIDTYPE* componentUUID 2784 ) 2785 { 2786 (void) hComp; 2787 (void) componentName; 2788 (void) componentVersion; 2789 (void) componentUUID; 2790 if (m_state == OMX_StateInvalid) { 2791 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State"); 2792 return OMX_ErrorInvalidState; 2793 } 2794 /* TBD -- Return the proper version */ 2795 if (specVersion) { 2796 specVersion->nVersion = OMX_SPEC_VERSION; 2797 } 2798 return OMX_ErrorNone; 2799 } 2800 /* ====================================================================== 2801 FUNCTION 2802 omx_vdec::SendCommand 2803 2804 DESCRIPTION 2805 Returns zero if all the buffers released.. 2806 2807 PARAMETERS 2808 None. 2809 2810 RETURN VALUE 2811 true/false 2812 2813 ========================================================================== */ 2814 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, 2815 OMX_IN OMX_COMMANDTYPE cmd, 2816 OMX_IN OMX_U32 param1, 2817 OMX_IN OMX_PTR cmdData 2818 ) 2819 { 2820 (void) hComp; 2821 (void) cmdData; 2822 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client"); 2823 if (m_state == OMX_StateInvalid) { 2824 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State"); 2825 return OMX_ErrorInvalidState; 2826 } 2827 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX 2828 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) { 2829 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush " 2830 "to invalid port: %u", (unsigned int)param1); 2831 return OMX_ErrorBadPortIndex; 2832 } 2833 2834 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); 2835 sem_wait(&m_cmd_lock); 2836 DEBUG_PRINT_LOW("send_command: Command Processed"); 2837 return OMX_ErrorNone; 2838 } 2839 2840 /* ====================================================================== 2841 FUNCTION 2842 omx_vdec::SendCommand 2843 2844 DESCRIPTION 2845 Returns zero if all the buffers released.. 2846 2847 PARAMETERS 2848 None. 2849 2850 RETURN VALUE 2851 true/false 2852 2853 ========================================================================== */ 2854 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, 2855 OMX_IN OMX_COMMANDTYPE cmd, 2856 OMX_IN OMX_U32 param1, 2857 OMX_IN OMX_PTR cmdData 2858 ) 2859 { 2860 (void) hComp; 2861 (void) cmdData; 2862 OMX_ERRORTYPE eRet = OMX_ErrorNone; 2863 OMX_STATETYPE eState = (OMX_STATETYPE) param1; 2864 int bFlag = 1,sem_posted = 0,ret=0; 2865 2866 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd); 2867 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d", 2868 m_state, eState); 2869 2870 if (cmd == OMX_CommandStateSet) { 2871 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued"); 2872 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState); 2873 /***************************/ 2874 /* Current State is Loaded */ 2875 /***************************/ 2876 if (m_state == OMX_StateLoaded) { 2877 if (eState == OMX_StateIdle) { 2878 //if all buffers are allocated or all ports disabled 2879 if (allocate_done() || 2880 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) { 2881 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle"); 2882 } else { 2883 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending"); 2884 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); 2885 // Skip the event notification 2886 bFlag = 0; 2887 } 2888 } 2889 /* Requesting transition from Loaded to Loaded */ 2890 else if (eState == OMX_StateLoaded) { 2891 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded"); 2892 post_event(OMX_EventError,OMX_ErrorSameState,\ 2893 OMX_COMPONENT_GENERATE_EVENT); 2894 eRet = OMX_ErrorSameState; 2895 } 2896 /* Requesting transition from Loaded to WaitForResources */ 2897 else if (eState == OMX_StateWaitForResources) { 2898 /* Since error is None , we will post an event 2899 at the end of this function definition */ 2900 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources"); 2901 } 2902 /* Requesting transition from Loaded to Executing */ 2903 else if (eState == OMX_StateExecuting) { 2904 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing"); 2905 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2906 OMX_COMPONENT_GENERATE_EVENT); 2907 eRet = OMX_ErrorIncorrectStateTransition; 2908 } 2909 /* Requesting transition from Loaded to Pause */ 2910 else if (eState == OMX_StatePause) { 2911 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause"); 2912 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2913 OMX_COMPONENT_GENERATE_EVENT); 2914 eRet = OMX_ErrorIncorrectStateTransition; 2915 } 2916 /* Requesting transition from Loaded to Invalid */ 2917 else if (eState == OMX_StateInvalid) { 2918 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid"); 2919 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2920 eRet = OMX_ErrorInvalidState; 2921 } else { 2922 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\ 2923 eState); 2924 eRet = OMX_ErrorBadParameter; 2925 } 2926 } 2927 2928 /***************************/ 2929 /* Current State is IDLE */ 2930 /***************************/ 2931 else if (m_state == OMX_StateIdle) { 2932 if (eState == OMX_StateLoaded) { 2933 if (release_done()) { 2934 /* 2935 * Since error is None , we will post an event at the end 2936 * of this function definition 2937 * Reset buffer requirements here to ensure setting buffer requirement 2938 * when component move to executing state from loaded state via Idle. 2939 */ 2940 drv_ctx.op_buf.buffer_size = 0; 2941 drv_ctx.op_buf.actualcount = 0; 2942 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded"); 2943 } else { 2944 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending"); 2945 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); 2946 // Skip the event notification 2947 bFlag = 0; 2948 } 2949 } 2950 /* Requesting transition from Idle to Executing */ 2951 else if (eState == OMX_StateExecuting) { 2952 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2953 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); 2954 bFlag = 1; 2955 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2956 m_state=OMX_StateExecuting; 2957 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful"); 2958 } 2959 /* Requesting transition from Idle to Idle */ 2960 else if (eState == OMX_StateIdle) { 2961 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle"); 2962 post_event(OMX_EventError,OMX_ErrorSameState,\ 2963 OMX_COMPONENT_GENERATE_EVENT); 2964 eRet = OMX_ErrorSameState; 2965 } 2966 /* Requesting transition from Idle to WaitForResources */ 2967 else if (eState == OMX_StateWaitForResources) { 2968 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources"); 2969 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2970 OMX_COMPONENT_GENERATE_EVENT); 2971 eRet = OMX_ErrorIncorrectStateTransition; 2972 } 2973 /* Requesting transition from Idle to Pause */ 2974 else if (eState == OMX_StatePause) { 2975 /*To pause the Video core we need to start the driver*/ 2976 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, 2977 NULL) < */0) { 2978 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED"); 2979 omx_report_error (); 2980 eRet = OMX_ErrorHardware; 2981 } else { 2982 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); 2983 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause"); 2984 bFlag = 0; 2985 } 2986 } 2987 /* Requesting transition from Idle to Invalid */ 2988 else if (eState == OMX_StateInvalid) { 2989 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid"); 2990 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2991 eRet = OMX_ErrorInvalidState; 2992 } else { 2993 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState); 2994 eRet = OMX_ErrorBadParameter; 2995 } 2996 } 2997 2998 /******************************/ 2999 /* Current State is Executing */ 3000 /******************************/ 3001 else if (m_state == OMX_StateExecuting) { 3002 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting"); 3003 /* Requesting transition from Executing to Idle */ 3004 if (eState == OMX_StateIdle) { 3005 /* Since error is None , we will post an event 3006 at the end of this function definition 3007 */ 3008 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle"); 3009 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 3010 if (!sem_posted) { 3011 sem_posted = 1; 3012 sem_post (&m_cmd_lock); 3013 execute_omx_flush(OMX_ALL); 3014 } 3015 bFlag = 0; 3016 } 3017 /* Requesting transition from Executing to Paused */ 3018 else if (eState == OMX_StatePause) { 3019 DEBUG_PRINT_LOW("PAUSE Command Issued"); 3020 m_state = OMX_StatePause; 3021 bFlag = 1; 3022 } 3023 /* Requesting transition from Executing to Loaded */ 3024 else if (eState == OMX_StateLoaded) { 3025 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded"); 3026 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3027 OMX_COMPONENT_GENERATE_EVENT); 3028 eRet = OMX_ErrorIncorrectStateTransition; 3029 } 3030 /* Requesting transition from Executing to WaitForResources */ 3031 else if (eState == OMX_StateWaitForResources) { 3032 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources"); 3033 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3034 OMX_COMPONENT_GENERATE_EVENT); 3035 eRet = OMX_ErrorIncorrectStateTransition; 3036 } 3037 /* Requesting transition from Executing to Executing */ 3038 else if (eState == OMX_StateExecuting) { 3039 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing"); 3040 post_event(OMX_EventError,OMX_ErrorSameState,\ 3041 OMX_COMPONENT_GENERATE_EVENT); 3042 eRet = OMX_ErrorSameState; 3043 } 3044 /* Requesting transition from Executing to Invalid */ 3045 else if (eState == OMX_StateInvalid) { 3046 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid"); 3047 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 3048 eRet = OMX_ErrorInvalidState; 3049 } else { 3050 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState); 3051 eRet = OMX_ErrorBadParameter; 3052 } 3053 } 3054 /***************************/ 3055 /* Current State is Pause */ 3056 /***************************/ 3057 else if (m_state == OMX_StatePause) { 3058 /* Requesting transition from Pause to Executing */ 3059 if (eState == OMX_StateExecuting) { 3060 DEBUG_PRINT_LOW("Pause --> Executing"); 3061 m_state = OMX_StateExecuting; 3062 bFlag = 1; 3063 } 3064 /* Requesting transition from Pause to Idle */ 3065 else if (eState == OMX_StateIdle) { 3066 /* Since error is None , we will post an event 3067 at the end of this function definition */ 3068 DEBUG_PRINT_LOW("Pause --> Idle"); 3069 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 3070 if (!sem_posted) { 3071 sem_posted = 1; 3072 sem_post (&m_cmd_lock); 3073 execute_omx_flush(OMX_ALL); 3074 } 3075 bFlag = 0; 3076 } 3077 /* Requesting transition from Pause to loaded */ 3078 else if (eState == OMX_StateLoaded) { 3079 DEBUG_PRINT_ERROR("Pause --> loaded"); 3080 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3081 OMX_COMPONENT_GENERATE_EVENT); 3082 eRet = OMX_ErrorIncorrectStateTransition; 3083 } 3084 /* Requesting transition from Pause to WaitForResources */ 3085 else if (eState == OMX_StateWaitForResources) { 3086 DEBUG_PRINT_ERROR("Pause --> WaitForResources"); 3087 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3088 OMX_COMPONENT_GENERATE_EVENT); 3089 eRet = OMX_ErrorIncorrectStateTransition; 3090 } 3091 /* Requesting transition from Pause to Pause */ 3092 else if (eState == OMX_StatePause) { 3093 DEBUG_PRINT_ERROR("Pause --> Pause"); 3094 post_event(OMX_EventError,OMX_ErrorSameState,\ 3095 OMX_COMPONENT_GENERATE_EVENT); 3096 eRet = OMX_ErrorSameState; 3097 } 3098 /* Requesting transition from Pause to Invalid */ 3099 else if (eState == OMX_StateInvalid) { 3100 DEBUG_PRINT_ERROR("Pause --> Invalid"); 3101 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 3102 eRet = OMX_ErrorInvalidState; 3103 } else { 3104 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState); 3105 eRet = OMX_ErrorBadParameter; 3106 } 3107 } 3108 /***************************/ 3109 /* Current State is WaitForResources */ 3110 /***************************/ 3111 else if (m_state == OMX_StateWaitForResources) { 3112 /* Requesting transition from WaitForResources to Loaded */ 3113 if (eState == OMX_StateLoaded) { 3114 /* Since error is None , we will post an event 3115 at the end of this function definition */ 3116 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded"); 3117 } 3118 /* Requesting transition from WaitForResources to WaitForResources */ 3119 else if (eState == OMX_StateWaitForResources) { 3120 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources"); 3121 post_event(OMX_EventError,OMX_ErrorSameState, 3122 OMX_COMPONENT_GENERATE_EVENT); 3123 eRet = OMX_ErrorSameState; 3124 } 3125 /* Requesting transition from WaitForResources to Executing */ 3126 else if (eState == OMX_StateExecuting) { 3127 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing"); 3128 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3129 OMX_COMPONENT_GENERATE_EVENT); 3130 eRet = OMX_ErrorIncorrectStateTransition; 3131 } 3132 /* Requesting transition from WaitForResources to Pause */ 3133 else if (eState == OMX_StatePause) { 3134 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause"); 3135 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 3136 OMX_COMPONENT_GENERATE_EVENT); 3137 eRet = OMX_ErrorIncorrectStateTransition; 3138 } 3139 /* Requesting transition from WaitForResources to Invalid */ 3140 else if (eState == OMX_StateInvalid) { 3141 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid"); 3142 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 3143 eRet = OMX_ErrorInvalidState; 3144 } 3145 /* Requesting transition from WaitForResources to Loaded - 3146 is NOT tested by Khronos TS */ 3147 3148 } else { 3149 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState); 3150 eRet = OMX_ErrorBadParameter; 3151 } 3152 } 3153 /********************************/ 3154 /* Current State is Invalid */ 3155 /*******************************/ 3156 else if (m_state == OMX_StateInvalid) { 3157 /* State Transition from Inavlid to any state */ 3158 if (eState == (OMX_StateLoaded || OMX_StateWaitForResources 3159 || OMX_StateIdle || OMX_StateExecuting 3160 || OMX_StatePause || OMX_StateInvalid)) { 3161 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded"); 3162 post_event(OMX_EventError,OMX_ErrorInvalidState,\ 3163 OMX_COMPONENT_GENERATE_EVENT); 3164 eRet = OMX_ErrorInvalidState; 3165 } 3166 } else if (cmd == OMX_CommandFlush) { 3167 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued" 3168 "with param1: %u", (unsigned int)param1); 3169 #ifdef _MSM8974_ 3170 send_codec_config(); 3171 #endif 3172 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX || 3173 param1 == OMX_ALL)) { 3174 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) { 3175 struct timespec ts; 3176 3177 clock_gettime(CLOCK_REALTIME, &ts); 3178 ts.tv_sec += 2; 3179 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ", 3180 m_queued_codec_config_count); 3181 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED); 3182 if (sem_timedwait(&m_safe_flush, &ts)) { 3183 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers"); 3184 } 3185 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED); 3186 } 3187 } 3188 3189 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) { 3190 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); 3191 } 3192 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) { 3193 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 3194 } 3195 if (!sem_posted) { 3196 sem_posted = 1; 3197 DEBUG_PRINT_LOW("Set the Semaphore"); 3198 sem_post (&m_cmd_lock); 3199 execute_omx_flush(param1); 3200 } 3201 bFlag = 0; 3202 } else if ( cmd == OMX_CommandPortEnable) { 3203 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued" 3204 "with param1: %u", (unsigned int)param1); 3205 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { 3206 m_inp_bEnabled = OMX_TRUE; 3207 3208 if ( (m_state == OMX_StateLoaded && 3209 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 3210 || allocate_input_done()) { 3211 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, 3212 OMX_COMPONENT_GENERATE_EVENT); 3213 } else { 3214 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 3215 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); 3216 // Skip the event notification 3217 bFlag = 0; 3218 } 3219 } 3220 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) { 3221 DEBUG_PRINT_LOW("Enable output Port command recieved"); 3222 m_out_bEnabled = OMX_TRUE; 3223 3224 if ( (m_state == OMX_StateLoaded && 3225 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 3226 || (allocate_output_done())) { 3227 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, 3228 OMX_COMPONENT_GENERATE_EVENT); 3229 3230 } else { 3231 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 3232 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 3233 // Skip the event notification 3234 bFlag = 0; 3235 /* enable/disable downscaling if required */ 3236 ret = decide_downscalar(); 3237 if (ret) { 3238 DEBUG_PRINT_LOW("decide_downscalar failed\n"); 3239 } 3240 } 3241 } 3242 } else if (cmd == OMX_CommandPortDisable) { 3243 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued" 3244 "with param1: %u", (unsigned int)param1); 3245 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { 3246 codec_config_flag = false; 3247 m_inp_bEnabled = OMX_FALSE; 3248 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 3249 && release_input_done()) { 3250 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, 3251 OMX_COMPONENT_GENERATE_EVENT); 3252 } else { 3253 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); 3254 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) { 3255 if (!sem_posted) { 3256 sem_posted = 1; 3257 sem_post (&m_cmd_lock); 3258 } 3259 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); 3260 } 3261 3262 // Skip the event notification 3263 bFlag = 0; 3264 } 3265 } 3266 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) { 3267 m_out_bEnabled = OMX_FALSE; 3268 DEBUG_PRINT_LOW("Disable output Port command recieved"); 3269 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 3270 && release_output_done()) { 3271 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ 3272 OMX_COMPONENT_GENERATE_EVENT); 3273 } else { 3274 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 3275 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) { 3276 if (!sem_posted) { 3277 sem_posted = 1; 3278 sem_post (&m_cmd_lock); 3279 } 3280 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 3281 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); 3282 } 3283 // Skip the event notification 3284 bFlag = 0; 3285 3286 } 3287 } 3288 } else { 3289 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd); 3290 eRet = OMX_ErrorNotImplemented; 3291 } 3292 if (eRet == OMX_ErrorNone && bFlag) { 3293 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); 3294 } 3295 if (!sem_posted) { 3296 sem_post(&m_cmd_lock); 3297 } 3298 3299 return eRet; 3300 } 3301 3302 /* ====================================================================== 3303 FUNCTION 3304 omx_vdec::ExecuteOmxFlush 3305 3306 DESCRIPTION 3307 Executes the OMX flush. 3308 3309 PARAMETERS 3310 flushtype - input flush(1)/output flush(0)/ both. 3311 3312 RETURN VALUE 3313 true/false 3314 3315 ========================================================================== */ 3316 bool omx_vdec::execute_omx_flush(OMX_U32 flushType) 3317 { 3318 bool bRet = false; 3319 struct v4l2_plane plane; 3320 struct v4l2_buffer v4l2_buf; 3321 struct v4l2_decoder_cmd dec; 3322 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType); 3323 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 3324 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH; 3325 3326 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig); 3327 3328 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) { 3329 output_flush_progress = true; 3330 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 3331 } else { 3332 /* XXX: The driver/hardware does not support flushing of individual ports 3333 * in all states. So we pretty much need to flush both ports internally, 3334 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it 3335 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set, 3336 * we automatically omit sending the FLUSH done for the "opposite" port. */ 3337 input_flush_progress = true; 3338 output_flush_progress = true; 3339 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 3340 request_perf_level(VIDC_TURBO); 3341 } 3342 3343 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { 3344 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType); 3345 bRet = false; 3346 } 3347 3348 return bRet; 3349 } 3350 /*========================================================================= 3351 FUNCTION : execute_output_flush 3352 3353 DESCRIPTION 3354 Executes the OMX flush at OUTPUT PORT. 3355 3356 PARAMETERS 3357 None. 3358 3359 RETURN VALUE 3360 true/false 3361 ==========================================================================*/ 3362 bool omx_vdec::execute_output_flush() 3363 { 3364 unsigned long p1 = 0; // Parameter - 1 3365 unsigned long p2 = 0; // Parameter - 2 3366 unsigned long ident = 0; 3367 bool bRet = true; 3368 3369 /*Generate FBD for all Buffers in the FTBq*/ 3370 pthread_mutex_lock(&m_lock); 3371 DEBUG_PRINT_LOW("Initiate Output Flush"); 3372 3373 //reset last render TS 3374 if(m_last_rendered_TS > 0) { 3375 m_last_rendered_TS = 0; 3376 } 3377 3378 while (m_ftb_q.m_size) { 3379 DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d", 3380 m_ftb_q.m_size,pending_output_buffers); 3381 m_ftb_q.pop_entry(&p1,&p2,&ident); 3382 DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2); 3383 if (ident == m_fill_output_msg ) { 3384 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2); 3385 } else if (ident == OMX_COMPONENT_GENERATE_FBD) { 3386 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1); 3387 } 3388 } 3389 pthread_mutex_unlock(&m_lock); 3390 output_flush_progress = false; 3391 3392 if (arbitrary_bytes) { 3393 prev_ts = LLONG_MAX; 3394 rst_prev_ts = true; 3395 } 3396 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); 3397 return bRet; 3398 } 3399 /*========================================================================= 3400 FUNCTION : execute_input_flush 3401 3402 DESCRIPTION 3403 Executes the OMX flush at INPUT PORT. 3404 3405 PARAMETERS 3406 None. 3407 3408 RETURN VALUE 3409 true/false 3410 ==========================================================================*/ 3411 bool omx_vdec::execute_input_flush() 3412 { 3413 unsigned i =0; 3414 unsigned long p1 = 0; // Parameter - 1 3415 unsigned long p2 = 0; // Parameter - 2 3416 unsigned long ident = 0; 3417 bool bRet = true; 3418 3419 /*Generate EBD for all Buffers in the ETBq*/ 3420 DEBUG_PRINT_LOW("Initiate Input Flush"); 3421 3422 pthread_mutex_lock(&m_lock); 3423 DEBUG_PRINT_LOW("Check if the Queue is empty"); 3424 while (m_etb_q.m_size) { 3425 m_etb_q.pop_entry(&p1,&p2,&ident); 3426 3427 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { 3428 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 3429 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 3430 } else if (ident == OMX_COMPONENT_GENERATE_ETB) { 3431 pending_input_buffers++; 3432 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers); 3433 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 3434 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 3435 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 3436 } else if (ident == OMX_COMPONENT_GENERATE_EBD) { 3437 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p", 3438 (OMX_BUFFERHEADERTYPE *)p1); 3439 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 3440 } 3441 } 3442 time_stamp_dts.flush_timestamp(); 3443 /*Check if Heap Buffers are to be flushed*/ 3444 if (arbitrary_bytes && !(codec_config_flag)) { 3445 DEBUG_PRINT_LOW("Reset all the variables before flusing"); 3446 h264_scratch.nFilledLen = 0; 3447 nal_count = 0; 3448 look_ahead_nal = false; 3449 frame_count = 0; 3450 h264_last_au_ts = LLONG_MAX; 3451 h264_last_au_flags = 0; 3452 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 3453 m_demux_entries = 0; 3454 DEBUG_PRINT_LOW("Initialize parser"); 3455 if (m_frame_parser.mutils) { 3456 m_frame_parser.mutils->initialize_frame_checking_environment(); 3457 } 3458 3459 while (m_input_pending_q.m_size) { 3460 m_input_pending_q.pop_entry(&p1,&p2,&ident); 3461 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); 3462 } 3463 3464 if (psource_frame) { 3465 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); 3466 psource_frame = NULL; 3467 } 3468 3469 if (pdest_frame) { 3470 pdest_frame->nFilledLen = 0; 3471 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL, 3472 (unsigned int)NULL); 3473 pdest_frame = NULL; 3474 } 3475 m_frame_parser.flush(); 3476 } else if (codec_config_flag) { 3477 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer " 3478 "is not sent to the driver yet"); 3479 } 3480 pthread_mutex_unlock(&m_lock); 3481 input_flush_progress = false; 3482 if (!arbitrary_bytes) { 3483 prev_ts = LLONG_MAX; 3484 rst_prev_ts = true; 3485 } 3486 #ifdef _ANDROID_ 3487 if (m_debug_timestamp) { 3488 m_timestamp_list.reset_ts_list(); 3489 } 3490 #endif 3491 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); 3492 return bRet; 3493 } 3494 3495 /*========================================================================= 3496 FUNCTION : notify_flush_done 3497 3498 DESCRIPTION 3499 Notifies flush done to the OMX Client. 3500 3501 PARAMETERS 3502 ctxt -- Context information related to the self.. 3503 3504 RETURN VALUE 3505 NONE 3506 ==========================================================================*/ 3507 void omx_vdec::notify_flush_done(void *ctxt) { 3508 3509 omx_vdec *pThis = (omx_vdec *) ctxt; 3510 3511 if (!pThis->input_flush_progress && !pThis->output_flush_progress) { 3512 if (BITMASK_PRESENT(&pThis->m_flags, 3513 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) { 3514 DEBUG_PRINT_LOW("Notify Output Flush done"); 3515 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 3516 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 3517 OMX_EventCmdComplete,OMX_CommandFlush, 3518 OMX_CORE_OUTPUT_PORT_INDEX,NULL ); 3519 } 3520 3521 if (BITMASK_PRESENT(&pThis->m_flags, 3522 OMX_COMPONENT_INPUT_FLUSH_PENDING)) { 3523 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); 3524 DEBUG_PRINT_LOW("Input Flush completed - Notify Client"); 3525 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 3526 OMX_EventCmdComplete,OMX_CommandFlush, 3527 OMX_CORE_INPUT_PORT_INDEX,NULL ); 3528 } 3529 } 3530 } 3531 3532 /* ====================================================================== 3533 FUNCTION 3534 omx_vdec::SendCommandEvent 3535 3536 DESCRIPTION 3537 Send the event to decoder pipe. This is needed to generate the callbacks 3538 in decoder thread context. 3539 3540 PARAMETERS 3541 None. 3542 3543 RETURN VALUE 3544 true/false 3545 3546 ========================================================================== */ 3547 bool omx_vdec::post_event(unsigned long p1, 3548 unsigned long p2, 3549 unsigned long id) 3550 { 3551 bool bRet = false; 3552 3553 /* Just drop messages typically generated by hardware (w/o client request), 3554 * if we've reported an error to client. */ 3555 if (m_error_propogated) { 3556 switch (id) { 3557 case OMX_COMPONENT_GENERATE_PORT_RECONFIG: 3558 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: 3559 DEBUG_PRINT_ERROR("Dropping message %lx " 3560 "since client expected to be in error state", id); 3561 return false; 3562 default: 3563 /* whatever */ 3564 break; 3565 } 3566 } 3567 3568 pthread_mutex_lock(&m_lock); 3569 3570 if (id == m_fill_output_msg || 3571 id == OMX_COMPONENT_GENERATE_FBD || 3572 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG || 3573 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) { 3574 m_ftb_q.insert_entry(p1,p2,id); 3575 } else if (id == OMX_COMPONENT_GENERATE_ETB || 3576 id == OMX_COMPONENT_GENERATE_EBD || 3577 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY || 3578 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) { 3579 m_etb_q.insert_entry(p1,p2,id); 3580 } else { 3581 m_cmd_q.insert_entry(p1,p2,id); 3582 } 3583 3584 bRet = true; 3585 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this); 3586 post_message(this, id); 3587 3588 pthread_mutex_unlock(&m_lock); 3589 3590 return bRet; 3591 } 3592 3593 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) 3594 { 3595 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3596 if (!profileLevelType) 3597 return OMX_ErrorBadParameter; 3598 3599 if (profileLevelType->nPortIndex == 0) { 3600 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 3601 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; 3602 if (profileLevelType->nProfileIndex == 0) { 3603 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; 3604 } else if (profileLevelType->nProfileIndex == 1) { 3605 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; 3606 } else if (profileLevelType->nProfileIndex == 2) { 3607 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; 3608 } else if (profileLevelType->nProfileIndex == 3) { 3609 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline; 3610 } else if (profileLevelType->nProfileIndex == 4) { 3611 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline; 3612 } else if (profileLevelType->nProfileIndex == 5) { 3613 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedHigh; 3614 } else if (profileLevelType->nProfileIndex == 6) { 3615 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh; 3616 } else { 3617 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3618 (unsigned int)profileLevelType->nProfileIndex); 3619 eRet = OMX_ErrorNoMore; 3620 } 3621 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 3622 if (profileLevelType->nProfileIndex == 0) { 3623 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh; 3624 profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51; 3625 } else { 3626 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3627 (unsigned int)profileLevelType->nProfileIndex); 3628 eRet = OMX_ErrorNoMore; 3629 } 3630 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 3631 if (profileLevelType->nProfileIndex == 0) { 3632 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; 3633 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; 3634 } else if (profileLevelType->nProfileIndex == 1) { 3635 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; 3636 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; 3637 } else if (profileLevelType->nProfileIndex == 2) { 3638 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10; 3639 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; 3640 } else { 3641 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3642 (unsigned int)profileLevelType->nProfileIndex); 3643 eRet = OMX_ErrorNoMore; 3644 } 3645 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) { 3646 if (profileLevelType->nProfileIndex == 0) { 3647 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; 3648 profileLevelType->eLevel = OMX_VIDEO_H263Level70; 3649 } else { 3650 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3651 (unsigned int)profileLevelType->nProfileIndex); 3652 eRet = OMX_ErrorNoMore; 3653 } 3654 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 3655 if (profileLevelType->nProfileIndex == 0) { 3656 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; 3657 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; 3658 } else if (profileLevelType->nProfileIndex == 1) { 3659 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; 3660 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; 3661 } else { 3662 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3663 (unsigned int)profileLevelType->nProfileIndex); 3664 eRet = OMX_ErrorNoMore; 3665 } 3666 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) || 3667 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) { 3668 eRet = OMX_ErrorNoMore; 3669 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 3670 if (profileLevelType->nProfileIndex == 0) { 3671 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; 3672 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; 3673 } else if (profileLevelType->nProfileIndex == 1) { 3674 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; 3675 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; 3676 } else { 3677 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3678 (unsigned int)profileLevelType->nProfileIndex); 3679 eRet = OMX_ErrorNoMore; 3680 } 3681 } else { 3682 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind); 3683 eRet = OMX_ErrorNoMore; 3684 } 3685 } else { 3686 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u", 3687 (unsigned int)profileLevelType->nPortIndex); 3688 eRet = OMX_ErrorBadPortIndex; 3689 } 3690 return eRet; 3691 } 3692 3693 /* ====================================================================== 3694 FUNCTION 3695 omx_vdec::GetParameter 3696 3697 DESCRIPTION 3698 OMX Get Parameter method implementation 3699 3700 PARAMETERS 3701 <TBD>. 3702 3703 RETURN VALUE 3704 Error None if successful. 3705 3706 ========================================================================== */ 3707 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, 3708 OMX_IN OMX_INDEXTYPE paramIndex, 3709 OMX_INOUT OMX_PTR paramData) 3710 { 3711 (void) hComp; 3712 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3713 3714 DEBUG_PRINT_LOW("get_parameter:"); 3715 if (m_state == OMX_StateInvalid) { 3716 DEBUG_PRINT_ERROR("Get Param in Invalid State"); 3717 return OMX_ErrorInvalidState; 3718 } 3719 if (paramData == NULL) { 3720 DEBUG_PRINT_LOW("Get Param in Invalid paramData"); 3721 return OMX_ErrorBadParameter; 3722 } 3723 switch ((unsigned long)paramIndex) { 3724 case OMX_IndexParamPortDefinition: { 3725 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); 3726 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = 3727 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3728 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); 3729 decide_dpb_buffer_mode(is_down_scalar_enabled); 3730 eRet = update_portdef(portDefn); 3731 if (eRet == OMX_ErrorNone) 3732 m_port_def = *portDefn; 3733 break; 3734 } 3735 case OMX_IndexParamVideoInit: { 3736 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3737 OMX_PORT_PARAM_TYPE *portParamType = 3738 (OMX_PORT_PARAM_TYPE *) paramData; 3739 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); 3740 3741 portParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3742 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3743 portParamType->nPorts = 2; 3744 portParamType->nStartPortNumber = 0; 3745 break; 3746 } 3747 case OMX_IndexParamVideoPortFormat: { 3748 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); 3749 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3750 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3751 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); 3752 3753 portFmt->nVersion.nVersion = OMX_SPEC_VERSION; 3754 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 3755 3756 if (0 == portFmt->nPortIndex) { 3757 if (0 == portFmt->nIndex) { 3758 portFmt->eColorFormat = OMX_COLOR_FormatUnused; 3759 portFmt->eCompressionFormat = eCompressionFormat; 3760 } else { 3761 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3762 " NoMore compression formats"); 3763 eRet = OMX_ErrorNoMore; 3764 } 3765 } else if (1 == portFmt->nPortIndex) { 3766 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; 3767 3768 // Distinguish non-surface mode from normal playback use-case based on 3769 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2" 3770 // For non-android, use the default list 3771 // Also use default format-list if FLEXIBLE YUV is supported, 3772 // as the client negotiates the standard color-format if it needs to 3773 bool useNonSurfaceMode = false; 3774 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) 3775 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE); 3776 #endif 3777 if (is_thulium_v1) { 3778 portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex); 3779 } else { 3780 portFmt->eColorFormat = useNonSurfaceMode ? 3781 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) : 3782 getPreferredColorFormatDefaultMode(portFmt->nIndex); 3783 } 3784 3785 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) { 3786 eRet = OMX_ErrorNoMore; 3787 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3788 " NoMore Color formats"); 3789 } 3790 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat); 3791 } else { 3792 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d", 3793 (int)portFmt->nPortIndex); 3794 eRet = OMX_ErrorBadPortIndex; 3795 } 3796 break; 3797 } 3798 /*Component should support this port definition*/ 3799 case OMX_IndexParamAudioInit: { 3800 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3801 OMX_PORT_PARAM_TYPE *audioPortParamType = 3802 (OMX_PORT_PARAM_TYPE *) paramData; 3803 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); 3804 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3805 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3806 audioPortParamType->nPorts = 0; 3807 audioPortParamType->nStartPortNumber = 0; 3808 break; 3809 } 3810 /*Component should support this port definition*/ 3811 case OMX_IndexParamImageInit: { 3812 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3813 OMX_PORT_PARAM_TYPE *imagePortParamType = 3814 (OMX_PORT_PARAM_TYPE *) paramData; 3815 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); 3816 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3817 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3818 imagePortParamType->nPorts = 0; 3819 imagePortParamType->nStartPortNumber = 0; 3820 break; 3821 3822 } 3823 /*Component should support this port definition*/ 3824 case OMX_IndexParamOtherInit: { 3825 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x", 3826 paramIndex); 3827 eRet =OMX_ErrorUnsupportedIndex; 3828 break; 3829 } 3830 case OMX_IndexParamStandardComponentRole: { 3831 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); 3832 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3833 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3834 comp_role->nVersion.nVersion = OMX_SPEC_VERSION; 3835 comp_role->nSize = sizeof(*comp_role); 3836 3837 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d", 3838 paramIndex); 3839 strlcpy((char*)comp_role->cRole,(const char*)m_cRole, 3840 OMX_MAX_STRINGNAME_SIZE); 3841 break; 3842 } 3843 /* Added for parameter test */ 3844 case OMX_IndexParamPriorityMgmt: { 3845 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); 3846 OMX_PRIORITYMGMTTYPE *priorityMgmType = 3847 (OMX_PRIORITYMGMTTYPE *) paramData; 3848 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); 3849 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; 3850 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE); 3851 3852 break; 3853 } 3854 /* Added for parameter test */ 3855 case OMX_IndexParamCompBufferSupplier: { 3856 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); 3857 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = 3858 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3859 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); 3860 3861 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE); 3862 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; 3863 if (0 == bufferSupplierType->nPortIndex) 3864 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3865 else if (1 == bufferSupplierType->nPortIndex) 3866 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3867 else 3868 eRet = OMX_ErrorBadPortIndex; 3869 3870 3871 break; 3872 } 3873 case OMX_IndexParamVideoAvc: { 3874 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x", 3875 paramIndex); 3876 break; 3877 } 3878 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 3879 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x", 3880 paramIndex); 3881 break; 3882 } 3883 case OMX_IndexParamVideoH263: { 3884 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x", 3885 paramIndex); 3886 break; 3887 } 3888 case OMX_IndexParamVideoMpeg4: { 3889 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x", 3890 paramIndex); 3891 break; 3892 } 3893 case OMX_IndexParamVideoMpeg2: { 3894 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x", 3895 paramIndex); 3896 break; 3897 } 3898 case OMX_IndexParamVideoProfileLevelQuerySupported: { 3899 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 3900 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex); 3901 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = 3902 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; 3903 eRet = get_supported_profile_level(profileLevelType); 3904 break; 3905 } 3906 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3907 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: { 3908 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams); 3909 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); 3910 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; 3911 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3912 3913 if (secure_mode && !secure_scaling_to_non_secure_opb) { 3914 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | 3915 GRALLOC_USAGE_PRIVATE_UNCACHED); 3916 } else { 3917 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED; 3918 } 3919 } else { 3920 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!"); 3921 eRet = OMX_ErrorBadParameter; 3922 } 3923 } 3924 break; 3925 #endif 3926 3927 #ifdef FLEXYUV_SUPPORTED 3928 case OMX_QcomIndexFlexibleYUVDescription: { 3929 DEBUG_PRINT_LOW("get_parameter: describeColorFormat"); 3930 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams); 3931 eRet = describeColorFormat(paramData); 3932 break; 3933 } 3934 #endif 3935 case OMX_IndexParamVideoProfileLevelCurrent: { 3936 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 3937 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; 3938 struct v4l2_control profile_control, level_control; 3939 3940 switch (drv_ctx.decoder_format) { 3941 case VDEC_CODECTYPE_H264: 3942 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; 3943 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; 3944 break; 3945 default: 3946 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264"); 3947 eRet = OMX_ErrorNotImplemented; 3948 break; 3949 } 3950 3951 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) { 3952 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) { 3953 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: 3954 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: 3955 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline; 3956 break; 3957 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: 3958 pParam->eProfile = OMX_VIDEO_AVCProfileMain; 3959 break; 3960 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: 3961 pParam->eProfile = OMX_VIDEO_AVCProfileExtended; 3962 break; 3963 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: 3964 pParam->eProfile = OMX_VIDEO_AVCProfileHigh; 3965 break; 3966 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10: 3967 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10; 3968 break; 3969 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422: 3970 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422; 3971 break; 3972 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: 3973 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA: 3974 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA: 3975 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA: 3976 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA: 3977 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE: 3978 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH: 3979 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA: 3980 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH: 3981 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH: 3982 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH: 3983 eRet = OMX_ErrorUnsupportedIndex; 3984 break; 3985 } 3986 } else { 3987 eRet = OMX_ErrorUnsupportedIndex; 3988 } 3989 3990 3991 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) { 3992 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) { 3993 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: 3994 pParam->eLevel = OMX_VIDEO_AVCLevel1; 3995 break; 3996 case V4L2_MPEG_VIDEO_H264_LEVEL_1B: 3997 pParam->eLevel = OMX_VIDEO_AVCLevel1b; 3998 break; 3999 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: 4000 pParam->eLevel = OMX_VIDEO_AVCLevel11; 4001 break; 4002 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: 4003 pParam->eLevel = OMX_VIDEO_AVCLevel12; 4004 break; 4005 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: 4006 pParam->eLevel = OMX_VIDEO_AVCLevel13; 4007 break; 4008 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: 4009 pParam->eLevel = OMX_VIDEO_AVCLevel2; 4010 break; 4011 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: 4012 pParam->eLevel = OMX_VIDEO_AVCLevel21; 4013 break; 4014 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: 4015 pParam->eLevel = OMX_VIDEO_AVCLevel22; 4016 break; 4017 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: 4018 pParam->eLevel = OMX_VIDEO_AVCLevel3; 4019 break; 4020 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: 4021 pParam->eLevel = OMX_VIDEO_AVCLevel31; 4022 break; 4023 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: 4024 pParam->eLevel = OMX_VIDEO_AVCLevel32; 4025 break; 4026 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: 4027 pParam->eLevel = OMX_VIDEO_AVCLevel4; 4028 break; 4029 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: 4030 pParam->eLevel = OMX_VIDEO_AVCLevel41; 4031 break; 4032 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: 4033 pParam->eLevel = OMX_VIDEO_AVCLevel42; 4034 break; 4035 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: 4036 pParam->eLevel = OMX_VIDEO_AVCLevel5; 4037 break; 4038 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: 4039 pParam->eLevel = OMX_VIDEO_AVCLevel51; 4040 break; 4041 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2: 4042 pParam->eLevel = OMX_VIDEO_AVCLevel52; 4043 break; 4044 } 4045 } else { 4046 eRet = OMX_ErrorUnsupportedIndex; 4047 } 4048 4049 break; 4050 4051 } 4052 case OMX_QTIIndexParamVideoClientExtradata: 4053 { 4054 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE); 4055 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata"); 4056 QOMX_EXTRADATA_ENABLE *pParam = 4057 (QOMX_EXTRADATA_ENABLE *)paramData; 4058 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) { 4059 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE; 4060 eRet = OMX_ErrorNone; 4061 } else { 4062 eRet = OMX_ErrorUnsupportedIndex; 4063 } 4064 break; 4065 } 4066 case OMX_QTIIndexParamDitherControl: 4067 { 4068 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL); 4069 DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL"); 4070 QOMX_VIDEO_DITHER_CONTROL *pParam = 4071 (QOMX_VIDEO_DITHER_CONTROL *) paramData; 4072 pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config; 4073 eRet = OMX_ErrorNone; 4074 break; 4075 } 4076 default: { 4077 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex); 4078 eRet =OMX_ErrorUnsupportedIndex; 4079 } 4080 4081 } 4082 4083 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)", 4084 drv_ctx.video_resolution.frame_width, 4085 drv_ctx.video_resolution.frame_height, 4086 drv_ctx.video_resolution.stride, 4087 drv_ctx.video_resolution.scan_lines); 4088 4089 return eRet; 4090 } 4091 4092 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 4093 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) 4094 { 4095 DEBUG_PRINT_LOW("Inside use_android_native_buffer"); 4096 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4097 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; 4098 4099 if ((params == NULL) || 4100 (params->nativeBuffer == NULL) || 4101 (params->nativeBuffer->handle == NULL) || 4102 !m_enable_android_native_buffers) 4103 return OMX_ErrorBadParameter; 4104 m_use_android_native_buffers = OMX_TRUE; 4105 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 4106 private_handle_t *handle = (private_handle_t *)nBuf->handle; 4107 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port 4108 OMX_U8 *buffer = NULL; 4109 if (!secure_mode) { 4110 buffer = (OMX_U8*)mmap(0, handle->size, 4111 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 4112 if (buffer == MAP_FAILED) { 4113 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 4114 return OMX_ErrorInsufficientResources; 4115 } 4116 } 4117 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); 4118 } else { 4119 eRet = OMX_ErrorBadParameter; 4120 } 4121 return eRet; 4122 } 4123 #endif 4124 4125 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() { 4126 struct v4l2_control control; 4127 struct v4l2_format fmt; 4128 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER; 4129 control.value = 1; 4130 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 4131 if (rc < 0) { 4132 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); 4133 return OMX_ErrorHardware; 4134 } 4135 m_smoothstreaming_mode = true; 4136 return OMX_ErrorNone; 4137 } 4138 4139 /* ====================================================================== 4140 FUNCTION 4141 omx_vdec::Setparameter 4142 4143 DESCRIPTION 4144 OMX Set Parameter method implementation. 4145 4146 PARAMETERS 4147 <TBD>. 4148 4149 RETURN VALUE 4150 OMX Error None if successful. 4151 4152 ========================================================================== */ 4153 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, 4154 OMX_IN OMX_INDEXTYPE paramIndex, 4155 OMX_IN OMX_PTR paramData) 4156 { 4157 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4158 int ret=0; 4159 struct v4l2_format fmt; 4160 #ifdef _ANDROID_ 4161 char property_value[PROPERTY_VALUE_MAX] = {0}; 4162 #endif 4163 if (m_state == OMX_StateInvalid) { 4164 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 4165 return OMX_ErrorInvalidState; 4166 } 4167 if (paramData == NULL) { 4168 DEBUG_PRINT_ERROR("Get Param in Invalid paramData"); 4169 return OMX_ErrorBadParameter; 4170 } 4171 if ((m_state != OMX_StateLoaded) && 4172 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && 4173 (m_out_bEnabled == OMX_TRUE) && 4174 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && 4175 (m_inp_bEnabled == OMX_TRUE)) { 4176 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 4177 return OMX_ErrorIncorrectStateOperation; 4178 } 4179 switch ((unsigned long)paramIndex) { 4180 case OMX_IndexParamPortDefinition: { 4181 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); 4182 OMX_PARAM_PORTDEFINITIONTYPE *portDefn; 4183 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 4184 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has 4185 //been called. 4186 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", 4187 (int)portDefn->format.video.nFrameHeight, 4188 (int)portDefn->format.video.nFrameWidth); 4189 4190 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 4191 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d", 4192 portDefn->nBufferCountActual); 4193 eRet = OMX_ErrorBadParameter; 4194 break; 4195 } 4196 if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) { 4197 if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS || 4198 portDefn->nBufferSize != m_client_out_extradata_info.getSize()) { 4199 DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d", 4200 portDefn->nBufferCountActual, portDefn->nBufferSize); 4201 eRet = OMX_ErrorBadParameter; 4202 break; 4203 } 4204 m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize, 4205 portDefn->nBufferCountActual); 4206 break; 4207 } 4208 4209 if (OMX_DirOutput == portDefn->eDir) { 4210 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); 4211 bool port_format_changed = false; 4212 m_display_id = portDefn->format.video.pNativeWindow; 4213 unsigned int buffer_size; 4214 /* update output port resolution with client supplied dimensions 4215 in case scaling is enabled, else it follows input resolution set 4216 */ 4217 decide_dpb_buffer_mode(is_down_scalar_enabled); 4218 if (is_down_scalar_enabled) { 4219 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)", 4220 (unsigned int)portDefn->format.video.nFrameWidth, 4221 (unsigned int)portDefn->format.video.nFrameHeight); 4222 if (portDefn->format.video.nFrameHeight != 0x0 && 4223 portDefn->format.video.nFrameWidth != 0x0) { 4224 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4225 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4226 fmt.fmt.pix_mp.pixelformat = capture_capability; 4227 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 4228 if (ret) { 4229 DEBUG_PRINT_ERROR("Get Resolution failed"); 4230 eRet = OMX_ErrorHardware; 4231 break; 4232 } 4233 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) || 4234 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) { 4235 port_format_changed = true; 4236 } 4237 4238 /* set crop info */ 4239 rectangle.nLeft = 0; 4240 rectangle.nTop = 0; 4241 rectangle.nWidth = portDefn->format.video.nFrameWidth; 4242 rectangle.nHeight = portDefn->format.video.nFrameHeight; 4243 4244 m_extradata_info.output_crop_rect.nLeft = 0; 4245 m_extradata_info.output_crop_rect.nTop = 0; 4246 m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth; 4247 m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight; 4248 4249 eRet = is_video_session_supported(); 4250 if (eRet) 4251 break; 4252 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4253 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4254 fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight; 4255 fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth; 4256 fmt.fmt.pix_mp.pixelformat = capture_capability; 4257 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", 4258 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width); 4259 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4260 if (ret) { 4261 DEBUG_PRINT_ERROR("Set Resolution failed"); 4262 eRet = OMX_ErrorUnsupportedSetting; 4263 } else 4264 eRet = get_buffer_req(&drv_ctx.op_buf); 4265 } 4266 4267 if (eRet) { 4268 break; 4269 } 4270 4271 if (secure_mode) { 4272 struct v4l2_control control; 4273 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD; 4274 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 4275 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id); 4276 eRet = OMX_ErrorHardware; 4277 } else { 4278 /* This is a workaround for a bug in fw which uses stride 4279 * and slice instead of width and height to check against 4280 * the threshold. 4281 */ 4282 OMX_U32 stride, slice; 4283 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 4284 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth); 4285 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight); 4286 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 4287 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth); 4288 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight); 4289 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) { 4290 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameWidth); 4291 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameHeight); 4292 } else { 4293 stride = portDefn->format.video.nFrameWidth; 4294 slice = portDefn->format.video.nFrameHeight; 4295 } 4296 4297 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice); 4298 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value); 4299 4300 if (stride * slice <= (OMX_U32)control.value) { 4301 secure_scaling_to_non_secure_opb = true; 4302 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ"); 4303 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2; 4304 control.value = 1; 4305 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) { 4306 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed"); 4307 eRet = OMX_ErrorUnsupportedSetting; 4308 } 4309 } 4310 } 4311 } 4312 } 4313 4314 if (eRet) { 4315 break; 4316 } 4317 4318 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 4319 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)", 4320 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); 4321 eRet = OMX_ErrorBadParameter; 4322 } else if (!client_buffers.get_buffer_req(buffer_size)) { 4323 DEBUG_PRINT_ERROR("Error in getting buffer requirements"); 4324 eRet = OMX_ErrorBadParameter; 4325 } else if (!port_format_changed) { 4326 4327 // Buffer count can change only when port is unallocated 4328 if (m_out_mem_ptr && 4329 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount || 4330 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) { 4331 4332 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !"); 4333 eRet = OMX_ErrorInvalidState; 4334 break; 4335 } 4336 4337 // route updating of buffer requirements via c2d proxy. 4338 // Based on whether c2d is enabled, requirements will be handed 4339 // to the vidc driver appropriately 4340 eRet = client_buffers.set_buffer_req(portDefn->nBufferSize, 4341 portDefn->nBufferCountActual); 4342 if (eRet == OMX_ErrorNone) { 4343 m_port_def = *portDefn; 4344 } else { 4345 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)", 4346 drv_ctx.op_buf.mincount, (unsigned int)buffer_size, 4347 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 4348 eRet = OMX_ErrorBadParameter; 4349 } 4350 } 4351 } else if (OMX_DirInput == portDefn->eDir) { 4352 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port"); 4353 bool port_format_changed = false; 4354 if ((portDefn->format.video.xFramerate >> 16) > 0 && 4355 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) { 4356 // Frame rate only should be set if this is a "known value" or to 4357 // activate ts prediction logic (arbitrary mode only) sending input 4358 // timestamps with max value (LLONG_MAX). 4359 m_fps_received = portDefn->format.video.xFramerate; 4360 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u", 4361 (unsigned int)portDefn->format.video.xFramerate >> 16); 4362 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, 4363 drv_ctx.frame_rate.fps_denominator); 4364 if (!drv_ctx.frame_rate.fps_numerator) { 4365 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 4366 drv_ctx.frame_rate.fps_numerator = 30; 4367 } 4368 if (drv_ctx.frame_rate.fps_denominator) 4369 drv_ctx.frame_rate.fps_numerator = (int) 4370 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 4371 drv_ctx.frame_rate.fps_denominator = 1; 4372 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 4373 drv_ctx.frame_rate.fps_numerator; 4374 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", 4375 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 4376 (float)drv_ctx.frame_rate.fps_denominator); 4377 4378 struct v4l2_outputparm oparm; 4379 /*XXX: we're providing timing info as seconds per frame rather than frames 4380 * per second.*/ 4381 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 4382 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 4383 4384 struct v4l2_streamparm sparm; 4385 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4386 sparm.parm.output = oparm; 4387 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 4388 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected"); 4389 eRet = OMX_ErrorHardware; 4390 break; 4391 } 4392 m_perf_control.request_cores(frm_int); 4393 } 4394 4395 if (drv_ctx.video_resolution.frame_height != 4396 portDefn->format.video.nFrameHeight || 4397 drv_ctx.video_resolution.frame_width != 4398 portDefn->format.video.nFrameWidth) { 4399 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)", 4400 (unsigned int)portDefn->format.video.nFrameWidth, 4401 (unsigned int)portDefn->format.video.nFrameHeight); 4402 port_format_changed = true; 4403 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth; 4404 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight; 4405 if (frameHeight != 0x0 && frameWidth != 0x0) { 4406 if (m_smoothstreaming_mode && 4407 ((frameWidth * frameHeight) < 4408 (m_smoothstreaming_width * m_smoothstreaming_height))) { 4409 frameWidth = m_smoothstreaming_width; 4410 frameHeight = m_smoothstreaming_height; 4411 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u " 4412 "for adaptive-playback/smooth-streaming", 4413 (unsigned int)frameWidth, (unsigned int)frameHeight); 4414 } 4415 4416 m_extradata_info.output_crop_rect.nLeft = 0; 4417 m_extradata_info.output_crop_rect.nTop = 0; 4418 m_extradata_info.output_crop_rect.nWidth = frameWidth; 4419 m_extradata_info.output_crop_rect.nHeight = frameHeight; 4420 4421 update_resolution(frameWidth, frameHeight, 4422 frameWidth, frameHeight); 4423 eRet = is_video_session_supported(); 4424 if (eRet) 4425 break; 4426 if (is_down_scalar_enabled) { 4427 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4428 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4429 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 4430 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 4431 fmt.fmt.pix_mp.pixelformat = output_capability; 4432 DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d", 4433 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); 4434 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4435 } else { 4436 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4437 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4438 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 4439 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 4440 fmt.fmt.pix_mp.pixelformat = output_capability; 4441 DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d", 4442 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); 4443 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4444 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4445 fmt.fmt.pix_mp.pixelformat = capture_capability; 4446 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4447 } 4448 if (ret) { 4449 DEBUG_PRINT_ERROR("Set Resolution failed"); 4450 eRet = OMX_ErrorUnsupportedSetting; 4451 } else { 4452 if (!is_down_scalar_enabled) 4453 eRet = get_buffer_req(&drv_ctx.op_buf); 4454 } 4455 } 4456 } 4457 if (m_custom_buffersize.input_buffersize 4458 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) { 4459 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d", 4460 m_custom_buffersize.input_buffersize, portDefn->nBufferSize); 4461 eRet = OMX_ErrorBadParameter; 4462 break; 4463 } 4464 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 4465 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)", 4466 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); 4467 eRet = OMX_ErrorBadParameter; 4468 break; 4469 } 4470 // Buffer count can change only when port is unallocated 4471 if (m_inp_mem_ptr && 4472 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount || 4473 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) { 4474 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !"); 4475 eRet = OMX_ErrorInvalidState; 4476 break; 4477 } 4478 4479 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount 4480 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) { 4481 port_format_changed = true; 4482 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf; 4483 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; 4484 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) & 4485 (~(buffer_prop->alignment - 1)); 4486 eRet = set_buffer_req(buffer_prop); 4487 } 4488 if (false == port_format_changed) { 4489 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)", 4490 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size, 4491 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 4492 eRet = OMX_ErrorBadParameter; 4493 } 4494 } else if (portDefn->eDir == OMX_DirMax) { 4495 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", 4496 (int)portDefn->nPortIndex); 4497 eRet = OMX_ErrorBadPortIndex; 4498 } 4499 } 4500 break; 4501 case OMX_IndexParamVideoPortFormat: { 4502 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); 4503 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 4504 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 4505 int ret=0; 4506 struct v4l2_format fmt; 4507 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u", 4508 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex); 4509 4510 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4511 if (1 == portFmt->nPortIndex) { 4512 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4513 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 4514 if (ret < 0) { 4515 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__); 4516 return OMX_ErrorBadParameter; 4517 } 4518 enum vdec_output_fromat op_format; 4519 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4520 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m || 4521 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4522 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView || 4523 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar || 4524 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 4525 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12; 4526 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4527 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 4528 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC; 4529 } else 4530 eRet = OMX_ErrorBadParameter; 4531 4532 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4533 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 4534 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC; 4535 } else { 4536 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12; 4537 } 4538 4539 if (eRet == OMX_ErrorNone) { 4540 drv_ctx.output_format = op_format; 4541 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4542 if (ret) { 4543 DEBUG_PRINT_ERROR("Set output format failed"); 4544 eRet = OMX_ErrorUnsupportedSetting; 4545 /*TODO: How to handle this case */ 4546 } else { 4547 eRet = get_buffer_req(&drv_ctx.op_buf); 4548 } 4549 } 4550 if (eRet == OMX_ErrorNone) { 4551 if (!client_buffers.set_color_format(portFmt->eColorFormat)) { 4552 DEBUG_PRINT_ERROR("Set color format failed"); 4553 eRet = OMX_ErrorBadParameter; 4554 } 4555 } 4556 } 4557 } 4558 break; 4559 4560 case OMX_QcomIndexPortDefn: { 4561 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE); 4562 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = 4563 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; 4564 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u", 4565 (unsigned int)portFmt->nFramePackingFormat); 4566 4567 /* Input port */ 4568 if (portFmt->nPortIndex == 0) { 4569 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how: 4570 // - headers are allocated and 4571 // - headers-indices are derived 4572 // Avoid changing arbitrary_bytes when the port is already allocated 4573 if (m_inp_mem_ptr) { 4574 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!"); 4575 return OMX_ErrorUnsupportedSetting; 4576 } 4577 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) { 4578 if (secure_mode || m_input_pass_buffer_fd) { 4579 arbitrary_bytes = false; 4580 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode"); 4581 eRet = OMX_ErrorUnsupportedSetting; 4582 } else { 4583 arbitrary_bytes = true; 4584 } 4585 } else if (portFmt->nFramePackingFormat == 4586 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) { 4587 arbitrary_bytes = false; 4588 #ifdef _ANDROID_ 4589 property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); 4590 if (atoi(property_value)) { 4591 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command"); 4592 arbitrary_bytes = true; 4593 } 4594 #endif 4595 } else { 4596 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u", 4597 (unsigned int)portFmt->nFramePackingFormat); 4598 eRet = OMX_ErrorUnsupportedSetting; 4599 } 4600 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 4601 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port"); 4602 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && 4603 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && 4604 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) { 4605 m_out_mem_region_smi = OMX_TRUE; 4606 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 4607 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set"); 4608 m_use_output_pmem = OMX_TRUE; 4609 } 4610 } 4611 } 4612 } 4613 if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", 4614 OMX_MAX_STRINGNAME_SIZE)) { 4615 arbitrary_bytes = true; 4616 DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264"); 4617 } 4618 break; 4619 4620 case OMX_QTIIndexParamVideoClientExtradata: { 4621 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE); 4622 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata"); 4623 QOMX_EXTRADATA_ENABLE *pParam = 4624 (QOMX_EXTRADATA_ENABLE *)paramData; 4625 4626 if (m_state != OMX_StateLoaded) { 4627 DEBUG_PRINT_ERROR("Set Parameter called in Invalid state"); 4628 return OMX_ErrorIncorrectStateOperation; 4629 } 4630 4631 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) { 4632 m_client_out_extradata_info.enable_client_extradata(pParam->bEnable); 4633 } else { 4634 DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex); 4635 eRet = OMX_ErrorUnsupportedIndex; 4636 } 4637 break; 4638 } 4639 case OMX_IndexParamStandardComponentRole: { 4640 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); 4641 OMX_PARAM_COMPONENTROLETYPE *comp_role; 4642 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 4643 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", 4644 comp_role->cRole); 4645 4646 if ((m_state == OMX_StateLoaded)&& 4647 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) { 4648 DEBUG_PRINT_LOW("Set Parameter called in valid state"); 4649 } else { 4650 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 4651 return OMX_ErrorIncorrectStateOperation; 4652 } 4653 4654 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) { 4655 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) { 4656 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE); 4657 } else { 4658 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4659 eRet =OMX_ErrorUnsupportedSetting; 4660 } 4661 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 4662 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 4663 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 4664 } else { 4665 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4666 eRet = OMX_ErrorUnsupportedSetting; 4667 } 4668 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 4669 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 4670 strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE); 4671 } else { 4672 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4673 eRet = OMX_ErrorUnsupportedSetting; 4674 } 4675 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 4676 if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 4677 strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE); 4678 } else { 4679 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4680 eRet =OMX_ErrorUnsupportedSetting; 4681 } 4682 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 4683 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 4684 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE); 4685 } else { 4686 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4687 eRet = OMX_ErrorUnsupportedSetting; 4688 } 4689 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) || 4690 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) || 4691 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE)) 4692 ) { 4693 if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) { 4694 strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE); 4695 } else { 4696 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4697 eRet =OMX_ErrorUnsupportedSetting; 4698 } 4699 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) || 4700 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) 4701 ) { 4702 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) { 4703 strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE); 4704 } else { 4705 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4706 eRet =OMX_ErrorUnsupportedSetting; 4707 } 4708 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) { 4709 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 4710 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) { 4711 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE); 4712 } else { 4713 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4714 eRet = OMX_ErrorUnsupportedSetting; 4715 } 4716 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 4717 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) || 4718 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) { 4719 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE); 4720 } else { 4721 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4722 eRet = OMX_ErrorUnsupportedSetting; 4723 } 4724 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 4725 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 4726 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 4727 } else { 4728 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4729 eRet = OMX_ErrorUnsupportedSetting; 4730 } 4731 } else { 4732 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind); 4733 eRet = OMX_ErrorInvalidComponentName; 4734 } 4735 break; 4736 } 4737 4738 case OMX_IndexParamPriorityMgmt: { 4739 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); 4740 if (m_state != OMX_StateLoaded) { 4741 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 4742 return OMX_ErrorIncorrectStateOperation; 4743 } 4744 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; 4745 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u", 4746 (unsigned int)priorityMgmtype->nGroupID); 4747 4748 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u", 4749 (unsigned int)priorityMgmtype->nGroupPriority); 4750 4751 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; 4752 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; 4753 4754 break; 4755 } 4756 4757 case OMX_IndexParamCompBufferSupplier: { 4758 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); 4759 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 4760 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", 4761 bufferSupplierType->eBufferSupplier); 4762 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) 4763 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; 4764 4765 else 4766 4767 eRet = OMX_ErrorBadPortIndex; 4768 4769 break; 4770 4771 } 4772 case OMX_IndexParamVideoAvc: { 4773 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d", 4774 paramIndex); 4775 break; 4776 } 4777 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 4778 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d", 4779 paramIndex); 4780 break; 4781 } 4782 case OMX_IndexParamVideoH263: { 4783 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d", 4784 paramIndex); 4785 break; 4786 } 4787 case OMX_IndexParamVideoMpeg4: { 4788 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d", 4789 paramIndex); 4790 break; 4791 } 4792 case OMX_IndexParamVideoMpeg2: { 4793 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d", 4794 paramIndex); 4795 break; 4796 } 4797 case OMX_QTIIndexParamLowLatencyMode: { 4798 struct v4l2_control control; 4799 int rc = 0; 4800 QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam = 4801 (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData; 4802 if (pParam->bLowLatencyMode) { 4803 DEBUG_PRINT_HIGH("Enabling DECODE order"); 4804 time_stamp_dts.set_timestamp_reorder_mode(false); 4805 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 4806 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 4807 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4808 if (rc) { 4809 DEBUG_PRINT_ERROR("Set picture order failed"); 4810 eRet = OMX_ErrorUnsupportedSetting; 4811 } 4812 } 4813 break; 4814 } 4815 case OMX_QcomIndexParamVideoDecoderPictureOrder: { 4816 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER); 4817 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = 4818 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; 4819 struct v4l2_control control; 4820 int pic_order,rc=0; 4821 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d", 4822 pictureOrder->eOutputPictureOrder); 4823 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) { 4824 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 4825 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) { 4826 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 4827 time_stamp_dts.set_timestamp_reorder_mode(false); 4828 } else 4829 eRet = OMX_ErrorBadParameter; 4830 if (eRet == OMX_ErrorNone) { 4831 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 4832 control.value = pic_order; 4833 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4834 if (rc) { 4835 DEBUG_PRINT_ERROR("Set picture order failed"); 4836 eRet = OMX_ErrorUnsupportedSetting; 4837 } 4838 } 4839 m_decode_order_mode = 4840 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER; 4841 break; 4842 } 4843 case OMX_QcomIndexParamConcealMBMapExtraData: 4844 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4845 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false, 4846 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4847 break; 4848 case OMX_QcomIndexParamFrameInfoExtraData: 4849 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4850 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, 4851 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4852 break; 4853 case OMX_ExtraDataFrameDimension: 4854 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4855 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false, 4856 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4857 break; 4858 case OMX_QcomIndexParamInterlaceExtraData: 4859 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4860 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false, 4861 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4862 break; 4863 case OMX_QcomIndexParamH264TimeInfo: 4864 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4865 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false, 4866 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4867 break; 4868 case OMX_QcomIndexParamVideoFramePackingExtradata: 4869 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4870 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false, 4871 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4872 break; 4873 case OMX_QcomIndexParamVideoQPExtraData: 4874 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4875 eRet = enable_extradata(OMX_QP_EXTRADATA, false, 4876 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4877 break; 4878 case OMX_QcomIndexParamVideoInputBitsInfoExtraData: 4879 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4880 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false, 4881 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4882 break; 4883 case OMX_QcomIndexEnableExtnUserData: 4884 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4885 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false, 4886 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4887 break; 4888 case OMX_QTIIndexParamVQZipSEIExtraData: 4889 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4890 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false, 4891 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4892 break; 4893 case OMX_QcomIndexParamVideoDivx: { 4894 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; 4895 } 4896 break; 4897 case OMX_QcomIndexPlatformPvt: { 4898 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN); 4899 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); 4900 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; 4901 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 4902 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); 4903 eRet = OMX_ErrorUnsupportedSetting; 4904 } else { 4905 m_out_pvt_entry_pmem = OMX_TRUE; 4906 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 4907 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set"); 4908 m_use_output_pmem = OMX_TRUE; 4909 } 4910 } 4911 4912 } 4913 break; 4914 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: { 4915 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); 4916 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); 4917 struct v4l2_control control; 4918 int rc; 4919 drv_ctx.idr_only_decoding = 1; 4920 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 4921 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 4922 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4923 if (rc) { 4924 DEBUG_PRINT_ERROR("Set picture order failed"); 4925 eRet = OMX_ErrorUnsupportedSetting; 4926 } else { 4927 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE; 4928 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE; 4929 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4930 if (rc) { 4931 DEBUG_PRINT_ERROR("Sync frame setting failed"); 4932 eRet = OMX_ErrorUnsupportedSetting; 4933 } 4934 /*Setting sync frame decoding on driver might change buffer 4935 * requirements so update them here*/ 4936 if (get_buffer_req(&drv_ctx.ip_buf)) { 4937 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements"); 4938 eRet = OMX_ErrorUnsupportedSetting; 4939 } 4940 if (get_buffer_req(&drv_ctx.op_buf)) { 4941 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements"); 4942 eRet = OMX_ErrorUnsupportedSetting; 4943 } 4944 } 4945 } 4946 break; 4947 4948 case OMX_QcomIndexParamIndexExtraDataType: { 4949 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); 4950 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; 4951 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && 4952 (extradataIndexType->bEnabled == OMX_TRUE) && 4953 (extradataIndexType->nPortIndex == 1)) { 4954 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming"); 4955 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled); 4956 4957 } 4958 } 4959 break; 4960 case OMX_QcomIndexParamEnableSmoothStreaming: { 4961 #ifndef SMOOTH_STREAMING_DISABLED 4962 eRet = enable_smoothstreaming(); 4963 #else 4964 eRet = OMX_ErrorUnsupportedSetting; 4965 #endif 4966 } 4967 break; 4968 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 4969 /* Need to allow following two set_parameters even in Idle 4970 * state. This is ANDROID architecture which is not in sync 4971 * with openmax standard. */ 4972 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: { 4973 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams); 4974 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; 4975 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { 4976 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!"); 4977 eRet = OMX_ErrorUnsupportedSetting; 4978 break; 4979 } else if (m_out_mem_ptr) { 4980 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !"); 4981 eRet = OMX_ErrorInvalidState; 4982 break; 4983 } 4984 if (enableNativeBuffers) { 4985 m_enable_android_native_buffers = enableNativeBuffers->enable; 4986 } 4987 #if !defined(FLEXYUV_SUPPORTED) 4988 if (m_enable_android_native_buffers) { 4989 // Use the most-preferred-native-color-format as surface-mode is hinted here 4990 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) { 4991 DEBUG_PRINT_ERROR("Failed to set native color format!"); 4992 eRet = OMX_ErrorUnsupportedSetting; 4993 } 4994 } 4995 #endif 4996 } 4997 break; 4998 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: { 4999 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams); 5000 eRet = use_android_native_buffer(hComp, paramData); 5001 } 5002 break; 5003 #if ALLOCATE_OUTPUT_NATIVEHANDLE 5004 case OMX_GoogleAndroidIndexAllocateNativeHandle: { 5005 5006 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData; 5007 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams); 5008 5009 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) { 5010 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!"); 5011 eRet = OMX_ErrorUnsupportedSetting; 5012 break; 5013 } else if (m_inp_mem_ptr) { 5014 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !"); 5015 eRet = OMX_ErrorInvalidState; 5016 break; 5017 } 5018 5019 if (allocateNativeHandleParams != NULL) { 5020 allocate_native_handle = allocateNativeHandleParams->enable; 5021 } 5022 } 5023 break; 5024 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE 5025 #endif 5026 case OMX_QcomIndexParamEnableTimeStampReorder: { 5027 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER); 5028 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; 5029 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) { 5030 if (reorder->bEnable == OMX_TRUE) { 5031 frm_int =0; 5032 time_stamp_dts.set_timestamp_reorder_mode(true); 5033 } else 5034 time_stamp_dts.set_timestamp_reorder_mode(false); 5035 } else { 5036 time_stamp_dts.set_timestamp_reorder_mode(false); 5037 if (reorder->bEnable == OMX_TRUE) { 5038 eRet = OMX_ErrorUnsupportedSetting; 5039 } 5040 } 5041 } 5042 break; 5043 case OMX_IndexParamVideoProfileLevelCurrent: { 5044 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 5045 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = 5046 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; 5047 if (pParam) { 5048 m_profile_lvl.eProfile = pParam->eProfile; 5049 m_profile_lvl.eLevel = pParam->eLevel; 5050 } 5051 break; 5052 5053 } 5054 case OMX_QcomIndexParamVideoMetaBufferMode: 5055 { 5056 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams); 5057 StoreMetaDataInBuffersParams *metabuffer = 5058 (StoreMetaDataInBuffersParams *)paramData; 5059 if (!metabuffer) { 5060 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer); 5061 eRet = OMX_ErrorBadParameter; 5062 break; 5063 } 5064 if (m_disable_dynamic_buf_mode) { 5065 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled"); 5066 eRet = OMX_ErrorUnsupportedSetting; 5067 break; 5068 } 5069 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 5070 5071 if (m_out_mem_ptr) { 5072 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !"); 5073 eRet = OMX_ErrorInvalidState; 5074 break; 5075 } 5076 //set property dynamic buffer mode to driver. 5077 struct v4l2_control control; 5078 struct v4l2_format fmt; 5079 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT; 5080 if (metabuffer->bStoreMetaData == true) { 5081 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC; 5082 } else { 5083 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC; 5084 } 5085 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 5086 if (!rc) { 5087 DEBUG_PRINT_HIGH("%s buffer mode", 5088 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic"); 5089 dynamic_buf_mode = metabuffer->bStoreMetaData; 5090 } else { 5091 DEBUG_PRINT_ERROR("Failed to %s buffer mode", 5092 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic"); 5093 eRet = OMX_ErrorUnsupportedSetting; 5094 } 5095 } else { 5096 DEBUG_PRINT_ERROR( 5097 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u", 5098 (unsigned int)metabuffer->nPortIndex); 5099 eRet = OMX_ErrorUnsupportedSetting; 5100 } 5101 break; 5102 } 5103 case OMX_QcomIndexParamVideoDownScalar: 5104 { 5105 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR); 5106 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData; 5107 struct v4l2_control control; 5108 int rc; 5109 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable); 5110 5111 if (pParam && pParam->bEnable) { 5112 rc = enable_downscalar(); 5113 if (rc < 0) { 5114 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__); 5115 return OMX_ErrorUnsupportedSetting; 5116 } 5117 m_force_down_scalar = pParam->bEnable; 5118 } else { 5119 rc = disable_downscalar(); 5120 if (rc < 0) { 5121 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__); 5122 return OMX_ErrorUnsupportedSetting; 5123 } 5124 m_force_down_scalar = pParam->bEnable; 5125 } 5126 break; 5127 } 5128 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 5129 case OMX_QcomIndexParamVideoAdaptivePlaybackMode: 5130 { 5131 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams); 5132 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback"); 5133 PrepareForAdaptivePlaybackParams* pParams = 5134 (PrepareForAdaptivePlaybackParams *) paramData; 5135 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 5136 if (!pParams->bEnable) { 5137 return OMX_ErrorNone; 5138 } 5139 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth 5140 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) { 5141 DEBUG_PRINT_ERROR( 5142 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]", 5143 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight, 5144 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight); 5145 eRet = OMX_ErrorBadParameter; 5146 } else { 5147 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight); 5148 } 5149 } else { 5150 DEBUG_PRINT_ERROR( 5151 "Prepare for adaptive playback supported only on output port"); 5152 eRet = OMX_ErrorBadParameter; 5153 } 5154 break; 5155 } 5156 5157 case OMX_QTIIndexParamVideoPreferAdaptivePlayback: 5158 { 5159 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 5160 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback"); 5161 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable; 5162 if (m_disable_dynamic_buf_mode) { 5163 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set"); 5164 } 5165 break; 5166 } 5167 #endif 5168 case OMX_QcomIndexParamVideoCustomBufferSize: 5169 { 5170 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE); 5171 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize"); 5172 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData; 5173 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 5174 struct v4l2_control control; 5175 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT; 5176 control.value = pParam->nBufferSize; 5177 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 5178 DEBUG_PRINT_ERROR("Failed to set input buffer size"); 5179 eRet = OMX_ErrorUnsupportedSetting; 5180 } else { 5181 eRet = get_buffer_req(&drv_ctx.ip_buf); 5182 if (eRet == OMX_ErrorNone) { 5183 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size; 5184 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d", 5185 m_custom_buffersize.input_buffersize); 5186 } else { 5187 DEBUG_PRINT_ERROR("Failed to get buffer requirement"); 5188 } 5189 } 5190 } else { 5191 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port"); 5192 eRet = OMX_ErrorBadParameter; 5193 } 5194 break; 5195 } 5196 case OMX_QTIIndexParamVQZIPSEIType: 5197 { 5198 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE); 5199 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType"); 5200 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam = 5201 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData; 5202 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable); 5203 5204 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false, 5205 ((QOMX_ENABLETYPE *)paramData)->bEnable); 5206 if (eRet != OMX_ErrorNone) { 5207 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata"); 5208 eRet = OMX_ErrorBadParameter; 5209 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA; 5210 break; 5211 } 5212 eRet = enable_extradata(OMX_QP_EXTRADATA, false, 5213 ((QOMX_ENABLETYPE *)paramData)->bEnable); 5214 if (eRet != OMX_ErrorNone) { 5215 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata"); 5216 eRet = OMX_ErrorBadParameter; 5217 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA; 5218 client_extradata = client_extradata & ~OMX_QP_EXTRADATA; 5219 break; 5220 } 5221 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, 5222 ((QOMX_ENABLETYPE *)paramData)->bEnable); 5223 if (eRet != OMX_ErrorNone) { 5224 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata"); 5225 eRet = OMX_ErrorBadParameter; 5226 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA; 5227 client_extradata = client_extradata & ~OMX_QP_EXTRADATA; 5228 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA; 5229 } 5230 break; 5231 } 5232 case OMX_QTIIndexParamPassInputBufferFd: 5233 { 5234 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 5235 if (arbitrary_bytes) { 5236 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode"); 5237 eRet = OMX_ErrorUnsupportedSetting; 5238 break; 5239 } 5240 5241 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable; 5242 if (m_input_pass_buffer_fd) 5243 DEBUG_PRINT_LOW("Enable passing input buffer FD"); 5244 break; 5245 } 5246 case OMX_QTIIndexParamForceCompressedForDPB: 5247 { 5248 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE); 5249 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB"); 5250 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam = 5251 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData; 5252 if (m_disable_ubwc_mode) { 5253 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled"); 5254 eRet = OMX_ErrorUnsupportedSetting; 5255 break; 5256 } 5257 if (!paramData) { 5258 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL"); 5259 eRet = OMX_ErrorBadParameter; 5260 break; 5261 } 5262 5263 m_force_compressed_for_dpb = pParam->bEnable; 5264 break; 5265 } 5266 case OMX_QTIIndexParamForceUnCompressedForOPB: 5267 { 5268 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB"); 5269 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam = 5270 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData; 5271 if (!paramData) { 5272 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL"); 5273 eRet = OMX_ErrorBadParameter; 5274 break; 5275 } 5276 m_disable_ubwc_mode = pParam->bEnable; 5277 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled"); 5278 break; 5279 } 5280 case OMX_QTIIndexParamDitherControl: 5281 { 5282 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL); 5283 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl"); 5284 QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData; 5285 DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType); 5286 if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) || 5287 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) { 5288 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range"); 5289 eRet = OMX_ErrorBadParameter; 5290 break; 5291 } 5292 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE; 5293 DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config); 5294 break; 5295 } 5296 default: { 5297 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex); 5298 eRet = OMX_ErrorUnsupportedIndex; 5299 } 5300 } 5301 if (eRet != OMX_ErrorNone) 5302 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex); 5303 return eRet; 5304 } 5305 5306 /* ====================================================================== 5307 FUNCTION 5308 omx_vdec::GetConfig 5309 5310 DESCRIPTION 5311 OMX Get Config Method implementation. 5312 5313 PARAMETERS 5314 <TBD>. 5315 5316 RETURN VALUE 5317 OMX Error None if successful. 5318 5319 ========================================================================== */ 5320 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, 5321 OMX_IN OMX_INDEXTYPE configIndex, 5322 OMX_INOUT OMX_PTR configData) 5323 { 5324 (void) hComp; 5325 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5326 5327 if (m_state == OMX_StateInvalid) { 5328 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 5329 return OMX_ErrorInvalidState; 5330 } 5331 5332 switch ((unsigned long)configIndex) { 5333 case OMX_QcomIndexConfigInterlaced: { 5334 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE); 5335 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = 5336 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; 5337 if (configFmt->nPortIndex == 1) { 5338 if (configFmt->nIndex == 0) { 5339 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; 5340 } else if (configFmt->nIndex == 1) { 5341 configFmt->eInterlaceType = 5342 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 5343 } else if (configFmt->nIndex == 2) { 5344 configFmt->eInterlaceType = 5345 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 5346 } else { 5347 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" 5348 " NoMore Interlaced formats"); 5349 eRet = OMX_ErrorNoMore; 5350 } 5351 5352 } else { 5353 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port", 5354 (int)configFmt->nPortIndex); 5355 eRet = OMX_ErrorBadPortIndex; 5356 } 5357 break; 5358 } 5359 case OMX_QcomIndexQueryNumberOfVideoDecInstance: { 5360 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES); 5361 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = 5362 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; 5363 decoderinstances->nNumOfInstances = 16; 5364 /*TODO: How to handle this case */ 5365 break; 5366 } 5367 case OMX_QcomIndexConfigVideoFramePackingArrangement: { 5368 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) { 5369 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT); 5370 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = 5371 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; 5372 memcpy(configFmt, &m_frame_pack_arrangement, 5373 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 5374 } else { 5375 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); 5376 } 5377 break; 5378 } 5379 case OMX_IndexConfigCommonOutputCrop: { 5380 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE); 5381 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData; 5382 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE)); 5383 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u", 5384 rectangle.nLeft, rectangle.nTop, 5385 rectangle.nWidth, rectangle.nHeight); 5386 break; 5387 } 5388 case OMX_QcomIndexConfigPerfLevel: { 5389 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL); 5390 struct v4l2_control control; 5391 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 5392 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 5393 5394 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 5395 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 5396 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno); 5397 eRet = OMX_ErrorHardware; 5398 } 5399 5400 if (eRet == OMX_ErrorNone) { 5401 switch (control.value) { 5402 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: 5403 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo; 5404 break; 5405 default: 5406 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value); 5407 /* Fall through */ 5408 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: 5409 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal; 5410 break; 5411 } 5412 } 5413 5414 break; 5415 } 5416 case OMX_QcomIndexConfigH264EntropyCodingCabac: { 5417 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE); 5418 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData; 5419 struct v4l2_control control; 5420 5421 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) { 5422 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264"); 5423 eRet = OMX_ErrorNotImplemented; 5424 break; 5425 } 5426 5427 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; 5428 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) { 5429 coding->bCabac = (OMX_BOOL) 5430 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC); 5431 /* We can't query driver at the moment for the cabac mode, so 5432 * just use 0xff...f as a place holder for future improvement */ 5433 coding->nCabacInitIdc = ~0; 5434 } else { 5435 eRet = OMX_ErrorUnsupportedIndex; 5436 } 5437 5438 break; 5439 } 5440 case OMX_QTIIndexConfigDescribeColorAspects: 5441 { 5442 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); 5443 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; 5444 5445 if (params->bRequestingDataSpace) { 5446 DEBUG_PRINT_HIGH("Does not handle dataspace request"); 5447 return OMX_ErrorUnsupportedSetting; 5448 } 5449 5450 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client"); 5451 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal"); 5452 5453 // For VPX, use client-color if specified. 5454 // For the rest, try to use the stream-color if present 5455 bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 || 5456 output_capability == V4L2_PIX_FMT_VP9); 5457 5458 const ColorAspects &preferredColor = preferClientColor ? 5459 m_client_color_space.sAspects : m_internal_color_space.sAspects; 5460 const ColorAspects &defaultColor = preferClientColor ? 5461 m_internal_color_space.sAspects : m_client_color_space.sAspects; 5462 5463 params->sAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ? 5464 preferredColor.mPrimaries : defaultColor.mPrimaries; 5465 params->sAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ? 5466 preferredColor.mTransfer : defaultColor.mTransfer; 5467 params->sAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ? 5468 preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs; 5469 params->sAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ? 5470 preferredColor.mRange : defaultColor.mRange; 5471 5472 print_debug_color_aspects(&(params->sAspects), "GetConfig"); 5473 5474 break; 5475 } 5476 case OMX_QTIIndexConfigDescribeHDRColorInfo: 5477 { 5478 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams); 5479 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData; 5480 auto_lock lock(m_hdr_info_client_lock); 5481 5482 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR"); 5483 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR"); 5484 5485 if (m_change_client_hdr_info) { 5486 DEBUG_PRINT_LOW("Updating Client's HDR Info with internal"); 5487 memcpy(&m_client_hdr_info.sInfo, 5488 &m_internal_hdr_info.sInfo, sizeof(HDRStaticInfo)); 5489 m_change_client_hdr_info = false; 5490 } 5491 5492 memcpy(&(params->sInfo), &(m_client_hdr_info.sInfo), sizeof(HDRStaticInfo)); 5493 5494 break; 5495 } 5496 case OMX_IndexConfigAndroidVendorExtension: 5497 { 5498 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); 5499 5500 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext = 5501 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData); 5502 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext); 5503 return get_vendor_extension_config(ext); 5504 } 5505 default: 5506 { 5507 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); 5508 eRet = OMX_ErrorBadParameter; 5509 } 5510 5511 } 5512 5513 return eRet; 5514 } 5515 5516 /* ====================================================================== 5517 FUNCTION 5518 omx_vdec::SetConfig 5519 5520 DESCRIPTION 5521 OMX Set Config method implementation 5522 5523 PARAMETERS 5524 <TBD>. 5525 5526 RETURN VALUE 5527 OMX Error None if successful. 5528 ========================================================================== */ 5529 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, 5530 OMX_IN OMX_INDEXTYPE configIndex, 5531 OMX_IN OMX_PTR configData) 5532 { 5533 (void) hComp; 5534 if (m_state == OMX_StateInvalid) { 5535 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 5536 return OMX_ErrorInvalidState; 5537 } 5538 5539 OMX_ERRORTYPE ret = OMX_ErrorNone; 5540 OMX_VIDEO_CONFIG_NALSIZE *pNal; 5541 5542 DEBUG_PRINT_LOW("Set Config Called"); 5543 5544 if (configIndex == OMX_IndexConfigVideoNalSize) { 5545 struct v4l2_control temp; 5546 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT; 5547 5548 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE); 5549 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); 5550 switch (pNal->nNaluBytes) { 5551 case 0: 5552 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES; 5553 break; 5554 case 2: 5555 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH; 5556 break; 5557 case 4: 5558 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH; 5559 break; 5560 default: 5561 return OMX_ErrorUnsupportedSetting; 5562 } 5563 5564 if (!arbitrary_bytes) { 5565 /* In arbitrary bytes mode, the assembler strips out nal size and replaces 5566 * with start code, so only need to notify driver in frame by frame mode */ 5567 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) { 5568 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT"); 5569 return OMX_ErrorHardware; 5570 } 5571 } 5572 5573 nal_length = pNal->nNaluBytes; 5574 m_frame_parser.init_nal_length(nal_length); 5575 5576 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length); 5577 return ret; 5578 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) { 5579 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData; 5580 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps); 5581 5582 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 5583 if (config->bEnabled) { 5584 if ((config->nFps >> 16) > 0 && 5585 (config->nFps >> 16) <= MAX_SUPPORTED_FPS) { 5586 m_fps_received = config->nFps; 5587 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u", 5588 (unsigned int)config->nFps >> 16); 5589 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator, 5590 drv_ctx.frame_rate.fps_denominator); 5591 5592 if (!drv_ctx.frame_rate.fps_numerator) { 5593 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 5594 drv_ctx.frame_rate.fps_numerator = 30; 5595 } 5596 5597 if (drv_ctx.frame_rate.fps_denominator) { 5598 drv_ctx.frame_rate.fps_numerator = (int) 5599 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 5600 } 5601 5602 drv_ctx.frame_rate.fps_denominator = 1; 5603 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 5604 drv_ctx.frame_rate.fps_numerator; 5605 5606 struct v4l2_outputparm oparm; 5607 /*XXX: we're providing timing info as seconds per frame rather than frames 5608 * per second.*/ 5609 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 5610 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 5611 5612 struct v4l2_streamparm sparm; 5613 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 5614 sparm.parm.output = oparm; 5615 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 5616 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 5617 performance might be affected"); 5618 ret = OMX_ErrorHardware; 5619 } 5620 client_set_fps = true; 5621 } else { 5622 DEBUG_PRINT_ERROR("Frame rate not supported."); 5623 ret = OMX_ErrorUnsupportedSetting; 5624 } 5625 } else { 5626 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate"); 5627 client_set_fps = false; 5628 } 5629 } else { 5630 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d", 5631 (int)config->nPortIndex); 5632 ret = OMX_ErrorBadPortIndex; 5633 } 5634 5635 return ret; 5636 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) { 5637 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 5638 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 5639 struct v4l2_control control; 5640 5641 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel); 5642 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 5643 5644 switch (perf->ePerfLevel) { 5645 case OMX_QCOM_PerfLevelNominal: 5646 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; 5647 m_need_turbo &= ~TURBO_MODE_CLIENT_REQUESTED; 5648 break; 5649 case OMX_QCOM_PerfLevelTurbo: 5650 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 5651 m_need_turbo |= TURBO_MODE_CLIENT_REQUESTED; 5652 break; 5653 default: 5654 ret = OMX_ErrorUnsupportedSetting; 5655 break; 5656 } 5657 5658 if (ret == OMX_ErrorNone) { 5659 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? 5660 OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 5661 } 5662 5663 return ret; 5664 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) { 5665 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config = 5666 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData; 5667 struct v4l2_control control; 5668 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType); 5669 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE; 5670 5671 switch (config->eDecodeType) { 5672 case OMX_QCOM_PictypeDecode_I: 5673 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON; 5674 break; 5675 case OMX_QCOM_PictypeDecode_IPB: 5676 default: 5677 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF; 5678 break; 5679 } 5680 5681 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? 5682 OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 5683 if (ret) 5684 DEBUG_PRINT_ERROR("Failed to set picture type decode"); 5685 5686 return ret; 5687 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) { 5688 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData; 5689 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32); 5690 5691 struct v4l2_control control; 5692 5693 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; 5694 if (priority->nU32 == 0) 5695 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE; 5696 else 5697 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; 5698 5699 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 5700 DEBUG_PRINT_ERROR("Failed to set Priority"); 5701 ret = OMX_ErrorUnsupportedSetting; 5702 } 5703 return ret; 5704 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) { 5705 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData; 5706 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16); 5707 5708 struct v4l2_control control; 5709 5710 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE; 5711 control.value = rate->nU32; 5712 5713 operating_frame_rate = rate->nU32 >> 16; 5714 5715 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 5716 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources : 5717 OMX_ErrorUnsupportedSetting; 5718 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)", 5719 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno)); 5720 } 5721 return ret; 5722 5723 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) { 5724 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); 5725 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; 5726 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) { 5727 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true); 5728 } 5729 5730 print_debug_color_aspects(&(params->sAspects), "Set Config"); 5731 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams)); 5732 return ret; 5733 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) { 5734 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams); 5735 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData; 5736 if (!DEFAULT_EXTRADATA & OMX_HDR_COLOR_INFO_EXTRADATA) { 5737 ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, true, true); 5738 if (ret != OMX_ErrorNone) { 5739 DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA"); 5740 return ret; 5741 } 5742 } 5743 5744 print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR"); 5745 memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams)); 5746 return ret; 5747 5748 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) { 5749 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); 5750 5751 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext = 5752 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData); 5753 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext); 5754 5755 return set_vendor_extension_config(ext); 5756 } 5757 5758 return OMX_ErrorNotImplemented; 5759 } 5760 5761 #define extn_equals(param, extn) (!strcmp(param, extn)) 5762 5763 /* ====================================================================== 5764 FUNCTION 5765 omx_vdec::GetExtensionIndex 5766 5767 DESCRIPTION 5768 OMX GetExtensionIndex method implementaion. <TBD> 5769 5770 PARAMETERS 5771 <TBD>. 5772 5773 RETURN VALUE 5774 OMX Error None if everything successful. 5775 5776 ========================================================================== */ 5777 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, 5778 OMX_IN OMX_STRING paramName, 5779 OMX_OUT OMX_INDEXTYPE* indexType) 5780 { 5781 (void) hComp; 5782 if (m_state == OMX_StateInvalid) { 5783 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State"); 5784 return OMX_ErrorInvalidState; 5785 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) { 5786 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; 5787 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) { 5788 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; 5789 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) { 5790 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata; 5791 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) { 5792 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement; 5793 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) { 5794 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData; 5795 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) { 5796 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData; 5797 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) { 5798 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData; 5799 } 5800 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 5801 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) { 5802 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; 5803 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) { 5804 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; 5805 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) { 5806 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; 5807 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) { 5808 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; 5809 } 5810 #if ALLOCATE_OUTPUT_NATIVEHANDLE 5811 else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) { 5812 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle; 5813 } 5814 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE 5815 #endif 5816 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { 5817 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; 5818 } 5819 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 5820 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) { 5821 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode; 5822 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) { 5823 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback; 5824 } 5825 #endif 5826 #ifdef FLEXYUV_SUPPORTED 5827 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) { 5828 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription; 5829 } 5830 #endif 5831 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) { 5832 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd; 5833 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) { 5834 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB; 5835 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) { 5836 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB; 5837 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) { 5838 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode; 5839 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) { 5840 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata; 5841 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { 5842 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; 5843 } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) { 5844 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo; 5845 } else { 5846 DEBUG_PRINT_HIGH("Extension: %s not implemented", paramName); 5847 return OMX_ErrorNotImplemented; 5848 } 5849 return OMX_ErrorNone; 5850 } 5851 5852 /* ====================================================================== 5853 FUNCTION 5854 omx_vdec::GetState 5855 5856 DESCRIPTION 5857 Returns the state information back to the caller.<TBD> 5858 5859 PARAMETERS 5860 <TBD>. 5861 5862 RETURN VALUE 5863 Error None if everything is successful. 5864 ========================================================================== */ 5865 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, 5866 OMX_OUT OMX_STATETYPE* state) 5867 { 5868 (void) hComp; 5869 *state = m_state; 5870 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state); 5871 return OMX_ErrorNone; 5872 } 5873 5874 /* ====================================================================== 5875 FUNCTION 5876 omx_vdec::ComponentTunnelRequest 5877 5878 DESCRIPTION 5879 OMX Component Tunnel Request method implementation. <TBD> 5880 5881 PARAMETERS 5882 None. 5883 5884 RETURN VALUE 5885 OMX Error None if everything successful. 5886 5887 ========================================================================== */ 5888 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, 5889 OMX_IN OMX_U32 port, 5890 OMX_IN OMX_HANDLETYPE peerComponent, 5891 OMX_IN OMX_U32 peerPort, 5892 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) 5893 { 5894 (void) hComp; 5895 (void) port; 5896 (void) peerComponent; 5897 (void) peerPort; 5898 (void) tunnelSetup; 5899 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented"); 5900 return OMX_ErrorNotImplemented; 5901 } 5902 5903 /* ====================================================================== 5904 FUNCTION 5905 omx_vdec::UseOutputBuffer 5906 5907 DESCRIPTION 5908 Helper function for Use buffer in the input pin 5909 5910 PARAMETERS 5911 None. 5912 5913 RETURN VALUE 5914 true/false 5915 5916 ========================================================================== */ 5917 OMX_ERRORTYPE omx_vdec::allocate_extradata() 5918 { 5919 #ifdef USE_ION 5920 if (drv_ctx.extradata_info.buffer_size) { 5921 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { 5922 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 5923 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5924 free_ion_memory(&drv_ctx.extradata_info.ion); 5925 } 5926 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); 5927 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( 5928 drv_ctx.extradata_info.size, 4096, 5929 &drv_ctx.extradata_info.ion.ion_alloc_data, 5930 &drv_ctx.extradata_info.ion.fd_ion_data, 0); 5931 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) { 5932 DEBUG_PRINT_ERROR("Failed to alloc extradata memory"); 5933 return OMX_ErrorInsufficientResources; 5934 } 5935 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL, 5936 drv_ctx.extradata_info.size, 5937 PROT_READ|PROT_WRITE, MAP_SHARED, 5938 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0); 5939 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) { 5940 DEBUG_PRINT_ERROR("Failed to map extradata memory"); 5941 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5942 free_ion_memory(&drv_ctx.extradata_info.ion); 5943 return OMX_ErrorInsufficientResources; 5944 } 5945 } 5946 #endif 5947 if (!m_other_extradata) { 5948 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size); 5949 if (!m_other_extradata) { 5950 DEBUG_PRINT_ERROR("Failed to alloc memory\n"); 5951 return OMX_ErrorInsufficientResources; 5952 } 5953 } 5954 return OMX_ErrorNone; 5955 } 5956 5957 void omx_vdec::free_extradata() 5958 { 5959 #ifdef USE_ION 5960 if (drv_ctx.extradata_info.uaddr) { 5961 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 5962 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5963 free_ion_memory(&drv_ctx.extradata_info.ion); 5964 } 5965 #endif 5966 if (m_other_extradata) { 5967 free(m_other_extradata); 5968 m_other_extradata = NULL; 5969 } 5970 } 5971 5972 OMX_ERRORTYPE omx_vdec::use_output_buffer( 5973 OMX_IN OMX_HANDLETYPE hComp, 5974 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5975 OMX_IN OMX_U32 port, 5976 OMX_IN OMX_PTR appData, 5977 OMX_IN OMX_U32 bytes, 5978 OMX_IN OMX_U8* buffer) 5979 { 5980 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5981 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 5982 unsigned i= 0; // Temporary counter 5983 struct vdec_setbuffer_cmd setbuffers; 5984 OMX_PTR privateAppData = NULL; 5985 private_handle_t *handle = NULL; 5986 OMX_U8 *buff = buffer; 5987 struct v4l2_buffer buf; 5988 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 5989 int extra_idx = 0; 5990 (void) hComp; 5991 (void) port; 5992 5993 if (!m_out_mem_ptr) { 5994 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); 5995 eRet = allocate_output_headers(); 5996 if (eRet == OMX_ErrorNone) 5997 eRet = allocate_extradata(); 5998 } 5999 6000 if (eRet == OMX_ErrorNone) { 6001 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 6002 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 6003 break; 6004 } 6005 } 6006 } 6007 6008 if (i >= drv_ctx.op_buf.actualcount) { 6009 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount); 6010 eRet = OMX_ErrorInsufficientResources; 6011 } 6012 6013 if (eRet != OMX_ErrorNone) 6014 return eRet; 6015 6016 if (dynamic_buf_mode) { 6017 *bufferHdr = (m_out_mem_ptr + i ); 6018 (*bufferHdr)->pBuffer = NULL; 6019 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) { 6020 enum v4l2_buf_type buf_type; 6021 int rr = 0; 6022 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6023 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) { 6024 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr); 6025 return OMX_ErrorInsufficientResources; 6026 } else { 6027 streaming[CAPTURE_PORT] = true; 6028 DEBUG_PRINT_LOW("STREAMON Successful"); 6029 } 6030 6031 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 6032 request_perf_level(VIDC_TURBO); 6033 } 6034 BITMASK_SET(&m_out_bm_count,i); 6035 (*bufferHdr)->pAppPrivate = appData; 6036 (*bufferHdr)->pBuffer = buffer; 6037 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 6038 return eRet; 6039 } 6040 6041 if (eRet == OMX_ErrorNone) { 6042 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) 6043 if (m_enable_android_native_buffers) { 6044 if (m_use_android_native_buffers) { 6045 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; 6046 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 6047 handle = (private_handle_t *)nBuf->handle; 6048 privateAppData = params->pAppPrivate; 6049 } else { 6050 handle = (private_handle_t *)buff; 6051 privateAppData = appData; 6052 } 6053 if (!handle) { 6054 DEBUG_PRINT_ERROR("handle is invalid"); 6055 return OMX_ErrorBadParameter; 6056 } 6057 6058 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { 6059 if (secure_mode && secure_scaling_to_non_secure_opb) { 6060 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it", 6061 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 6062 } else { 6063 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," 6064 " expected %u, got %u", 6065 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 6066 return OMX_ErrorBadParameter; 6067 } 6068 } 6069 6070 drv_ctx.op_buf.buffer_size = handle->size; 6071 6072 if (!m_use_android_native_buffers) { 6073 if (!secure_mode) { 6074 buff = (OMX_U8*)mmap(0, handle->size, 6075 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 6076 if (buff == MAP_FAILED) { 6077 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 6078 return OMX_ErrorInsufficientResources; 6079 } 6080 } 6081 } 6082 #if defined(_ANDROID_ICS_) 6083 native_buffer[i].nativehandle = handle; 6084 native_buffer[i].privatehandle = handle; 6085 #endif 6086 if (!handle) { 6087 DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); 6088 return OMX_ErrorBadParameter; 6089 } 6090 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; 6091 drv_ctx.ptr_outputbuffer[i].offset = 0; 6092 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 6093 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 6094 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size; 6095 } else 6096 #endif 6097 6098 if (!ouput_egl_buffers && !m_use_output_pmem) { 6099 #ifdef USE_ION 6100 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 6101 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, 6102 &drv_ctx.op_buf_ion_info[i].ion_alloc_data, 6103 &drv_ctx.op_buf_ion_info[i].fd_ion_data, 6104 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0); 6105 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { 6106 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd); 6107 return OMX_ErrorInsufficientResources; 6108 } 6109 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 6110 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 6111 #else 6112 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 6113 open (MEM_DEVICE,O_RDWR); 6114 6115 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 6116 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 6117 return OMX_ErrorInsufficientResources; 6118 } 6119 6120 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */ 6121 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) { 6122 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 6123 open (MEM_DEVICE,O_RDWR); 6124 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 6125 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 6126 return OMX_ErrorInsufficientResources; 6127 } 6128 } 6129 6130 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, 6131 drv_ctx.op_buf.buffer_size, 6132 drv_ctx.op_buf.alignment)) { 6133 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 6134 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 6135 return OMX_ErrorInsufficientResources; 6136 } 6137 #endif 6138 if (!secure_mode) { 6139 drv_ctx.ptr_outputbuffer[i].bufferaddr = 6140 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, 6141 PROT_READ|PROT_WRITE, MAP_SHARED, 6142 drv_ctx.ptr_outputbuffer[i].pmem_fd,0); 6143 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { 6144 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 6145 #ifdef USE_ION 6146 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 6147 #endif 6148 DEBUG_PRINT_ERROR("Unable to mmap output buffer"); 6149 return OMX_ErrorInsufficientResources; 6150 } 6151 } 6152 drv_ctx.ptr_outputbuffer[i].offset = 0; 6153 privateAppData = appData; 6154 } else { 6155 6156 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem); 6157 if (!appData || !bytes ) { 6158 if (!secure_mode && !buffer) { 6159 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case"); 6160 return OMX_ErrorBadParameter; 6161 } 6162 } 6163 6164 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; 6165 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; 6166 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; 6167 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry || 6168 !pmem_list->nEntries || 6169 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 6170 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer"); 6171 return OMX_ErrorBadParameter; 6172 } 6173 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 6174 pmem_list->entryList->entry; 6175 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx", 6176 pmem_info->pmem_fd); 6177 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; 6178 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; 6179 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 6180 drv_ctx.ptr_outputbuffer[i].mmaped_size = 6181 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 6182 privateAppData = appData; 6183 } 6184 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 6185 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; 6186 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 6187 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 6188 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 6189 6190 *bufferHdr = (m_out_mem_ptr + i ); 6191 if (secure_mode) 6192 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 6193 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 6194 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], 6195 sizeof (vdec_bufferpayload)); 6196 6197 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i, 6198 drv_ctx.ptr_outputbuffer[i].bufferaddr, 6199 drv_ctx.ptr_outputbuffer[i].pmem_fd ); 6200 6201 buf.index = i; 6202 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6203 buf.memory = V4L2_MEMORY_USERPTR; 6204 plane[0].length = drv_ctx.op_buf.buffer_size; 6205 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 6206 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 6207 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd; 6208 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 6209 plane[0].data_offset = 0; 6210 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 6211 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 6212 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 6213 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 6214 #ifdef USE_ION 6215 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 6216 #endif 6217 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 6218 plane[extra_idx].data_offset = 0; 6219 } else if (extra_idx >= VIDEO_MAX_PLANES) { 6220 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 6221 return OMX_ErrorBadParameter; 6222 } 6223 buf.m.planes = plane; 6224 buf.length = drv_ctx.num_planes; 6225 6226 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) { 6227 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 6228 /*TODO: How to handle this case */ 6229 return OMX_ErrorInsufficientResources; 6230 } 6231 6232 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 6233 enum v4l2_buf_type buf_type; 6234 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6235 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 6236 return OMX_ErrorInsufficientResources; 6237 } else { 6238 streaming[CAPTURE_PORT] = true; 6239 DEBUG_PRINT_LOW("STREAMON Successful"); 6240 } 6241 6242 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 6243 request_perf_level(VIDC_TURBO); 6244 } 6245 6246 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; 6247 if (m_enable_android_native_buffers) { 6248 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle); 6249 (*bufferHdr)->pBuffer = (OMX_U8 *)handle; 6250 } else { 6251 (*bufferHdr)->pBuffer = buff; 6252 } 6253 (*bufferHdr)->pAppPrivate = privateAppData; 6254 BITMASK_SET(&m_out_bm_count,i); 6255 } 6256 return eRet; 6257 } 6258 6259 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() { 6260 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6261 OMX_BUFFERHEADERTYPE *bufHdr = NULL; 6262 int i = 0; 6263 6264 if (!m_client_output_extradata_mem_ptr) { 6265 int nBufferCount = 0; 6266 6267 nBufferCount = m_client_out_extradata_info.getBufferCount(); 6268 DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount); 6269 6270 m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE)); 6271 6272 if (m_client_output_extradata_mem_ptr) { 6273 bufHdr = m_client_output_extradata_mem_ptr; 6274 for (i=0; i < nBufferCount; i++) { 6275 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6276 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 6277 // Set the values when we determine the right HxW param 6278 bufHdr->nAllocLen = 0; 6279 bufHdr->nFilledLen = 0; 6280 bufHdr->pAppPrivate = NULL; 6281 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_EXTRADATA_INDEX; 6282 bufHdr->pBuffer = NULL; 6283 bufHdr->pOutputPortPrivate = NULL; 6284 bufHdr++; 6285 } 6286 } else { 6287 DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\ 6288 m_client_output_extradata_mem_ptr); 6289 eRet = OMX_ErrorInsufficientResources; 6290 } 6291 } 6292 return eRet; 6293 } 6294 OMX_ERRORTYPE omx_vdec::use_client_output_extradata_buffer( 6295 OMX_IN OMX_HANDLETYPE hComp, 6296 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6297 OMX_IN OMX_U32 port, 6298 OMX_IN OMX_PTR appData, 6299 OMX_IN OMX_U32 bytes, 6300 OMX_IN OMX_U8* buffer) 6301 { 6302 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6303 unsigned i = 0; // Temporary counter 6304 unsigned buffer_count = m_client_out_extradata_info.getBufferCount();; 6305 OMX_U32 buffer_size = m_client_out_extradata_info.getSize(); 6306 (void) hComp; 6307 6308 if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX || 6309 !client_extradata || bytes != buffer_size|| bufferHdr == NULL) { 6310 DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d," 6311 "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port, 6312 OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr); 6313 eRet = OMX_ErrorBadParameter; 6314 return eRet; 6315 } 6316 6317 if (!m_client_output_extradata_mem_ptr) { 6318 eRet = allocate_client_output_extradata_headers(); 6319 } 6320 6321 if (eRet == OMX_ErrorNone) { 6322 for (i = 0; i < buffer_count; i++) { 6323 if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) { 6324 break; 6325 } 6326 } 6327 } 6328 6329 if (i >= buffer_count) { 6330 DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count); 6331 eRet = OMX_ErrorInsufficientResources; 6332 } 6333 6334 if (eRet == OMX_ErrorNone) { 6335 BITMASK_SET(&m_out_extradata_bm_count,i); 6336 *bufferHdr = (m_client_output_extradata_mem_ptr + i ); 6337 (*bufferHdr)->pAppPrivate = appData; 6338 (*bufferHdr)->pBuffer = buffer; 6339 (*bufferHdr)->nAllocLen = bytes; 6340 } 6341 6342 return eRet; 6343 } 6344 /* ====================================================================== 6345 FUNCTION 6346 omx_vdec::use_input_heap_buffers 6347 6348 DESCRIPTION 6349 OMX Use Buffer Heap allocation method implementation. 6350 6351 PARAMETERS 6352 <TBD>. 6353 6354 RETURN VALUE 6355 OMX Error None , if everything successful. 6356 6357 ========================================================================== */ 6358 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( 6359 OMX_IN OMX_HANDLETYPE hComp, 6360 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6361 OMX_IN OMX_U32 port, 6362 OMX_IN OMX_PTR appData, 6363 OMX_IN OMX_U32 bytes, 6364 OMX_IN OMX_U8* buffer) 6365 { 6366 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer); 6367 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6368 6369 if (secure_mode) { 6370 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode"); 6371 return OMX_ErrorUndefined; 6372 } 6373 6374 if (!m_inp_heap_ptr) 6375 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) 6376 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 6377 drv_ctx.ip_buf.actualcount); 6378 if (!m_phdr_pmem_ptr) 6379 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) 6380 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 6381 drv_ctx.ip_buf.actualcount); 6382 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) { 6383 DEBUG_PRINT_ERROR("Insufficent memory"); 6384 eRet = OMX_ErrorInsufficientResources; 6385 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) { 6386 input_use_buffer = true; 6387 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); 6388 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; 6389 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; 6390 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; 6391 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; 6392 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; 6393 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; 6394 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); 6395 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); 6396 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt], 6397 (unsigned)NULL, (unsigned)NULL)) { 6398 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 6399 return OMX_ErrorInsufficientResources; 6400 } 6401 m_in_alloc_cnt++; 6402 } else { 6403 DEBUG_PRINT_ERROR("All i/p buffers have been set!"); 6404 eRet = OMX_ErrorInsufficientResources; 6405 } 6406 return eRet; 6407 } 6408 6409 /* ====================================================================== 6410 FUNCTION 6411 omx_vdec::UseBuffer 6412 6413 DESCRIPTION 6414 OMX Use Buffer method implementation. 6415 6416 PARAMETERS 6417 <TBD>. 6418 6419 RETURN VALUE 6420 OMX Error None , if everything successful. 6421 6422 ========================================================================== */ 6423 OMX_ERRORTYPE omx_vdec::use_buffer( 6424 OMX_IN OMX_HANDLETYPE hComp, 6425 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6426 OMX_IN OMX_U32 port, 6427 OMX_IN OMX_PTR appData, 6428 OMX_IN OMX_U32 bytes, 6429 OMX_IN OMX_U8* buffer) 6430 { 6431 OMX_ERRORTYPE error = OMX_ErrorNone; 6432 struct vdec_setbuffer_cmd setbuffers; 6433 6434 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) { 6435 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer); 6436 return OMX_ErrorBadParameter; 6437 } 6438 if (m_state == OMX_StateInvalid) { 6439 DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); 6440 return OMX_ErrorInvalidState; 6441 } 6442 if (port == OMX_CORE_INPUT_PORT_INDEX) { 6443 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), 6444 // ensure that use-buffer was called for previous allocation. 6445 // Mix-and-match of useBuffer and allocateBuffer is not allowed 6446 if (m_inp_mem_ptr && !input_use_buffer) { 6447 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !"); 6448 return OMX_ErrorUndefined; 6449 } 6450 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); 6451 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 6452 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested 6453 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) { 6454 error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer); 6455 } else { 6456 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 6457 error = OMX_ErrorBadPortIndex; 6458 } 6459 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error); 6460 if (error == OMX_ErrorNone) { 6461 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 6462 // Send the callback now 6463 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 6464 post_event(OMX_CommandStateSet,OMX_StateIdle, 6465 OMX_COMPONENT_GENERATE_EVENT); 6466 } 6467 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && 6468 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 6469 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 6470 post_event(OMX_CommandPortEnable, 6471 OMX_CORE_INPUT_PORT_INDEX, 6472 OMX_COMPONENT_GENERATE_EVENT); 6473 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && 6474 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 6475 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 6476 post_event(OMX_CommandPortEnable, 6477 OMX_CORE_OUTPUT_PORT_INDEX, 6478 OMX_COMPONENT_GENERATE_EVENT); 6479 } 6480 } 6481 return error; 6482 } 6483 6484 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, 6485 OMX_BUFFERHEADERTYPE *pmem_bufferHdr) 6486 { 6487 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) { 6488 if (m_inp_heap_ptr[bufferindex].pBuffer) 6489 free(m_inp_heap_ptr[bufferindex].pBuffer); 6490 m_inp_heap_ptr[bufferindex].pBuffer = NULL; 6491 } 6492 if (pmem_bufferHdr) 6493 free_input_buffer(pmem_bufferHdr); 6494 return OMX_ErrorNone; 6495 } 6496 6497 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 6498 { 6499 unsigned int index = 0; 6500 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) { 6501 return OMX_ErrorBadParameter; 6502 } 6503 6504 index = bufferHdr - m_inp_mem_ptr; 6505 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 6506 6507 auto_lock l(buf_lock); 6508 bufferHdr->pInputPortPrivate = NULL; 6509 6510 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) { 6511 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 6512 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) { 6513 struct vdec_setbuffer_cmd setbuffers; 6514 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; 6515 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], 6516 sizeof (vdec_bufferpayload)); 6517 if (!secure_mode) { 6518 DEBUG_PRINT_LOW("unmap the input buffer fd=%d", 6519 drv_ctx.ptr_inputbuffer[index].pmem_fd); 6520 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p", 6521 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size, 6522 drv_ctx.ptr_inputbuffer[index].bufferaddr); 6523 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, 6524 drv_ctx.ptr_inputbuffer[index].mmaped_size); 6525 } 6526 6527 if (allocate_native_handle){ 6528 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer; 6529 native_handle_close(nh); 6530 native_handle_delete(nh); 6531 } else { 6532 // Close fd for non-secure and secure non-native-handle case 6533 close(drv_ctx.ptr_inputbuffer[index].pmem_fd); 6534 } 6535 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; 6536 6537 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) { 6538 free(m_desc_buffer_ptr[index].buf_addr); 6539 m_desc_buffer_ptr[index].buf_addr = NULL; 6540 m_desc_buffer_ptr[index].desc_data_size = 0; 6541 } 6542 #ifdef USE_ION 6543 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); 6544 #endif 6545 m_in_alloc_cnt--; 6546 } 6547 } 6548 6549 return OMX_ErrorNone; 6550 } 6551 6552 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 6553 { 6554 unsigned int index = 0; 6555 6556 if (bufferHdr == NULL || m_out_mem_ptr == NULL) { 6557 return OMX_ErrorBadParameter; 6558 } 6559 6560 index = bufferHdr - m_out_mem_ptr; 6561 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index); 6562 6563 if (index < drv_ctx.op_buf.actualcount 6564 && drv_ctx.ptr_outputbuffer) { 6565 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index, 6566 drv_ctx.ptr_outputbuffer[index].bufferaddr); 6567 6568 struct vdec_setbuffer_cmd setbuffers; 6569 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 6570 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], 6571 sizeof (vdec_bufferpayload)); 6572 6573 if (!dynamic_buf_mode) { 6574 if (streaming[CAPTURE_PORT] && 6575 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) { 6576 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) { 6577 DEBUG_PRINT_ERROR("STREAMOFF Failed"); 6578 } else { 6579 DEBUG_PRINT_LOW("STREAMOFF Successful"); 6580 } 6581 } 6582 #ifdef _ANDROID_ 6583 if (m_enable_android_native_buffers) { 6584 if (!secure_mode) { 6585 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { 6586 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, 6587 drv_ctx.ptr_outputbuffer[index].mmaped_size); 6588 } 6589 } 6590 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; 6591 } else { 6592 #endif 6593 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0 6594 && !ouput_egl_buffers && !m_use_output_pmem) { 6595 if (drv_ctx.op_buf_map_info[index].free_buffer) { 6596 if (!secure_mode) { 6597 DEBUG_PRINT_LOW("unmap the output buffer fd = %d", 6598 drv_ctx.ptr_outputbuffer[0].pmem_fd); 6599 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p", 6600 (unsigned int)drv_ctx.op_buf_map_info[index].map_size, 6601 drv_ctx.op_buf_map_info[index].base_address); 6602 munmap (drv_ctx.op_buf_map_info[index].base_address, 6603 drv_ctx.op_buf_map_info[index].map_size); 6604 } 6605 close (drv_ctx.ptr_outputbuffer[index].pmem_fd); 6606 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; 6607 #ifdef USE_ION 6608 free_ion_memory(&drv_ctx.op_buf_ion_info[index]); 6609 #endif 6610 } else { 6611 drv_ctx.op_buf_ion_info[index].ion_device_fd = -1; 6612 drv_ctx.op_buf_ion_info[index].ion_alloc_data.handle = 0; 6613 drv_ctx.op_buf_ion_info[index].fd_ion_data.fd = -1; 6614 } 6615 drv_ctx.op_buf_map_info[index].free_buffer = false; 6616 drv_ctx.op_buf_map_info[index].base_address = NULL; 6617 drv_ctx.op_buf_map_info[index].map_size = 0; 6618 drv_ctx.op_buf_map_info[index].offset = 0; 6619 } 6620 #ifdef _ANDROID_ 6621 } 6622 #endif 6623 } //!dynamic_buf_mode 6624 if (release_output_done()) { 6625 free_extradata(); 6626 } 6627 } 6628 6629 return OMX_ErrorNone; 6630 6631 } 6632 6633 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, 6634 OMX_BUFFERHEADERTYPE **bufferHdr, 6635 OMX_U32 port, 6636 OMX_PTR appData, 6637 OMX_U32 bytes) 6638 { 6639 OMX_BUFFERHEADERTYPE *input = NULL; 6640 unsigned char *buf_addr = NULL; 6641 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6642 unsigned i = 0; 6643 6644 /* Sanity Check*/ 6645 if (bufferHdr == NULL) { 6646 return OMX_ErrorBadParameter; 6647 } 6648 6649 if (m_inp_heap_ptr == NULL) { 6650 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ 6651 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 6652 drv_ctx.ip_buf.actualcount); 6653 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ 6654 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 6655 drv_ctx.ip_buf.actualcount); 6656 6657 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) { 6658 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed "); 6659 return OMX_ErrorInsufficientResources; 6660 } 6661 } 6662 6663 /*Find a Free index*/ 6664 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 6665 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) { 6666 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 6667 break; 6668 } 6669 } 6670 6671 if (i < drv_ctx.ip_buf.actualcount) { 6672 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); 6673 6674 if (buf_addr == NULL) { 6675 return OMX_ErrorInsufficientResources; 6676 } 6677 6678 *bufferHdr = (m_inp_heap_ptr + i); 6679 input = *bufferHdr; 6680 BITMASK_SET(&m_heap_inp_bm_count,i); 6681 6682 input->pBuffer = (OMX_U8 *)buf_addr; 6683 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6684 input->nVersion.nVersion = OMX_SPEC_VERSION; 6685 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 6686 input->pAppPrivate = appData; 6687 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 6688 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr ); 6689 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); 6690 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]); 6691 /*Add the Buffers to freeq*/ 6692 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i], 6693 (unsigned)NULL, (unsigned)NULL)) { 6694 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 6695 return OMX_ErrorInsufficientResources; 6696 } 6697 } else { 6698 return OMX_ErrorBadParameter; 6699 } 6700 6701 return eRet; 6702 6703 } 6704 6705 6706 /* ====================================================================== 6707 FUNCTION 6708 omx_vdec::AllocateInputBuffer 6709 6710 DESCRIPTION 6711 Helper function for allocate buffer in the input pin 6712 6713 PARAMETERS 6714 None. 6715 6716 RETURN VALUE 6717 true/false 6718 6719 ========================================================================== */ 6720 OMX_ERRORTYPE omx_vdec::allocate_input_buffer( 6721 OMX_IN OMX_HANDLETYPE hComp, 6722 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6723 OMX_IN OMX_U32 port, 6724 OMX_IN OMX_PTR appData, 6725 OMX_IN OMX_U32 bytes) 6726 { 6727 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6728 struct vdec_setbuffer_cmd setbuffers; 6729 OMX_BUFFERHEADERTYPE *input = NULL; 6730 unsigned i = 0; 6731 unsigned char *buf_addr = NULL; 6732 int pmem_fd = -1; 6733 6734 (void) hComp; 6735 (void) port; 6736 6737 6738 if (bytes != drv_ctx.ip_buf.buffer_size) { 6739 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u", 6740 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size); 6741 return OMX_ErrorBadParameter; 6742 } 6743 6744 if (!m_inp_mem_ptr) { 6745 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)", 6746 drv_ctx.ip_buf.actualcount, 6747 (unsigned int)drv_ctx.ip_buf.buffer_size); 6748 6749 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ 6750 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); 6751 6752 if (m_inp_mem_ptr == NULL) { 6753 return OMX_ErrorInsufficientResources; 6754 } 6755 6756 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ 6757 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); 6758 6759 if (drv_ctx.ptr_inputbuffer == NULL) { 6760 return OMX_ErrorInsufficientResources; 6761 } 6762 #ifdef USE_ION 6763 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ 6764 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); 6765 6766 if (drv_ctx.ip_buf_ion_info == NULL) { 6767 return OMX_ErrorInsufficientResources; 6768 } 6769 #endif 6770 6771 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) { 6772 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; 6773 #ifdef USE_ION 6774 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; 6775 #endif 6776 } 6777 } 6778 6779 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 6780 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 6781 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 6782 break; 6783 } 6784 } 6785 6786 if (i < drv_ctx.ip_buf.actualcount) { 6787 struct v4l2_buffer buf; 6788 struct v4l2_plane plane; 6789 int rc; 6790 DEBUG_PRINT_LOW("Allocate input Buffer"); 6791 #ifdef USE_ION 6792 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 6793 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, 6794 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, 6795 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? 6796 SECURE_FLAGS_INPUT_BUFFER : 0); 6797 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { 6798 return OMX_ErrorInsufficientResources; 6799 } 6800 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; 6801 #else 6802 pmem_fd = open (MEM_DEVICE,O_RDWR); 6803 6804 if (pmem_fd < 0) { 6805 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 6806 return OMX_ErrorInsufficientResources; 6807 } 6808 6809 if (pmem_fd == 0) { 6810 pmem_fd = open (MEM_DEVICE,O_RDWR); 6811 6812 if (pmem_fd < 0) { 6813 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 6814 return OMX_ErrorInsufficientResources; 6815 } 6816 } 6817 6818 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, 6819 drv_ctx.ip_buf.alignment)) { 6820 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 6821 close(pmem_fd); 6822 return OMX_ErrorInsufficientResources; 6823 } 6824 #endif 6825 if (!secure_mode) { 6826 buf_addr = (unsigned char *)mmap(NULL, 6827 drv_ctx.ip_buf.buffer_size, 6828 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); 6829 6830 if (buf_addr == MAP_FAILED) { 6831 close(pmem_fd); 6832 #ifdef USE_ION 6833 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); 6834 #endif 6835 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer"); 6836 return OMX_ErrorInsufficientResources; 6837 } 6838 } 6839 *bufferHdr = (m_inp_mem_ptr + i); 6840 if (secure_mode) 6841 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; 6842 else 6843 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; 6844 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; 6845 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; 6846 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; 6847 drv_ctx.ptr_inputbuffer [i].offset = 0; 6848 6849 6850 buf.index = i; 6851 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6852 buf.memory = V4L2_MEMORY_USERPTR; 6853 plane.bytesused = 0; 6854 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size; 6855 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr; 6856 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd; 6857 plane.reserved[1] = 0; 6858 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset; 6859 buf.m.planes = &plane; 6860 buf.length = 1; 6861 6862 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i, 6863 drv_ctx.ptr_inputbuffer[i].bufferaddr); 6864 6865 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 6866 6867 if (rc) { 6868 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 6869 /*TODO: How to handle this case */ 6870 return OMX_ErrorInsufficientResources; 6871 } 6872 6873 input = *bufferHdr; 6874 BITMASK_SET(&m_inp_bm_count,i); 6875 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr); 6876 if (allocate_native_handle) { 6877 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/); 6878 if (!nh) { 6879 DEBUG_PRINT_ERROR("Native handle create failed"); 6880 return OMX_ErrorInsufficientResources; 6881 } 6882 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd; 6883 input->pBuffer = (OMX_U8 *)nh; 6884 } else if (secure_mode || m_input_pass_buffer_fd) { 6885 /*Legacy method, pass ion fd stashed directly in pBuffer*/ 6886 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd; 6887 } else { 6888 input->pBuffer = (OMX_U8 *)buf_addr; 6889 } 6890 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6891 input->nVersion.nVersion = OMX_SPEC_VERSION; 6892 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 6893 input->pAppPrivate = appData; 6894 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 6895 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; 6896 6897 if (drv_ctx.disable_dmx) { 6898 eRet = allocate_desc_buffer(i); 6899 } 6900 } else { 6901 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found"); 6902 eRet = OMX_ErrorInsufficientResources; 6903 } 6904 return eRet; 6905 } 6906 6907 6908 /* ====================================================================== 6909 FUNCTION 6910 omx_vdec::AllocateOutputBuffer 6911 6912 DESCRIPTION 6913 Helper fn for AllocateBuffer in the output pin 6914 6915 PARAMETERS 6916 <TBD>. 6917 6918 RETURN VALUE 6919 OMX Error None if everything went well. 6920 6921 ========================================================================== */ 6922 OMX_ERRORTYPE omx_vdec::allocate_output_buffer( 6923 OMX_IN OMX_HANDLETYPE hComp, 6924 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6925 OMX_IN OMX_U32 port, 6926 OMX_IN OMX_PTR appData, 6927 OMX_IN OMX_U32 bytes) 6928 { 6929 (void)hComp; 6930 (void)port; 6931 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6932 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 6933 unsigned i= 0; // Temporary counter 6934 struct vdec_setbuffer_cmd setbuffers; 6935 int extra_idx = 0; 6936 #ifdef USE_ION 6937 int ion_device_fd =-1; 6938 struct ion_allocation_data ion_alloc_data; 6939 struct ion_fd_data fd_ion_data; 6940 #endif 6941 if (!m_out_mem_ptr) { 6942 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)", 6943 drv_ctx.op_buf.actualcount, 6944 (unsigned int)drv_ctx.op_buf.buffer_size); 6945 int nBufHdrSize = 0; 6946 int nPlatformEntrySize = 0; 6947 int nPlatformListSize = 0; 6948 int nPMEMInfoSize = 0; 6949 6950 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 6951 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 6952 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 6953 6954 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)", 6955 drv_ctx.op_buf.actualcount); 6956 nBufHdrSize = drv_ctx.op_buf.actualcount * 6957 sizeof(OMX_BUFFERHEADERTYPE); 6958 6959 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 6960 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 6961 nPlatformListSize = drv_ctx.op_buf.actualcount * 6962 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 6963 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 6964 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 6965 6966 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 6967 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 6968 nPMEMInfoSize, 6969 nPlatformListSize); 6970 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, 6971 drv_ctx.op_buf.actualcount); 6972 unsigned char *pmem_baseaddress_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {NULL}; 6973 int pmem_fd[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {-1}; 6974 int alloc_size[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {0}; 6975 static const int block_max_size = 128 * 1024 * 1024; 6976 unsigned int block_buf_count = block_max_size / drv_ctx.op_buf.buffer_size; 6977 unsigned int last_block_buf_count = 0, block_count = 1; 6978 if (drv_ctx.op_buf.actualcount <= block_buf_count) { 6979 block_buf_count = drv_ctx.op_buf.actualcount; 6980 } else { 6981 last_block_buf_count = drv_ctx.op_buf.actualcount % block_buf_count; 6982 block_count = (drv_ctx.op_buf.actualcount + block_buf_count - 1) / block_buf_count; 6983 } 6984 unsigned int idx = 0; 6985 DEBUG_PRINT_LOW("block_count = %d block_buf_count = %d last_block_buf_count = %d", 6986 block_count, block_buf_count, last_block_buf_count); 6987 #ifdef USE_ION 6988 struct vdec_ion op_buf_ion_info_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS]; 6989 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED; 6990 for (; idx < block_count; idx++) { 6991 int cnt = ((idx == block_count - 1) && last_block_buf_count) ? 6992 last_block_buf_count : block_buf_count; 6993 alloc_size[idx] = drv_ctx.op_buf.buffer_size * cnt; 6994 // Allocate output buffers as cached to improve performance of software-reading 6995 // of the YUVs. Output buffers are cache-invalidated in driver. 6996 // If color-conversion is involved, Only the C2D output buffers are cached, no 6997 // need to cache the decoder's output buffers 6998 op_buf_ion_info_temp[idx].ion_device_fd = alloc_map_ion_memory( 6999 alloc_size[idx], 7000 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment, 7001 &op_buf_ion_info_temp[idx].ion_alloc_data, &op_buf_ion_info_temp[idx].fd_ion_data, 7002 (secure_mode && !secure_scaling_to_non_secure_opb) ? 7003 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag); 7004 if (op_buf_ion_info_temp[idx].ion_device_fd < 0) { 7005 DEBUG_PRINT_LOW("Failed to allocate chunk %ul size = %d", idx, alloc_size[idx]); 7006 break; 7007 } 7008 pmem_fd[idx] = op_buf_ion_info_temp[idx].fd_ion_data.fd; 7009 DEBUG_PRINT_LOW("Allocated chunk %ul fd = %ul size = %d", idx, pmem_fd[idx], alloc_size[idx]); 7010 } 7011 if (idx != block_count) { 7012 for (OMX_U32 i = 0; i < idx; i++) { 7013 close(pmem_fd[i]); 7014 free_ion_memory(&op_buf_ion_info_temp[i]); 7015 } 7016 return OMX_ErrorInsufficientResources; 7017 } 7018 7019 #else 7020 for (idx = 0; idx < block_count; idx++) { 7021 pmem_fd[idx] = open (MEM_DEVICE,O_RDWR); 7022 7023 if (pmem_fd[idx] < 0) { 7024 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 7025 drv_ctx.op_buf.buffer_size); 7026 break; 7027 } 7028 int cnt = ((idx == block_count - 1) && last_block_buf_count) ? 7029 last_block_buf_count : block_buf_count; 7030 if (!align_pmem_buffers(pmem_fd[idx], drv_ctx.op_buf.buffer_size * cnt, 7031 drv_ctx.op_buf.alignment)) { 7032 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 7033 close(pmem_fd[idx]); 7034 break; 7035 } 7036 } 7037 if (idx != block_count) { 7038 for (i = 0; i < idx; i++) { 7039 close(pmem_fd[i]); 7040 } 7041 return OMX_ErrorInsufficientResources; 7042 } 7043 #endif 7044 if (!secure_mode) { 7045 idx = 0; 7046 for (; idx < block_count; idx++) { 7047 pmem_baseaddress_temp[idx] = (unsigned char *)mmap(NULL, 7048 alloc_size[idx], 7049 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd[idx], 0); 7050 7051 if (pmem_baseaddress_temp[idx] == MAP_FAILED) { 7052 DEBUG_PRINT_ERROR("MMAP failed for Size %u for fd = %d", 7053 (unsigned int)alloc_size[idx], pmem_fd[idx]); 7054 close(pmem_fd[idx]); 7055 #ifdef USE_ION 7056 free_ion_memory(&op_buf_ion_info_temp[idx]); 7057 #endif 7058 break; 7059 } 7060 } 7061 if (idx != block_count) { 7062 for (i = 0; i < idx; i++) { 7063 munmap(pmem_baseaddress_temp[idx], alloc_size[idx]); 7064 close(pmem_fd[i]); 7065 #ifdef USE_ION 7066 free_ion_memory(&op_buf_ion_info_temp[i]); 7067 #endif 7068 } 7069 return OMX_ErrorInsufficientResources; 7070 } 7071 } 7072 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 7073 // Alloc mem for platform specific info 7074 char *pPtr=NULL; 7075 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 7076 nPMEMInfoSize,1); 7077 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ 7078 calloc (sizeof(struct vdec_bufferpayload), 7079 drv_ctx.op_buf.actualcount); 7080 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 7081 calloc (sizeof (struct vdec_output_frameinfo), 7082 drv_ctx.op_buf.actualcount); 7083 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 7084 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer "); 7085 return OMX_ErrorInsufficientResources; 7086 } 7087 7088 #ifdef USE_ION 7089 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ 7090 calloc (sizeof(struct vdec_ion), 7091 drv_ctx.op_buf.actualcount); 7092 if (!drv_ctx.op_buf_ion_info) { 7093 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 7094 return OMX_ErrorInsufficientResources; 7095 } 7096 #endif 7097 drv_ctx.op_buf_map_info = (struct vdec_ion_map_info *)\ 7098 calloc (sizeof(struct vdec_ion_map_info), 7099 drv_ctx.op_buf.actualcount); 7100 if (!drv_ctx.op_buf_map_info) { 7101 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_map_info"); 7102 return OMX_ErrorInsufficientResources; 7103 } 7104 7105 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 7106 && drv_ctx.ptr_respbuffer) { 7107 drv_ctx.ptr_outputbuffer[0].mmaped_size = 7108 (drv_ctx.op_buf.buffer_size * 7109 drv_ctx.op_buf.actualcount); 7110 bufHdr = m_out_mem_ptr; 7111 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 7112 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 7113 (((char *) m_platform_list) + nPlatformListSize); 7114 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 7115 (((char *) m_platform_entry) + nPlatformEntrySize); 7116 pPlatformList = m_platform_list; 7117 pPlatformEntry = m_platform_entry; 7118 pPMEMInfo = m_pmem_info; 7119 7120 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 7121 7122 // Settting the entire storage nicely 7123 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry); 7124 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 7125 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 7126 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 7127 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 7128 // Set the values when we determine the right HxW param 7129 bufHdr->nAllocLen = bytes; 7130 bufHdr->nFilledLen = 0; 7131 bufHdr->pAppPrivate = appData; 7132 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 7133 // Platform specific PMEM Information 7134 // Initialize the Platform Entry 7135 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i); 7136 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 7137 pPlatformEntry->entry = pPMEMInfo; 7138 // Initialize the Platform List 7139 pPlatformList->nEntries = 1; 7140 pPlatformList->entryList = pPlatformEntry; 7141 // Keep pBuffer NULL till vdec is opened 7142 bufHdr->pBuffer = NULL; 7143 bufHdr->nOffset = 0; 7144 7145 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i; 7146 pPMEMInfo->pmem_fd = -1; 7147 bufHdr->pPlatformPrivate = pPlatformList; 7148 7149 int block_idx = i / block_buf_count; 7150 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd[block_idx]; 7151 m_pmem_info[i].pmem_fd = pmem_fd[block_idx]; 7152 #ifdef USE_ION 7153 drv_ctx.op_buf_ion_info[i].ion_device_fd = op_buf_ion_info_temp[block_idx].ion_device_fd; 7154 drv_ctx.op_buf_ion_info[i].ion_alloc_data = op_buf_ion_info_temp[block_idx].ion_alloc_data; 7155 drv_ctx.op_buf_ion_info[i].fd_ion_data = op_buf_ion_info_temp[block_idx].fd_ion_data; 7156 #endif 7157 drv_ctx.op_buf_map_info[i].free_buffer = !(i % block_buf_count); 7158 drv_ctx.op_buf_map_info[i].base_address = pmem_baseaddress_temp[block_idx]; 7159 drv_ctx.op_buf_map_info[i].map_size = alloc_size[block_idx]; 7160 drv_ctx.op_buf_map_info[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count); 7161 7162 /*Create a mapping between buffers*/ 7163 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 7164 drv_ctx.ptr_respbuffer[i].client_data = (void *)\ 7165 &drv_ctx.ptr_outputbuffer[i]; 7166 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count); 7167 drv_ctx.ptr_outputbuffer[i].bufferaddr = 7168 pmem_baseaddress_temp[block_idx] + (drv_ctx.op_buf.buffer_size * (i % block_buf_count)); 7169 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 7170 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 7171 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 7172 7173 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p", 7174 pmem_fd[block_idx], (unsigned int)drv_ctx.ptr_outputbuffer[i].offset, 7175 drv_ctx.ptr_outputbuffer[i].bufferaddr); 7176 // Move the buffer and buffer header pointers 7177 bufHdr++; 7178 pPMEMInfo++; 7179 pPlatformEntry++; 7180 pPlatformList++; 7181 } 7182 } else { 7183 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 7184 m_out_mem_ptr, pPtr); 7185 if (m_out_mem_ptr) { 7186 free(m_out_mem_ptr); 7187 m_out_mem_ptr = NULL; 7188 } 7189 if (pPtr) { 7190 free(pPtr); 7191 pPtr = NULL; 7192 } 7193 if (drv_ctx.ptr_outputbuffer) { 7194 free(drv_ctx.ptr_outputbuffer); 7195 drv_ctx.ptr_outputbuffer = NULL; 7196 } 7197 if (drv_ctx.ptr_respbuffer) { 7198 free(drv_ctx.ptr_respbuffer); 7199 drv_ctx.ptr_respbuffer = NULL; 7200 } 7201 #ifdef USE_ION 7202 if (drv_ctx.op_buf_ion_info) { 7203 DEBUG_PRINT_LOW("Free o/p ion context"); 7204 free(drv_ctx.op_buf_ion_info); 7205 drv_ctx.op_buf_ion_info = NULL; 7206 } 7207 #endif 7208 free(drv_ctx.op_buf_map_info); 7209 drv_ctx.op_buf_map_info = NULL; 7210 eRet = OMX_ErrorInsufficientResources; 7211 } 7212 if (eRet == OMX_ErrorNone) 7213 eRet = allocate_extradata(); 7214 } 7215 7216 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 7217 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 7218 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i); 7219 break; 7220 } 7221 } 7222 7223 if (eRet == OMX_ErrorNone) { 7224 if (i < drv_ctx.op_buf.actualcount) { 7225 struct v4l2_buffer buf; 7226 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 7227 int rc; 7228 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 7229 7230 drv_ctx.ptr_outputbuffer[i].buffer_len = 7231 drv_ctx.op_buf.buffer_size; 7232 7233 *bufferHdr = (m_out_mem_ptr + i ); 7234 if (secure_mode) { 7235 #ifdef USE_ION 7236 drv_ctx.ptr_outputbuffer[i].bufferaddr = 7237 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 7238 #else 7239 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 7240 #endif 7241 } 7242 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; 7243 7244 buf.index = i; 7245 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 7246 buf.memory = V4L2_MEMORY_USERPTR; 7247 plane[0].length = drv_ctx.op_buf.buffer_size; 7248 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 7249 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 7250 #ifdef USE_ION 7251 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 7252 #endif 7253 plane[0].reserved[1] = drv_ctx.op_buf_map_info[i].offset; 7254 plane[0].data_offset = 0; 7255 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 7256 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 7257 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 7258 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 7259 #ifdef USE_ION 7260 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 7261 #endif 7262 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 7263 plane[extra_idx].data_offset = 0; 7264 } else if (extra_idx >= VIDEO_MAX_PLANES) { 7265 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx); 7266 return OMX_ErrorBadParameter; 7267 } 7268 buf.m.planes = plane; 7269 buf.length = drv_ctx.num_planes; 7270 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr); 7271 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 7272 if (rc) { 7273 /*TODO: How to handle this case */ 7274 return OMX_ErrorInsufficientResources; 7275 } 7276 7277 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { 7278 enum v4l2_buf_type buf_type; 7279 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 7280 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 7281 if (rc) { 7282 return OMX_ErrorInsufficientResources; 7283 } else { 7284 streaming[CAPTURE_PORT] = true; 7285 DEBUG_PRINT_LOW("STREAMON Successful"); 7286 } 7287 7288 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 7289 request_perf_level(VIDC_TURBO); 7290 } 7291 7292 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 7293 (*bufferHdr)->pAppPrivate = appData; 7294 BITMASK_SET(&m_out_bm_count,i); 7295 } else { 7296 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient"); 7297 eRet = OMX_ErrorInsufficientResources; 7298 } 7299 } 7300 7301 return eRet; 7302 } 7303 7304 7305 // AllocateBuffer -- API Call 7306 /* ====================================================================== 7307 FUNCTION 7308 omx_vdec::AllocateBuffer 7309 7310 DESCRIPTION 7311 Returns zero if all the buffers released.. 7312 7313 PARAMETERS 7314 None. 7315 7316 RETURN VALUE 7317 true/false 7318 7319 ========================================================================== */ 7320 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, 7321 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 7322 OMX_IN OMX_U32 port, 7323 OMX_IN OMX_PTR appData, 7324 OMX_IN OMX_U32 bytes) 7325 { 7326 unsigned i = 0; 7327 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type 7328 7329 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port); 7330 if (m_state == OMX_StateInvalid) { 7331 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State"); 7332 return OMX_ErrorInvalidState; 7333 } 7334 7335 if (port == OMX_CORE_INPUT_PORT_INDEX) { 7336 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), 7337 // ensure that use-buffer was never called. 7338 // Mix-and-match of useBuffer and allocateBuffer is not allowed 7339 if (m_inp_mem_ptr && input_use_buffer) { 7340 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !"); 7341 return OMX_ErrorUndefined; 7342 } 7343 if (arbitrary_bytes) { 7344 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); 7345 } else { 7346 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); 7347 } 7348 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 7349 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port, 7350 appData,bytes); 7351 } else { 7352 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 7353 eRet = OMX_ErrorBadPortIndex; 7354 } 7355 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); 7356 if (eRet == OMX_ErrorNone) { 7357 if (allocate_done()) { 7358 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 7359 // Send the callback now 7360 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 7361 post_event(OMX_CommandStateSet,OMX_StateIdle, 7362 OMX_COMPONENT_GENERATE_EVENT); 7363 } 7364 } 7365 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) { 7366 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 7367 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 7368 post_event(OMX_CommandPortEnable, 7369 OMX_CORE_INPUT_PORT_INDEX, 7370 OMX_COMPONENT_GENERATE_EVENT); 7371 } 7372 } 7373 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) { 7374 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 7375 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 7376 post_event(OMX_CommandPortEnable, 7377 OMX_CORE_OUTPUT_PORT_INDEX, 7378 OMX_COMPONENT_GENERATE_EVENT); 7379 } 7380 } 7381 } 7382 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet); 7383 return eRet; 7384 } 7385 7386 // Free Buffer - API call 7387 /* ====================================================================== 7388 FUNCTION 7389 omx_vdec::FreeBuffer 7390 7391 DESCRIPTION 7392 7393 PARAMETERS 7394 None. 7395 7396 RETURN VALUE 7397 true/false 7398 7399 ========================================================================== */ 7400 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, 7401 OMX_IN OMX_U32 port, 7402 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7403 { 7404 OMX_ERRORTYPE eRet = OMX_ErrorNone; 7405 unsigned int nPortIndex; 7406 (void) hComp; 7407 DEBUG_PRINT_LOW("In for decoder free_buffer"); 7408 7409 if (m_state == OMX_StateIdle && 7410 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 7411 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); 7412 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| 7413 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) { 7414 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port); 7415 } else if ((port == OMX_CORE_INPUT_PORT_INDEX && 7416 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) || 7417 (port == OMX_CORE_OUTPUT_PORT_INDEX && 7418 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) { 7419 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port); 7420 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) { 7421 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled"); 7422 post_event(OMX_EventError, 7423 OMX_ErrorPortUnpopulated, 7424 OMX_COMPONENT_GENERATE_EVENT); 7425 7426 return OMX_ErrorIncorrectStateOperation; 7427 } else if (m_state != OMX_StateInvalid) { 7428 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers"); 7429 post_event(OMX_EventError, 7430 OMX_ErrorPortUnpopulated, 7431 OMX_COMPONENT_GENERATE_EVENT); 7432 } 7433 7434 if (port == OMX_CORE_INPUT_PORT_INDEX) { 7435 /*Check if arbitrary bytes*/ 7436 if (!arbitrary_bytes && !input_use_buffer) 7437 nPortIndex = buffer - m_inp_mem_ptr; 7438 else 7439 nPortIndex = buffer - m_inp_heap_ptr; 7440 7441 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); 7442 if (nPortIndex < drv_ctx.ip_buf.actualcount && 7443 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { 7444 // Clear the bit associated with it. 7445 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); 7446 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); 7447 if (input_use_buffer == true) { 7448 7449 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex); 7450 if (m_phdr_pmem_ptr) 7451 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); 7452 } else { 7453 if (arbitrary_bytes) { 7454 if (m_phdr_pmem_ptr) 7455 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); 7456 else 7457 free_input_buffer(nPortIndex,NULL); 7458 } else 7459 free_input_buffer(buffer); 7460 } 7461 m_inp_bPopulated = OMX_FALSE; 7462 if(release_input_done()) 7463 release_buffers(this, VDEC_BUFFER_TYPE_INPUT); 7464 /*Free the Buffer Header*/ 7465 if (release_input_done()) { 7466 DEBUG_PRINT_HIGH("ALL input buffers are freed/released"); 7467 free_input_buffer_header(); 7468 } 7469 } else { 7470 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid"); 7471 eRet = OMX_ErrorBadPortIndex; 7472 } 7473 7474 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) 7475 && release_input_done()) { 7476 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 7477 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); 7478 post_event(OMX_CommandPortDisable, 7479 OMX_CORE_INPUT_PORT_INDEX, 7480 OMX_COMPONENT_GENERATE_EVENT); 7481 } 7482 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 7483 // check if the buffer is valid 7484 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 7485 if (nPortIndex < drv_ctx.op_buf.actualcount && 7486 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { 7487 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); 7488 // Clear the bit associated with it. 7489 BITMASK_CLEAR(&m_out_bm_count,nPortIndex); 7490 m_out_bPopulated = OMX_FALSE; 7491 client_buffers.free_output_buffer (buffer); 7492 7493 if(release_output_done()) { 7494 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT); 7495 } 7496 if (release_output_done()) { 7497 free_output_buffer_header(); 7498 } 7499 } else { 7500 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid"); 7501 eRet = OMX_ErrorBadPortIndex; 7502 } 7503 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) 7504 && release_output_done()) { 7505 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it"); 7506 7507 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 7508 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 7509 #ifdef _ANDROID_ICS_ 7510 if (m_enable_android_native_buffers) { 7511 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); 7512 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 7513 } 7514 #endif 7515 7516 post_event(OMX_CommandPortDisable, 7517 OMX_CORE_OUTPUT_PORT_INDEX, 7518 OMX_COMPONENT_GENERATE_EVENT); 7519 } 7520 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) { 7521 nPortIndex = buffer - m_client_output_extradata_mem_ptr; 7522 DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex); 7523 7524 BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex); 7525 7526 if (release_output_extradata_done()) { 7527 free_output_extradata_buffer_header(); 7528 } 7529 } else { 7530 eRet = OMX_ErrorBadPortIndex; 7531 } 7532 if ((eRet == OMX_ErrorNone) && 7533 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 7534 if (release_done()) { 7535 /* 7536 * Reset buffer requirements here to ensure setting buffer requirement 7537 * when component move to executing state from loaded state via idle. 7538 */ 7539 drv_ctx.op_buf.buffer_size = 0; 7540 drv_ctx.op_buf.actualcount = 0; 7541 7542 // Send the callback now 7543 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); 7544 post_event(OMX_CommandStateSet, OMX_StateLoaded, 7545 OMX_COMPONENT_GENERATE_EVENT); 7546 } 7547 } 7548 return eRet; 7549 } 7550 7551 7552 /* ====================================================================== 7553 FUNCTION 7554 omx_vdec::EmptyThisBuffer 7555 7556 DESCRIPTION 7557 This routine is used to push the encoded video frames to 7558 the video decoder. 7559 7560 PARAMETERS 7561 None. 7562 7563 RETURN VALUE 7564 OMX Error None if everything went successful. 7565 7566 ========================================================================== */ 7567 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 7568 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7569 { 7570 OMX_ERRORTYPE ret1 = OMX_ErrorNone; 7571 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; 7572 7573 if (m_state != OMX_StateExecuting && 7574 m_state != OMX_StatePause && 7575 m_state != OMX_StateIdle) { 7576 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State"); 7577 return OMX_ErrorInvalidState; 7578 } 7579 7580 if (buffer == NULL) { 7581 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL"); 7582 return OMX_ErrorBadParameter; 7583 } 7584 7585 if (!m_inp_bEnabled) { 7586 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled."); 7587 return OMX_ErrorIncorrectStateOperation; 7588 } 7589 7590 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) { 7591 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex); 7592 return OMX_ErrorBadPortIndex; 7593 } 7594 7595 if (perf_flag) { 7596 if (!latency) { 7597 dec_time.stop(); 7598 latency = dec_time.processing_time_us(); 7599 dec_time.start(); 7600 } 7601 } 7602 7603 if (arbitrary_bytes) { 7604 nBufferIndex = buffer - m_inp_heap_ptr; 7605 } else { 7606 if (input_use_buffer == true) { 7607 nBufferIndex = buffer - m_inp_heap_ptr; 7608 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { 7609 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode"); 7610 return OMX_ErrorBadParameter; 7611 } 7612 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; 7613 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; 7614 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; 7615 buffer = &m_inp_mem_ptr[nBufferIndex]; 7616 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u", 7617 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen); 7618 } else { 7619 nBufferIndex = buffer - m_inp_mem_ptr; 7620 } 7621 } 7622 7623 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { 7624 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); 7625 return OMX_ErrorBadParameter; 7626 } 7627 7628 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 7629 codec_config_flag = true; 7630 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); 7631 } 7632 7633 /* The client should not set this when codec is in arbitrary bytes mode */ 7634 if (m_input_pass_buffer_fd) { 7635 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr; 7636 } 7637 7638 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)", 7639 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen); 7640 if (arbitrary_bytes) { 7641 post_event ((unsigned long)hComp,(unsigned long)buffer, 7642 OMX_COMPONENT_GENERATE_ETB_ARBITRARY); 7643 } else { 7644 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB); 7645 } 7646 time_stamp_dts.insert_timestamp(buffer); 7647 return OMX_ErrorNone; 7648 } 7649 7650 /* ====================================================================== 7651 FUNCTION 7652 omx_vdec::empty_this_buffer_proxy 7653 7654 DESCRIPTION 7655 This routine is used to push the encoded video frames to 7656 the video decoder. 7657 7658 PARAMETERS 7659 None. 7660 7661 RETURN VALUE 7662 OMX Error None if everything went successful. 7663 7664 ========================================================================== */ 7665 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, 7666 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7667 { 7668 VIDC_TRACE_NAME_HIGH("ETB"); 7669 (void) hComp; 7670 int push_cnt = 0,i=0; 7671 unsigned nPortIndex = 0; 7672 OMX_ERRORTYPE ret = OMX_ErrorNone; 7673 struct vdec_input_frameinfo frameinfo; 7674 struct vdec_bufferpayload *temp_buffer; 7675 struct vdec_seqheader seq_header; 7676 bool port_setting_changed = true; 7677 7678 /*Should we generate a Aync error event*/ 7679 if (buffer == NULL || buffer->pInputPortPrivate == NULL) { 7680 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid"); 7681 return OMX_ErrorBadParameter; 7682 } 7683 7684 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 7685 7686 if (nPortIndex >= drv_ctx.ip_buf.actualcount) { 7687 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", 7688 nPortIndex); 7689 return OMX_ErrorBadParameter; 7690 } 7691 7692 pending_input_buffers++; 7693 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers); 7694 7695 /* return zero length and not an EOS buffer */ 7696 if (!arbitrary_bytes && (buffer->nFilledLen == 0) && 7697 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) { 7698 DEBUG_PRINT_HIGH("return zero legth buffer"); 7699 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 7700 OMX_COMPONENT_GENERATE_EBD); 7701 return OMX_ErrorNone; 7702 } 7703 7704 if (input_flush_progress == true) { 7705 DEBUG_PRINT_LOW("Flush in progress return buffer "); 7706 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 7707 OMX_COMPONENT_GENERATE_EBD); 7708 return OMX_ErrorNone; 7709 } 7710 7711 auto_lock l(buf_lock); 7712 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; 7713 7714 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) { 7715 return OMX_ErrorBadParameter; 7716 } 7717 /* If its first frame, H264 codec and reject is true, then parse the nal 7718 and get the profile. Based on this, reject the clip playback */ 7719 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 && 7720 m_reject_avc_1080p_mp) { 7721 first_frame = 1; 7722 DEBUG_PRINT_ERROR("Parse nal to get the profile"); 7723 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen, 7724 NALU_TYPE_SPS); 7725 m_profile = h264_parser->get_profile(); 7726 ret = is_video_session_supported(); 7727 if (ret) { 7728 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD); 7729 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT); 7730 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */ 7731 m_state = OMX_StateInvalid; 7732 return OMX_ErrorNone; 7733 } 7734 } 7735 7736 VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000); 7737 VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen); 7738 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7739 /*for use buffer we need to memcpy the data*/ 7740 temp_buffer->buffer_len = buffer->nFilledLen; 7741 7742 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) { 7743 if (buffer->nFilledLen <= temp_buffer->buffer_len) { 7744 if (arbitrary_bytes) { 7745 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); 7746 } else { 7747 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), 7748 buffer->nFilledLen); 7749 } 7750 } else { 7751 return OMX_ErrorBadParameter; 7752 } 7753 7754 } 7755 7756 frameinfo.bufferaddr = temp_buffer->bufferaddr; 7757 frameinfo.client_data = (void *) buffer; 7758 frameinfo.datalen = temp_buffer->buffer_len; 7759 frameinfo.flags = 0; 7760 frameinfo.offset = buffer->nOffset; 7761 frameinfo.pmem_fd = temp_buffer->pmem_fd; 7762 frameinfo.pmem_offset = temp_buffer->offset; 7763 frameinfo.timestamp = buffer->nTimeStamp; 7764 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) { 7765 DEBUG_PRINT_LOW("ETB: dmx enabled"); 7766 if (m_demux_entries == 0) { 7767 extract_demux_addr_offsets(buffer); 7768 } 7769 7770 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries); 7771 handle_demux_data(buffer); 7772 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; 7773 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; 7774 } else { 7775 frameinfo.desc_addr = NULL; 7776 frameinfo.desc_size = 0; 7777 } 7778 if (!arbitrary_bytes) { 7779 frameinfo.flags |= buffer->nFlags; 7780 } 7781 7782 #ifdef _ANDROID_ 7783 if (m_debug_timestamp) { 7784 if (arbitrary_bytes) { 7785 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 7786 m_timestamp_list.insert_ts(buffer->nTimeStamp); 7787 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 7788 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 7789 m_timestamp_list.insert_ts(buffer->nTimeStamp); 7790 } 7791 } 7792 #endif 7793 7794 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); 7795 7796 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 7797 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7798 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7799 } 7800 7801 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 7802 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached"); 7803 frameinfo.flags |= VDEC_BUFFERFLAG_EOS; 7804 h264_scratch.nFilledLen = 0; 7805 nal_count = 0; 7806 look_ahead_nal = false; 7807 frame_count = 0; 7808 if (m_frame_parser.mutils) 7809 m_frame_parser.mutils->initialize_frame_checking_environment(); 7810 m_frame_parser.flush(); 7811 h264_last_au_ts = LLONG_MAX; 7812 h264_last_au_flags = 0; 7813 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 7814 m_demux_entries = 0; 7815 } 7816 struct v4l2_buffer buf; 7817 struct v4l2_plane plane; 7818 memset( (void *)&buf, 0, sizeof(buf)); 7819 memset( (void *)&plane, 0, sizeof(plane)); 7820 int rc; 7821 unsigned long print_count; 7822 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 7823 buf.flags = V4L2_QCOM_BUF_FLAG_EOS; 7824 DEBUG_PRINT_HIGH("INPUT EOS reached") ; 7825 } 7826 OMX_ERRORTYPE eRet = OMX_ErrorNone; 7827 buf.index = nPortIndex; 7828 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 7829 buf.memory = V4L2_MEMORY_USERPTR; 7830 plane.bytesused = temp_buffer->buffer_len; 7831 plane.length = drv_ctx.ip_buf.buffer_size; 7832 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr - 7833 (unsigned long)temp_buffer->offset; 7834 plane.reserved[0] = temp_buffer->pmem_fd; 7835 plane.reserved[1] = temp_buffer->offset; 7836 plane.data_offset = 0; 7837 buf.m.planes = &plane; 7838 buf.length = 1; 7839 if (frameinfo.timestamp >= LLONG_MAX) { 7840 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID; 7841 } 7842 //assumption is that timestamp is in milliseconds 7843 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000; 7844 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000); 7845 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0; 7846 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0; 7847 7848 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 7849 DEBUG_PRINT_LOW("Increment codec_config buffer counter"); 7850 android_atomic_inc(&m_queued_codec_config_count); 7851 } 7852 7853 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 7854 if (rc) { 7855 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client"); 7856 m_cb.EmptyBufferDone(hComp, m_app_data, buffer); 7857 return OMX_ErrorHardware; 7858 } 7859 7860 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 7861 codec_config_flag = false; 7862 } 7863 if (!streaming[OUTPUT_PORT]) { 7864 enum v4l2_buf_type buf_type; 7865 int ret,r; 7866 7867 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 7868 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 7869 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 7870 if (!ret) { 7871 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful"); 7872 streaming[OUTPUT_PORT] = true; 7873 } else if (errno == EBUSY) { 7874 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD"); 7875 post_event ((unsigned long)buffer, VDEC_S_SUCCESS, 7876 OMX_COMPONENT_GENERATE_EBD); 7877 return OMX_ErrorInsufficientResources; 7878 } else { 7879 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT"); 7880 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued"); 7881 post_event ((unsigned long)buffer, VDEC_S_SUCCESS, 7882 OMX_COMPONENT_GENERATE_EBD); 7883 return OMX_ErrorBadParameter; 7884 } 7885 } 7886 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)", 7887 frameinfo.bufferaddr, (long long)frameinfo.timestamp, 7888 (unsigned int)frameinfo.datalen); 7889 7890 return ret; 7891 } 7892 7893 /* ====================================================================== 7894 FUNCTION 7895 omx_vdec::FillThisBuffer 7896 7897 DESCRIPTION 7898 IL client uses this method to release the frame buffer 7899 after displaying them. 7900 7901 PARAMETERS 7902 None. 7903 7904 RETURN VALUE 7905 true/false 7906 7907 ========================================================================== */ 7908 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 7909 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7910 { 7911 if (m_state != OMX_StateExecuting && 7912 m_state != OMX_StatePause && 7913 m_state != OMX_StateIdle) { 7914 DEBUG_PRINT_ERROR("FTB in Invalid State"); 7915 return OMX_ErrorInvalidState; 7916 } 7917 7918 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { 7919 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex); 7920 return OMX_ErrorBadPortIndex; 7921 } 7922 7923 if (!m_out_bEnabled) { 7924 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); 7925 return OMX_ErrorIncorrectStateOperation; 7926 } 7927 7928 unsigned nPortIndex = 0; 7929 if (dynamic_buf_mode) { 7930 private_handle_t *handle = NULL; 7931 struct VideoDecoderOutputMetaData *meta; 7932 unsigned int nPortIndex = 0; 7933 7934 if (!buffer || !buffer->pBuffer) { 7935 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer); 7936 return OMX_ErrorBadParameter; 7937 } 7938 7939 //get the buffer type and fd info 7940 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer; 7941 handle = (private_handle_t *)meta->pHandle; 7942 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle); 7943 7944 if (!handle) { 7945 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle); 7946 return OMX_ErrorBadParameter; 7947 } 7948 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF 7949 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 7950 if (nPortIndex < drv_ctx.op_buf.actualcount && 7951 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 7952 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd; 7953 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer; 7954 7955 //Store private handle from GraphicBuffer 7956 native_buffer[nPortIndex].privatehandle = handle; 7957 native_buffer[nPortIndex].nativehandle = handle; 7958 } else { 7959 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex); 7960 return OMX_ErrorBadParameter; 7961 } 7962 7963 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite 7964 //this with a more sane size so that we don't compensate in rest of code 7965 //We'll restore this size later on, so that it's transparent to client 7966 buffer->nFilledLen = 0; 7967 buffer->nAllocLen = handle->size; 7968 7969 if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) { 7970 m_is_display_session = true; 7971 } else { 7972 m_is_display_session = false; 7973 } 7974 DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session); 7975 7976 drv_ctx.op_buf.buffer_size = handle->size; 7977 } 7978 7979 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 7980 if (buffer == NULL || 7981 (nPortIndex >= drv_ctx.op_buf.actualcount)) { 7982 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 7983 nPortIndex, drv_ctx.op_buf.actualcount); 7984 return OMX_ErrorBadParameter; 7985 } 7986 7987 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7988 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg); 7989 return OMX_ErrorNone; 7990 } 7991 /* ====================================================================== 7992 FUNCTION 7993 omx_vdec::fill_this_buffer_proxy 7994 7995 DESCRIPTION 7996 IL client uses this method to release the frame buffer 7997 after displaying them. 7998 7999 PARAMETERS 8000 None. 8001 8002 RETURN VALUE 8003 true/false 8004 8005 ========================================================================== */ 8006 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( 8007 OMX_IN OMX_HANDLETYPE hComp, 8008 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) 8009 { 8010 VIDC_TRACE_NAME_HIGH("FTB"); 8011 OMX_ERRORTYPE nRet = OMX_ErrorNone; 8012 OMX_BUFFERHEADERTYPE *buffer = bufferAdd; 8013 unsigned nPortIndex = 0; 8014 struct vdec_fillbuffer_cmd fillbuffer; 8015 struct vdec_bufferpayload *ptr_outputbuffer = NULL; 8016 struct vdec_output_frameinfo *ptr_respbuffer = NULL; 8017 8018 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 8019 8020 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) { 8021 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 8022 nPortIndex, drv_ctx.op_buf.actualcount); 8023 return OMX_ErrorBadParameter; 8024 } 8025 8026 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", 8027 bufferAdd, bufferAdd->pBuffer); 8028 /*Return back the output buffer to client*/ 8029 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) { 8030 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition"); 8031 buffer->nFilledLen = 0; 8032 m_cb.FillBufferDone (hComp,m_app_data,buffer); 8033 return OMX_ErrorNone; 8034 } 8035 8036 if (dynamic_buf_mode) { 8037 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0; 8038 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen; 8039 buf_ref_add(nPortIndex); 8040 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen; 8041 } 8042 8043 pending_output_buffers++; 8044 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers); 8045 buffer = client_buffers.get_dr_buf_hdr(bufferAdd); 8046 if (!buffer) { 8047 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid"); 8048 return OMX_ErrorBadParameter; 8049 } 8050 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; 8051 if (ptr_respbuffer) { 8052 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; 8053 } 8054 8055 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) { 8056 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); 8057 buffer->nFilledLen = 0; 8058 m_cb.FillBufferDone (hComp,m_app_data,buffer); 8059 pending_output_buffers--; 8060 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers); 8061 return OMX_ErrorBadParameter; 8062 } 8063 8064 int rc = 0; 8065 struct v4l2_buffer buf; 8066 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 8067 memset( (void *)&buf, 0, sizeof(buf)); 8068 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); 8069 unsigned int extra_idx = 0; 8070 8071 buf.index = nPortIndex; 8072 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8073 buf.memory = V4L2_MEMORY_USERPTR; 8074 plane[0].bytesused = buffer->nFilledLen; 8075 plane[0].length = buffer->nAllocLen; 8076 plane[0].m.userptr = 8077 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr - 8078 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset; 8079 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 8080 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 8081 plane[0].data_offset = 0; 8082 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 8083 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 8084 plane[extra_idx].bytesused = 0; 8085 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 8086 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size); 8087 #ifdef USE_ION 8088 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 8089 #endif 8090 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; 8091 plane[extra_idx].data_offset = 0; 8092 } else if (extra_idx >= VIDEO_MAX_PLANES) { 8093 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx); 8094 return OMX_ErrorBadParameter; 8095 } 8096 buf.m.planes = plane; 8097 buf.length = drv_ctx.num_planes; 8098 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d", 8099 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress); 8100 8101 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 8102 if (rc) { 8103 buffer->nFilledLen = 0; 8104 DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno)); 8105 m_cb.FillBufferDone(hComp, m_app_data, buffer); 8106 return OMX_ErrorHardware; 8107 } 8108 8109 return OMX_ErrorNone; 8110 } 8111 8112 /* ====================================================================== 8113 FUNCTION 8114 omx_vdec::SetCallbacks 8115 8116 DESCRIPTION 8117 Set the callbacks. 8118 8119 PARAMETERS 8120 None. 8121 8122 RETURN VALUE 8123 OMX Error None if everything successful. 8124 8125 ========================================================================== */ 8126 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, 8127 OMX_IN OMX_CALLBACKTYPE* callbacks, 8128 OMX_IN OMX_PTR appData) 8129 { 8130 (void) hComp; 8131 m_cb = *callbacks; 8132 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ 8133 m_cb.EventHandler,m_cb.FillBufferDone); 8134 m_app_data = appData; 8135 return OMX_ErrorNotImplemented; 8136 } 8137 8138 /* ====================================================================== 8139 FUNCTION 8140 omx_vdec::ComponentDeInit 8141 8142 DESCRIPTION 8143 Destroys the component and release memory allocated to the heap. 8144 8145 PARAMETERS 8146 <TBD>. 8147 8148 RETURN VALUE 8149 OMX Error None if everything successful. 8150 8151 ========================================================================== */ 8152 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) 8153 { 8154 (void) hComp; 8155 8156 unsigned i = 0; 8157 if (OMX_StateLoaded != m_state) { 8158 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\ 8159 m_state); 8160 DEBUG_PRINT_ERROR("Playback Ended - FAILED"); 8161 } else { 8162 DEBUG_PRINT_HIGH("Playback Ended - PASSED"); 8163 } 8164 8165 /*Check if the output buffers have to be cleaned up*/ 8166 if (m_out_mem_ptr) { 8167 DEBUG_PRINT_LOW("Freeing the Output Memory"); 8168 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) { 8169 if (BITMASK_PRESENT(&m_out_bm_count, i)) { 8170 BITMASK_CLEAR(&m_out_bm_count, i); 8171 client_buffers.free_output_buffer (&m_out_mem_ptr[i]); 8172 } 8173 8174 if (release_output_done()) { 8175 break; 8176 } 8177 } 8178 #ifdef _ANDROID_ICS_ 8179 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 8180 #endif 8181 } 8182 8183 /*Check if the input buffers have to be cleaned up*/ 8184 if (m_inp_mem_ptr || m_inp_heap_ptr) { 8185 DEBUG_PRINT_LOW("Freeing the Input Memory"); 8186 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) { 8187 8188 if (BITMASK_PRESENT(&m_inp_bm_count, i)) { 8189 BITMASK_CLEAR(&m_inp_bm_count, i); 8190 if (m_inp_mem_ptr) 8191 free_input_buffer (i,&m_inp_mem_ptr[i]); 8192 else 8193 free_input_buffer (i,NULL); 8194 } 8195 8196 if (release_input_done()) { 8197 break; 8198 } 8199 } 8200 } 8201 free_input_buffer_header(); 8202 free_output_buffer_header(); 8203 if (h264_scratch.pBuffer) { 8204 free(h264_scratch.pBuffer); 8205 h264_scratch.pBuffer = NULL; 8206 } 8207 8208 if (h264_parser) { 8209 delete h264_parser; 8210 h264_parser = NULL; 8211 } 8212 8213 if (m_frame_parser.mutils) { 8214 DEBUG_PRINT_LOW("Free utils parser"); 8215 delete (m_frame_parser.mutils); 8216 m_frame_parser.mutils = NULL; 8217 } 8218 8219 if (m_platform_list) { 8220 free(m_platform_list); 8221 m_platform_list = NULL; 8222 } 8223 if (m_vendor_config.pData) { 8224 free(m_vendor_config.pData); 8225 m_vendor_config.pData = NULL; 8226 } 8227 8228 // Reset counters in mesg queues 8229 m_ftb_q.m_size=0; 8230 m_cmd_q.m_size=0; 8231 m_etb_q.m_size=0; 8232 m_ftb_q.m_read = m_ftb_q.m_write =0; 8233 m_cmd_q.m_read = m_cmd_q.m_write =0; 8234 m_etb_q.m_read = m_etb_q.m_write =0; 8235 #ifdef _ANDROID_ 8236 if (m_debug_timestamp) { 8237 m_timestamp_list.reset_ts_list(); 8238 } 8239 #endif 8240 8241 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG"); 8242 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, 8243 // NULL); 8244 DEBUG_PRINT_HIGH("Close the driver instance"); 8245 8246 if (m_debug.infile) { 8247 fclose(m_debug.infile); 8248 m_debug.infile = NULL; 8249 } 8250 if (m_debug.outfile) { 8251 fclose(m_debug.outfile); 8252 m_debug.outfile = NULL; 8253 } 8254 if (m_debug.out_ymeta_file) { 8255 fclose(m_debug.out_ymeta_file); 8256 m_debug.out_ymeta_file = NULL; 8257 } 8258 if (m_debug.out_uvmeta_file) { 8259 fclose(m_debug.out_uvmeta_file); 8260 m_debug.out_uvmeta_file = NULL; 8261 } 8262 #ifdef OUTPUT_EXTRADATA_LOG 8263 if (outputExtradataFile) 8264 fclose (outputExtradataFile); 8265 #endif 8266 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete"); 8267 return OMX_ErrorNone; 8268 } 8269 8270 /* ====================================================================== 8271 FUNCTION 8272 omx_vdec::UseEGLImage 8273 8274 DESCRIPTION 8275 OMX Use EGL Image method implementation <TBD>. 8276 8277 PARAMETERS 8278 <TBD>. 8279 8280 RETURN VALUE 8281 Not Implemented error. 8282 8283 ========================================================================== */ 8284 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, 8285 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 8286 OMX_IN OMX_U32 port, 8287 OMX_IN OMX_PTR appData, 8288 OMX_IN void* eglImage) 8289 { 8290 (void) appData; 8291 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; 8292 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; 8293 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; 8294 8295 #ifdef USE_EGL_IMAGE_GPU 8296 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; 8297 EGLint fd = -1, offset = 0,pmemPtr = 0; 8298 #else 8299 int fd = -1, offset = 0; 8300 #endif 8301 DEBUG_PRINT_HIGH("use EGL image support for decoder"); 8302 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { 8303 DEBUG_PRINT_ERROR("Invalid EGL image"); 8304 } 8305 #ifdef USE_EGL_IMAGE_GPU 8306 if (m_display_id == NULL) { 8307 DEBUG_PRINT_ERROR("Display ID is not set by IL client"); 8308 return OMX_ErrorInsufficientResources; 8309 } 8310 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) 8311 eglGetProcAddress("eglQueryImageKHR"); 8312 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd); 8313 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset); 8314 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr); 8315 #else //with OMX test app 8316 struct temp_egl { 8317 int pmem_fd; 8318 int offset; 8319 }; 8320 struct temp_egl *temp_egl_id = NULL; 8321 void * pmemPtr = (void *) eglImage; 8322 temp_egl_id = (struct temp_egl *)eglImage; 8323 if (temp_egl_id != NULL) { 8324 fd = temp_egl_id->pmem_fd; 8325 offset = temp_egl_id->offset; 8326 } 8327 #endif 8328 if (fd < 0) { 8329 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd); 8330 return OMX_ErrorInsufficientResources; 8331 } 8332 pmem_info.pmem_fd = (OMX_U32) fd; 8333 pmem_info.offset = (OMX_U32) offset; 8334 pmem_entry.entry = (void *) &pmem_info; 8335 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 8336 pmem_list.entryList = &pmem_entry; 8337 pmem_list.nEntries = 1; 8338 ouput_egl_buffers = true; 8339 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, 8340 (void *)&pmem_list, drv_ctx.op_buf.buffer_size, 8341 (OMX_U8 *)pmemPtr)) { 8342 DEBUG_PRINT_ERROR("use buffer call failed for egl image"); 8343 return OMX_ErrorInsufficientResources; 8344 } 8345 return OMX_ErrorNone; 8346 } 8347 8348 /* ====================================================================== 8349 FUNCTION 8350 omx_vdec::ComponentRoleEnum 8351 8352 DESCRIPTION 8353 OMX Component Role Enum method implementation. 8354 8355 PARAMETERS 8356 <TBD>. 8357 8358 RETURN VALUE 8359 OMX Error None if everything is successful. 8360 ========================================================================== */ 8361 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, 8362 OMX_OUT OMX_U8* role, 8363 OMX_IN OMX_U32 index) 8364 { 8365 (void) hComp; 8366 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8367 8368 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 8369 if ((0 == index) && role) { 8370 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); 8371 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8372 } else { 8373 eRet = OMX_ErrorNoMore; 8374 } 8375 } 8376 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 8377 if ((0 == index) && role) { 8378 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); 8379 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8380 } else { 8381 eRet = OMX_ErrorNoMore; 8382 } 8383 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) { 8384 if ((0 == index) && role) { 8385 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 8386 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8387 } else { 8388 DEBUG_PRINT_LOW("No more roles"); 8389 eRet = OMX_ErrorNoMore; 8390 } 8391 } 8392 8393 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || 8394 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) { 8395 if ((0 == index) && role) { 8396 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 8397 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8398 } else { 8399 DEBUG_PRINT_LOW("No more roles"); 8400 eRet = OMX_ErrorNoMore; 8401 } 8402 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 8403 if ((0 == index) && role) { 8404 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 8405 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8406 } else { 8407 DEBUG_PRINT_LOW("No more roles"); 8408 eRet = OMX_ErrorNoMore; 8409 } 8410 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 8411 if ((0 == index) && role) { 8412 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 8413 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8414 } else { 8415 DEBUG_PRINT_LOW("No more roles"); 8416 eRet = OMX_ErrorNoMore; 8417 } 8418 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 8419 if ((0 == index) && role) { 8420 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 8421 DEBUG_PRINT_LOW("component_role_enum: role %s", role); 8422 } else { 8423 DEBUG_PRINT_LOW("No more roles"); 8424 eRet = OMX_ErrorNoMore; 8425 } 8426 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || 8427 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) 8428 ) { 8429 if ((0 == index) && role) { 8430 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 8431 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8432 } else { 8433 DEBUG_PRINT_LOW("No more roles"); 8434 eRet = OMX_ErrorNoMore; 8435 } 8436 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) { 8437 if ((0 == index) && role) { 8438 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 8439 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8440 } else { 8441 DEBUG_PRINT_LOW("No more roles"); 8442 eRet = OMX_ErrorNoMore; 8443 } 8444 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) { 8445 if ((0 == index) && role) { 8446 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE); 8447 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 8448 } else { 8449 DEBUG_PRINT_LOW("No more roles"); 8450 eRet = OMX_ErrorNoMore; 8451 } 8452 } else { 8453 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component"); 8454 eRet = OMX_ErrorInvalidComponentName; 8455 } 8456 return eRet; 8457 } 8458 8459 8460 8461 8462 /* ====================================================================== 8463 FUNCTION 8464 omx_vdec::AllocateDone 8465 8466 DESCRIPTION 8467 Checks if entire buffer pool is allocated by IL Client or not. 8468 Need this to move to IDLE state. 8469 8470 PARAMETERS 8471 None. 8472 8473 RETURN VALUE 8474 true/false. 8475 8476 ========================================================================== */ 8477 bool omx_vdec::allocate_done(void) 8478 { 8479 bool bRet = false; 8480 bool bRet_In = false; 8481 bool bRet_Out = false; 8482 bool bRet_Out_Extra = false; 8483 8484 bRet_In = allocate_input_done(); 8485 bRet_Out = allocate_output_done(); 8486 bRet_Out_Extra = allocate_output_extradata_done(); 8487 8488 if (bRet_In && bRet_Out && bRet_Out_Extra) { 8489 bRet = true; 8490 } 8491 8492 return bRet; 8493 } 8494 /* ====================================================================== 8495 FUNCTION 8496 omx_vdec::AllocateInputDone 8497 8498 DESCRIPTION 8499 Checks if I/P buffer pool is allocated by IL Client or not. 8500 8501 PARAMETERS 8502 None. 8503 8504 RETURN VALUE 8505 true/false. 8506 8507 ========================================================================== */ 8508 bool omx_vdec::allocate_input_done(void) 8509 { 8510 bool bRet = false; 8511 unsigned i=0; 8512 8513 if (m_inp_mem_ptr == NULL) { 8514 return bRet; 8515 } 8516 if (m_inp_mem_ptr ) { 8517 for (; i<drv_ctx.ip_buf.actualcount; i++) { 8518 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 8519 break; 8520 } 8521 } 8522 } 8523 if (i == drv_ctx.ip_buf.actualcount) { 8524 bRet = true; 8525 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers"); 8526 } 8527 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) { 8528 m_inp_bPopulated = OMX_TRUE; 8529 } 8530 return bRet; 8531 } 8532 /* ====================================================================== 8533 FUNCTION 8534 omx_vdec::AllocateOutputDone 8535 8536 DESCRIPTION 8537 Checks if entire O/P buffer pool is allocated by IL Client or not. 8538 8539 PARAMETERS 8540 None. 8541 8542 RETURN VALUE 8543 true/false. 8544 8545 ========================================================================== */ 8546 bool omx_vdec::allocate_output_done(void) 8547 { 8548 bool bRet = false; 8549 unsigned j=0; 8550 8551 if (m_out_mem_ptr == NULL) { 8552 return bRet; 8553 } 8554 8555 if (m_out_mem_ptr) { 8556 for (; j < drv_ctx.op_buf.actualcount; j++) { 8557 if (BITMASK_ABSENT(&m_out_bm_count,j)) { 8558 break; 8559 } 8560 } 8561 } 8562 8563 if (j == drv_ctx.op_buf.actualcount) { 8564 bRet = true; 8565 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers"); 8566 if (m_out_bEnabled) 8567 m_out_bPopulated = OMX_TRUE; 8568 } 8569 8570 return bRet; 8571 } 8572 8573 bool omx_vdec::allocate_output_extradata_done(void) { 8574 bool bRet = false; 8575 unsigned j=0; 8576 unsigned nBufferCount = 0; 8577 8578 nBufferCount = m_client_out_extradata_info.getBufferCount(); 8579 8580 if (!m_client_out_extradata_info.is_client_extradata_enabled()) { 8581 return true; 8582 } 8583 8584 if (m_client_output_extradata_mem_ptr) { 8585 for (; j < nBufferCount; j++) { 8586 if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) { 8587 break; 8588 } 8589 } 8590 8591 if (j == nBufferCount) { 8592 bRet = true; 8593 DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers"); 8594 } 8595 } 8596 8597 return bRet; 8598 } 8599 /* ====================================================================== 8600 FUNCTION 8601 omx_vdec::ReleaseDone 8602 8603 DESCRIPTION 8604 Checks if IL client has released all the buffers. 8605 8606 PARAMETERS 8607 None. 8608 8609 RETURN VALUE 8610 true/false 8611 8612 ========================================================================== */ 8613 bool omx_vdec::release_done(void) 8614 { 8615 bool bRet = false; 8616 8617 if (release_input_done()) { 8618 if (release_output_done()) { 8619 if (release_output_extradata_done()) { 8620 bRet = true; 8621 } 8622 } 8623 } 8624 return bRet; 8625 } 8626 8627 8628 /* ====================================================================== 8629 FUNCTION 8630 omx_vdec::ReleaseOutputDone 8631 8632 DESCRIPTION 8633 Checks if IL client has released all the buffers. 8634 8635 PARAMETERS 8636 None. 8637 8638 RETURN VALUE 8639 true/false 8640 8641 ========================================================================== */ 8642 bool omx_vdec::release_output_done(void) 8643 { 8644 bool bRet = false; 8645 unsigned i=0,j=0; 8646 8647 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr); 8648 if (m_out_mem_ptr) { 8649 for (; j < drv_ctx.op_buf.actualcount ; j++) { 8650 if (BITMASK_PRESENT(&m_out_bm_count,j)) { 8651 break; 8652 } 8653 } 8654 if (j == drv_ctx.op_buf.actualcount) { 8655 m_out_bm_count = 0; 8656 bRet = true; 8657 } 8658 } else { 8659 m_out_bm_count = 0; 8660 bRet = true; 8661 } 8662 return bRet; 8663 } 8664 /* ====================================================================== 8665 FUNCTION 8666 omx_vdec::ReleaseInputDone 8667 8668 DESCRIPTION 8669 Checks if IL client has released all the buffers. 8670 8671 PARAMETERS 8672 None. 8673 8674 RETURN VALUE 8675 true/false 8676 8677 ========================================================================== */ 8678 bool omx_vdec::release_input_done(void) 8679 { 8680 bool bRet = false; 8681 unsigned i=0,j=0; 8682 8683 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr); 8684 if (m_inp_mem_ptr) { 8685 for (; j<drv_ctx.ip_buf.actualcount; j++) { 8686 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) { 8687 break; 8688 } 8689 } 8690 if (j==drv_ctx.ip_buf.actualcount) { 8691 bRet = true; 8692 } 8693 } else { 8694 bRet = true; 8695 } 8696 return bRet; 8697 } 8698 8699 bool omx_vdec::release_output_extradata_done(void) { 8700 bool bRet = false; 8701 unsigned i=0,j=0, buffer_count=0; 8702 8703 buffer_count = m_client_out_extradata_info.getBufferCount(); 8704 DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d", 8705 m_client_output_extradata_mem_ptr, buffer_count); 8706 8707 if (m_client_output_extradata_mem_ptr) { 8708 for (; j<buffer_count; j++) { 8709 if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) { 8710 break; 8711 } 8712 } 8713 if (j == buffer_count) { 8714 bRet = true; 8715 } 8716 } else { 8717 bRet = true; 8718 } 8719 return bRet; 8720 } 8721 8722 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, 8723 OMX_BUFFERHEADERTYPE * buffer) 8724 { 8725 VIDC_TRACE_NAME_HIGH("FBD"); 8726 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; 8727 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) { 8728 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer); 8729 return OMX_ErrorBadParameter; 8730 } else if (output_flush_progress) { 8731 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); 8732 buffer->nFilledLen = 0; 8733 buffer->nTimeStamp = 0; 8734 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 8735 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 8736 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 8737 } 8738 8739 if (m_debug_extradata) { 8740 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 8741 DEBUG_PRINT_HIGH("***************************************************"); 8742 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received"); 8743 DEBUG_PRINT_HIGH("***************************************************"); 8744 } 8745 8746 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) { 8747 DEBUG_PRINT_HIGH("***************************************************"); 8748 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 8749 DEBUG_PRINT_HIGH("***************************************************"); 8750 } 8751 } 8752 8753 8754 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld", 8755 buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp); 8756 pending_output_buffers --; 8757 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers); 8758 8759 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8760 DEBUG_PRINT_HIGH("Output EOS has been reached"); 8761 if (!output_flush_progress) 8762 post_event((unsigned)NULL, (unsigned)NULL, 8763 OMX_COMPONENT_GENERATE_EOS_DONE); 8764 8765 if (psource_frame) { 8766 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); 8767 psource_frame = NULL; 8768 } 8769 if (pdest_frame) { 8770 pdest_frame->nFilledLen = 0; 8771 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL, 8772 (unsigned)NULL); 8773 pdest_frame = NULL; 8774 } 8775 } 8776 8777 #ifdef OUTPUT_EXTRADATA_LOG 8778 if (outputExtradataFile) { 8779 int buf_index = buffer - m_out_mem_ptr; 8780 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr); 8781 8782 OMX_OTHER_EXTRADATATYPE *p_extra = NULL; 8783 p_extra = (OMX_OTHER_EXTRADATATYPE *) 8784 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3)); 8785 8786 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) { 8787 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x", 8788 p_extra->nSize, p_extra->eType); 8789 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); 8790 8791 if (p_extra->eType == OMX_ExtraDataNone) { 8792 break; 8793 } 8794 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 8795 } 8796 } 8797 #endif 8798 8799 /* For use buffer we need to copy the data */ 8800 if (!output_flush_progress) { 8801 /* This is the error check for non-recoverable errros */ 8802 bool is_duplicate_ts_valid = true; 8803 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive); 8804 8805 if (output_capability == V4L2_PIX_FMT_MPEG4 || 8806 output_capability == V4L2_PIX_FMT_MPEG2 || 8807 output_capability == V4L2_PIX_FMT_DIVX || 8808 output_capability == V4L2_PIX_FMT_DIVX_311) 8809 is_duplicate_ts_valid = false; 8810 8811 if ((output_capability == V4L2_PIX_FMT_H264 || 8812 output_capability == V4L2_PIX_FMT_H264_MVC) && 8813 is_interlaced) { 8814 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) { 8815 is_interlaced = false; 8816 } 8817 } 8818 8819 if (buffer->nFilledLen > 0) { 8820 time_stamp_dts.get_next_timestamp(buffer, 8821 is_interlaced && is_duplicate_ts_valid); 8822 if (m_debug_timestamp) { 8823 { 8824 OMX_TICKS expected_ts = 0; 8825 m_timestamp_list.pop_min_ts(expected_ts); 8826 if (is_interlaced && is_duplicate_ts_valid) { 8827 m_timestamp_list.pop_min_ts(expected_ts); 8828 } 8829 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", 8830 buffer->nTimeStamp, expected_ts); 8831 8832 if (buffer->nTimeStamp != expected_ts) { 8833 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check"); 8834 } 8835 } 8836 } 8837 } 8838 } 8839 VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000); 8840 8841 if (m_cb.FillBufferDone) { 8842 if (buffer->nFilledLen > 0) { 8843 if (arbitrary_bytes) 8844 adjust_timestamp(buffer->nTimeStamp); 8845 else 8846 set_frame_rate(buffer->nTimeStamp); 8847 8848 proc_frms++; 8849 if (perf_flag) { 8850 if (1 == proc_frms) { 8851 dec_time.stop(); 8852 latency = dec_time.processing_time_us() - latency; 8853 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); 8854 dec_time.start(); 8855 fps_metrics.start(); 8856 } 8857 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8858 OMX_U64 proc_time = 0; 8859 fps_metrics.stop(); 8860 proc_time = fps_metrics.processing_time_us(); 8861 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)", 8862 (unsigned int)proc_frms, (float)proc_time / 1e6, 8863 (float)(1e6 * proc_frms) / proc_time); 8864 } 8865 } 8866 } 8867 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8868 prev_ts = LLONG_MAX; 8869 rst_prev_ts = true; 8870 proc_frms = 0; 8871 } 8872 8873 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 8874 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) 8875 buffer->pPlatformPrivate)->entryList->entry; 8876 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd); 8877 OMX_BUFFERHEADERTYPE *il_buffer; 8878 il_buffer = client_buffers.get_il_buf_hdr(buffer); 8879 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator); 8880 8881 if (il_buffer && m_last_rendered_TS >= 0) { 8882 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS); 8883 8884 // Current frame can be send for rendering if 8885 // (a) current FPS is <= 60 8886 // (b) is the next frame after the frame with TS 0 8887 // (c) is the first frame after seek 8888 // (d) the delta TS b\w two consecutive frames is > 16 ms 8889 // (e) its TS is equal to previous frame TS 8890 // (f) if marked EOS 8891 8892 if(current_framerate <= 60 || m_last_rendered_TS == 0 || 8893 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 || 8894 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 8895 m_last_rendered_TS = il_buffer->nTimeStamp; 8896 } else { 8897 //mark for droping 8898 buffer->nFilledLen = 0; 8899 } 8900 8901 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)", 8902 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS, 8903 il_buffer->nTimeStamp,ts_delta); 8904 8905 //above code makes sure that delta b\w two consecutive frames is not 8906 //greater than 16ms, slow-mo feature, so cap fps to max 60 8907 if (current_framerate > 60 ) { 8908 current_framerate = 60; 8909 } 8910 } 8911 8912 // add current framerate to gralloc meta data 8913 if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && m_out_mem_ptr) { 8914 // If valid fps was received, directly send it to display for the 1st fbd. 8915 // Otherwise, calculate fps using fbd timestamps 8916 float refresh_rate = m_fps_prev; 8917 if (m_fps_received) { 8918 if (1 == proc_frms) { 8919 refresh_rate = m_fps_received / (float)(1<<16); 8920 } 8921 } else { 8922 // check if dynamic refresh rate change feature enabled or not 8923 if (m_drc_enable) { 8924 // set coarse fps when 2 fbds received and 8925 // set fps again when 30 fbds received as it should be 8926 // more accurate than the one set when only 2 fbds received. 8927 if (2 == proc_frms || 30 == proc_frms) { 8928 if (drv_ctx.frame_rate.fps_denominator) { 8929 refresh_rate = drv_ctx.frame_rate.fps_numerator / 8930 (float) drv_ctx.frame_rate.fps_denominator; 8931 } 8932 } 8933 } else { 8934 // calculate and set refresh rate for every frame from second frame onwards 8935 // display will assume the default refresh rate for first frame (which is 60 fps) 8936 if (m_fps_prev) { 8937 if (drv_ctx.frame_rate.fps_denominator) { 8938 refresh_rate = drv_ctx.frame_rate.fps_numerator / 8939 (float) drv_ctx.frame_rate.fps_denominator; 8940 } 8941 } 8942 } 8943 } 8944 if (refresh_rate > 60) { 8945 refresh_rate = 60; 8946 } 8947 DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms); 8948 OMX_U32 buf_index = buffer - m_out_mem_ptr; 8949 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 8950 UPDATE_REFRESH_RATE, (void*)&refresh_rate); 8951 m_fps_prev = refresh_rate; 8952 } 8953 8954 if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) { 8955 OMX_U32 buf_index = buffer - m_out_mem_ptr; 8956 DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode); 8957 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 8958 S3D_FORMAT, (void*)&stereo_output_mode); 8959 } 8960 8961 if (il_buffer) { 8962 log_output_buffers(il_buffer); 8963 if (dynamic_buf_mode) { 8964 unsigned int nPortIndex = 0; 8965 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 8966 8967 // Since we're passing around handles, adjust nFilledLen and nAllocLen 8968 // to size of the handle. Do it _after_ log_output_buffers which 8969 // requires the respective sizes to be accurate. 8970 8971 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 8972 buffer->nFilledLen = buffer->nFilledLen ? 8973 sizeof(struct VideoDecoderOutputMetaData) : 0; 8974 8975 //Clear graphic buffer handles in dynamic mode 8976 if (nPortIndex < drv_ctx.op_buf.actualcount && 8977 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 8978 native_buffer[nPortIndex].privatehandle = NULL; 8979 native_buffer[nPortIndex].nativehandle = NULL; 8980 } else { 8981 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex); 8982 return OMX_ErrorBadParameter; 8983 } 8984 } 8985 m_cb.FillBufferDone (hComp,m_app_data,il_buffer); 8986 } else { 8987 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr"); 8988 return OMX_ErrorBadParameter; 8989 } 8990 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd); 8991 } else { 8992 return OMX_ErrorBadParameter; 8993 } 8994 8995 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 8996 if (m_smoothstreaming_mode && m_out_mem_ptr) { 8997 OMX_U32 buf_index = buffer - m_out_mem_ptr; 8998 BufferDim_t dim; 8999 private_handle_t *private_handle = NULL; 9000 dim.sliceWidth = framesize.nWidth; 9001 dim.sliceHeight = framesize.nHeight; 9002 if (buf_index < drv_ctx.op_buf.actualcount && 9003 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 9004 native_buffer[buf_index].privatehandle) 9005 private_handle = native_buffer[buf_index].privatehandle; 9006 if (private_handle) { 9007 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d", 9008 dim.sliceWidth, dim.sliceHeight); 9009 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim); 9010 } 9011 } 9012 #endif 9013 9014 return OMX_ErrorNone; 9015 } 9016 9017 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, 9018 OMX_BUFFERHEADERTYPE* buffer) 9019 { 9020 VIDC_TRACE_NAME_HIGH("EBD"); 9021 int nBufferIndex = buffer - m_inp_mem_ptr; 9022 9023 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) { 9024 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); 9025 return OMX_ErrorBadParameter; 9026 } 9027 9028 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x", 9029 buffer, buffer->pBuffer, buffer->nFlags); 9030 pending_input_buffers--; 9031 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers); 9032 9033 if (arbitrary_bytes) { 9034 if (pdest_frame == NULL && input_flush_progress == false) { 9035 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer); 9036 pdest_frame = buffer; 9037 buffer->nFilledLen = 0; 9038 buffer->nTimeStamp = LLONG_MAX; 9039 push_input_buffer (hComp); 9040 } else { 9041 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer); 9042 buffer->nFilledLen = 0; 9043 if (!m_input_free_q.insert_entry((unsigned long)buffer, 9044 (unsigned)NULL, (unsigned)NULL)) { 9045 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error"); 9046 } 9047 } 9048 } else if (m_cb.EmptyBufferDone) { 9049 buffer->nFilledLen = 0; 9050 if (input_use_buffer == true) { 9051 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; 9052 } 9053 9054 /* Restore the FD that we over-wrote in ETB */ 9055 if (m_input_pass_buffer_fd) { 9056 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd; 9057 } 9058 9059 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); 9060 } 9061 return OMX_ErrorNone; 9062 } 9063 9064 int omx_vdec::async_message_process (void *context, void* message) 9065 { 9066 omx_vdec* omx = NULL; 9067 struct vdec_msginfo *vdec_msg = NULL; 9068 OMX_BUFFERHEADERTYPE* omxhdr = NULL; 9069 struct v4l2_buffer *v4l2_buf_ptr = NULL; 9070 struct v4l2_plane *plane = NULL; 9071 struct vdec_output_frameinfo *output_respbuf = NULL; 9072 int rc=1; 9073 if (context == NULL || message == NULL) { 9074 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check"); 9075 return -1; 9076 } 9077 vdec_msg = (struct vdec_msginfo *)message; 9078 9079 omx = reinterpret_cast<omx_vdec*>(context); 9080 9081 switch (vdec_msg->msgcode) { 9082 9083 case VDEC_MSG_EVT_HW_ERROR: 9084 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9085 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 9086 break; 9087 9088 case VDEC_MSG_EVT_HW_OVERLOAD: 9089 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9090 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD); 9091 break; 9092 9093 case VDEC_MSG_EVT_HW_UNSUPPORTED: 9094 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9095 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); 9096 break; 9097 9098 case VDEC_MSG_RESP_START_DONE: 9099 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9100 OMX_COMPONENT_GENERATE_START_DONE); 9101 break; 9102 9103 case VDEC_MSG_RESP_STOP_DONE: 9104 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9105 OMX_COMPONENT_GENERATE_STOP_DONE); 9106 break; 9107 9108 case VDEC_MSG_RESP_RESUME_DONE: 9109 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9110 OMX_COMPONENT_GENERATE_RESUME_DONE); 9111 break; 9112 9113 case VDEC_MSG_RESP_PAUSE_DONE: 9114 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9115 OMX_COMPONENT_GENERATE_PAUSE_DONE); 9116 break; 9117 9118 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 9119 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9120 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); 9121 break; 9122 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 9123 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9124 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); 9125 break; 9126 case VDEC_MSG_RESP_INPUT_FLUSHED: 9127 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 9128 9129 /* omxhdr = (OMX_BUFFERHEADERTYPE* ) 9130 vdec_msg->msgdata.input_frame_clientdata; */ 9131 9132 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata; 9133 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL || 9134 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) { 9135 omxhdr = NULL; 9136 vdec_msg->status_code = VDEC_S_EFATAL; 9137 break; 9138 9139 } 9140 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index; 9141 9142 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) { 9143 DEBUG_PRINT_HIGH("Unsupported input"); 9144 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 9145 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 9146 } 9147 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 9148 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 9149 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR; 9150 } 9151 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 9152 9153 DEBUG_PRINT_LOW("Decrement codec_config buffer counter"); 9154 android_atomic_dec(&omx->m_queued_codec_config_count); 9155 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) && 9156 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) { 9157 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer"); 9158 sem_post(&omx->m_safe_flush); 9159 } 9160 } 9161 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || 9162 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 9163 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 9164 } 9165 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code, 9166 OMX_COMPONENT_GENERATE_EBD); 9167 break; 9168 case VDEC_MSG_EVT_INFO_FIELD_DROPPED: 9169 int64_t *timestamp; 9170 timestamp = (int64_t *) malloc(sizeof(int64_t)); 9171 if (timestamp) { 9172 *timestamp = vdec_msg->msgdata.output_frame.time_stamp; 9173 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code, 9174 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); 9175 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", 9176 (long long)vdec_msg->msgdata.output_frame.time_stamp); 9177 } 9178 break; 9179 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 9180 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 9181 9182 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; 9183 if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL || 9184 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) { 9185 omxhdr = NULL; 9186 vdec_msg->status_code = VDEC_S_EFATAL; 9187 break; 9188 } 9189 plane = v4l2_buf_ptr->m.planes; 9190 omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index; 9191 9192 if (omxhdr && omxhdr->pOutputPortPrivate && 9193 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) && 9194 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate 9195 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) { 9196 9197 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) { 9198 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; 9199 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; 9200 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp; 9201 omxhdr->nFlags = 0; 9202 9203 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) { 9204 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS; 9205 //rc = -1; 9206 } 9207 if (omxhdr->nFilledLen) { 9208 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 9209 } 9210 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 9211 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 9212 } else { 9213 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME; 9214 } 9215 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) { 9216 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 9217 } 9218 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) { 9219 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY; 9220 } 9221 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) { 9222 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF; 9223 } 9224 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) { 9225 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY; 9226 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d", 9227 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd); 9228 } 9229 9230 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) && 9231 !omx->output_flush_progress && 9232 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) && 9233 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) { 9234 omx->time_stamp_dts.remove_time_stamp( 9235 omxhdr->nTimeStamp, 9236 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 9237 ?true:false); 9238 9239 omxhdr->nFilledLen = 0; 9240 omx->pending_output_buffers--; 9241 omx->post_event ((unsigned long)NULL,(unsigned long)omx->client_buffers.get_il_buf_hdr(omxhdr), 9242 OMX_COMPONENT_GENERATE_FTB); 9243 break; 9244 } 9245 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 9246 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 9247 } 9248 9249 output_respbuf = (struct vdec_output_frameinfo *)\ 9250 omxhdr->pOutputPortPrivate; 9251 if (!output_respbuf) { 9252 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received"); 9253 return -1; 9254 } 9255 output_respbuf->len = vdec_msg->msgdata.output_frame.len; 9256 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; 9257 9258 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) { 9259 output_respbuf->pic_type = PICTURE_TYPE_I; 9260 } 9261 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) { 9262 output_respbuf->pic_type = PICTURE_TYPE_P; 9263 } 9264 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) { 9265 output_respbuf->pic_type = PICTURE_TYPE_B; 9266 } 9267 9268 if (vdec_msg->msgdata.output_frame.len) { 9269 if (!omx->output_flush_progress && (omxhdr->nFilledLen > 0)) { 9270 // set the default colorspace advised by client, since the bitstream may be 9271 // devoid of colorspace-info. 9272 if (omx->m_enable_android_native_buffers) { 9273 ColorSpace_t color_space = ITU_R_601; 9274 9275 // Disabled ? 9276 // WA for VP8. Vp8 encoder does not embed color-info (yet!). 9277 // Encoding RGBA results in 601-LR for all resolutions. 9278 // This conflicts with the client't defaults which are based on resolution. 9279 // Eg: 720p will be encoded as 601-LR. Client will say 709. 9280 // Re-enable this code once vp8 encoder generates color-info and hence the 9281 // decoder will be able to override with the correct source color. 9282 #if 0 9283 switch (omx->m_client_color_space.sAspects.mPrimaries) { 9284 case ColorAspects::PrimariesBT601_6_625: 9285 case ColorAspects::PrimariesBT601_6_525: 9286 { 9287 color_space = omx->m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ? 9288 ITU_R_601_FR : ITU_R_601; 9289 break; 9290 } 9291 case ColorAspects::PrimariesBT709_5: 9292 { 9293 color_space = ITU_R_709; 9294 break; 9295 } 9296 default: 9297 { 9298 break; 9299 } 9300 } 9301 #endif 9302 DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)", 9303 color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709); 9304 omx->set_colorspace_in_handle(color_space, omxhdr - omx->m_out_mem_ptr); 9305 } 9306 } 9307 9308 DEBUG_PRINT_LOW("Processing extradata"); 9309 omx->handle_extradata(omxhdr); 9310 9311 if (omx->m_extradata_info.output_crop_updated) { 9312 DEBUG_PRINT_LOW("Read FBD crop from output extra data"); 9313 vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft; 9314 vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop; 9315 vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth; 9316 vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight; 9317 vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width; 9318 vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height; 9319 } else { 9320 DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields"); 9321 vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2]; 9322 vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3]; 9323 vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4]; 9324 vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5]; 9325 vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6]; 9326 vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7]; 9327 9328 /* Copy these values back to OMX internal variables to make both handlign same*/ 9329 9330 omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left; 9331 omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top; 9332 omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right; 9333 omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom; 9334 omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width; 9335 omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height; 9336 } 9337 } 9338 9339 vdec_msg->msgdata.output_frame.bufferaddr = 9340 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; 9341 9342 if (vdec_msg->msgdata.output_frame.len) 9343 memcpy(&omx->drv_ctx.frame_size, 9344 &vdec_msg->msgdata.output_frame.framesize, 9345 sizeof(struct vdec_framesize)); 9346 9347 DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)" 9348 " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)", 9349 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd, 9350 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp, 9351 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags, 9352 (unsigned int)vdec_msg->msgdata.output_frame.len, 9353 vdec_msg->msgdata.output_frame.framesize.left, 9354 vdec_msg->msgdata.output_frame.framesize.top, 9355 vdec_msg->msgdata.output_frame.framesize.right, 9356 vdec_msg->msgdata.output_frame.framesize.bottom); 9357 9358 /* Post event if resolution OR crop changed */ 9359 /* filled length will be changed if resolution changed */ 9360 /* Crop parameters can be changed even without resolution change */ 9361 if (omxhdr->nFilledLen 9362 && ((omx->prev_n_filled_len != omxhdr->nFilledLen) 9363 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left) 9364 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top) 9365 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right) 9366 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom) 9367 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width) 9368 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) { 9369 9370 DEBUG_PRINT_HIGH("Parameters 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", 9371 omx->prev_n_filled_len, 9372 omx->drv_ctx.video_resolution.frame_width, 9373 omx->drv_ctx.video_resolution.frame_height, 9374 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top, 9375 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom, 9376 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width, 9377 vdec_msg->msgdata.output_frame.picsize.frame_height, 9378 vdec_msg->msgdata.output_frame.framesize.left, 9379 vdec_msg->msgdata.output_frame.framesize.top, 9380 vdec_msg->msgdata.output_frame.framesize.right, 9381 vdec_msg->msgdata.output_frame.framesize.bottom); 9382 9383 omx->drv_ctx.video_resolution.frame_width = 9384 vdec_msg->msgdata.output_frame.picsize.frame_width; 9385 omx->drv_ctx.video_resolution.frame_height = 9386 vdec_msg->msgdata.output_frame.picsize.frame_height; 9387 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 9388 omx->drv_ctx.video_resolution.stride = 9389 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width); 9390 omx->drv_ctx.video_resolution.scan_lines = 9391 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height); 9392 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 9393 omx->drv_ctx.video_resolution.stride = 9394 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width); 9395 omx->drv_ctx.video_resolution.scan_lines = 9396 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height); 9397 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) { 9398 omx->drv_ctx.video_resolution.stride = 9399 VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width); 9400 omx->drv_ctx.video_resolution.scan_lines = 9401 VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height); 9402 } 9403 9404 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX, 9405 OMX_IndexConfigCommonOutputCrop, 9406 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 9407 } 9408 9409 if (omxhdr->nFilledLen) 9410 omx->prev_n_filled_len = omxhdr->nFilledLen; 9411 9412 if (omxhdr && omxhdr->nFilledLen && !omx->m_need_turbo) { 9413 omx->request_perf_level(VIDC_NOMINAL); 9414 } 9415 if (omx->output_use_buffer && omxhdr->pBuffer && 9416 vdec_msg->msgdata.output_frame.bufferaddr) 9417 memcpy ( omxhdr->pBuffer, (void *) 9418 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr + 9419 (unsigned long)vdec_msg->msgdata.output_frame.offset), 9420 vdec_msg->msgdata.output_frame.len); 9421 } else { 9422 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u", 9423 (unsigned int)vdec_msg->msgdata.output_frame.len, 9424 omxhdr->nAllocLen, omx->prev_n_filled_len); 9425 omxhdr->nFilledLen = 0; 9426 } 9427 9428 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code, 9429 OMX_COMPONENT_GENERATE_FBD); 9430 9431 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) { 9432 omx->post_event ((unsigned long)NULL, vdec_msg->status_code, 9433 OMX_COMPONENT_GENERATE_EOS_DONE); 9434 } else { 9435 omx->post_event ((unsigned int)NULL, vdec_msg->status_code, 9436 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 9437 } 9438 break; 9439 case VDEC_MSG_EVT_CONFIG_CHANGED: 9440 DEBUG_PRINT_HIGH("Port settings changed"); 9441 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width; 9442 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height; 9443 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition, 9444 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 9445 if (!omx->m_need_turbo) { 9446 omx->request_perf_level(VIDC_NOMINAL); 9447 } 9448 break; 9449 default: 9450 break; 9451 } 9452 return rc; 9453 } 9454 9455 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( 9456 OMX_HANDLETYPE hComp, 9457 OMX_BUFFERHEADERTYPE *buffer 9458 ) 9459 { 9460 unsigned address,p2,id; 9461 DEBUG_PRINT_LOW("Empty this arbitrary"); 9462 9463 if (buffer == NULL) { 9464 return OMX_ErrorBadParameter; 9465 } 9466 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 9467 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld", 9468 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp); 9469 9470 /* return zero length and not an EOS buffer */ 9471 /* return buffer if input flush in progress */ 9472 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && 9473 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) { 9474 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress"); 9475 m_cb.EmptyBufferDone (hComp,m_app_data,buffer); 9476 return OMX_ErrorNone; 9477 } 9478 9479 if (psource_frame == NULL) { 9480 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp); 9481 psource_frame = buffer; 9482 DEBUG_PRINT_LOW("Try to Push One Input Buffer "); 9483 push_input_buffer (hComp); 9484 } else { 9485 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer); 9486 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL, 9487 (unsigned)NULL)) { 9488 return OMX_ErrorBadParameter; 9489 } 9490 } 9491 9492 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 9493 codec_config_flag = false; 9494 } 9495 return OMX_ErrorNone; 9496 } 9497 9498 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) 9499 { 9500 unsigned long address,p2,id; 9501 OMX_ERRORTYPE ret = OMX_ErrorNone; 9502 9503 if (pdest_frame == NULL || psource_frame == NULL) { 9504 /*Check if we have a destination buffer*/ 9505 if (pdest_frame == NULL) { 9506 DEBUG_PRINT_LOW("Get a Destination buffer from the queue"); 9507 if (m_input_free_q.m_size) { 9508 m_input_free_q.pop_entry(&address,&p2,&id); 9509 pdest_frame = (OMX_BUFFERHEADERTYPE *)address; 9510 pdest_frame->nFilledLen = 0; 9511 pdest_frame->nTimeStamp = LLONG_MAX; 9512 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame); 9513 } 9514 } 9515 9516 /*Check if we have a destination buffer*/ 9517 if (psource_frame == NULL) { 9518 DEBUG_PRINT_LOW("Get a source buffer from the queue"); 9519 if (m_input_pending_q.m_size) { 9520 m_input_pending_q.pop_entry(&address,&p2,&id); 9521 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 9522 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 9523 psource_frame->nTimeStamp); 9524 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 9525 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 9526 9527 } 9528 } 9529 9530 } 9531 9532 while ((pdest_frame != NULL) && (psource_frame != NULL)) { 9533 switch (codec_type_parse) { 9534 case CODEC_TYPE_MPEG4: 9535 case CODEC_TYPE_H263: 9536 case CODEC_TYPE_MPEG2: 9537 ret = push_input_sc_codec(hComp); 9538 break; 9539 case CODEC_TYPE_H264: 9540 ret = push_input_h264(hComp); 9541 break; 9542 case CODEC_TYPE_HEVC: 9543 ret = push_input_hevc(hComp); 9544 break; 9545 case CODEC_TYPE_VC1: 9546 ret = push_input_vc1(hComp); 9547 break; 9548 default: 9549 break; 9550 } 9551 if (ret != OMX_ErrorNone) { 9552 DEBUG_PRINT_ERROR("Pushing input Buffer Failed"); 9553 omx_report_error (); 9554 break; 9555 } 9556 } 9557 9558 return ret; 9559 } 9560 9561 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp) 9562 { 9563 OMX_U32 partial_frame = 1; 9564 OMX_BOOL generate_ebd = OMX_TRUE; 9565 unsigned long address = 0, p2 = 0, id = 0; 9566 9567 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld", 9568 psource_frame,psource_frame->nTimeStamp); 9569 if (m_frame_parser.parse_sc_frame(psource_frame, 9570 pdest_frame,&partial_frame) == -1) { 9571 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 9572 return OMX_ErrorBadParameter; 9573 } 9574 9575 if (partial_frame == 0) { 9576 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d", 9577 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count); 9578 9579 9580 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp); 9581 /*First Parsed buffer will have only header Hence skip*/ 9582 if (frame_count == 0) { 9583 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame "); 9584 9585 if (codec_type_parse == CODEC_TYPE_MPEG4 || 9586 codec_type_parse == CODEC_TYPE_DIVX) { 9587 mp4StreamType psBits; 9588 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset; 9589 psBits.numBytes = pdest_frame->nFilledLen; 9590 mp4_headerparser.parseHeader(&psBits); 9591 } 9592 9593 frame_count++; 9594 } else { 9595 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 9596 if (pdest_frame->nFilledLen) { 9597 /*Push the frame to the Decoder*/ 9598 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9599 return OMX_ErrorBadParameter; 9600 } 9601 frame_count++; 9602 pdest_frame = NULL; 9603 9604 if (m_input_free_q.m_size) { 9605 m_input_free_q.pop_entry(&address,&p2,&id); 9606 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 9607 pdest_frame->nFilledLen = 0; 9608 } 9609 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) { 9610 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL"); 9611 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL, 9612 (unsigned)NULL); 9613 pdest_frame = NULL; 9614 } 9615 } 9616 } else { 9617 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen); 9618 /*Check if Destination Buffer is full*/ 9619 if (pdest_frame->nAllocLen == 9620 pdest_frame->nFilledLen + pdest_frame->nOffset) { 9621 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled"); 9622 return OMX_ErrorStreamCorrupt; 9623 } 9624 } 9625 9626 if (psource_frame->nFilledLen == 0) { 9627 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 9628 if (pdest_frame) { 9629 pdest_frame->nFlags |= psource_frame->nFlags; 9630 pdest_frame->nTimeStamp = psource_frame->nTimeStamp; 9631 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld", 9632 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 9633 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 9634 (unsigned int)pdest_frame->nFilledLen,frame_count++); 9635 /*Push the frame to the Decoder*/ 9636 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9637 return OMX_ErrorBadParameter; 9638 } 9639 frame_count++; 9640 pdest_frame = NULL; 9641 } else { 9642 DEBUG_PRINT_LOW("Last frame in else dest addr") ; 9643 generate_ebd = OMX_FALSE; 9644 } 9645 } 9646 if (generate_ebd) { 9647 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame); 9648 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 9649 psource_frame = NULL; 9650 9651 if (m_input_pending_q.m_size) { 9652 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 9653 m_input_pending_q.pop_entry(&address,&p2,&id); 9654 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 9655 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 9656 psource_frame->nTimeStamp); 9657 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 9658 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 9659 } 9660 } 9661 } 9662 return OMX_ErrorNone; 9663 } 9664 9665 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) 9666 { 9667 OMX_U32 partial_frame = 1; 9668 unsigned long address = 0, p2 = 0, id = 0; 9669 OMX_BOOL isNewFrame = OMX_FALSE; 9670 OMX_BOOL generate_ebd = OMX_TRUE; 9671 9672 if (h264_scratch.pBuffer == NULL) { 9673 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated"); 9674 return OMX_ErrorBadParameter; 9675 } 9676 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u " 9677 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal); 9678 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen); 9679 if (h264_scratch.nFilledLen && look_ahead_nal) { 9680 look_ahead_nal = false; 9681 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9682 h264_scratch.nFilledLen) { 9683 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9684 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9685 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9686 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame"); 9687 h264_scratch.nFilledLen = 0; 9688 } else { 9689 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264"); 9690 return OMX_ErrorBadParameter; 9691 } 9692 } 9693 9694 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result 9695 in EOS flag getting associated with the destination 9696 */ 9697 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) && 9698 pdest_frame->nFilledLen) { 9699 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'"); 9700 generate_ebd = OMX_FALSE; 9701 } 9702 9703 if (nal_length == 0) { 9704 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code"); 9705 if (m_frame_parser.parse_sc_frame(psource_frame, 9706 &h264_scratch,&partial_frame) == -1) { 9707 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 9708 return OMX_ErrorBadParameter; 9709 } 9710 } else { 9711 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length); 9712 if (m_frame_parser.parse_h264_nallength(psource_frame, 9713 &h264_scratch,&partial_frame) == -1) { 9714 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 9715 return OMX_ErrorBadParameter; 9716 } 9717 } 9718 9719 if (partial_frame == 0) { 9720 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 9721 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 9722 nal_count++; 9723 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 9724 h264_scratch.nFlags = psource_frame->nFlags; 9725 } else { 9726 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen); 9727 if (h264_scratch.nFilledLen) { 9728 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen, 9729 NALU_TYPE_SPS); 9730 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9731 if (client_extradata & OMX_TIMEINFO_EXTRADATA) 9732 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 9733 h264_scratch.nFilledLen, NALU_TYPE_SEI); 9734 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 9735 // If timeinfo is present frame info from SEI is already processed 9736 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 9737 h264_scratch.nFilledLen, NALU_TYPE_SEI); 9738 #endif 9739 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 9740 nal_count++; 9741 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) { 9742 pdest_frame->nTimeStamp = h264_last_au_ts; 9743 pdest_frame->nFlags = h264_last_au_flags; 9744 #ifdef PANSCAN_HDLR 9745 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 9746 h264_parser->update_panscan_data(h264_last_au_ts); 9747 #endif 9748 } 9749 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR || 9750 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) { 9751 h264_last_au_ts = h264_scratch.nTimeStamp; 9752 h264_last_au_flags = h264_scratch.nFlags; 9753 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9754 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 9755 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts); 9756 if (!VALID_TS(h264_last_au_ts)) 9757 h264_last_au_ts = ts_in_sei; 9758 } 9759 #endif 9760 } else 9761 h264_last_au_ts = LLONG_MAX; 9762 } 9763 9764 if (!isNewFrame) { 9765 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9766 h264_scratch.nFilledLen) { 9767 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u", 9768 (unsigned int)h264_scratch.nFilledLen); 9769 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9770 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9771 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9772 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ) 9773 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 9774 h264_scratch.nFilledLen = 0; 9775 } else { 9776 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264"); 9777 return OMX_ErrorBadParameter; 9778 } 9779 } else if(h264_scratch.nFilledLen) { 9780 look_ahead_nal = true; 9781 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu", 9782 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 9783 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 9784 (unsigned int)pdest_frame->nFilledLen,frame_count++); 9785 9786 if (pdest_frame->nFilledLen == 0) { 9787 DEBUG_PRINT_LOW("Copy the Current Frame since and push it"); 9788 look_ahead_nal = false; 9789 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9790 h264_scratch.nFilledLen) { 9791 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9792 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9793 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9794 h264_scratch.nFilledLen = 0; 9795 } else { 9796 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264"); 9797 return OMX_ErrorBadParameter; 9798 } 9799 } else { 9800 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 9801 DEBUG_PRINT_LOW("Reset the EOS Flag"); 9802 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 9803 } 9804 /*Push the frame to the Decoder*/ 9805 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9806 return OMX_ErrorBadParameter; 9807 } 9808 //frame_count++; 9809 pdest_frame = NULL; 9810 if (m_input_free_q.m_size) { 9811 m_input_free_q.pop_entry(&address,&p2,&id); 9812 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 9813 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame); 9814 pdest_frame->nFilledLen = 0; 9815 pdest_frame->nFlags = 0; 9816 pdest_frame->nTimeStamp = LLONG_MAX; 9817 } 9818 } 9819 } 9820 } 9821 } else { 9822 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen); 9823 /*Check if Destination Buffer is full*/ 9824 if (h264_scratch.nAllocLen == 9825 h264_scratch.nFilledLen + h264_scratch.nOffset) { 9826 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 9827 return OMX_ErrorStreamCorrupt; 9828 } 9829 } 9830 9831 if (!psource_frame->nFilledLen) { 9832 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame); 9833 9834 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 9835 if (pdest_frame) { 9836 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 9837 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9838 h264_scratch.nFilledLen) { 9839 if(pdest_frame->nFilledLen == 0) { 9840 /* No residual frame from before, send whatever 9841 * we have left */ 9842 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9843 h264_scratch.pBuffer, h264_scratch.nFilledLen); 9844 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9845 h264_scratch.nFilledLen = 0; 9846 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 9847 } else { 9848 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 9849 if(!isNewFrame) { 9850 /* Have a residual frame, but we know that the 9851 * AU in this frame is belonging to whatever 9852 * frame we had left over. So append it */ 9853 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9854 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9855 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9856 h264_scratch.nFilledLen = 0; 9857 if (h264_last_au_ts != LLONG_MAX) 9858 pdest_frame->nTimeStamp = h264_last_au_ts; 9859 } else { 9860 /* Completely new frame, let's just push what 9861 * we have now. The resulting EBD would trigger 9862 * another push */ 9863 generate_ebd = OMX_FALSE; 9864 pdest_frame->nTimeStamp = h264_last_au_ts; 9865 h264_last_au_ts = h264_scratch.nTimeStamp; 9866 } 9867 } 9868 } else { 9869 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264"); 9870 return OMX_ErrorBadParameter; 9871 } 9872 9873 /* Iff we coalesced two buffers, inherit the flags of both bufs */ 9874 if(generate_ebd == OMX_TRUE) { 9875 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 9876 } 9877 9878 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu", 9879 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 9880 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++); 9881 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9882 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 9883 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp); 9884 if (!VALID_TS(pdest_frame->nTimeStamp)) 9885 pdest_frame->nTimeStamp = ts_in_sei; 9886 } 9887 #endif 9888 /*Push the frame to the Decoder*/ 9889 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9890 return OMX_ErrorBadParameter; 9891 } 9892 frame_count++; 9893 pdest_frame = NULL; 9894 } else { 9895 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 9896 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 9897 generate_ebd = OMX_FALSE; 9898 } 9899 } 9900 } 9901 if (generate_ebd && !psource_frame->nFilledLen) { 9902 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 9903 psource_frame = NULL; 9904 if (m_input_pending_q.m_size) { 9905 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 9906 m_input_pending_q.pop_entry(&address,&p2,&id); 9907 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 9908 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u", 9909 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 9910 } 9911 } 9912 return OMX_ErrorNone; 9913 } 9914 9915 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc) 9916 { 9917 OMX_ERRORTYPE rc = OMX_ErrorNone; 9918 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) { 9919 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen); 9920 if (pDst->nTimeStamp == LLONG_MAX) { 9921 pDst->nTimeStamp = pSrc->nTimeStamp; 9922 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp); 9923 } 9924 pDst->nFilledLen += pSrc->nFilledLen; 9925 pSrc->nFilledLen = 0; 9926 } else { 9927 DEBUG_PRINT_ERROR("Error: Destination buffer overflow"); 9928 rc = OMX_ErrorBadParameter; 9929 } 9930 return rc; 9931 } 9932 9933 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp) 9934 { 9935 OMX_U32 partial_frame = 1; 9936 unsigned long address,p2,id; 9937 OMX_BOOL isNewFrame = OMX_FALSE; 9938 OMX_BOOL generate_ebd = OMX_TRUE; 9939 OMX_ERRORTYPE rc = OMX_ErrorNone; 9940 if (h264_scratch.pBuffer == NULL) { 9941 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated"); 9942 return OMX_ErrorBadParameter; 9943 } 9944 9945 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \ 9946 pdest_frame nFilledLen %u nTimeStamp %lld", 9947 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 9948 9949 if (h264_scratch.nFilledLen && look_ahead_nal) { 9950 look_ahead_nal = false; 9951 rc = copy_buffer(pdest_frame, &h264_scratch); 9952 if (rc != OMX_ErrorNone) { 9953 return rc; 9954 } 9955 } 9956 9957 if (nal_length == 0) { 9958 if (m_frame_parser.parse_sc_frame(psource_frame, 9959 &h264_scratch,&partial_frame) == -1) { 9960 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 9961 return OMX_ErrorBadParameter; 9962 } 9963 } else { 9964 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length); 9965 if (m_frame_parser.parse_h264_nallength(psource_frame, 9966 &h264_scratch,&partial_frame) == -1) { 9967 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 9968 return OMX_ErrorBadParameter; 9969 } 9970 } 9971 9972 if (partial_frame == 0) { 9973 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 9974 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 9975 nal_count++; 9976 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 9977 h264_scratch.nFlags = psource_frame->nFlags; 9978 } else { 9979 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen); 9980 if (h264_scratch.nFilledLen) { 9981 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame); 9982 nal_count++; 9983 } 9984 9985 if (!isNewFrame) { 9986 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \ 9987 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld", 9988 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp, 9989 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 9990 rc = copy_buffer(pdest_frame, &h264_scratch); 9991 if (rc != OMX_ErrorNone) { 9992 return rc; 9993 } 9994 } else { 9995 look_ahead_nal = true; 9996 if (pdest_frame->nFilledLen == 0) { 9997 look_ahead_nal = false; 9998 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer"); 9999 rc = copy_buffer(pdest_frame, &h264_scratch); 10000 if (rc != OMX_ErrorNone) { 10001 return OMX_ErrorBadParameter; 10002 } 10003 } else { 10004 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 10005 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 10006 } 10007 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \ 10008 nTimeStamp %lld, look_ahead_nal in h264_scratch \ 10009 nFilledLen %u nTimeStamp %lld", 10010 frame_count++, (unsigned int)pdest_frame->nFilledLen, 10011 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen, 10012 h264_scratch.nTimeStamp); 10013 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 10014 return OMX_ErrorBadParameter; 10015 } 10016 pdest_frame = NULL; 10017 if (m_input_free_q.m_size) { 10018 m_input_free_q.pop_entry(&address, &p2, &id); 10019 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 10020 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame); 10021 pdest_frame->nFilledLen = 0; 10022 pdest_frame->nFlags = 0; 10023 pdest_frame->nTimeStamp = LLONG_MAX; 10024 } 10025 } 10026 } 10027 } 10028 } else { 10029 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \ 10030 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \ 10031 nFilledLen %u nTimeStamp %lld", 10032 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp, 10033 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp, 10034 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp); 10035 10036 if (h264_scratch.nAllocLen == 10037 h264_scratch.nFilledLen + h264_scratch.nOffset) { 10038 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 10039 return OMX_ErrorStreamCorrupt; 10040 } 10041 } 10042 10043 if (!psource_frame->nFilledLen) { 10044 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame); 10045 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 10046 if (pdest_frame) { 10047 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 10048 rc = copy_buffer(pdest_frame, &h264_scratch); 10049 if ( rc != OMX_ErrorNone ) { 10050 return rc; 10051 } 10052 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 10053 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 10054 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld", 10055 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 10056 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 10057 return OMX_ErrorBadParameter; 10058 } 10059 frame_count++; 10060 pdest_frame = NULL; 10061 } else { 10062 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 10063 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 10064 generate_ebd = OMX_FALSE; 10065 } 10066 } 10067 } 10068 10069 if (generate_ebd && !psource_frame->nFilledLen) { 10070 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame); 10071 psource_frame = NULL; 10072 if (m_input_pending_q.m_size) { 10073 m_input_pending_q.pop_entry(&address, &p2, &id); 10074 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 10075 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld", 10076 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp); 10077 } 10078 } 10079 return OMX_ErrorNone; 10080 } 10081 10082 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp) 10083 { 10084 OMX_U8 *buf, *pdest; 10085 OMX_U32 partial_frame = 1; 10086 OMX_U32 buf_len, dest_len; 10087 10088 if (first_frame == 0) { 10089 first_frame = 1; 10090 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes"); 10091 if (!m_vendor_config.pData) { 10092 DEBUG_PRINT_LOW("Check profile type in 1st source buffer"); 10093 buf = psource_frame->pBuffer; 10094 buf_len = psource_frame->nFilledLen; 10095 10096 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) == 10097 VC1_SP_MP_START_CODE) { 10098 m_vc1_profile = VC1_SP_MP_RCV; 10099 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) { 10100 m_vc1_profile = VC1_AP; 10101 } else { 10102 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer"); 10103 return OMX_ErrorStreamCorrupt; 10104 } 10105 } else { 10106 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen + 10107 pdest_frame->nOffset; 10108 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen + 10109 pdest_frame->nOffset); 10110 10111 if (dest_len < m_vendor_config.nDataSize) { 10112 DEBUG_PRINT_ERROR("Destination buffer full"); 10113 return OMX_ErrorBadParameter; 10114 } else { 10115 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize); 10116 pdest_frame->nFilledLen += m_vendor_config.nDataSize; 10117 } 10118 } 10119 } 10120 10121 switch (m_vc1_profile) { 10122 case VC1_AP: 10123 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code"); 10124 if (push_input_sc_codec(hComp) != OMX_ErrorNone) { 10125 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code"); 10126 return OMX_ErrorBadParameter; 10127 } 10128 break; 10129 10130 case VC1_SP_MP_RCV: 10131 default: 10132 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode"); 10133 return OMX_ErrorBadParameter; 10134 } 10135 return OMX_ErrorNone; 10136 } 10137 10138 #ifndef USE_ION 10139 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, 10140 OMX_U32 alignment) 10141 { 10142 struct pmem_allocation allocation; 10143 allocation.size = buffer_size; 10144 allocation.align = clip2(alignment); 10145 if (allocation.align < 4096) { 10146 allocation.align = 4096; 10147 } 10148 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) { 10149 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)", 10150 allocation.align, allocation.size); 10151 return false; 10152 } 10153 return true; 10154 } 10155 #endif 10156 #ifdef USE_ION 10157 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, 10158 OMX_U32 alignment, struct ion_allocation_data *alloc_data, 10159 struct ion_fd_data *fd_data, int flag) 10160 { 10161 int fd = -EINVAL; 10162 int rc = -EINVAL; 10163 int ion_dev_flag; 10164 struct vdec_ion ion_buf_info; 10165 if (!alloc_data || buffer_size <= 0 || !fd_data) { 10166 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory"); 10167 return -EINVAL; 10168 } 10169 ion_dev_flag = O_RDONLY; 10170 fd = open (MEM_DEVICE, ion_dev_flag); 10171 if (fd < 0) { 10172 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd); 10173 return fd; 10174 } 10175 10176 alloc_data->flags = flag; 10177 alloc_data->len = buffer_size; 10178 alloc_data->align = clip2(alignment); 10179 if (alloc_data->align < 4096) { 10180 alloc_data->align = 4096; 10181 } 10182 10183 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID); 10184 if (secure_mode && (alloc_data->flags & ION_SECURE)) { 10185 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID); 10186 } 10187 10188 /* Use secure display cma heap for obvious reasons. */ 10189 if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) { 10190 alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); 10191 } 10192 10193 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); 10194 if (rc || !alloc_data->handle) { 10195 DEBUG_PRINT_ERROR("ION ALLOC memory failed"); 10196 alloc_data->handle = 0; 10197 close(fd); 10198 fd = -ENOMEM; 10199 return fd; 10200 } 10201 fd_data->handle = alloc_data->handle; 10202 rc = ioctl(fd,ION_IOC_MAP,fd_data); 10203 if (rc) { 10204 DEBUG_PRINT_ERROR("ION MAP failed "); 10205 ion_buf_info.ion_alloc_data = *alloc_data; 10206 ion_buf_info.ion_device_fd = fd; 10207 ion_buf_info.fd_ion_data = *fd_data; 10208 free_ion_memory(&ion_buf_info); 10209 fd_data->fd =-1; 10210 fd = -ENOMEM; 10211 } 10212 10213 return fd; 10214 } 10215 10216 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) 10217 { 10218 10219 if (!buf_ion_info) { 10220 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata"); 10221 return; 10222 } 10223 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, 10224 &buf_ion_info->ion_alloc_data.handle)) { 10225 DEBUG_PRINT_ERROR("ION: free failed" ); 10226 } 10227 close(buf_ion_info->ion_device_fd); 10228 buf_ion_info->ion_device_fd = -1; 10229 buf_ion_info->ion_alloc_data.handle = 0; 10230 buf_ion_info->fd_ion_data.fd = -1; 10231 } 10232 #endif 10233 void omx_vdec::free_output_buffer_header() 10234 { 10235 DEBUG_PRINT_HIGH("ALL output buffers are freed/released"); 10236 output_use_buffer = false; 10237 ouput_egl_buffers = false; 10238 10239 if (m_out_mem_ptr) { 10240 free (m_out_mem_ptr); 10241 m_out_mem_ptr = NULL; 10242 } 10243 10244 if (m_platform_list) { 10245 free(m_platform_list); 10246 m_platform_list = NULL; 10247 } 10248 10249 if (drv_ctx.ptr_respbuffer) { 10250 free (drv_ctx.ptr_respbuffer); 10251 drv_ctx.ptr_respbuffer = NULL; 10252 } 10253 if (drv_ctx.ptr_outputbuffer) { 10254 free (drv_ctx.ptr_outputbuffer); 10255 drv_ctx.ptr_outputbuffer = NULL; 10256 } 10257 #ifdef USE_ION 10258 if (drv_ctx.op_buf_ion_info) { 10259 DEBUG_PRINT_LOW("Free o/p ion context"); 10260 free(drv_ctx.op_buf_ion_info); 10261 drv_ctx.op_buf_ion_info = NULL; 10262 } 10263 #endif 10264 free(drv_ctx.op_buf_map_info); 10265 drv_ctx.op_buf_map_info = NULL; 10266 buf_ref_remove(); 10267 } 10268 10269 void omx_vdec::free_input_buffer_header() 10270 { 10271 input_use_buffer = false; 10272 if (arbitrary_bytes) { 10273 if (m_inp_heap_ptr) { 10274 DEBUG_PRINT_LOW("Free input Heap Pointer"); 10275 free (m_inp_heap_ptr); 10276 m_inp_heap_ptr = NULL; 10277 } 10278 10279 if (m_phdr_pmem_ptr) { 10280 DEBUG_PRINT_LOW("Free input pmem header Pointer"); 10281 free (m_phdr_pmem_ptr); 10282 m_phdr_pmem_ptr = NULL; 10283 } 10284 } 10285 if (m_inp_mem_ptr) { 10286 DEBUG_PRINT_LOW("Free input pmem Pointer area"); 10287 free (m_inp_mem_ptr); 10288 m_inp_mem_ptr = NULL; 10289 } 10290 /* We just freed all the buffer headers, every thing in m_input_free_q, 10291 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */ 10292 while (m_input_free_q.m_size) { 10293 unsigned long address, p2, id; 10294 m_input_free_q.pop_entry(&address, &p2, &id); 10295 } 10296 while (m_input_pending_q.m_size) { 10297 unsigned long address, p2, id; 10298 m_input_pending_q.pop_entry(&address, &p2, &id); 10299 } 10300 pdest_frame = NULL; 10301 psource_frame = NULL; 10302 if (drv_ctx.ptr_inputbuffer) { 10303 DEBUG_PRINT_LOW("Free Driver Context pointer"); 10304 free (drv_ctx.ptr_inputbuffer); 10305 drv_ctx.ptr_inputbuffer = NULL; 10306 } 10307 #ifdef USE_ION 10308 if (drv_ctx.ip_buf_ion_info) { 10309 DEBUG_PRINT_LOW("Free ion context"); 10310 free(drv_ctx.ip_buf_ion_info); 10311 drv_ctx.ip_buf_ion_info = NULL; 10312 } 10313 #endif 10314 } 10315 10316 void omx_vdec::free_output_extradata_buffer_header() { 10317 client_extradata = false; 10318 if (m_client_output_extradata_mem_ptr) { 10319 DEBUG_PRINT_LOW("Free extradata pmem Pointer area"); 10320 free(m_client_output_extradata_mem_ptr); 10321 m_client_output_extradata_mem_ptr = NULL; 10322 } 10323 } 10324 10325 int omx_vdec::stream_off(OMX_U32 port) 10326 { 10327 enum v4l2_buf_type btype; 10328 int rc = 0; 10329 enum v4l2_ports v4l2_port = OUTPUT_PORT; 10330 10331 if (port == OMX_CORE_INPUT_PORT_INDEX) { 10332 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10333 v4l2_port = OUTPUT_PORT; 10334 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 10335 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10336 v4l2_port = CAPTURE_PORT; 10337 } else if (port == OMX_ALL) { 10338 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX); 10339 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 10340 10341 if (!rc_input) 10342 return rc_input; 10343 else 10344 return rc_output; 10345 } 10346 10347 if (!streaming[v4l2_port]) { 10348 // already streamed off, warn and move on 10349 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port," 10350 " which is already streamed off", v4l2_port); 10351 return 0; 10352 } 10353 10354 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port); 10355 10356 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); 10357 if (rc) { 10358 /*TODO: How to handle this case */ 10359 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port); 10360 } else { 10361 streaming[v4l2_port] = false; 10362 } 10363 10364 return rc; 10365 } 10366 10367 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) 10368 { 10369 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10370 struct v4l2_requestbuffers bufreq; 10371 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0; 10372 unsigned int final_extra_data_size = 0; 10373 struct v4l2_format fmt; 10374 int ret = 0; 10375 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 10376 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 10377 bufreq.memory = V4L2_MEMORY_USERPTR; 10378 bufreq.count = 1; 10379 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 10380 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10381 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10382 fmt.fmt.pix_mp.pixelformat = output_capability; 10383 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 10384 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10385 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10386 fmt.fmt.pix_mp.pixelformat = capture_capability; 10387 } else { 10388 eRet = OMX_ErrorBadParameter; 10389 } 10390 if (eRet==OMX_ErrorNone) { 10391 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 10392 } 10393 if (ret) { 10394 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 10395 /*TODO: How to handle this case */ 10396 eRet = OMX_ErrorInsufficientResources; 10397 return eRet; 10398 } else { 10399 bool is_res_1080p_or_below = (drv_ctx.video_resolution.frame_width <= 1920 && 10400 drv_ctx.video_resolution.frame_height <= 1088) || 10401 (drv_ctx.video_resolution.frame_height <= 1088 && 10402 drv_ctx.video_resolution.frame_width <= 1920); 10403 10404 int fps = drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator; 10405 bool fps_above_180 = (fps >= 180 || operating_frame_rate >= 180) ? true : false; 10406 bool increase_output = (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) && (bufreq.count >= 16); 10407 10408 if (increase_output && fps_above_180 && 10409 output_capability == V4L2_PIX_FMT_H264 && 10410 is_res_1080p_or_below) { 10411 m_need_turbo |= TURBO_MODE_HIGH_FPS; 10412 DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate); 10413 DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps", 10414 bufreq.count, bufreq.count + 10); 10415 bufreq.count += 10; 10416 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 10417 if (ret) { 10418 DEBUG_PRINT_ERROR("(Failed to set updated buffer count to driver"); 10419 eRet = OMX_ErrorInsufficientResources; 10420 return eRet; 10421 } 10422 DEBUG_PRINT_LOW("new buf count = %d set to driver", bufreq.count); 10423 request_perf_level(VIDC_TURBO); 10424 } 10425 10426 buffer_prop->actualcount = bufreq.count; 10427 buffer_prop->mincount = bufreq.count; 10428 DEBUG_PRINT_HIGH("Count = %d",bufreq.count); 10429 } 10430 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 10431 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 10432 10433 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 10434 10435 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 10436 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes; 10437 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage); 10438 10439 if (ret) { 10440 /*TODO: How to handle this case */ 10441 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 10442 eRet = OMX_ErrorInsufficientResources; 10443 } else { 10444 int extra_idx = 0; 10445 10446 eRet = is_video_session_supported(); 10447 if (eRet) 10448 return eRet; 10449 10450 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; 10451 buf_size = buffer_prop->buffer_size; 10452 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 10453 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 10454 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage; 10455 } else if (extra_idx >= VIDEO_MAX_PLANES) { 10456 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 10457 return OMX_ErrorBadParameter; 10458 } 10459 10460 default_extra_data_size = VENUS_EXTRADATA_SIZE( 10461 drv_ctx.video_resolution.frame_height, 10462 drv_ctx.video_resolution.frame_width); 10463 final_extra_data_size = extra_data_size > default_extra_data_size ? 10464 extra_data_size : default_extra_data_size; 10465 10466 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) & 10467 (~(buffer_prop->alignment - 1)); 10468 10469 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size; 10470 drv_ctx.extradata_info.count = buffer_prop->actualcount; 10471 drv_ctx.extradata_info.buffer_size = final_extra_data_size; 10472 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 10473 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)", 10474 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size); 10475 if (extra_data_size) 10476 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)", 10477 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size); 10478 10479 if (in_reconfig) // BufReq will be set to driver when port is disabled 10480 buffer_prop->buffer_size = buf_size; 10481 else if (buf_size != buffer_prop->buffer_size) { 10482 buffer_prop->buffer_size = buf_size; 10483 eRet = set_buffer_req(buffer_prop); 10484 } 10485 } 10486 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)", 10487 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 10488 return eRet; 10489 } 10490 10491 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) 10492 { 10493 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10494 unsigned buf_size = 0; 10495 struct v4l2_format fmt, c_fmt; 10496 struct v4l2_requestbuffers bufreq; 10497 int ret = 0; 10498 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)", 10499 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 10500 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 10501 if (buf_size != buffer_prop->buffer_size) { 10502 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)", 10503 (unsigned int)buffer_prop->buffer_size, buf_size); 10504 eRet = OMX_ErrorBadParameter; 10505 } else { 10506 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 10507 memset(&c_fmt, 0x0, sizeof(struct v4l2_format)); 10508 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 10509 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 10510 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size; 10511 10512 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 10513 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10514 fmt.fmt.pix_mp.pixelformat = output_capability; 10515 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 10516 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 10517 c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10518 c_fmt.fmt.pix_mp.pixelformat = capture_capability; 10519 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt); 10520 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size; 10521 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt); 10522 } else { 10523 eRet = OMX_ErrorBadParameter; 10524 } 10525 10526 if (ret) { 10527 /*TODO: How to handle this case */ 10528 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret); 10529 eRet = OMX_ErrorInsufficientResources; 10530 } 10531 10532 bufreq.memory = V4L2_MEMORY_USERPTR; 10533 bufreq.count = buffer_prop->actualcount; 10534 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 10535 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10536 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 10537 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10538 } else { 10539 eRet = OMX_ErrorBadParameter; 10540 } 10541 10542 if (eRet==OMX_ErrorNone) { 10543 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 10544 } 10545 10546 if (ret) { 10547 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret); 10548 /*TODO: How to handle this case */ 10549 eRet = OMX_ErrorInsufficientResources; 10550 } else if (bufreq.count < buffer_prop->actualcount) { 10551 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers" 10552 " on v4l2 port %d to %d (prefers %d)", bufreq.type, 10553 buffer_prop->actualcount, bufreq.count); 10554 eRet = OMX_ErrorInsufficientResources; 10555 } else { 10556 if (!client_buffers.update_buffer_req()) { 10557 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); 10558 eRet = OMX_ErrorInsufficientResources; 10559 } 10560 } 10561 } 10562 return eRet; 10563 } 10564 10565 OMX_ERRORTYPE omx_vdec::update_picture_resolution() 10566 { 10567 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10568 return eRet; 10569 } 10570 10571 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) 10572 { 10573 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10574 struct v4l2_format fmt; 10575 if (!portDefn) { 10576 return OMX_ErrorBadParameter; 10577 } 10578 DEBUG_PRINT_LOW("omx_vdec::update_portdef"); 10579 portDefn->nVersion.nVersion = OMX_SPEC_VERSION; 10580 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 10581 portDefn->eDomain = OMX_PortDomainVideo; 10582 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 10583 if (0 == portDefn->nPortIndex) { 10584 portDefn->eDir = OMX_DirInput; 10585 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; 10586 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; 10587 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size; 10588 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; 10589 portDefn->format.video.eCompressionFormat = eCompressionFormat; 10590 //for input port, always report the fps value set by client, 10591 //to distinguish whether client got valid fps from parser. 10592 portDefn->format.video.xFramerate = m_fps_received; 10593 portDefn->bEnabled = m_inp_bEnabled; 10594 portDefn->bPopulated = m_inp_bPopulated; 10595 10596 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10597 fmt.fmt.pix_mp.pixelformat = output_capability; 10598 ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 10599 } else if (1 == portDefn->nPortIndex) { 10600 unsigned int buf_size = 0; 10601 int ret = 0; 10602 if (in_reconfig && !is_down_scalar_enabled) { 10603 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10604 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 10605 fmt.fmt.pix_mp.pixelformat = capture_capability; 10606 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10607 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 10608 } 10609 10610 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10611 fmt.fmt.pix_mp.pixelformat = capture_capability; 10612 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 10613 if (ret) { 10614 DEBUG_PRINT_ERROR("Get Resolution failed"); 10615 return OMX_ErrorHardware; 10616 } 10617 drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; 10618 if (!client_buffers.update_buffer_req()) { 10619 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed"); 10620 return OMX_ErrorHardware; 10621 } 10622 10623 if (!client_buffers.get_buffer_req(buf_size)) { 10624 DEBUG_PRINT_ERROR("update buffer requirements"); 10625 return OMX_ErrorHardware; 10626 } 10627 portDefn->nBufferSize = buf_size; 10628 portDefn->eDir = OMX_DirOutput; 10629 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; 10630 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; 10631 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 10632 if (drv_ctx.frame_rate.fps_denominator > 0) 10633 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator / 10634 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format 10635 else { 10636 DEBUG_PRINT_ERROR("Error: Divide by zero"); 10637 return OMX_ErrorBadParameter; 10638 } 10639 portDefn->bEnabled = m_out_bEnabled; 10640 portDefn->bPopulated = m_out_bPopulated; 10641 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) { 10642 DEBUG_PRINT_ERROR("Error in getting color format"); 10643 return OMX_ErrorHardware; 10644 } 10645 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 10646 fmt.fmt.pix_mp.pixelformat = capture_capability; 10647 } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) { 10648 portDefn->nBufferSize = m_client_out_extradata_info.getSize(); 10649 portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS; 10650 portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS; 10651 portDefn->eDir = OMX_DirOutput; 10652 } else { 10653 portDefn->eDir = OMX_DirMax; 10654 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", 10655 (int)portDefn->nPortIndex); 10656 eRet = OMX_ErrorBadPortIndex; 10657 } 10658 update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, 10659 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]); 10660 10661 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; 10662 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; 10663 portDefn->format.video.nStride = drv_ctx.video_resolution.stride; 10664 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; 10665 10666 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) || 10667 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) { 10668 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16); 10669 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height; 10670 } 10671 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d " 10672 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u", 10673 (unsigned int)portDefn->nPortIndex, 10674 (unsigned int)portDefn->format.video.nFrameWidth, 10675 (unsigned int)portDefn->format.video.nFrameHeight, 10676 (int)portDefn->format.video.nStride, 10677 (unsigned int)portDefn->format.video.nSliceHeight, 10678 (unsigned int)portDefn->format.video.eColorFormat, 10679 (unsigned int)portDefn->nBufferSize, 10680 (unsigned int)portDefn->nBufferCountActual); 10681 10682 return eRet; 10683 } 10684 10685 OMX_ERRORTYPE omx_vdec::allocate_output_headers() 10686 { 10687 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10688 OMX_BUFFERHEADERTYPE *bufHdr = NULL; 10689 unsigned i = 0; 10690 10691 if (!m_out_mem_ptr) { 10692 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation"); 10693 int nBufHdrSize = 0; 10694 int nPlatformEntrySize = 0; 10695 int nPlatformListSize = 0; 10696 int nPMEMInfoSize = 0; 10697 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 10698 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 10699 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 10700 10701 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)", 10702 drv_ctx.op_buf.actualcount); 10703 nBufHdrSize = drv_ctx.op_buf.actualcount * 10704 sizeof(OMX_BUFFERHEADERTYPE); 10705 10706 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 10707 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 10708 nPlatformListSize = drv_ctx.op_buf.actualcount * 10709 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 10710 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 10711 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 10712 10713 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 10714 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 10715 nPMEMInfoSize, 10716 nPlatformListSize); 10717 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize, 10718 m_out_bm_count); 10719 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 10720 // Alloc mem for platform specific info 10721 char *pPtr=NULL; 10722 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 10723 nPMEMInfoSize,1); 10724 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ 10725 calloc (sizeof(struct vdec_bufferpayload), 10726 drv_ctx.op_buf.actualcount); 10727 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 10728 calloc (sizeof (struct vdec_output_frameinfo), 10729 drv_ctx.op_buf.actualcount); 10730 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 10731 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer"); 10732 return OMX_ErrorInsufficientResources; 10733 } 10734 10735 #ifdef USE_ION 10736 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ 10737 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); 10738 if (!drv_ctx.op_buf_ion_info) { 10739 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 10740 return OMX_ErrorInsufficientResources; 10741 } 10742 #endif 10743 if (dynamic_buf_mode) { 10744 out_dynamic_list = (struct dynamic_buf_list *) \ 10745 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount); 10746 if (out_dynamic_list) { 10747 for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++) 10748 out_dynamic_list[i].dup_fd = -1; 10749 } 10750 } 10751 10752 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 10753 && drv_ctx.ptr_respbuffer) { 10754 bufHdr = m_out_mem_ptr; 10755 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 10756 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 10757 (((char *) m_platform_list) + nPlatformListSize); 10758 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 10759 (((char *) m_platform_entry) + nPlatformEntrySize); 10760 pPlatformList = m_platform_list; 10761 pPlatformEntry = m_platform_entry; 10762 pPMEMInfo = m_pmem_info; 10763 10764 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 10765 10766 // Settting the entire storage nicely 10767 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, 10768 m_out_mem_ptr,pPlatformEntry); 10769 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 10770 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 10771 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 10772 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 10773 // Set the values when we determine the right HxW param 10774 bufHdr->nAllocLen = 0; 10775 bufHdr->nFilledLen = 0; 10776 bufHdr->pAppPrivate = NULL; 10777 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 10778 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 10779 pPlatformEntry->entry = pPMEMInfo; 10780 // Initialize the Platform List 10781 pPlatformList->nEntries = 1; 10782 pPlatformList->entryList = pPlatformEntry; 10783 // Keep pBuffer NULL till vdec is opened 10784 bufHdr->pBuffer = NULL; 10785 pPMEMInfo->offset = 0; 10786 pPMEMInfo->pmem_fd = -1; 10787 bufHdr->pPlatformPrivate = pPlatformList; 10788 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; 10789 #ifdef USE_ION 10790 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; 10791 #endif 10792 /*Create a mapping between buffers*/ 10793 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 10794 drv_ctx.ptr_respbuffer[i].client_data = (void *) \ 10795 &drv_ctx.ptr_outputbuffer[i]; 10796 // Move the buffer and buffer header pointers 10797 bufHdr++; 10798 pPMEMInfo++; 10799 pPlatformEntry++; 10800 pPlatformList++; 10801 } 10802 } else { 10803 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 10804 m_out_mem_ptr, pPtr); 10805 if (m_out_mem_ptr) { 10806 free(m_out_mem_ptr); 10807 m_out_mem_ptr = NULL; 10808 } 10809 if (pPtr) { 10810 free(pPtr); 10811 pPtr = NULL; 10812 } 10813 if (drv_ctx.ptr_outputbuffer) { 10814 free(drv_ctx.ptr_outputbuffer); 10815 drv_ctx.ptr_outputbuffer = NULL; 10816 } 10817 if (drv_ctx.ptr_respbuffer) { 10818 free(drv_ctx.ptr_respbuffer); 10819 drv_ctx.ptr_respbuffer = NULL; 10820 } 10821 #ifdef USE_ION 10822 if (drv_ctx.op_buf_ion_info) { 10823 DEBUG_PRINT_LOW("Free o/p ion context"); 10824 free(drv_ctx.op_buf_ion_info); 10825 drv_ctx.op_buf_ion_info = NULL; 10826 } 10827 #endif 10828 free(drv_ctx.op_buf_map_info); 10829 drv_ctx.op_buf_map_info = NULL; 10830 eRet = OMX_ErrorInsufficientResources; 10831 } 10832 } else { 10833 eRet = OMX_ErrorInsufficientResources; 10834 } 10835 return eRet; 10836 } 10837 10838 void omx_vdec::complete_pending_buffer_done_cbs() 10839 { 10840 unsigned long p1, p2, ident; 10841 omx_cmd_queue tmp_q, pending_bd_q; 10842 pthread_mutex_lock(&m_lock); 10843 // pop all pending GENERATE FDB from ftb queue 10844 while (m_ftb_q.m_size) { 10845 m_ftb_q.pop_entry(&p1,&p2,&ident); 10846 if (ident == OMX_COMPONENT_GENERATE_FBD) { 10847 pending_bd_q.insert_entry(p1,p2,ident); 10848 } else { 10849 tmp_q.insert_entry(p1,p2,ident); 10850 } 10851 } 10852 //return all non GENERATE FDB to ftb queue 10853 while (tmp_q.m_size) { 10854 tmp_q.pop_entry(&p1,&p2,&ident); 10855 m_ftb_q.insert_entry(p1,p2,ident); 10856 } 10857 // pop all pending GENERATE EDB from etb queue 10858 while (m_etb_q.m_size) { 10859 m_etb_q.pop_entry(&p1,&p2,&ident); 10860 if (ident == OMX_COMPONENT_GENERATE_EBD) { 10861 pending_bd_q.insert_entry(p1,p2,ident); 10862 } else { 10863 tmp_q.insert_entry(p1,p2,ident); 10864 } 10865 } 10866 //return all non GENERATE FDB to etb queue 10867 while (tmp_q.m_size) { 10868 tmp_q.pop_entry(&p1,&p2,&ident); 10869 m_etb_q.insert_entry(p1,p2,ident); 10870 } 10871 pthread_mutex_unlock(&m_lock); 10872 // process all pending buffer dones 10873 while (pending_bd_q.m_size) { 10874 pending_bd_q.pop_entry(&p1,&p2,&ident); 10875 switch (ident) { 10876 case OMX_COMPONENT_GENERATE_EBD: 10877 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) { 10878 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!"); 10879 omx_report_error (); 10880 } 10881 break; 10882 10883 case OMX_COMPONENT_GENERATE_FBD: 10884 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) { 10885 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!"); 10886 omx_report_error (); 10887 } 10888 break; 10889 } 10890 } 10891 } 10892 10893 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) 10894 { 10895 OMX_U32 new_frame_interval = 0; 10896 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts 10897 && llabs(act_timestamp - prev_ts) > 2000) { 10898 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ? 10899 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual); 10900 if (new_frame_interval != frm_int || frm_int == 0) { 10901 frm_int = new_frame_interval; 10902 if (frm_int) { 10903 drv_ctx.frame_rate.fps_numerator = 1e6; 10904 drv_ctx.frame_rate.fps_denominator = frm_int; 10905 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", 10906 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 10907 (float)drv_ctx.frame_rate.fps_denominator); 10908 m_perf_control.request_cores(frm_int); 10909 /* We need to report the difference between this FBD and the previous FBD 10910 * back to the driver for clock scaling purposes. */ 10911 struct v4l2_outputparm oparm; 10912 /*XXX: we're providing timing info as seconds per frame rather than frames 10913 * per second.*/ 10914 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 10915 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 10916 10917 struct v4l2_streamparm sparm; 10918 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10919 sparm.parm.output = oparm; 10920 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 10921 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 10922 performance might be affected"); 10923 } 10924 10925 } 10926 } 10927 } 10928 prev_ts = act_timestamp; 10929 } 10930 10931 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) 10932 { 10933 if (rst_prev_ts && VALID_TS(act_timestamp)) { 10934 prev_ts = act_timestamp; 10935 prev_ts_actual = act_timestamp; 10936 rst_prev_ts = false; 10937 } else if (VALID_TS(prev_ts)) { 10938 bool codec_cond = (drv_ctx.timestamp_adjust)? 10939 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) : 10940 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual); 10941 prev_ts_actual = act_timestamp; //unadjusted previous timestamp 10942 if (frm_int > 0 && codec_cond) { 10943 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); 10944 act_timestamp = prev_ts + frm_int; 10945 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); 10946 prev_ts = act_timestamp; 10947 } else { 10948 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) { 10949 // ensure that timestamps can never step backwards when in display order 10950 act_timestamp = prev_ts; 10951 } 10952 set_frame_rate(act_timestamp); 10953 } 10954 } else if (frm_int > 0) // In this case the frame rate was set along 10955 { // with the port definition, start ts with 0 10956 act_timestamp = prev_ts = 0; // and correct if a valid ts is received. 10957 rst_prev_ts = true; 10958 } 10959 } 10960 10961 OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index) 10962 { 10963 return m_out_mem_ptr + index; 10964 } 10965 10966 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range, 10967 OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects) 10968 { 10969 switch (primaries) { 10970 case MSM_VIDC_BT709_5: 10971 *color_space = ITU_R_709; 10972 aspects->mPrimaries = ColorAspects::PrimariesBT709_5; 10973 break; 10974 case MSM_VIDC_BT470_6_M: 10975 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M; 10976 break; 10977 case MSM_VIDC_BT601_6_625: 10978 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; 10979 break; 10980 case MSM_VIDC_BT601_6_525: 10981 *color_space = range ? ITU_R_601_FR : ITU_R_601; 10982 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525; 10983 break; 10984 case MSM_VIDC_GENERIC_FILM: 10985 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm; 10986 break; 10987 case MSM_VIDC_BT2020: 10988 aspects->mPrimaries = ColorAspects::PrimariesBT2020; 10989 break; 10990 case MSM_VIDC_UNSPECIFIED: 10991 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default 10992 default: 10993 //aspects->mPrimaries = ColorAspects::PrimariesOther; 10994 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 10995 break; 10996 } 10997 10998 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited; 10999 11000 switch (transfer) { 11001 case MSM_VIDC_TRANSFER_BT709_5: 11002 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625: 11003 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 11004 break; 11005 case MSM_VIDC_TRANSFER_BT_470_6_M: 11006 aspects->mTransfer = ColorAspects::TransferGamma22; 11007 break; 11008 case MSM_VIDC_TRANSFER_BT_470_6_BG: 11009 aspects->mTransfer = ColorAspects::TransferGamma28; 11010 break; 11011 case MSM_VIDC_TRANSFER_SMPTE_240M: 11012 aspects->mTransfer = ColorAspects::TransferSMPTE240M; 11013 break; 11014 case MSM_VIDC_TRANSFER_LINEAR: 11015 aspects->mTransfer = ColorAspects::TransferLinear; 11016 break; 11017 case MSM_VIDC_TRANSFER_IEC_61966: 11018 aspects->mTransfer = ColorAspects::TransferXvYCC; 11019 break; 11020 case MSM_VIDC_TRANSFER_BT_1361: 11021 aspects->mTransfer = ColorAspects::TransferBT1361; 11022 break; 11023 case MSM_VIDC_TRANSFER_SRGB: 11024 aspects->mTransfer = ColorAspects::TransferSRGB; 11025 break; 11026 default: 11027 //aspects->mTransfer = ColorAspects::TransferOther; 11028 aspects->mTransfer = m_client_color_space.sAspects.mTransfer; 11029 break; 11030 } 11031 11032 switch (matrix) { 11033 case MSM_VIDC_MATRIX_BT_709_5: 11034 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 11035 break; 11036 case MSM_VIDC_MATRIX_FCC_47: 11037 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M; 11038 break; 11039 case MSM_VIDC_MATRIX_601_6_625: 11040 case MSM_VIDC_MATRIX_601_6_525: 11041 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; 11042 break; 11043 case MSM_VIDC_MATRIX_SMPTE_240M: 11044 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M; 11045 break; 11046 case MSM_VIDC_MATRIX_BT_2020: 11047 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; 11048 break; 11049 case MSM_VIDC_MATRIX_BT_2020_CONST: 11050 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant; 11051 break; 11052 default: 11053 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther; 11054 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; 11055 break; 11056 } 11057 } 11058 11059 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) { 11060 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)", 11061 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange), 11062 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs)); 11063 } 11064 11065 void omx_vdec::prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range, 11066 OMX_U32 transfer, OMX_U32 matrix, 11067 ColorMetaData *color_mdata) 11068 { 11069 11070 /* ColorAspects in qdMetaData */ 11071 color_mdata->colorPrimaries = (enum ColorPrimaries) primaries; 11072 color_mdata->range = (enum ColorRange)range; 11073 color_mdata->transfer = (enum GammaTransfer)transfer; 11074 color_mdata->matrixCoefficients = (enum MatrixCoEfficients)matrix; 11075 } 11076 11077 bool omx_vdec::handle_color_space_info(void *data, 11078 ColorSpace_t *color_space, 11079 ColorMetaData *color_mdata, 11080 bool& set_color_aspects_only) 11081 { 11082 ColorAspects tempAspects; 11083 memset(&tempAspects, 0x0, sizeof(ColorAspects)); 11084 ColorAspects *aspects = &tempAspects; 11085 11086 /* Set default ColorAspects */ 11087 prepare_color_aspects_metadata(ColorPrimaries_BT601_6_625, Range_Full, 11088 Transfer_SMPTE_170M, MatrixCoEff_BT601_6_625, 11089 color_mdata); 11090 11091 switch(output_capability) { 11092 case V4L2_PIX_FMT_MPEG2: 11093 { 11094 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload; 11095 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data; 11096 11097 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to 11098 * understand this code */ 11099 11100 if (seqdisp_payload && seqdisp_payload->color_descp) { 11101 11102 convert_color_space_info(seqdisp_payload->color_primaries, 1, 11103 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs, 11104 color_space,aspects); 11105 m_disp_hor_size = seqdisp_payload->disp_width; 11106 m_disp_vert_size = seqdisp_payload->disp_height; 11107 set_color_aspects_only = true; 11108 prepare_color_aspects_metadata(seqdisp_payload->color_primaries, 1, 11109 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs, 11110 color_mdata); 11111 } 11112 } 11113 break; 11114 case V4L2_PIX_FMT_H264: 11115 case V4L2_PIX_FMT_HEVC: 11116 { 11117 struct msm_vidc_vui_display_info_payload *display_info_payload; 11118 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data; 11119 11120 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */ 11121 11122 if (display_info_payload->video_signal_present_flag && 11123 display_info_payload->color_description_present_flag) { 11124 convert_color_space_info(display_info_payload->color_primaries, 11125 display_info_payload->video_full_range_flag, 11126 display_info_payload->transfer_characteristics, 11127 display_info_payload->matrix_coefficients, 11128 color_space,aspects); 11129 set_color_aspects_only = true; 11130 prepare_color_aspects_metadata(display_info_payload->color_primaries, 11131 display_info_payload->video_full_range_flag, 11132 display_info_payload->transfer_characteristics, 11133 display_info_payload->matrix_coefficients, 11134 color_mdata); 11135 } 11136 } 11137 break; 11138 case V4L2_PIX_FMT_VC1_ANNEX_G: 11139 case V4L2_PIX_FMT_VC1_ANNEX_L: 11140 { 11141 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload; 11142 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data; 11143 11144 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23 11145 * SMPTE 421M to understand this code */ 11146 11147 if (m_enable_android_native_buffers && 11148 vc1_seq_disp_payload->color_primaries) { 11149 11150 convert_color_space_info(vc1_seq_disp_payload->color_primaries, 11151 1, 11152 vc1_seq_disp_payload->transfer_char, 11153 vc1_seq_disp_payload->matrix_coeffs, 11154 color_space,aspects); 11155 set_color_aspects_only = true; 11156 prepare_color_aspects_metadata(vc1_seq_disp_payload->color_primaries, 11157 1, 11158 vc1_seq_disp_payload->transfer_char, 11159 vc1_seq_disp_payload->matrix_coeffs, 11160 color_mdata); 11161 } 11162 } 11163 break; 11164 case V4L2_PIX_FMT_VP8: 11165 { 11166 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; 11167 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; 11168 set_color_aspects_only = false; 11169 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011 11170 * to understand this code */ 11171 11172 if (vpx_color_space_payload->color_space == 0) { 11173 *color_space = ITU_R_601; 11174 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525; 11175 aspects->mRange = ColorAspects::RangeLimited; 11176 } else { 11177 DEBUG_PRINT_ERROR("Unsupported Color space for VP8"); 11178 break; 11179 } 11180 } 11181 break; 11182 case V4L2_PIX_FMT_VP9: 11183 { 11184 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; 11185 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; 11186 set_color_aspects_only = false; 11187 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016 11188 * to understand this code */ 11189 11190 switch(vpx_color_space_payload->color_space) { 11191 case MSM_VIDC_CS_BT_601: 11192 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; 11193 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 11194 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; 11195 aspects->mRange = m_client_color_space.sAspects.mRange; 11196 break; 11197 case MSM_VIDC_CS_BT_709: 11198 *color_space = ITU_R_709; 11199 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 11200 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 11201 aspects->mPrimaries = ColorAspects::PrimariesBT709_5; 11202 aspects->mRange = m_client_color_space.sAspects.mRange; 11203 break; 11204 case MSM_VIDC_CS_SMPTE_170: 11205 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 11206 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 11207 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 11208 aspects->mRange = m_client_color_space.sAspects.mRange; 11209 break; 11210 case MSM_VIDC_CS_SMPTE_240: 11211 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; 11212 aspects->mTransfer = ColorAspects::TransferSMPTE240M; 11213 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 11214 aspects->mRange = m_client_color_space.sAspects.mRange; 11215 break; 11216 case MSM_VIDC_CS_BT_2020: 11217 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; 11218 aspects->mTransfer = ColorAspects:: TransferSMPTE170M; 11219 aspects->mPrimaries = ColorAspects::PrimariesBT2020; 11220 aspects->mRange = m_client_color_space.sAspects.mRange; 11221 break; 11222 case MSM_VIDC_CS_RESERVED: 11223 aspects->mMatrixCoeffs = ColorAspects::MatrixOther; 11224 aspects->mTransfer = ColorAspects::TransferOther; 11225 aspects->mPrimaries = ColorAspects::PrimariesOther; 11226 aspects->mRange = m_client_color_space.sAspects.mRange; 11227 break; 11228 case MSM_VIDC_CS_RGB: 11229 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 11230 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 11231 aspects->mPrimaries = ColorAspects::PrimariesOther; 11232 aspects->mRange = m_client_color_space.sAspects.mRange; 11233 break; 11234 default: 11235 break; 11236 } 11237 } 11238 break; 11239 default: 11240 break; 11241 } 11242 11243 print_debug_color_aspects(aspects, "Bitstream"); 11244 11245 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries || 11246 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer || 11247 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs || 11248 m_internal_color_space.sAspects.mRange != aspects->mRange) { 11249 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects)); 11250 11251 m_color_mdata.colorPrimaries = color_mdata->colorPrimaries; 11252 m_color_mdata.range = color_mdata->range; 11253 m_color_mdata.transfer = color_mdata->transfer; 11254 m_color_mdata.matrixCoefficients = color_mdata->matrixCoefficients; 11255 11256 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change"); 11257 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal"); 11258 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client"); 11259 11260 post_event(OMX_CORE_OUTPUT_PORT_INDEX, 11261 OMX_QTIIndexConfigDescribeColorAspects, 11262 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 11263 return true; 11264 } 11265 return false; 11266 } 11267 11268 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) { 11269 private_handle_t *private_handle = NULL; 11270 if (buf_index < drv_ctx.op_buf.actualcount && 11271 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 11272 native_buffer[buf_index].privatehandle) { 11273 private_handle = native_buffer[buf_index].privatehandle; 11274 } 11275 if (private_handle) { 11276 setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space); 11277 } 11278 } 11279 11280 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix) 11281 { 11282 if (!hdr_info->mID) { 11283 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix, 11284 hdr_info->sType1.mR.x, hdr_info->sType1.mR.y); 11285 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix, 11286 hdr_info->sType1.mG.x, hdr_info->sType1.mG.y); 11287 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix, 11288 hdr_info->sType1.mB.x, hdr_info->sType1.mB.y); 11289 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix, 11290 hdr_info->sType1.mW.x, hdr_info->sType1.mW.y); 11291 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix, 11292 hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance); 11293 DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix, 11294 hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel); 11295 } 11296 11297 } 11298 11299 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata) 11300 { 11301 DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u", 11302 color_mdata->colorPrimaries, color_mdata->range, 11303 color_mdata->transfer, color_mdata->matrixCoefficients); 11304 11305 for(uint8_t i = 0; i < 3; i++) { 11306 for(uint8_t j = 0; j < 2; j++) { 11307 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]); 11308 } 11309 } 11310 11311 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d", 11312 color_mdata->masteringDisplayInfo.primaries.whitePoint[0], 11313 color_mdata->masteringDisplayInfo.primaries.whitePoint[1]); 11314 11315 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d", 11316 color_mdata->masteringDisplayInfo.maxDisplayLuminance, 11317 color_mdata->masteringDisplayInfo.minDisplayLuminance); 11318 11319 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d", 11320 color_mdata->contentLightLevel.maxContentLightLevel, 11321 color_mdata->contentLightLevel.minPicAverageLightLevel); 11322 11323 11324 } 11325 11326 bool omx_vdec::handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata) 11327 { 11328 struct msm_vidc_content_light_level_sei_payload *light_level_payload = 11329 (msm_vidc_content_light_level_sei_payload*)(data); 11330 11331 light_level_mdata->lightLevelSEIEnabled = true; 11332 light_level_mdata->maxContentLightLevel = light_level_payload->nMaxContentLight; 11333 light_level_mdata->minPicAverageLightLevel = light_level_payload->nMaxPicAverageLight; 11334 11335 if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) || 11336 (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) { 11337 m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight; 11338 m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight; 11339 return true; 11340 } 11341 return false; 11342 } 11343 11344 bool omx_vdec::handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata) 11345 { 11346 struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload = 11347 (msm_vidc_mastering_display_colour_sei_payload*)(data); 11348 HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo; 11349 bool internal_disp_changed_flag = false; 11350 11351 mastering_display_mdata->colorVolumeSEIEnabled = true; 11352 for (uint8_t i = 0; i < 3; i++) { 11353 mastering_display_mdata->primaries.rgbPrimaries[i][0] = mastering_display_payload->nDisplayPrimariesX[i]; 11354 mastering_display_mdata->primaries.rgbPrimaries[i][1] = mastering_display_payload->nDisplayPrimariesY[i]; 11355 } 11356 mastering_display_mdata->primaries.whitePoint[0] = mastering_display_payload->nWhitePointX; 11357 mastering_display_mdata->primaries.whitePoint[1] = mastering_display_payload->nWhitePointY; 11358 mastering_display_mdata->maxDisplayLuminance = mastering_display_payload->nMaxDisplayMasteringLuminance; 11359 mastering_display_mdata->minDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance; 11360 11361 internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[0]) || 11362 (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[0]); 11363 internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[1]) || 11364 (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[1]); 11365 internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[2]) || 11366 (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[2]); 11367 11368 internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) || 11369 (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY); 11370 11371 /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension 11372 requires it in cd/m2, so dividing by 10000 and rounding the value after division 11373 */ 11374 uint16_t max_display_luminance_cd_m2 = 11375 static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5); 11376 internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) || 11377 (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance); 11378 11379 if (internal_disp_changed_flag) { 11380 hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[0]; 11381 hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[0]; 11382 hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[1]; 11383 hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[1]; 11384 hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[2]; 11385 hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[2]; 11386 hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX; 11387 hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY; 11388 11389 hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2; 11390 hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance; 11391 } 11392 11393 return internal_disp_changed_flag; 11394 } 11395 11396 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index) 11397 { 11398 private_handle_t *private_handle = NULL; 11399 if (buf_index < drv_ctx.op_buf.actualcount && 11400 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 11401 native_buffer[buf_index].privatehandle) { 11402 private_handle = native_buffer[buf_index].privatehandle; 11403 } 11404 if (private_handle) { 11405 setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata); 11406 } 11407 } 11408 11409 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) 11410 { 11411 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL; 11412 OMX_U8 *pBuffer = NULL; 11413 OMX_U32 num_conceal_MB = 0; 11414 OMX_TICKS time_stamp = 0; 11415 OMX_U32 frame_rate = 0; 11416 unsigned long consumed_len = 0; 11417 OMX_U32 num_MB_in_frame; 11418 OMX_U32 recovery_sei_flags = 1; 11419 int enable = OMX_InterlaceFrameProgressive; 11420 bool internal_hdr_info_changed_flag = false; 11421 bool color_event = false; 11422 ColorMetaData color_mdata; 11423 memset(&color_mdata, 0x0, sizeof(ColorMetaData)); 11424 bool set_disp_color_aspects_only = false; 11425 ColorSpace_t color_space = ITU_R_601; 11426 11427 int buf_index = p_buf_hdr - m_out_mem_ptr; 11428 if (buf_index >= drv_ctx.extradata_info.count) { 11429 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", 11430 buf_index, drv_ctx.extradata_info.count); 11431 return; 11432 } 11433 struct msm_vidc_panscan_window_payload *panscan_payload = NULL; 11434 11435 if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) { 11436 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL"); 11437 return; 11438 } 11439 11440 if (!drv_ctx.extradata_info.uaddr) { 11441 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr"); 11442 return; 11443 } 11444 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) { 11445 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data"); 11446 p_extra = NULL; 11447 return; 11448 } 11449 if (!secure_mode) { 11450 pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len, 11451 PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0); 11452 if (pBuffer == MAP_FAILED) { 11453 DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno); 11454 return; 11455 } 11456 p_extra = (OMX_OTHER_EXTRADATATYPE *) 11457 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3)); 11458 } else 11459 p_extra = m_other_extradata; 11460 11461 AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len); 11462 if (m_client_output_extradata_mem_ptr && 11463 m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) { 11464 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer); 11465 } 11466 11467 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size; 11468 11469 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { 11470 p_extra = NULL; 11471 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); 11472 return; 11473 } 11474 m_extradata_info.output_crop_updated = OMX_FALSE; 11475 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; 11476 if (data && p_extra) { 11477 while ((consumed_len < drv_ctx.extradata_info.buffer_size) 11478 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) { 11479 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) { 11480 DEBUG_PRINT_LOW("Invalid extra data size"); 11481 break; 11482 } 11483 11484 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { 11485 p_extra = NULL; 11486 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); 11487 return; 11488 } 11489 11490 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType); 11491 switch ((unsigned long)data->eType) { 11492 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO: 11493 struct msm_vidc_interlace_payload *payload; 11494 OMX_U32 interlace_color_format; 11495 payload = (struct msm_vidc_interlace_payload *)(void *)data->data; 11496 if (payload) { 11497 enable = OMX_InterlaceFrameProgressive; 11498 switch (payload->format) { 11499 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE: 11500 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 11501 break; 11502 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST: 11503 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 11504 enable = OMX_InterlaceInterleaveFrameTopFieldFirst; 11505 break; 11506 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST: 11507 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst; 11508 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst; 11509 break; 11510 default: 11511 DEBUG_PRINT_LOW("default case - set to progressive"); 11512 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 11513 } 11514 switch (payload->color_format) { 11515 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12: 11516 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 11517 break; 11518 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC: 11519 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 11520 break; 11521 default: 11522 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 11523 DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame"); 11524 } 11525 } 11526 11527 if (m_enable_android_native_buffers) { 11528 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d", 11529 payload->format, interlace_color_format ,enable, 11530 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false); 11531 11532 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 11533 PP_PARAM_INTERLACED, (void*)&enable); 11534 11535 if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) { 11536 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 11537 LINEAR_FORMAT, (void*)&interlace_color_format); 11538 } else if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 11539 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 11540 LINEAR_FORMAT, NULL); 11541 } 11542 } 11543 if (client_extradata & OMX_INTERLACE_EXTRADATA) { 11544 append_interlace_extradata(p_extra, payload->format); 11545 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11546 if (p_client_extra) { 11547 append_interlace_extradata(p_client_extra, payload->format); 11548 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) 11549 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11550 } 11551 } 11552 break; 11553 case MSM_VIDC_EXTRADATA_FRAME_RATE: 11554 struct msm_vidc_framerate_payload *frame_rate_payload; 11555 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data; 11556 frame_rate = frame_rate_payload->frame_rate; 11557 break; 11558 case MSM_VIDC_EXTRADATA_TIMESTAMP: 11559 struct msm_vidc_ts_payload *time_stamp_payload; 11560 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data; 11561 time_stamp = time_stamp_payload->timestamp_lo; 11562 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32); 11563 p_buf_hdr->nTimeStamp = time_stamp; 11564 break; 11565 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB: 11566 struct msm_vidc_concealmb_payload *conceal_mb_payload; 11567 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data; 11568 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 11569 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 11570 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0); 11571 break; 11572 case MSM_VIDC_EXTRADATA_INDEX: 11573 int *etype; 11574 etype = (int *)(void *)data->data; 11575 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) { 11576 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload; 11577 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype); 11578 if (aspect_ratio_payload) { 11579 ((struct vdec_output_frameinfo *) 11580 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width; 11581 ((struct vdec_output_frameinfo *) 11582 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height; 11583 } 11584 } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) { 11585 struct msm_vidc_output_crop_payload *output_crop_payload; 11586 output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype); 11587 if (output_crop_payload) { 11588 m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left; 11589 m_extradata_info.output_crop_rect.nTop = output_crop_payload->top; 11590 m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width; 11591 m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height; 11592 m_extradata_info.output_width = output_crop_payload->width; 11593 m_extradata_info.output_height = output_crop_payload->height; 11594 m_extradata_info.output_crop_updated = OMX_TRUE; 11595 } 11596 } 11597 break; 11598 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI: 11599 struct msm_vidc_recoverysei_payload *recovery_sei_payload; 11600 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data; 11601 recovery_sei_flags = recovery_sei_payload->flags; 11602 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) { 11603 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 11604 DEBUG_PRINT_HIGH("***************************************************"); 11605 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 11606 DEBUG_PRINT_HIGH("***************************************************"); 11607 } 11608 break; 11609 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW: 11610 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data; 11611 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) { 11612 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n"); 11613 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n", 11614 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows); 11615 return; 11616 } 11617 break; 11618 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP: 11619 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO: 11620 case MSM_VIDC_EXTRADATA_VC1_SEQDISP: 11621 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO: 11622 color_event = handle_color_space_info((void *)data->data, &color_space, &color_mdata, set_disp_color_aspects_only); 11623 break; 11624 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING: 11625 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload; 11626 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data; 11627 switch (s3d_frame_packing_payload->fpa_type) { 11628 case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE: 11629 if (s3d_frame_packing_payload->content_interprtation_type == 1) 11630 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R; 11631 else if (s3d_frame_packing_payload->content_interprtation_type == 2) 11632 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L; 11633 else { 11634 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type"); 11635 stereo_output_mode = HAL_NO_3D; 11636 } 11637 break; 11638 case MSM_VIDC_FRAMEPACK_TOP_BOTTOM: 11639 stereo_output_mode = HAL_3D_TOP_BOTTOM; 11640 break; 11641 default: 11642 DEBUG_PRINT_ERROR("Unsupported framepacking type"); 11643 stereo_output_mode = HAL_NO_3D; 11644 } 11645 DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d", 11646 s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode); 11647 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) { 11648 append_framepack_extradata(p_extra, s3d_frame_packing_payload); 11649 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11650 if (p_client_extra) { 11651 append_framepack_extradata(p_client_extra, s3d_frame_packing_payload); 11652 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11653 } 11654 } 11655 break; 11656 case MSM_VIDC_EXTRADATA_FRAME_QP: 11657 struct msm_vidc_frame_qp_payload *qp_payload; 11658 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data; 11659 if (client_extradata & OMX_QP_EXTRADATA) { 11660 append_qp_extradata(p_extra, qp_payload); 11661 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11662 if (p_client_extra) { 11663 append_qp_extradata(p_client_extra, qp_payload); 11664 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11665 } 11666 } 11667 break; 11668 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO: 11669 struct msm_vidc_frame_bits_info_payload *bits_info_payload; 11670 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data; 11671 if (client_extradata & OMX_BITSINFO_EXTRADATA) { 11672 append_bitsinfo_extradata(p_extra, bits_info_payload); 11673 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11674 if (p_client_extra) { 11675 append_bitsinfo_extradata(p_client_extra, bits_info_payload); 11676 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11677 } 11678 } 11679 break; 11680 case MSM_VIDC_EXTRADATA_STREAM_USERDATA: 11681 if (client_extradata & OMX_EXTNUSER_EXTRADATA) { 11682 append_user_extradata(p_extra, data); 11683 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11684 if (p_client_extra) { 11685 append_user_extradata(p_client_extra, data); 11686 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11687 } 11688 } 11689 break; 11690 case MSM_VIDC_EXTRADATA_VQZIP_SEI: 11691 struct msm_vidc_vqzip_sei_payload *vqzip_payload; 11692 vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data; 11693 if (client_extradata & OMX_VQZIPSEI_EXTRADATA) { 11694 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 11695 append_vqzip_extradata(p_extra, vqzip_payload); 11696 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11697 if (p_client_extra) { 11698 append_vqzip_extradata(p_client_extra, vqzip_payload); 11699 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11700 } 11701 } 11702 break; 11703 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI: 11704 11705 internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data, 11706 &(color_mdata.contentLightLevel)); 11707 break; 11708 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI: 11709 internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data, 11710 &(color_mdata.masteringDisplayInfo)); 11711 break; 11712 default: 11713 DEBUG_PRINT_LOW("Unrecognized extradata"); 11714 goto unrecognized_extradata; 11715 } 11716 consumed_len += data->nSize; 11717 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); 11718 } 11719 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) { 11720 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 11721 append_frame_info_extradata(p_extra, 11722 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate, 11723 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *) 11724 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info); 11725 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11726 if (p_client_extra) { 11727 append_frame_info_extradata(p_client_extra, 11728 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate, 11729 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *) 11730 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info); 11731 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11732 } 11733 } 11734 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) { 11735 append_frame_dimension_extradata(p_extra); 11736 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4)); 11737 if (p_client_extra) { 11738 append_frame_dimension_extradata(p_client_extra); 11739 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4)); 11740 } 11741 } 11742 11743 if(internal_hdr_info_changed_flag) { 11744 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal"); 11745 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client"); 11746 memcpy(&m_color_mdata, &color_mdata, sizeof(ColorMetaData)); 11747 auto_lock lock(m_hdr_info_client_lock); 11748 m_change_client_hdr_info = true; 11749 if(!color_event) { 11750 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change"); 11751 post_event(OMX_CORE_OUTPUT_PORT_INDEX, 11752 OMX_QTIIndexConfigDescribeHDRColorInfo, 11753 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 11754 } 11755 } 11756 11757 if (m_enable_android_native_buffers) { 11758 if (set_disp_color_aspects_only) { 11759 print_debug_hdr_color_info_mdata(&m_color_mdata); 11760 set_colormetadata_in_handle(&m_color_mdata, buf_index); 11761 } else { 11762 DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709); 11763 set_colorspace_in_handle(color_space, buf_index); 11764 } 11765 } 11766 11767 } 11768 unrecognized_extradata: 11769 if (client_extradata && p_extra) { 11770 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 11771 append_terminator_extradata(p_extra); 11772 if (p_client_extra) { 11773 append_terminator_extradata(p_client_extra); 11774 } 11775 } 11776 if (secure_mode && p_extradata && m_other_extradata) { 11777 struct vdec_output_frameinfo *ptr_extradatabuff = NULL; 11778 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size); 11779 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate; 11780 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata; 11781 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size; 11782 ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd; 11783 ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size; 11784 ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size; 11785 } 11786 return; 11787 } 11788 11789 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata, 11790 bool is_internal, bool enable) 11791 { 11792 OMX_ERRORTYPE ret = OMX_ErrorNone; 11793 struct v4l2_control control; 11794 if (m_state != OMX_StateLoaded) { 11795 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); 11796 return OMX_ErrorIncorrectStateOperation; 11797 } 11798 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d", 11799 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal); 11800 11801 if (!is_internal) { 11802 if (enable) 11803 client_extradata |= requested_extradata; 11804 else 11805 client_extradata = client_extradata & ~requested_extradata; 11806 } 11807 11808 if (enable) { 11809 if (requested_extradata & OMX_INTERLACE_EXTRADATA) { 11810 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11811 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO; 11812 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11813 DEBUG_PRINT_HIGH("Failed to set interlaced extradata." 11814 " Quality of interlaced clips might be impacted."); 11815 } 11816 } 11817 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) { 11818 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11819 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE; 11820 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11821 DEBUG_PRINT_HIGH("Failed to set framerate extradata"); 11822 } 11823 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11824 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB; 11825 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11826 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata"); 11827 } 11828 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11829 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI; 11830 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11831 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata"); 11832 } 11833 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11834 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW; 11835 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11836 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 11837 } 11838 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11839 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO; 11840 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11841 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 11842 } 11843 if (output_capability == V4L2_PIX_FMT_MPEG2) { 11844 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11845 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; 11846 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11847 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 11848 } 11849 } 11850 } 11851 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) { 11852 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11853 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP; 11854 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11855 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata"); 11856 } 11857 } 11858 if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) { 11859 if (output_capability == V4L2_PIX_FMT_H264) { 11860 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA"); 11861 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11862 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING; 11863 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11864 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata"); 11865 } 11866 } else { 11867 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only"); 11868 } 11869 } 11870 if (requested_extradata & OMX_QP_EXTRADATA) { 11871 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11872 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP; 11873 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11874 DEBUG_PRINT_HIGH("Failed to set QP extradata"); 11875 } 11876 } 11877 if (requested_extradata & OMX_BITSINFO_EXTRADATA) { 11878 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11879 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO; 11880 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11881 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata"); 11882 } 11883 } 11884 if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) { 11885 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11886 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA; 11887 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11888 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata"); 11889 } 11890 } 11891 if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) { 11892 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11893 control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI; 11894 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11895 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata"); 11896 } 11897 client_extradata |= OMX_VQZIPSEI_EXTRADATA; 11898 11899 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11900 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP; 11901 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11902 DEBUG_PRINT_HIGH("Failed to set QP extradata"); 11903 } 11904 client_extradata |= OMX_QP_EXTRADATA; 11905 } 11906 if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) { 11907 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11908 control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP; 11909 DEBUG_PRINT_LOW("Enable output crop extra data"); 11910 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11911 DEBUG_PRINT_HIGH("Failed to set output crop extradata"); 11912 } 11913 } 11914 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) { 11915 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11916 switch(output_capability) { 11917 case V4L2_PIX_FMT_H264: 11918 case V4L2_PIX_FMT_HEVC: 11919 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY; 11920 break; 11921 case CODEC_TYPE_MPEG2: 11922 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; 11923 break; 11924 case V4L2_PIX_FMT_VP8: 11925 case V4L2_PIX_FMT_VP9: 11926 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE; 11927 break; 11928 case V4L2_PIX_FMT_VC1_ANNEX_G: 11929 case V4L2_PIX_FMT_VC1_ANNEX_L: 11930 control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP; 11931 break; 11932 default: 11933 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind); 11934 return ret; 11935 } 11936 11937 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11938 DEBUG_PRINT_HIGH("Failed to set Display info extradata"); 11939 } 11940 } 11941 if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) { 11942 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 11943 if (output_capability == V4L2_PIX_FMT_H264 || 11944 output_capability == V4L2_PIX_FMT_HEVC) { 11945 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI; 11946 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11947 DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata"); 11948 } 11949 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI; 11950 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11951 DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata"); 11952 } 11953 } 11954 } 11955 } 11956 ret = get_buffer_req(&drv_ctx.op_buf); 11957 return ret; 11958 } 11959 11960 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) 11961 { 11962 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; 11963 OMX_U8 *data_ptr = extra->data, data = 0; 11964 while (byte_count < extra->nDataSize) { 11965 data = *data_ptr; 11966 while (data) { 11967 num_MB += (data&0x01); 11968 data >>= 1; 11969 } 11970 data_ptr++; 11971 byte_count++; 11972 } 11973 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 11974 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 11975 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); 11976 } 11977 11978 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) 11979 { 11980 if (!m_debug_extradata || !extra) 11981 return; 11982 11983 11984 DEBUG_PRINT_HIGH( 11985 "============== Extra Data ==============\n" 11986 " Size: %u\n" 11987 " Version: %u\n" 11988 " PortIndex: %u\n" 11989 " Type: %x\n" 11990 " DataSize: %u", 11991 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion, 11992 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize); 11993 11994 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) { 11995 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 11996 DEBUG_PRINT_HIGH( 11997 "------ Interlace Format ------\n" 11998 " Size: %u\n" 11999 " Version: %u\n" 12000 " PortIndex: %u\n" 12001 " Is Interlace Format: %d\n" 12002 " Interlace Formats: %u\n" 12003 "=========== End of Interlace ===========", 12004 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex, 12005 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats); 12006 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) { 12007 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 12008 12009 DEBUG_PRINT_HIGH( 12010 "-------- Frame Format --------\n" 12011 " Picture Type: %d\n" 12012 " Interlace Type: %d\n" 12013 " Pan Scan Total Frame Num: %u\n" 12014 " Concealed Macro Blocks: %u\n" 12015 " Recovery SEI Flag: %u\n" 12016 " frame rate: %u\n" 12017 " Time Stamp: %llu\n" 12018 " Aspect Ratio X: %u\n" 12019 " Aspect Ratio Y: %u", 12020 fminfo->ePicType, 12021 fminfo->interlaceType, 12022 (unsigned int)fminfo->panScan.numWindows, 12023 (unsigned int)fminfo->nConcealedMacroblocks, 12024 (unsigned int)fminfo->nRecoverySeiFlag, 12025 (unsigned int)fminfo->nFrameRate, 12026 fminfo->nTimeStamp, 12027 (unsigned int)fminfo->aspectRatio.aspectRatioX, 12028 (unsigned int)fminfo->aspectRatio.aspectRatioY); 12029 12030 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) { 12031 DEBUG_PRINT_HIGH( 12032 "------------------------------" 12033 " Pan Scan Frame Num: %u\n" 12034 " Rectangle x: %d\n" 12035 " Rectangle y: %d\n" 12036 " Rectangle dx: %d\n" 12037 " Rectangle dy: %d", 12038 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y, 12039 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy); 12040 } 12041 12042 DEBUG_PRINT_HIGH("========= End of Frame Format =========="); 12043 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) { 12044 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 12045 DEBUG_PRINT_HIGH( 12046 "------------------ Framepack Format ----------\n" 12047 " id: %u \n" 12048 " cancel_flag: %u \n" 12049 " type: %u \n" 12050 " quincunx_sampling_flagFormat: %u \n" 12051 " content_interpretation_type: %u \n" 12052 " spatial_flipping_flag: %u \n" 12053 " frame0_flipped_flag: %u \n" 12054 " field_views_flag: %u \n" 12055 " current_frame_is_frame0_flag: %u \n" 12056 " frame0_self_contained_flag: %u \n" 12057 " frame1_self_contained_flag: %u \n" 12058 " frame0_grid_position_x: %u \n" 12059 " frame0_grid_position_y: %u \n" 12060 " frame1_grid_position_x: %u \n" 12061 " frame1_grid_position_y: %u \n" 12062 " reserved_byte: %u \n" 12063 " repetition_period: %u \n" 12064 " extension_flag: %u \n" 12065 "================== End of Framepack ===========", 12066 (unsigned int)framepack->id, 12067 (unsigned int)framepack->cancel_flag, 12068 (unsigned int)framepack->type, 12069 (unsigned int)framepack->quincunx_sampling_flag, 12070 (unsigned int)framepack->content_interpretation_type, 12071 (unsigned int)framepack->spatial_flipping_flag, 12072 (unsigned int)framepack->frame0_flipped_flag, 12073 (unsigned int)framepack->field_views_flag, 12074 (unsigned int)framepack->current_frame_is_frame0_flag, 12075 (unsigned int)framepack->frame0_self_contained_flag, 12076 (unsigned int)framepack->frame1_self_contained_flag, 12077 (unsigned int)framepack->frame0_grid_position_x, 12078 (unsigned int)framepack->frame0_grid_position_y, 12079 (unsigned int)framepack->frame1_grid_position_x, 12080 (unsigned int)framepack->frame1_grid_position_y, 12081 (unsigned int)framepack->reserved_byte, 12082 (unsigned int)framepack->repetition_period, 12083 (unsigned int)framepack->extension_flag); 12084 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) { 12085 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 12086 DEBUG_PRINT_HIGH( 12087 "---- QP (Frame quantization parameter) ----\n" 12088 " Frame QP: %u \n" 12089 "================ End of QP ================\n", 12090 (unsigned int)qp->nQP); 12091 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) { 12092 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data; 12093 DEBUG_PRINT_HIGH( 12094 "--------- Input bits information --------\n" 12095 " Header bits: %u \n" 12096 " Frame bits: %u \n" 12097 "===== End of Input bits information =====\n", 12098 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits); 12099 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) { 12100 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data; 12101 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data; 12102 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type); 12103 OMX_U32 i = 0; 12104 DEBUG_PRINT_HIGH( 12105 "-------------- Userdata -------------\n" 12106 " Stream userdata type: %u\n" 12107 " userdata size: %u\n" 12108 " STREAM_USERDATA:", 12109 (unsigned int)userdata->type, (unsigned int)userdata_size); 12110 for (i = 0; i < userdata_size; i+=4) { 12111 DEBUG_PRINT_HIGH(" %x %x %x %x", 12112 data_ptr[i], data_ptr[i+1], 12113 data_ptr[i+2], data_ptr[i+3]); 12114 } 12115 DEBUG_PRINT_HIGH( 12116 "=========== End of Userdata ==========="); 12117 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) { 12118 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data; 12119 DEBUG_PRINT_HIGH( 12120 "-------------- VQZip -------------\n" 12121 " Size: %u\n", 12122 (unsigned int)vq->nSize); 12123 DEBUG_PRINT_HIGH( "=========== End of VQZip ==========="); 12124 } else if (extra->eType == OMX_ExtraDataNone) { 12125 DEBUG_PRINT_HIGH("========== End of Terminator ==========="); 12126 } else { 12127 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); 12128 } 12129 } 12130 12131 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12132 OMX_U32 interlaced_format_type) 12133 { 12134 OMX_STREAMINTERLACEFORMAT *interlace_format; 12135 12136 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) { 12137 return; 12138 } 12139 if (!extra) { 12140 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input"); 12141 return; 12142 } 12143 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; 12144 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12145 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12146 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; 12147 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); 12148 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 12149 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); 12150 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; 12151 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12152 12153 if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) { 12154 interlace_format->bInterlaceFormat = OMX_FALSE; 12155 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; 12156 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 12157 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) { 12158 interlace_format->bInterlaceFormat = OMX_TRUE; 12159 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 12160 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 12161 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) { 12162 interlace_format->bInterlaceFormat = OMX_TRUE; 12163 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst; 12164 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst; 12165 } else { 12166 //default case - set to progressive 12167 interlace_format->bInterlaceFormat = OMX_FALSE; 12168 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; 12169 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 12170 } 12171 print_debug_extradata(extra); 12172 } 12173 12174 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra) 12175 { 12176 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension; 12177 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) { 12178 return; 12179 } 12180 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE; 12181 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12182 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12183 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension; 12184 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION); 12185 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data; 12186 frame_dimension->nDecWidth = rectangle.nLeft; 12187 frame_dimension->nDecHeight = rectangle.nTop; 12188 frame_dimension->nActualWidth = rectangle.nWidth; 12189 frame_dimension->nActualHeight = rectangle.nHeight; 12190 } 12191 12192 void omx_vdec::fill_aspect_ratio_info( 12193 struct vdec_aspectratioinfo *aspect_ratio_info, 12194 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info) 12195 { 12196 m_extradata = frame_info; 12197 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width; 12198 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height; 12199 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX, 12200 (unsigned int)m_extradata->aspectRatio.aspectRatioY); 12201 } 12202 12203 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12204 OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate, 12205 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload, 12206 struct vdec_aspectratioinfo *aspect_ratio_info) 12207 { 12208 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; 12209 struct msm_vidc_panscan_window *panscan_window; 12210 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) { 12211 return; 12212 } 12213 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; 12214 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12215 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12216 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; 12217 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); 12218 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 12219 switch (picture_type) { 12220 case PICTURE_TYPE_I: 12221 frame_info->ePicType = OMX_VIDEO_PictureTypeI; 12222 break; 12223 case PICTURE_TYPE_P: 12224 frame_info->ePicType = OMX_VIDEO_PictureTypeP; 12225 break; 12226 case PICTURE_TYPE_B: 12227 frame_info->ePicType = OMX_VIDEO_PictureTypeB; 12228 break; 12229 default: 12230 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; 12231 } 12232 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) 12233 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 12234 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) 12235 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 12236 else 12237 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; 12238 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); 12239 frame_info->nConcealedMacroblocks = num_conceal_mb; 12240 frame_info->nRecoverySeiFlag = recovery_sei_flag; 12241 frame_info->nFrameRate = frame_rate; 12242 frame_info->nTimeStamp = time_stamp; 12243 frame_info->panScan.numWindows = 0; 12244 if (output_capability == V4L2_PIX_FMT_MPEG2) { 12245 if (m_disp_hor_size && m_disp_vert_size) { 12246 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size; 12247 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size; 12248 } else { 12249 frame_info->displayAspectRatio.displayHorizontalSize = 0; 12250 frame_info->displayAspectRatio.displayVerticalSize = 0; 12251 } 12252 } 12253 12254 if (panscan_payload) { 12255 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows; 12256 panscan_window = &panscan_payload->wnd[0]; 12257 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) { 12258 frame_info->panScan.window[i].x = panscan_window->panscan_window_width; 12259 frame_info->panScan.window[i].y = panscan_window->panscan_window_height; 12260 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset; 12261 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset; 12262 panscan_window++; 12263 } 12264 } 12265 fill_aspect_ratio_info(aspect_ratio_info, frame_info); 12266 print_debug_extradata(extra); 12267 } 12268 12269 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) 12270 { 12271 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; 12272 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; 12273 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12274 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12275 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; 12276 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 12277 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data; 12278 *portDefn = m_port_def; 12279 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u " 12280 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight, 12281 (unsigned int)portDefn->format.video.nFrameWidth, 12282 (unsigned int)portDefn->format.video.nStride, 12283 (unsigned int)portDefn->format.video.nSliceHeight); 12284 } 12285 12286 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12287 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload) 12288 { 12289 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack; 12290 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) { 12291 DEBUG_PRINT_ERROR("frame packing size mismatch"); 12292 return; 12293 } 12294 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE; 12295 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12296 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12297 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement; 12298 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 12299 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 12300 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 12301 framepack->nVersion.nVersion = OMX_SPEC_VERSION; 12302 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12303 memcpy(&framepack->id, s3d_frame_packing_payload, 12304 sizeof(struct msm_vidc_s3d_frame_packing_payload)); 12305 memcpy(&m_frame_pack_arrangement, framepack, 12306 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 12307 print_debug_extradata(extra); 12308 } 12309 12310 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12311 struct msm_vidc_frame_qp_payload *qp_payload) 12312 { 12313 OMX_QCOM_EXTRADATA_QP * qp = NULL; 12314 if (!qp_payload) { 12315 DEBUG_PRINT_ERROR("QP payload is NULL"); 12316 return; 12317 } 12318 extra->nSize = OMX_QP_EXTRADATA_SIZE; 12319 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12320 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12321 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP; 12322 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP); 12323 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 12324 qp->nQP = qp_payload->frame_qp; 12325 print_debug_extradata(extra); 12326 } 12327 12328 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12329 struct msm_vidc_frame_bits_info_payload *bits_payload) 12330 { 12331 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL; 12332 if (!bits_payload) { 12333 DEBUG_PRINT_ERROR("bits info payload is NULL"); 12334 return; 12335 } 12336 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE; 12337 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12338 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12339 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo; 12340 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO); 12341 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data; 12342 bits->frame_bits = bits_payload->frame_bits; 12343 bits->header_bits = bits_payload->header_bits; 12344 print_debug_extradata(extra); 12345 } 12346 12347 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12348 OMX_OTHER_EXTRADATATYPE *p_user) 12349 { 12350 int userdata_size = 0; 12351 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL; 12352 userdata_payload = 12353 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data; 12354 userdata_size = p_user->nDataSize; 12355 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size; 12356 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12357 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12358 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData; 12359 extra->nDataSize = userdata_size; 12360 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize)) 12361 memcpy(extra->data, p_user->data, extra->nDataSize); 12362 print_debug_extradata(extra); 12363 } 12364 12365 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) 12366 { 12367 if (!client_extradata) { 12368 return; 12369 } 12370 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); 12371 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12372 extra->eType = OMX_ExtraDataNone; 12373 extra->nDataSize = 0; 12374 extra->data[0] = 0; 12375 12376 print_debug_extradata(extra); 12377 } 12378 12379 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra, 12380 struct msm_vidc_vqzip_sei_payload *vqzip_payload) 12381 { 12382 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL; 12383 12384 extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size; 12385 extra->nVersion.nVersion = OMX_SPEC_VERSION; 12386 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12387 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI; 12388 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size; 12389 12390 vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data; 12391 vq->nSize = vqzip_payload->size; 12392 memcpy(vq->data, vqzip_payload->data, vqzip_payload->size); 12393 12394 print_debug_extradata(extra); 12395 } 12396 12397 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) 12398 { 12399 OMX_ERRORTYPE eRet = OMX_ErrorNone; 12400 if (index >= drv_ctx.ip_buf.actualcount) { 12401 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found"); 12402 return OMX_ErrorInsufficientResources; 12403 } 12404 if (m_desc_buffer_ptr == NULL) { 12405 m_desc_buffer_ptr = (desc_buffer_hdr*) \ 12406 calloc( (sizeof(desc_buffer_hdr)), 12407 drv_ctx.ip_buf.actualcount); 12408 if (m_desc_buffer_ptr == NULL) { 12409 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed "); 12410 return OMX_ErrorInsufficientResources; 12411 } 12412 } 12413 12414 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); 12415 if (m_desc_buffer_ptr[index].buf_addr == NULL) { 12416 DEBUG_PRINT_ERROR("desc buffer Allocation failed "); 12417 return OMX_ErrorInsufficientResources; 12418 } 12419 12420 return eRet; 12421 } 12422 12423 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) 12424 { 12425 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries); 12426 if (m_demux_entries < 8192) { 12427 m_demux_offsets[m_demux_entries++] = address_offset; 12428 } 12429 return; 12430 } 12431 12432 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) 12433 { 12434 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; 12435 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; 12436 OMX_U32 index = 0; 12437 12438 m_demux_entries = 0; 12439 12440 while (index < bytes_to_parse) { 12441 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 12442 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || 12443 ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 12444 (buf[index+2] == 0x01)) ) { 12445 //Found start code, insert address offset 12446 insert_demux_addr_offset(index); 12447 if (buf[index+2] == 0x01) // 3 byte start code 12448 index += 3; 12449 else //4 byte start code 12450 index += 4; 12451 } else 12452 index++; 12453 } 12454 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries); 12455 return; 12456 } 12457 12458 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) 12459 { 12460 //fix this, handle 3 byte start code, vc1 terminator entry 12461 OMX_U8 *p_demux_data = NULL; 12462 OMX_U32 desc_data = 0; 12463 OMX_U32 start_addr = 0; 12464 OMX_U32 nal_size = 0; 12465 OMX_U32 suffix_byte = 0; 12466 OMX_U32 demux_index = 0; 12467 OMX_U32 buffer_index = 0; 12468 12469 if (m_desc_buffer_ptr == NULL) { 12470 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); 12471 return OMX_ErrorBadParameter; 12472 } 12473 12474 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 12475 if (buffer_index > drv_ctx.ip_buf.actualcount) { 12476 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index); 12477 return OMX_ErrorBadParameter; 12478 } 12479 12480 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; 12481 12482 if ( ((OMX_U8*)p_demux_data == NULL) || 12483 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) { 12484 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); 12485 return OMX_ErrorBadParameter; 12486 } else { 12487 for (; demux_index < m_demux_entries; demux_index++) { 12488 desc_data = 0; 12489 start_addr = m_demux_offsets[demux_index]; 12490 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) { 12491 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; 12492 } else { 12493 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; 12494 } 12495 if (demux_index < (m_demux_entries - 1)) { 12496 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; 12497 } else { 12498 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; 12499 } 12500 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)", 12501 (unsigned int)start_addr, 12502 (unsigned int)suffix_byte, 12503 (unsigned int)nal_size, 12504 (unsigned int)demux_index); 12505 desc_data = (start_addr >> 3) << 1; 12506 desc_data |= (start_addr & 7) << 21; 12507 desc_data |= suffix_byte << 24; 12508 12509 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 12510 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); 12511 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 12512 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 12513 12514 p_demux_data += 16; 12515 } 12516 if (codec_type_parse == CODEC_TYPE_VC1) { 12517 DEBUG_PRINT_LOW("VC1 terminator entry"); 12518 desc_data = 0; 12519 desc_data = 0x82 << 24; 12520 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 12521 memset(p_demux_data + 4, 0, sizeof(OMX_U32)); 12522 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 12523 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 12524 p_demux_data += 16; 12525 m_demux_entries++; 12526 } 12527 //Add zero word to indicate end of descriptors 12528 memset(p_demux_data, 0, sizeof(OMX_U32)); 12529 12530 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); 12531 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size); 12532 } 12533 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 12534 m_demux_entries = 0; 12535 DEBUG_PRINT_LOW("Demux table complete!"); 12536 return OMX_ErrorNone; 12537 } 12538 12539 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level) 12540 { 12541 struct v4l2_control control; 12542 char property_value[PROPERTY_VALUE_MAX] = {0}; 12543 12544 property_get("vendor.vidc.debug.turbo", property_value, "0"); 12545 memset(&control, 0, sizeof(v4l2_control)); 12546 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 12547 switch (perf_level) { 12548 case VIDC_NOMINAL: 12549 if (atoi(property_value)) 12550 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 12551 else 12552 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; 12553 break; 12554 case VIDC_TURBO: 12555 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 12556 break; 12557 default: 12558 DEBUG_PRINT_ERROR("Requested PERF level not supported"); 12559 break; 12560 } 12561 if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig) 12562 return; 12563 12564 DEBUG_PRINT_HIGH("changing performance level to %d", control.value); 12565 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 12566 current_perf_level = control.value; 12567 } else { 12568 DEBUG_PRINT_ERROR("Failed to set PERF level"); 12569 } 12570 } 12571 12572 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf() 12573 { 12574 enabled = false; 12575 omx = NULL; 12576 init_members(); 12577 ColorFormat = OMX_COLOR_FormatMax; 12578 dest_format = YCbCr420P; 12579 m_c2d_width = 0; 12580 m_c2d_height = 0; 12581 } 12582 12583 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client) 12584 { 12585 omx = reinterpret_cast<omx_vdec*>(client); 12586 } 12587 12588 void omx_vdec::allocate_color_convert_buf::init_members() 12589 { 12590 allocated_count = 0; 12591 buffer_size_req = 0; 12592 buffer_alignment_req = 0; 12593 m_c2d_width = m_c2d_height = 0; 12594 memset(m_platform_list_client,0,sizeof(m_platform_list_client)); 12595 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client)); 12596 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client)); 12597 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client)); 12598 #ifdef USE_ION 12599 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client)); 12600 #endif 12601 for (int i = 0; i < MAX_COUNT; i++) 12602 pmem_fd[i] = -1; 12603 } 12604 12605 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf() 12606 { 12607 c2d.destroy(); 12608 } 12609 12610 bool omx_vdec::allocate_color_convert_buf::update_buffer_req() 12611 { 12612 bool status = true; 12613 unsigned int src_size = 0, destination_size = 0; 12614 unsigned int height, width; 12615 struct v4l2_format fmt; 12616 OMX_COLOR_FORMATTYPE drv_color_format; 12617 12618 if (!omx) { 12619 DEBUG_PRINT_ERROR("Invalid client in color convert"); 12620 return false; 12621 } 12622 if (!enabled) { 12623 DEBUG_PRINT_HIGH("No color conversion required"); 12624 return status; 12625 } 12626 pthread_mutex_lock(&omx->c_lock); 12627 12628 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 12629 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 12630 fmt.fmt.pix_mp.pixelformat = omx->capture_capability; 12631 ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 12632 width = fmt.fmt.pix_mp.width; 12633 height = fmt.fmt.pix_mp.height; 12634 12635 bool resolution_upgrade = (height > m_c2d_height || 12636 width > m_c2d_width); 12637 if (resolution_upgrade) { 12638 // resolution upgraded ? ensure we are yet to allocate; 12639 // failing which, c2d buffers will never be reallocated and bad things will happen 12640 if (allocated_count > 0) { 12641 DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations", 12642 allocated_count); 12643 status = false; 12644 goto fail_update_buf_req; 12645 } 12646 } 12647 12648 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 && 12649 ColorFormat != OMX_COLOR_FormatYUV420Planar) { 12650 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion"); 12651 status = false; 12652 goto fail_update_buf_req; 12653 } 12654 c2d.close(); 12655 status = c2d.open(height, 12656 width, 12657 NV12_128m,dest_format); 12658 if (status) { 12659 status = c2d.get_buffer_size(C2D_INPUT,src_size); 12660 if (status) 12661 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size); 12662 } 12663 if (status) { 12664 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size || 12665 !destination_size) { 12666 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d" 12667 "driver size %u destination size %d", 12668 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size, 12669 destination_size); 12670 status = false; 12671 c2d.close(); 12672 buffer_size_req = 0; 12673 // TODO: make this fatal. Driver is not supposed to quote size 12674 // smaller than what C2D needs !! 12675 } else { 12676 buffer_size_req = destination_size; 12677 m_c2d_height = height; 12678 m_c2d_width = width; 12679 } 12680 } 12681 fail_update_buf_req: 12682 pthread_mutex_unlock(&omx->c_lock); 12683 return status; 12684 } 12685 12686 bool omx_vdec::allocate_color_convert_buf::set_color_format( 12687 OMX_COLOR_FORMATTYPE dest_color_format) 12688 { 12689 bool status = true, drv_colorformat_c2d_enable = false; 12690 bool dest_color_format_c2d_enable = false; 12691 OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused; 12692 if (!omx) { 12693 DEBUG_PRINT_ERROR("Invalid client in color convert"); 12694 return false; 12695 } 12696 pthread_mutex_lock(&omx->c_lock); 12697 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 12698 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 12699 drv_color_format = (OMX_COLOR_FORMATTYPE) 12700 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 12701 else 12702 drv_color_format = (OMX_COLOR_FORMATTYPE) 12703 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 12704 else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 12705 drv_color_format = (OMX_COLOR_FORMATTYPE) 12706 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 12707 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) { 12708 drv_color_format = (OMX_COLOR_FORMATTYPE) 12709 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed; 12710 } else { 12711 DEBUG_PRINT_ERROR("Incorrect color format"); 12712 status = false; 12713 } 12714 drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) && 12715 (drv_color_format != (OMX_COLOR_FORMATTYPE) 12716 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) && 12717 (drv_color_format != (OMX_COLOR_FORMATTYPE) 12718 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) && 12719 (drv_color_format != (OMX_COLOR_FORMATTYPE) 12720 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed); 12721 12722 dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE) 12723 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) && 12724 (dest_color_format != (OMX_COLOR_FORMATTYPE) 12725 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed); 12726 12727 if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) { 12728 DEBUG_PRINT_LOW("Enabling C2D"); 12729 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) && 12730 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) { 12731 DEBUG_PRINT_ERROR("Unsupported color format for c2d"); 12732 status = false; 12733 } else { 12734 ColorFormat = dest_color_format; 12735 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ? 12736 YCbCr420P : YCbCr420SP; 12737 if (enabled) 12738 c2d.destroy(); 12739 enabled = false; 12740 if (!c2d.init()) { 12741 DEBUG_PRINT_ERROR("open failed for c2d"); 12742 status = false; 12743 } else 12744 enabled = true; 12745 } 12746 } else { 12747 if (enabled) 12748 c2d.destroy(); 12749 enabled = false; 12750 } 12751 pthread_mutex_unlock(&omx->c_lock); 12752 return status; 12753 } 12754 12755 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() 12756 { 12757 if (!omx) { 12758 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 12759 return NULL; 12760 } 12761 if (!enabled) 12762 return omx->m_out_mem_ptr; 12763 return m_out_mem_ptr_client; 12764 } 12765 12766 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr 12767 (OMX_BUFFERHEADERTYPE *bufadd) 12768 { 12769 if (!omx) { 12770 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 12771 return NULL; 12772 } 12773 if (!enabled) 12774 return bufadd; 12775 12776 unsigned index = 0; 12777 index = bufadd - omx->m_out_mem_ptr; 12778 if (index < omx->drv_ctx.op_buf.actualcount) { 12779 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS); 12780 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp; 12781 bool status; 12782 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) { 12783 pthread_mutex_lock(&omx->c_lock); 12784 cache_clean_buffer(index); 12785 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd, 12786 omx->drv_ctx.op_buf_map_info[index].base_address, bufadd->pBuffer, pmem_fd[index], 12787 pmem_baseaddress[index], pmem_baseaddress[index]); 12788 if (!status) { 12789 DEBUG_PRINT_ERROR("Failed color conversion %d", status); 12790 m_out_mem_ptr_client[index].nFilledLen = 0; 12791 pthread_mutex_unlock(&omx->c_lock); 12792 return &m_out_mem_ptr_client[index]; 12793 } else { 12794 unsigned int filledLen = 0; 12795 c2d.get_output_filled_length(filledLen); 12796 m_out_mem_ptr_client[index].nFilledLen = filledLen; 12797 cache_clean_invalidate_buffer(index); 12798 } 12799 pthread_mutex_unlock(&omx->c_lock); 12800 } else 12801 m_out_mem_ptr_client[index].nFilledLen = 0; 12802 return &m_out_mem_ptr_client[index]; 12803 } 12804 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr"); 12805 return NULL; 12806 } 12807 12808 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr 12809 (OMX_BUFFERHEADERTYPE *bufadd) 12810 { 12811 if (!omx) { 12812 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 12813 return NULL; 12814 } 12815 if (!enabled) 12816 return bufadd; 12817 unsigned index = 0; 12818 index = bufadd - m_out_mem_ptr_client; 12819 if (index < omx->drv_ctx.op_buf.actualcount) { 12820 return &omx->m_out_mem_ptr[index]; 12821 } 12822 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr"); 12823 return NULL; 12824 } 12825 bool omx_vdec::allocate_color_convert_buf::get_buffer_req 12826 (unsigned int &buffer_size) 12827 { 12828 bool status = true; 12829 pthread_mutex_lock(&omx->c_lock); 12830 if (!enabled) 12831 buffer_size = omx->drv_ctx.op_buf.buffer_size; 12832 else { 12833 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) { 12834 DEBUG_PRINT_ERROR("Get buffer size failed"); 12835 status = false; 12836 goto fail_get_buffer_size; 12837 } 12838 } 12839 fail_get_buffer_size: 12840 pthread_mutex_unlock(&omx->c_lock); 12841 return status; 12842 } 12843 12844 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req( 12845 OMX_U32 buffer_size, OMX_U32 actual_count) { 12846 OMX_U32 expectedSize = enabled ? buffer_size_req : omx->drv_ctx.op_buf.buffer_size; 12847 12848 if (buffer_size < expectedSize) { 12849 DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)", 12850 buffer_size, expectedSize); 12851 return OMX_ErrorBadParameter; 12852 } 12853 if (actual_count < omx->drv_ctx.op_buf.actualcount) { 12854 DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)", 12855 actual_count, omx->drv_ctx.op_buf.actualcount); 12856 return OMX_ErrorBadParameter; 12857 } 12858 12859 bool reqs_updated = false; 12860 if (enabled) { 12861 // disallow changing buffer size/count while we have active allocated buffers 12862 if (allocated_count > 0) { 12863 DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations", 12864 buffer_size_req, buffer_size, allocated_count); 12865 return OMX_ErrorInvalidState; 12866 } 12867 12868 buffer_size_req = buffer_size; 12869 } else { 12870 if (buffer_size > omx->drv_ctx.op_buf.buffer_size) { 12871 omx->drv_ctx.op_buf.buffer_size = buffer_size; 12872 reqs_updated = true; 12873 } 12874 } 12875 12876 if (actual_count > omx->drv_ctx.op_buf.actualcount) { 12877 omx->drv_ctx.op_buf.actualcount = actual_count; 12878 reqs_updated = true; 12879 } 12880 12881 if (reqs_updated) { 12882 omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount; 12883 omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count * 12884 omx->drv_ctx.extradata_info.buffer_size; 12885 return omx->set_buffer_req(&(omx->drv_ctx.op_buf)); 12886 } 12887 return OMX_ErrorNone; 12888 } 12889 12890 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer( 12891 OMX_BUFFERHEADERTYPE *bufhdr) 12892 { 12893 unsigned int index = 0; 12894 12895 if (!enabled) 12896 return omx->free_output_buffer(bufhdr); 12897 if (enabled && omx->is_component_secure()) 12898 return OMX_ErrorNone; 12899 if (!allocated_count || !bufhdr) { 12900 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr); 12901 return OMX_ErrorBadParameter; 12902 } 12903 index = bufhdr - m_out_mem_ptr_client; 12904 if (index >= omx->drv_ctx.op_buf.actualcount) { 12905 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer"); 12906 return OMX_ErrorBadParameter; 12907 } 12908 if (pmem_fd[index] >= 0) { 12909 munmap(pmem_baseaddress[index], buffer_size_req); 12910 close(pmem_fd[index]); 12911 } 12912 pmem_fd[index] = -1; 12913 #ifdef USE_ION 12914 omx->free_ion_memory(&op_buf_ion_info[index]); 12915 #endif 12916 if (allocated_count > 0) 12917 allocated_count--; 12918 else 12919 allocated_count = 0; 12920 if (!allocated_count) { 12921 pthread_mutex_lock(&omx->c_lock); 12922 c2d.close(); 12923 init_members(); 12924 pthread_mutex_unlock(&omx->c_lock); 12925 } 12926 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]); 12927 } 12928 12929 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp, 12930 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes) 12931 { 12932 OMX_ERRORTYPE eRet = OMX_ErrorNone; 12933 if (!enabled) { 12934 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); 12935 return eRet; 12936 } 12937 if (enabled && omx->is_component_secure()) { 12938 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d", 12939 omx->is_component_secure()); 12940 return OMX_ErrorUnsupportedSetting; 12941 } 12942 if (!bufferHdr || bytes > buffer_size_req) { 12943 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr); 12944 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u", 12945 (unsigned int)buffer_size_req, (unsigned int)bytes); 12946 return OMX_ErrorBadParameter; 12947 } 12948 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) { 12949 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert"); 12950 return OMX_ErrorInsufficientResources; 12951 } 12952 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL; 12953 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr, 12954 port,appData,omx->drv_ctx.op_buf.buffer_size); 12955 if (eRet != OMX_ErrorNone || !temp_bufferHdr) { 12956 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert"); 12957 return eRet; 12958 } 12959 if ((temp_bufferHdr - omx->m_out_mem_ptr) >= 12960 (int)omx->drv_ctx.op_buf.actualcount) { 12961 DEBUG_PRINT_ERROR("Invalid header index %ld", 12962 (long int)(temp_bufferHdr - omx->m_out_mem_ptr)); 12963 return OMX_ErrorUndefined; 12964 } 12965 unsigned int i = allocated_count; 12966 #ifdef USE_ION 12967 // Allocate color-conversion buffers as cached to improve software-reading 12968 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit 12969 // cache invalidation. 12970 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory( 12971 buffer_size_req,buffer_alignment_req, 12972 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data, 12973 ION_FLAG_CACHED); 12974 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd; 12975 if (op_buf_ion_info[i].ion_device_fd < 0) { 12976 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert"); 12977 return OMX_ErrorInsufficientResources; 12978 } 12979 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req, 12980 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0); 12981 12982 if (pmem_baseaddress[i] == MAP_FAILED) { 12983 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req); 12984 close(pmem_fd[i]); 12985 omx->free_ion_memory(&op_buf_ion_info[i]); 12986 return OMX_ErrorInsufficientResources; 12987 } 12988 #endif 12989 m_pmem_info_client[i].offset = 0; 12990 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i]; 12991 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 12992 m_platform_list_client[i].nEntries = 1; 12993 m_platform_list_client[i].entryList = &m_platform_entry_client[i]; 12994 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL; 12995 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req; 12996 m_out_mem_ptr_client[i].nFilledLen = 0; 12997 m_out_mem_ptr_client[i].nFlags = 0; 12998 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 12999 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE); 13000 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION; 13001 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i]; 13002 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i]; 13003 m_out_mem_ptr_client[i].pAppPrivate = appData; 13004 *bufferHdr = &m_out_mem_ptr_client[i]; 13005 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr); 13006 allocated_count++; 13007 return eRet; 13008 } 13009 13010 bool omx_vdec::is_component_secure() 13011 { 13012 return secure_mode; 13013 } 13014 13015 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format) 13016 { 13017 bool status = true; 13018 if (!enabled) { 13019 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 13020 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 13021 dest_color_format = (OMX_COLOR_FORMATTYPE) 13022 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 13023 else 13024 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 13025 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){ 13026 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 13027 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC){ 13028 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed; 13029 } else 13030 status = false; 13031 } else { 13032 if (ColorFormat == OMX_COLOR_FormatYUV420Planar || 13033 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 13034 dest_color_format = ColorFormat; 13035 } else 13036 status = false; 13037 } 13038 return status; 13039 } 13040 13041 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops( 13042 unsigned int index, unsigned int cmd) 13043 { 13044 if (!enabled) { 13045 return OMX_ErrorNone; 13046 } 13047 13048 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) { 13049 DEBUG_PRINT_ERROR("%s: Invalid param", __func__); 13050 return OMX_ErrorBadParameter; 13051 } 13052 13053 struct ion_flush_data flush_data; 13054 struct ion_custom_data custom_data; 13055 13056 memset(&flush_data, 0x0, sizeof(flush_data)); 13057 memset(&custom_data, 0x0, sizeof(custom_data)); 13058 13059 flush_data.vaddr = pmem_baseaddress[index]; 13060 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd; 13061 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle; 13062 flush_data.length = buffer_size_req; 13063 custom_data.cmd = cmd; 13064 custom_data.arg = (unsigned long)&flush_data; 13065 13066 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d", 13067 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 13068 flush_data.fd, flush_data.handle, flush_data.vaddr, 13069 flush_data.length); 13070 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data); 13071 if (ret < 0) { 13072 DEBUG_PRINT_ERROR("Cache %s failed: %s\n", 13073 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 13074 strerror(errno)); 13075 return OMX_ErrorUndefined; 13076 } 13077 return OMX_ErrorNone; 13078 } 13079 13080 void omx_vdec::buf_ref_add(int nPortIndex) 13081 { 13082 unsigned long i = 0; 13083 bool buf_present = false; 13084 long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 13085 OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 13086 13087 if (!dynamic_buf_mode || !out_dynamic_list) { 13088 return; 13089 } 13090 13091 pthread_mutex_lock(&m_lock); 13092 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 13093 //check the buffer fd, offset, uv addr with list contents 13094 //If present increment reference. 13095 if ((out_dynamic_list[i].fd == fd) && 13096 (out_dynamic_list[i].offset == offset)) { 13097 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u", 13098 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 13099 if (!secure_mode) { 13100 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr; 13101 } 13102 buf_present = true; 13103 break; 13104 } 13105 } 13106 if (!buf_present) { 13107 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 13108 //search for a entry to insert details of the new buffer 13109 if (out_dynamic_list[i].dup_fd < 0) { 13110 out_dynamic_list[i].fd = fd; 13111 out_dynamic_list[i].offset = offset; 13112 out_dynamic_list[i].dup_fd = dup(fd); 13113 out_dynamic_list[i].ref_count++; 13114 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u", 13115 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 13116 13117 if (!secure_mode) { 13118 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = 13119 (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len, 13120 PROT_READ|PROT_WRITE, MAP_SHARED, 13121 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0); 13122 //mmap returns (void *)-1 on failure and sets error code in errno. 13123 if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) { 13124 DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno); 13125 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL; 13126 break; 13127 } 13128 out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr; 13129 out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len; 13130 DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size); 13131 } 13132 break; 13133 } 13134 } 13135 } 13136 pthread_mutex_unlock(&m_lock); 13137 } 13138 13139 void omx_vdec::buf_ref_remove() 13140 { 13141 unsigned long i = 0; 13142 13143 if (!dynamic_buf_mode || !out_dynamic_list) { 13144 return; 13145 } 13146 13147 pthread_mutex_lock(&m_lock); 13148 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 13149 if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) { 13150 DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size); 13151 munmap(out_dynamic_list[i].buffaddr, 13152 out_dynamic_list[i].mapped_size); 13153 } 13154 13155 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u", 13156 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 13157 close(out_dynamic_list[i].dup_fd); 13158 out_dynamic_list[i].dup_fd = -1; 13159 } 13160 pthread_mutex_unlock(&m_lock); 13161 13162 if (out_dynamic_list) { 13163 free(out_dynamic_list); 13164 out_dynamic_list = NULL; 13165 } 13166 } 13167 13168 #ifdef _MSM8974_ 13169 void omx_vdec::send_codec_config() { 13170 if (codec_config_flag) { 13171 unsigned long p1 = 0; // Parameter - 1 13172 unsigned long p2 = 0; // Parameter - 2 13173 unsigned long ident = 0; 13174 pthread_mutex_lock(&m_lock); 13175 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n"); 13176 while (m_etb_q.m_size) { 13177 m_etb_q.pop_entry(&p1,&p2,&ident); 13178 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { 13179 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 13180 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 13181 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 13182 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); 13183 omx_report_error(); 13184 } 13185 } else { 13186 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 13187 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 13188 } 13189 } else if (ident == OMX_COMPONENT_GENERATE_ETB) { 13190 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 13191 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ 13192 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 13193 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); 13194 omx_report_error (); 13195 } 13196 } else { 13197 pending_input_buffers++; 13198 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers); 13199 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 13200 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 13201 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 13202 } 13203 } else if (ident == OMX_COMPONENT_GENERATE_EBD) { 13204 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", 13205 (OMX_BUFFERHEADERTYPE *)p1); 13206 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 13207 } 13208 } 13209 pthread_mutex_unlock(&m_lock); 13210 } 13211 } 13212 #endif 13213 13214 omx_vdec::perf_control::perf_control() 13215 { 13216 m_perf_lib = NULL; 13217 m_perf_handle = 0; 13218 m_perf_lock_acquire = NULL; 13219 m_perf_lock_release = NULL; 13220 } 13221 13222 omx_vdec::perf_control::~perf_control() 13223 { 13224 if (m_perf_handle != 0 && m_perf_lock_release) { 13225 DEBUG_PRINT_LOW("NOTE2: release perf lock"); 13226 m_perf_lock_release(m_perf_handle); 13227 } 13228 if (m_perf_lib) { 13229 dlclose(m_perf_lib); 13230 } 13231 } 13232 13233 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0}; 13234 13235 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock; 13236 13237 void omx_vdec::perf_control::send_hint_to_mpctl(bool state) 13238 { 13239 if (load_lib() == false) { 13240 return; 13241 } 13242 m_perf_lock.lock(); 13243 /* 0x4401 maps to video decode playback hint 13244 * in perflock, enum number is 44 and state 13245 * being sent on perflock acquire is 01 (true) 13246 */ 13247 int arg = 0x4401; 13248 13249 if (state == true) { 13250 mpctl_obj.vid_inst_count++; 13251 } else if (state == false) { 13252 mpctl_obj.vid_inst_count--; 13253 } 13254 13255 if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) { 13256 mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int)); 13257 mpctl_obj.vid_acquired = true; 13258 DEBUG_PRINT_INFO("Video slvp perflock acquired"); 13259 } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) { 13260 m_perf_lock_release(mpctl_obj.vid_disp_handle); 13261 mpctl_obj.vid_acquired = false; 13262 DEBUG_PRINT_INFO("Video slvp perflock released"); 13263 } 13264 m_perf_lock.unlock(); 13265 } 13266 13267 void omx_vdec::perf_control::request_cores(int frame_duration_us) 13268 { 13269 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) { 13270 return; 13271 } 13272 bool retVal = load_lib(); 13273 if (retVal && m_perf_lock_acquire && m_perf_handle == 0) { 13274 int arg = 0x700 /*base value*/ + 2 /*cores*/; 13275 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int)); 13276 if (m_perf_handle) { 13277 DEBUG_PRINT_HIGH("perf lock acquired"); 13278 } 13279 } 13280 } 13281 13282 bool omx_vdec::perf_control::load_lib() 13283 { 13284 char perf_lib_path[PROPERTY_VALUE_MAX] = {0}; 13285 if (m_perf_lib) 13286 return true; 13287 13288 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) { 13289 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library"); 13290 goto handle_err; 13291 } 13292 13293 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) { 13294 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror()); 13295 goto handle_err; 13296 } else { 13297 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq"); 13298 if (m_perf_lock_acquire == NULL) { 13299 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq"); 13300 goto handle_err; 13301 } 13302 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel"); 13303 if (m_perf_lock_release == NULL) { 13304 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel"); 13305 goto handle_err; 13306 } 13307 } 13308 return true; 13309 13310 handle_err: 13311 if (m_perf_lib) { 13312 dlclose(m_perf_lib); 13313 } 13314 m_perf_lib = NULL; 13315 return false; 13316 } 13317 13318 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth, 13319 unsigned long nMaxFrameHeight) 13320 { 13321 13322 OMX_ERRORTYPE eRet = OMX_ErrorNone; 13323 int ret = 0; 13324 unsigned long min_res_buf_count = 0; 13325 13326 eRet = enable_smoothstreaming(); 13327 if (eRet != OMX_ErrorNone) { 13328 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver"); 13329 return eRet; 13330 } 13331 13332 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu", 13333 nMaxFrameWidth, 13334 nMaxFrameHeight); 13335 m_smoothstreaming_mode = true; 13336 m_smoothstreaming_width = nMaxFrameWidth; 13337 m_smoothstreaming_height = nMaxFrameHeight; 13338 13339 //Get upper limit buffer count for min supported resolution 13340 struct v4l2_format fmt; 13341 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 13342 fmt.fmt.pix_mp.height = m_decoder_capability.min_height; 13343 fmt.fmt.pix_mp.width = m_decoder_capability.min_width; 13344 fmt.fmt.pix_mp.pixelformat = output_capability; 13345 13346 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 13347 if (ret) { 13348 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u", 13349 m_decoder_capability.min_height, 13350 m_decoder_capability.min_width); 13351 return OMX_ErrorUnsupportedSetting; 13352 } 13353 13354 eRet = get_buffer_req(&drv_ctx.op_buf); 13355 if (eRet != OMX_ErrorNone) { 13356 DEBUG_PRINT_ERROR("failed to get_buffer_req"); 13357 return eRet; 13358 } 13359 13360 min_res_buf_count = drv_ctx.op_buf.mincount; 13361 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u", 13362 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width); 13363 13364 m_extradata_info.output_crop_rect.nLeft = 0; 13365 m_extradata_info.output_crop_rect.nTop = 0; 13366 m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width; 13367 m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height; 13368 13369 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, 13370 m_smoothstreaming_width, m_smoothstreaming_height); 13371 eRet = is_video_session_supported(); 13372 if (eRet != OMX_ErrorNone) { 13373 DEBUG_PRINT_ERROR("video session is not supported"); 13374 return eRet; 13375 } 13376 13377 //Get upper limit buffer size for max smooth streaming resolution set 13378 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 13379 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 13380 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 13381 fmt.fmt.pix_mp.pixelformat = output_capability; 13382 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 13383 if (ret) { 13384 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback"); 13385 return OMX_ErrorUnsupportedSetting; 13386 } 13387 13388 eRet = get_buffer_req(&drv_ctx.op_buf); 13389 if (eRet != OMX_ErrorNone) { 13390 DEBUG_PRINT_ERROR("failed to get_buffer_req!!"); 13391 return eRet; 13392 } 13393 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u", 13394 (unsigned int)drv_ctx.op_buf.buffer_size); 13395 13396 drv_ctx.op_buf.mincount = min_res_buf_count; 13397 drv_ctx.op_buf.actualcount = min_res_buf_count; 13398 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size; 13399 eRet = set_buffer_req(&drv_ctx.op_buf); 13400 if (eRet != OMX_ErrorNone) { 13401 DEBUG_PRINT_ERROR("failed to set_buffer_req"); 13402 return eRet; 13403 } 13404 13405 eRet = get_buffer_req(&drv_ctx.op_buf); 13406 if (eRet != OMX_ErrorNone) { 13407 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!"); 13408 return eRet; 13409 } 13410 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u", 13411 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size); 13412 return eRet; 13413 } 13414 13415 //static 13416 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { 13417 13418 #ifndef FLEXYUV_SUPPORTED 13419 return OMX_ErrorUndefined; 13420 #else 13421 13422 if (pParam == NULL) { 13423 DEBUG_PRINT_ERROR("describeColorFormat: invalid params"); 13424 return OMX_ErrorBadParameter; 13425 } 13426 13427 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam; 13428 13429 MediaImage *img = &(params->sMediaImage); 13430 switch(params->eColorFormat) { 13431 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m: 13432 { 13433 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 13434 img->mNumPlanes = 3; 13435 // mWidth and mHeight represent the W x H of the largest plane 13436 // In our case, this happens to be the Stride x Scanlines of Y plane 13437 img->mWidth = params->nFrameWidth; 13438 img->mHeight = params->nFrameHeight; 13439 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 13440 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight); 13441 img->mBitDepth = 8; 13442 //Plane 0 (Y) 13443 img->mPlane[MediaImage::Y].mOffset = 0; 13444 img->mPlane[MediaImage::Y].mColInc = 1; 13445 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride 13446 img->mPlane[MediaImage::Y].mHorizSubsampling = 1; 13447 img->mPlane[MediaImage::Y].mVertSubsampling = 1; 13448 //Plane 1 (U) 13449 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight; 13450 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV 13451 img->mPlane[MediaImage::U].mRowInc = 13452 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 13453 img->mPlane[MediaImage::U].mHorizSubsampling = 2; 13454 img->mPlane[MediaImage::U].mVertSubsampling = 2; 13455 //Plane 2 (V) 13456 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1; 13457 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV 13458 img->mPlane[MediaImage::V].mRowInc = 13459 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 13460 img->mPlane[MediaImage::V].mHorizSubsampling = 2; 13461 img->mPlane[MediaImage::V].mVertSubsampling = 2; 13462 break; 13463 } 13464 13465 case OMX_COLOR_FormatYUV420Planar: 13466 case OMX_COLOR_FormatYUV420SemiPlanar: 13467 // We need not describe the standard OMX linear formats as these are 13468 // understood by client. Fail this deliberately to let client fill-in 13469 return OMX_ErrorUnsupportedSetting; 13470 13471 default: 13472 // Rest all formats which are non-linear cannot be described 13473 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat); 13474 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 13475 return OMX_ErrorNone; 13476 }; 13477 13478 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat); 13479 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight); 13480 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight); 13481 for (size_t i = 0; i < img->mNumPlanes; ++i) { 13482 DEBUG_PRINT_LOW(" Plane[%zu] : offset=%d / xStep=%d / yStep = %d", 13483 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc); 13484 } 13485 return OMX_ErrorNone; 13486 #endif //FLEXYUV_SUPPORTED 13487 } 13488 13489 void omx_vdec::prefetchNewBuffers() { 13490 13491 struct v4l2_decoder_cmd dec; 13492 uint32_t prefetch_count; 13493 uint32_t prefetch_size; 13494 uint32_t want_size; 13495 uint32_t have_size; 13496 int color_fmt, rc; 13497 uint32_t new_calculated_size; 13498 uint32_t new_buffer_size; 13499 uint32_t new_buffer_count; 13500 uint32_t old_buffer_size; 13501 uint32_t old_buffer_count; 13502 13503 memset((void *)&dec, 0 , sizeof(dec)); 13504 DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n", 13505 drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount, 13506 drv_ctx.video_resolution.frame_width, 13507 drv_ctx.video_resolution.frame_height); 13508 dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT; 13509 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { 13510 DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno); 13511 } else { 13512 DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n", 13513 dec.raw.data[0], dec.raw.data[1]); 13514 } 13515 13516 switch ((int)drv_ctx.output_format) { 13517 case VDEC_YUV_FORMAT_NV12: 13518 color_fmt = COLOR_FMT_NV12; 13519 break; 13520 case VDEC_YUV_FORMAT_NV12_UBWC: 13521 color_fmt = COLOR_FMT_NV12_UBWC; 13522 break; 13523 case VDEC_YUV_FORMAT_NV12_TP10_UBWC: 13524 color_fmt = COLOR_FMT_NV12_BPP10_UBWC; 13525 break; 13526 default: 13527 color_fmt = -1; 13528 DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format); 13529 return; 13530 } 13531 13532 new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height); 13533 DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n", 13534 m_reconfig_width, m_reconfig_height, new_calculated_size); 13535 new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size; 13536 new_buffer_count = dec.raw.data[1]; 13537 old_buffer_size = drv_ctx.op_buf.buffer_size; 13538 old_buffer_count = drv_ctx.op_buf.actualcount; 13539 13540 new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count; 13541 13542 prefetch_count = new_buffer_count; 13543 prefetch_size = new_buffer_size - old_buffer_size; 13544 want_size = new_buffer_size * new_buffer_count; 13545 have_size = old_buffer_size * old_buffer_count; 13546 13547 if (want_size > have_size) { 13548 DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size); 13549 DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size); 13550 13551 int ion_fd = open(MEM_DEVICE, O_RDONLY); 13552 if (ion_fd < 0) { 13553 DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd); 13554 return; 13555 } 13556 13557 struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data)); 13558 struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data)); 13559 struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions)); 13560 size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count); 13561 13562 if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) { 13563 DEBUG_PRINT_ERROR("prefetch data allocation failed"); 13564 goto prefetch_exit; 13565 } 13566 13567 for (uint32_t i = 0; i < prefetch_count; i++) { 13568 sizes[i] = prefetch_size; 13569 } 13570 13571 regions[0].nr_sizes = prefetch_count; 13572 regions[0].sizes = sizes; 13573 regions[0].vmid = ION_FLAG_CP_PIXEL; 13574 13575 prefetch_data->nr_regions = 1; 13576 prefetch_data->regions = regions; 13577 prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID); 13578 13579 custom_data->cmd = ION_IOC_PREFETCH; 13580 custom_data->arg = (unsigned long )prefetch_data; 13581 13582 rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data); 13583 if (rc) { 13584 DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno); 13585 } 13586 13587 prefetch_exit: 13588 close(ion_fd); 13589 free(sizes); 13590 free(regions); 13591 free(prefetch_data); 13592 free(custom_data); 13593 } 13594 } 13595 13596 13597 // No code beyond this ! 13598 13599 // inline import of vendor-extensions implementation 13600 #include "omx_vdec_extensions.hpp" 13601