1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the name of The Linux Foundation nor 12 the names of its contributors may be used to endorse or promote 13 products derived from this software without specific prior written 14 permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 --------------------------------------------------------------------------*/ 28 29 /*============================================================================ 30 O p e n M A X w r a p p e r s 31 O p e n M A X C o r e 32 33 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 <media/msm_media_info.h> 56 #include <sys/eventfd.h> 57 #include <nativebase/nativebase.h> 58 59 #ifndef _ANDROID_ 60 #include <sys/ioctl.h> 61 #include <sys/mman.h> 62 #endif //_ANDROID_ 63 64 #ifdef _ANDROID_ 65 #include <cutils/properties.h> 66 #undef USE_EGL_IMAGE_GPU 67 #endif 68 69 #include <qdMetaData.h> 70 71 #ifdef ANDROID_JELLYBEAN_MR2 72 #include "QComOMXMetadata.h" 73 #endif 74 75 #ifdef USE_EGL_IMAGE_GPU 76 #include <EGL/egl.h> 77 #include <EGL/eglQCOM.h> 78 #define EGL_BUFFER_HANDLE 0x4F00 79 #define EGL_BUFFER_OFFSET 0x4F01 80 #endif 81 82 #define BUFFER_LOG_LOC "/data/misc/media" 83 84 #ifdef OUTPUT_EXTRADATA_LOG 85 FILE *outputExtradataFile; 86 char output_extradata_filename [] = "/data/misc/media/extradata"; 87 #endif 88 89 #define DEFAULT_FPS 30 90 #define MAX_SUPPORTED_FPS 120 91 #define DEFAULT_WIDTH_ALIGNMENT 128 92 #define DEFAULT_HEIGHT_ALIGNMENT 32 93 94 #define VC1_SP_MP_START_CODE 0xC5000000 95 #define VC1_SP_MP_START_CODE_MASK 0xFF000000 96 #define VC1_AP_SEQ_START_CODE 0x0F010000 97 #define VC1_STRUCT_C_PROFILE_MASK 0xF0 98 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 99 #define VC1_SIMPLE_PROFILE 0 100 #define VC1_MAIN_PROFILE 1 101 #define VC1_ADVANCE_PROFILE 3 102 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 103 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2 104 #define VC1_STRUCT_C_LEN 4 105 #define VC1_STRUCT_C_POS 8 106 #define VC1_STRUCT_A_POS 12 107 #define VC1_STRUCT_B_POS 24 108 #define VC1_SEQ_LAYER_SIZE 36 109 #define POLL_TIMEOUT 0x7fffffff 110 111 #define MEM_DEVICE "/dev/ion" 112 113 #ifdef _ANDROID_ 114 extern "C" { 115 #include<utils/Log.h> 116 } 117 #endif//_ANDROID_ 118 119 #define SZ_4K 0x1000 120 #define SZ_1M 0x100000 121 122 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } 123 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } 124 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0) 125 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1)) 126 127 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA) 128 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default 129 130 #ifndef ION_FLAG_CP_BITSTREAM 131 #define ION_FLAG_CP_BITSTREAM 0 132 #endif 133 134 #ifndef ION_FLAG_CP_PIXEL 135 #define ION_FLAG_CP_PIXEL 0 136 #endif 137 138 #ifdef MASTER_SIDE_CP 139 #define MEM_HEAP_ID ION_SECURE_HEAP_ID 140 #define SECURE_ALIGN SZ_4K 141 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM) 142 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL) 143 #else //SLAVE_SIDE_CP 144 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID 145 #define SECURE_ALIGN SZ_1M 146 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE 147 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE 148 #endif 149 150 static OMX_U32 maxSmoothStreamingWidth = 1920; 151 static OMX_U32 maxSmoothStreamingHeight = 1088; 152 153 void* async_message_thread (void *input) 154 { 155 OMX_BUFFERHEADERTYPE *buffer; 156 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 157 struct pollfd pfds[2]; 158 struct v4l2_buffer v4l2_buf; 159 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 160 struct v4l2_event dqevent; 161 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input); 162 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI; 163 pfds[1].events = POLLIN | POLLERR; 164 pfds[0].fd = omx->drv_ctx.video_driver_fd; 165 pfds[1].fd = omx->m_poll_efd; 166 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0; 167 DEBUG_PRINT_HIGH("omx_vdec: Async thread start"); 168 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); 169 while (!omx->async_thread_force_stop) { 170 rc = poll(pfds, 2, POLL_TIMEOUT); 171 if (!rc) { 172 DEBUG_PRINT_ERROR("Poll timedout"); 173 break; 174 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) { 175 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno); 176 break; 177 } 178 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) { 179 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited"); 180 break; 181 } 182 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) { 183 struct vdec_msginfo vdec_msg; 184 memset(&vdec_msg, 0, sizeof(vdec_msg)); 185 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 186 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 187 v4l2_buf.length = omx->drv_ctx.num_planes; 188 v4l2_buf.m.planes = plane; 189 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) { 190 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 191 vdec_msg.status_code=VDEC_S_SUCCESS; 192 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf; 193 vdec_msg.msgdata.output_frame.len=plane[0].bytesused; 194 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr; 195 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) + 196 (uint64_t)v4l2_buf.timestamp.tv_usec; 197 if (vdec_msg.msgdata.output_frame.len) { 198 vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2]; 199 vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3]; 200 vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4]; 201 vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5]; 202 vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6]; 203 vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7]; 204 } 205 if (omx->async_message_process(input,&vdec_msg) < 0) { 206 DEBUG_PRINT_HIGH("async_message_thread Exited"); 207 break; 208 } 209 } 210 } 211 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) { 212 struct vdec_msginfo vdec_msg; 213 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 214 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 215 v4l2_buf.length = 1; 216 v4l2_buf.m.planes = plane; 217 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) { 218 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE; 219 vdec_msg.status_code=VDEC_S_SUCCESS; 220 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf; 221 if (omx->async_message_process(input,&vdec_msg) < 0) { 222 DEBUG_PRINT_HIGH("async_message_thread Exited"); 223 break; 224 } 225 } 226 } 227 if (pfds[0].revents & POLLPRI) { 228 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent); 229 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) { 230 struct vdec_msginfo vdec_msg; 231 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 232 233 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED; 234 vdec_msg.status_code=VDEC_S_SUCCESS; 235 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0]; 236 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1]; 237 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient"); 238 if (omx->async_message_process(input,&vdec_msg) < 0) { 239 DEBUG_PRINT_HIGH("async_message_thread Exited"); 240 break; 241 } 242 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT ) { 243 struct vdec_msginfo vdec_msg; 244 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED; 245 vdec_msg.status_code=VDEC_S_SUCCESS; 246 omx->dpb_bit_depth = dqevent.u.data[0]; 247 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", dqevent.u.data[0]); 248 if (omx->async_message_process(input,&vdec_msg) < 0) { 249 DEBUG_PRINT_HIGH("async_message_thread Exited"); 250 break; 251 } 252 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) { 253 struct vdec_msginfo vdec_msg; 254 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE; 255 vdec_msg.status_code=VDEC_S_SUCCESS; 256 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved"); 257 if (omx->async_message_process(input,&vdec_msg) < 0) { 258 DEBUG_PRINT_HIGH("async_message_thread Exited"); 259 break; 260 } 261 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE; 262 vdec_msg.status_code=VDEC_S_SUCCESS; 263 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved"); 264 if (omx->async_message_process(input,&vdec_msg) < 0) { 265 DEBUG_PRINT_HIGH("async_message_thread Exited"); 266 break; 267 } 268 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) { 269 struct vdec_msginfo vdec_msg; 270 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD; 271 vdec_msg.status_code=VDEC_S_SUCCESS; 272 DEBUG_PRINT_ERROR("HW Overload received"); 273 if (omx->async_message_process(input,&vdec_msg) < 0) { 274 DEBUG_PRINT_HIGH("async_message_thread Exited"); 275 break; 276 } 277 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) { 278 struct vdec_msginfo vdec_msg; 279 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED; 280 vdec_msg.status_code=VDEC_S_SUCCESS; 281 DEBUG_PRINT_ERROR("HW Unsupported received"); 282 if (omx->async_message_process(input,&vdec_msg) < 0) { 283 DEBUG_PRINT_HIGH("async_message_thread Exited"); 284 break; 285 } 286 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) { 287 struct vdec_msginfo vdec_msg; 288 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR; 289 vdec_msg.status_code = VDEC_S_SUCCESS; 290 DEBUG_PRINT_HIGH("SYS Error Recieved"); 291 if (omx->async_message_process(input,&vdec_msg) < 0) { 292 DEBUG_PRINT_HIGH("async_message_thread Exited"); 293 break; 294 } 295 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) { 296 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 297 298 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]); 299 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) { 300 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data; 301 struct vdec_msginfo vdec_msg; 302 303 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]); 304 305 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 306 v4l2_buf.memory = V4L2_MEMORY_USERPTR; 307 v4l2_buf.length = omx->drv_ctx.num_planes; 308 v4l2_buf.m.planes = plane; 309 v4l2_buf.index = ptr[5]; 310 v4l2_buf.flags = 0; 311 312 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; 313 vdec_msg.status_code = VDEC_S_SUCCESS; 314 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf; 315 vdec_msg.msgdata.output_frame.len = 0; 316 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2]; 317 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) + 318 (uint64_t)ptr[4]; 319 if (omx->async_message_process(input,&vdec_msg) < 0) { 320 DEBUG_PRINT_HIGH("async_message_thread Exitedn"); 321 break; 322 } 323 } else { 324 DEBUG_PRINT_HIGH("VIDC Some Event recieved"); 325 continue; 326 } 327 } 328 } 329 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop"); 330 return NULL; 331 } 332 333 void* message_thread(void *input) 334 { 335 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input); 336 unsigned char id; 337 int n; 338 339 fd_set readFds; 340 int res = 0; 341 struct timeval tv; 342 343 DEBUG_PRINT_HIGH("omx_vdec: message thread start"); 344 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); 345 while (!omx->message_thread_stop) { 346 347 tv.tv_sec = 2; 348 tv.tv_usec = 0; 349 350 FD_ZERO(&readFds); 351 FD_SET(omx->m_pipe_in, &readFds); 352 353 res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv); 354 if (res < 0) { 355 DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno)); 356 continue; 357 } else if (res == 0 /*timeout*/ || omx->message_thread_stop) { 358 continue; 359 } 360 361 n = read(omx->m_pipe_in, &id, 1); 362 363 if (0 == n) { 364 break; 365 } 366 367 if (1 == n) { 368 omx->process_event_cb(omx, id); 369 } 370 371 if ((n < 0) && (errno != EINTR)) { 372 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno); 373 break; 374 } 375 } 376 DEBUG_PRINT_HIGH("omx_vdec: message thread stop"); 377 return 0; 378 } 379 380 void post_message(omx_vdec *omx, unsigned char id) 381 { 382 int ret_value; 383 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out); 384 ret_value = write(omx->m_pipe_out, &id, 1); 385 if (ret_value <= 0) { 386 DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno)); 387 } else { 388 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value); 389 } 390 } 391 392 // omx_cmd_queue destructor 393 omx_vdec::omx_cmd_queue::~omx_cmd_queue() 394 { 395 // Nothing to do 396 } 397 398 // omx cmd queue constructor 399 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) 400 { 401 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); 402 } 403 404 // omx cmd queue insert 405 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id) 406 { 407 bool ret = true; 408 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) { 409 m_q[m_write].id = id; 410 m_q[m_write].param1 = p1; 411 m_q[m_write].param2 = p2; 412 m_write++; 413 m_size ++; 414 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) { 415 m_write = 0; 416 } 417 } else { 418 ret = false; 419 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__); 420 } 421 return ret; 422 } 423 424 // omx cmd queue pop 425 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id) 426 { 427 bool ret = true; 428 if (m_size > 0) { 429 *id = m_q[m_read].id; 430 *p1 = m_q[m_read].param1; 431 *p2 = m_q[m_read].param2; 432 // Move the read pointer ahead 433 ++m_read; 434 --m_size; 435 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) { 436 m_read = 0; 437 } 438 } else { 439 ret = false; 440 } 441 return ret; 442 } 443 444 // Retrieve the first mesg type in the queue 445 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() 446 { 447 return m_q[m_read].id; 448 } 449 450 #ifdef _ANDROID_ 451 omx_vdec::ts_arr_list::ts_arr_list() 452 { 453 //initialize timestamps array 454 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) ); 455 } 456 omx_vdec::ts_arr_list::~ts_arr_list() 457 { 458 //free m_ts_arr_list? 459 } 460 461 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) 462 { 463 bool ret = true; 464 bool duplicate_ts = false; 465 int idx = 0; 466 467 //insert at the first available empty location 468 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 469 if (!m_ts_arr_list[idx].valid) { 470 //found invalid or empty entry, save timestamp 471 m_ts_arr_list[idx].valid = true; 472 m_ts_arr_list[idx].timestamp = ts; 473 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", 474 ts, idx); 475 break; 476 } 477 } 478 479 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) { 480 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); 481 ret = false; 482 } 483 return ret; 484 } 485 486 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) 487 { 488 bool ret = true; 489 int min_idx = -1; 490 OMX_TICKS min_ts = 0; 491 int idx = 0; 492 493 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 494 495 if (m_ts_arr_list[idx].valid) { 496 //found valid entry, save index 497 if (min_idx < 0) { 498 //first valid entry 499 min_ts = m_ts_arr_list[idx].timestamp; 500 min_idx = idx; 501 } else if (m_ts_arr_list[idx].timestamp < min_ts) { 502 min_ts = m_ts_arr_list[idx].timestamp; 503 min_idx = idx; 504 } 505 } 506 507 } 508 509 if (min_idx < 0) { 510 //no valid entries found 511 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); 512 ts = 0; 513 ret = false; 514 } else { 515 ts = m_ts_arr_list[min_idx].timestamp; 516 m_ts_arr_list[min_idx].valid = false; 517 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", 518 ts, min_idx); 519 } 520 521 return ret; 522 523 } 524 525 526 bool omx_vdec::ts_arr_list::reset_ts_list() 527 { 528 bool ret = true; 529 int idx = 0; 530 531 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); 532 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) { 533 m_ts_arr_list[idx].valid = false; 534 } 535 return ret; 536 } 537 #endif 538 539 // factory function executed by the core to create instances 540 void *get_omx_component_factory_fn(void) 541 { 542 return (new omx_vdec); 543 } 544 545 #ifdef _ANDROID_ 546 #ifdef USE_ION 547 VideoHeap::VideoHeap(int devicefd, size_t size, void* base, 548 ion_user_handle_t handle, int ionMapfd) 549 { 550 (void) devicefd; 551 (void) size; 552 (void) base; 553 (void) handle; 554 (void) ionMapfd; 555 // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); 556 } 557 #else 558 VideoHeap::VideoHeap(int fd, size_t size, void* base) 559 { 560 // dup file descriptor, map once, use pmem 561 init(dup(fd), base, size, 0 , MEM_DEVICE); 562 } 563 #endif 564 #endif // _ANDROID_ 565 /* ====================================================================== 566 FUNCTION 567 omx_vdec::omx_vdec 568 569 DESCRIPTION 570 Constructor 571 572 PARAMETERS 573 None 574 575 RETURN VALUE 576 None. 577 ========================================================================== */ 578 omx_vdec::omx_vdec(): m_error_propogated(false), 579 m_state(OMX_StateInvalid), 580 m_app_data(NULL), 581 m_inp_mem_ptr(NULL), 582 m_out_mem_ptr(NULL), 583 input_flush_progress (false), 584 output_flush_progress (false), 585 input_use_buffer (false), 586 output_use_buffer (false), 587 ouput_egl_buffers(false), 588 m_use_output_pmem(OMX_FALSE), 589 m_out_mem_region_smi(OMX_FALSE), 590 m_out_pvt_entry_pmem(OMX_FALSE), 591 pending_input_buffers(0), 592 pending_output_buffers(0), 593 m_out_bm_count(0), 594 m_inp_bm_count(0), 595 m_inp_bPopulated(OMX_FALSE), 596 m_out_bPopulated(OMX_FALSE), 597 m_flags(0), 598 #ifdef _ANDROID_ 599 m_heap_ptr(NULL), 600 #endif 601 m_inp_bEnabled(OMX_TRUE), 602 m_out_bEnabled(OMX_TRUE), 603 m_in_alloc_cnt(0), 604 m_platform_list(NULL), 605 m_platform_entry(NULL), 606 m_pmem_info(NULL), 607 h264_parser(NULL), 608 arbitrary_bytes (true), 609 psource_frame (NULL), 610 pdest_frame (NULL), 611 m_inp_heap_ptr (NULL), 612 m_phdr_pmem_ptr(NULL), 613 m_heap_inp_bm_count (0), 614 codec_type_parse ((codec_type)0), 615 first_frame_meta (true), 616 frame_count (0), 617 nal_count (0), 618 nal_length(0), 619 look_ahead_nal (false), 620 first_frame(0), 621 first_buffer(NULL), 622 first_frame_size (0), 623 m_device_file_ptr(NULL), 624 m_vc1_profile((vc1_profile_type)0), 625 h264_last_au_ts(LLONG_MAX), 626 h264_last_au_flags(0), 627 m_disp_hor_size(0), 628 m_disp_vert_size(0), 629 prev_ts(LLONG_MAX), 630 prev_ts_actual(LLONG_MAX), 631 rst_prev_ts(true), 632 frm_int(0), 633 in_reconfig(false), 634 m_display_id(NULL), 635 client_extradata(0), 636 m_reject_avc_1080p_mp (0), 637 #ifdef _ANDROID_ 638 m_enable_android_native_buffers(OMX_FALSE), 639 m_use_android_native_buffers(OMX_FALSE), 640 #endif 641 m_desc_buffer_ptr(NULL), 642 secure_mode(false), 643 allocate_native_handle(false), 644 m_other_extradata(NULL), 645 m_profile(0), 646 client_set_fps(false), 647 m_last_rendered_TS(-1), 648 m_queued_codec_config_count(0), 649 current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL), 650 secure_scaling_to_non_secure_opb(false), 651 m_force_compressed_for_dpb(false) 652 { 653 m_pipe_in = -1; 654 m_pipe_out = -1; 655 m_poll_efd = -1; 656 drv_ctx.video_driver_fd = -1; 657 drv_ctx.extradata_info.ion.fd_ion_data.fd = -1; 658 /* Assumption is that , to begin with , we have all the frames with decoder */ 659 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8); 660 memset(&m_debug,0,sizeof(m_debug)); 661 #ifdef _ANDROID_ 662 char property_value[PROPERTY_VALUE_MAX] = {0}; 663 property_get("vidc.debug.level", property_value, "1"); 664 debug_level = atoi(property_value); 665 property_value[0] = '\0'; 666 667 DEBUG_PRINT_HIGH("In OMX vdec Constructor"); 668 669 property_get("vidc.dec.debug.perf", property_value, "0"); 670 perf_flag = atoi(property_value); 671 if (perf_flag) { 672 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); 673 dec_time.start(); 674 proc_frms = latency = 0; 675 } 676 prev_n_filled_len = 0; 677 property_value[0] = '\0'; 678 property_get("vidc.dec.debug.ts", property_value, "0"); 679 m_debug_timestamp = atoi(property_value); 680 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); 681 if (m_debug_timestamp) { 682 time_stamp_dts.set_timestamp_reorder_mode(true); 683 time_stamp_dts.enable_debug_print(true); 684 } 685 686 property_value[0] = '\0'; 687 property_get("vidc.dec.debug.concealedmb", property_value, "0"); 688 m_debug_concealedmb = atoi(property_value); 689 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); 690 691 property_value[0] = '\0'; 692 property_get("vidc.dec.profile.check", property_value, "0"); 693 m_reject_avc_1080p_mp = atoi(property_value); 694 DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp); 695 696 property_value[0] = '\0'; 697 property_get("vidc.dec.log.in", property_value, "0"); 698 m_debug.in_buffer_log = atoi(property_value); 699 700 property_value[0] = '\0'; 701 property_get("vidc.dec.log.out", property_value, "0"); 702 m_debug.out_buffer_log = atoi(property_value); 703 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC); 704 705 property_value[0] = '\0'; 706 property_get("vidc.dec.meta.log.out", property_value, "0"); 707 m_debug.out_meta_buffer_log = atoi(property_value); 708 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC); 709 710 property_value[0] = '\0'; 711 property_get("vidc.log.loc", property_value, ""); 712 if (*property_value) 713 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX); 714 715 property_value[0] = '\0'; 716 property_get("vidc.dec.120fps.enabled", property_value, "0"); 717 718 //if this feature is not enabled then reset this value -ve 719 if(atoi(property_value)) { 720 DEBUG_PRINT_LOW("feature 120 FPS decode enabled"); 721 m_last_rendered_TS = 0; 722 } 723 724 property_value[0] = '\0'; 725 property_get("vidc.dec.debug.dyn.disabled", property_value, "0"); 726 m_disable_dynamic_buf_mode = atoi(property_value); 727 DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode); 728 729 #ifdef _UBWC_ 730 property_value[0] = '\0'; 731 property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0"); 732 m_disable_ubwc_mode = atoi(property_value); 733 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled"); 734 #else 735 m_disable_ubwc_mode = true; 736 #endif 737 #endif 738 memset(&m_cmp,0,sizeof(m_cmp)); 739 memset(&m_cb,0,sizeof(m_cb)); 740 memset (&drv_ctx,0,sizeof(drv_ctx)); 741 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); 742 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); 743 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 744 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize)); 745 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams)); 746 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams)); 747 m_demux_entries = 0; 748 msg_thread_id = 0; 749 async_thread_id = 0; 750 msg_thread_created = false; 751 async_thread_created = false; 752 async_thread_force_stop = false; 753 message_thread_stop = false; 754 #ifdef _ANDROID_ICS_ 755 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 756 #endif 757 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 758 759 /* invalidate m_frame_pack_arrangement */ 760 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 761 m_frame_pack_arrangement.cancel_flag = 1; 762 763 drv_ctx.timestamp_adjust = false; 764 m_vendor_config.pData = NULL; 765 pthread_mutex_init(&m_lock, NULL); 766 pthread_mutex_init(&c_lock, NULL); 767 pthread_mutex_init(&buf_lock, NULL); 768 sem_init(&m_cmd_lock,0,0); 769 sem_init(&m_safe_flush, 0, 0); 770 streaming[CAPTURE_PORT] = 771 streaming[OUTPUT_PORT] = false; 772 #ifdef _ANDROID_ 773 char extradata_value[PROPERTY_VALUE_MAX] = {0}; 774 property_get("vidc.dec.debug.extradata", extradata_value, "0"); 775 m_debug_extradata = atoi(extradata_value); 776 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata); 777 #endif 778 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB; 779 client_buffers.set_vdec_client(this); 780 dynamic_buf_mode = false; 781 out_dynamic_list = NULL; 782 is_down_scalar_enabled = false; 783 m_downscalar_width = 0; 784 m_downscalar_height = 0; 785 m_force_down_scalar = 0; 786 m_reconfig_height = 0; 787 m_reconfig_width = 0; 788 m_smoothstreaming_mode = false; 789 m_smoothstreaming_width = 0; 790 m_smoothstreaming_height = 0; 791 m_decode_order_mode = false; 792 is_q6_platform = false; 793 m_perf_control.send_hint_to_mpctl(true); 794 m_input_pass_buffer_fd = false; 795 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; 796 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; 797 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; 798 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; 799 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; 800 801 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; 802 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; 803 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; 804 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; 805 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; 806 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams); 807 } 808 809 static const int event_type[] = { 810 V4L2_EVENT_MSM_VIDC_FLUSH_DONE, 811 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT, 812 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT, 813 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT, 814 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE, 815 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER, 816 V4L2_EVENT_MSM_VIDC_SYS_ERROR, 817 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD, 818 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED 819 }; 820 821 static OMX_ERRORTYPE subscribe_to_events(int fd) 822 { 823 OMX_ERRORTYPE eRet = OMX_ErrorNone; 824 struct v4l2_event_subscription sub; 825 int array_sz = sizeof(event_type)/sizeof(int); 826 int i,rc; 827 if (fd < 0) { 828 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 829 return OMX_ErrorBadParameter; 830 } 831 832 for (i = 0; i < array_sz; ++i) { 833 memset(&sub, 0, sizeof(sub)); 834 sub.type = event_type[i]; 835 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); 836 if (rc) { 837 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type); 838 break; 839 } 840 } 841 if (i < array_sz) { 842 for (--i; i >=0 ; i--) { 843 memset(&sub, 0, sizeof(sub)); 844 sub.type = event_type[i]; 845 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 846 if (rc) 847 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 848 } 849 eRet = OMX_ErrorNotImplemented; 850 } 851 return eRet; 852 } 853 854 855 static OMX_ERRORTYPE unsubscribe_to_events(int fd) 856 { 857 OMX_ERRORTYPE eRet = OMX_ErrorNone; 858 struct v4l2_event_subscription sub; 859 int array_sz = sizeof(event_type)/sizeof(int); 860 int i,rc; 861 if (fd < 0) { 862 DEBUG_PRINT_ERROR("Invalid input: %d", fd); 863 return OMX_ErrorBadParameter; 864 } 865 866 for (i = 0; i < array_sz; ++i) { 867 memset(&sub, 0, sizeof(sub)); 868 sub.type = event_type[i]; 869 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); 870 if (rc) { 871 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type); 872 break; 873 } 874 } 875 return eRet; 876 } 877 878 /* ====================================================================== 879 FUNCTION 880 omx_vdec::~omx_vdec 881 882 DESCRIPTION 883 Destructor 884 885 PARAMETERS 886 None 887 888 RETURN VALUE 889 None. 890 ========================================================================== */ 891 omx_vdec::~omx_vdec() 892 { 893 m_pmem_info = NULL; 894 DEBUG_PRINT_HIGH("In OMX vdec Destructor"); 895 if (msg_thread_created) { 896 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread"); 897 message_thread_stop = true; 898 post_message(this, OMX_COMPONENT_CLOSE_MSG); 899 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); 900 pthread_join(msg_thread_id,NULL); 901 } 902 close(m_pipe_in); 903 close(m_pipe_out); 904 m_pipe_in = -1; 905 m_pipe_out = -1; 906 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); 907 if(eventfd_write(m_poll_efd, 1)) { 908 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno); 909 async_thread_force_stop = true; 910 } 911 912 if (async_thread_created) 913 pthread_join(async_thread_id,NULL); 914 unsubscribe_to_events(drv_ctx.video_driver_fd); 915 close(m_poll_efd); 916 close(drv_ctx.video_driver_fd); 917 pthread_mutex_destroy(&m_lock); 918 pthread_mutex_destroy(&c_lock); 919 pthread_mutex_destroy(&buf_lock); 920 sem_destroy(&m_cmd_lock); 921 if (perf_flag) { 922 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); 923 dec_time.end(); 924 } 925 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd); 926 m_perf_control.send_hint_to_mpctl(false); 927 } 928 929 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type) 930 { 931 struct v4l2_requestbuffers bufreq; 932 int rc = 0; 933 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 934 bufreq.memory = V4L2_MEMORY_USERPTR; 935 bufreq.count = 0; 936 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 937 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 938 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) { 939 bufreq.memory = V4L2_MEMORY_USERPTR; 940 bufreq.count = 0; 941 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 942 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 943 } 944 return rc; 945 } 946 947 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format) 948 { 949 int rc = 0; 950 struct v4l2_ext_control ctrl[2]; 951 struct v4l2_ext_controls controls; 952 953 DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s", 954 is_split_mode ? "split" : "combined", 955 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc": 956 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc": 957 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb": 958 "unknown", 959 capture_capability == V4L2_PIX_FMT_NV12 ? "nv12": 960 capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc": 961 "unknown"); 962 963 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE; 964 if (is_split_mode) { 965 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY; 966 } else { 967 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY; 968 } 969 970 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT; 971 ctrl[1].value = dpb_color_format; 972 973 controls.count = 2; 974 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 975 controls.controls = ctrl; 976 977 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls); 978 if (rc) { 979 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc); 980 return OMX_ErrorUnsupportedSetting; 981 } 982 return OMX_ErrorNone; 983 } 984 985 986 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode) 987 { 988 OMX_ERRORTYPE eRet = OMX_ErrorNone; 989 990 bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC; 991 992 bool is_res_above_1080p = (drv_ctx.video_resolution.frame_width > 1920 && 993 drv_ctx.video_resolution.frame_height > 1088) || 994 (drv_ctx.video_resolution.frame_height > 1088 && 995 drv_ctx.video_resolution.frame_width > 1920); 996 997 if (cpu_access) { 998 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) { 999 if ((m_force_compressed_for_dpb || is_res_above_1080p) && 1000 !force_split_mode) { 1001 //split DPB-OPB 1002 //DPB -> UBWC , OPB -> Linear 1003 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC); 1004 } else if (force_split_mode) { 1005 //DPB -> Linear, OPB -> Linear 1006 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1007 } else { 1008 //DPB-OPB combined linear 1009 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1010 } 1011 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) { 1012 //split DPB-OPB 1013 //DPB -> UBWC, OPB -> Linear 1014 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC); 1015 } 1016 } else { //no cpu access 1017 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) { 1018 if (force_split_mode) { 1019 //split DPB-OPB 1020 //DPB -> UBWC, OPB -> UBWC 1021 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC); 1022 } else { 1023 //DPB-OPB combined UBWC 1024 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE); 1025 } 1026 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) { 1027 //split DPB-OPB 1028 //DPB -> UBWC, OPB -> UBWC 1029 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC); 1030 } 1031 } 1032 if (eRet) { 1033 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet); 1034 } 1035 return eRet; 1036 } 1037 1038 int omx_vdec::enable_downscalar() 1039 { 1040 int rc = 0; 1041 struct v4l2_control control; 1042 struct v4l2_format fmt; 1043 1044 if (is_down_scalar_enabled) { 1045 DEBUG_PRINT_LOW("%s: already enabled", __func__); 1046 return 0; 1047 } 1048 1049 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar"); 1050 rc = decide_dpb_buffer_mode(true); 1051 if (rc) { 1052 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__); 1053 return rc; 1054 } 1055 is_down_scalar_enabled = true; 1056 1057 memset(&control, 0x0, sizeof(struct v4l2_control)); 1058 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO; 1059 control.value = 1; 1060 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 1061 if (rc) { 1062 DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__); 1063 return rc; 1064 } 1065 1066 return 0; 1067 } 1068 1069 int omx_vdec::disable_downscalar() 1070 { 1071 int rc = 0; 1072 struct v4l2_control control; 1073 1074 if (!is_down_scalar_enabled) { 1075 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled"); 1076 return 0; 1077 } 1078 1079 rc = decide_dpb_buffer_mode(false); 1080 if (rc < 0) { 1081 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__); 1082 return rc; 1083 } 1084 is_down_scalar_enabled = false; 1085 1086 return rc; 1087 } 1088 1089 int omx_vdec::decide_downscalar() 1090 { 1091 int rc = 0; 1092 struct v4l2_format fmt; 1093 enum color_fmts color_format; 1094 1095 if (!m_downscalar_width || !m_downscalar_height) { 1096 DEBUG_PRINT_LOW("%s: downscalar not supported", __func__); 1097 return 0; 1098 } 1099 1100 if (m_force_down_scalar) { 1101 DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar); 1102 return 0; 1103 } 1104 1105 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1106 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1107 fmt.fmt.pix_mp.pixelformat = capture_capability; 1108 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 1109 if (rc < 0) { 1110 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__); 1111 return rc; 1112 } 1113 1114 DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__, 1115 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height); 1116 1117 if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) { 1118 rc = enable_downscalar(); 1119 if (rc < 0) { 1120 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__); 1121 return rc; 1122 } 1123 1124 OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ? 1125 fmt.fmt.pix_mp.width : m_downscalar_width; 1126 OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ? 1127 fmt.fmt.pix_mp.height : m_downscalar_height; 1128 switch (capture_capability) { 1129 case V4L2_PIX_FMT_NV12: 1130 color_format = COLOR_FMT_NV12; 1131 break; 1132 case V4L2_PIX_FMT_NV12_UBWC: 1133 color_format = COLOR_FMT_NV12_UBWC; 1134 break; 1135 case V4L2_PIX_FMT_NV12_TP10_UBWC: 1136 color_format = COLOR_FMT_NV12_BPP10_UBWC; 1137 break; 1138 default: 1139 DEBUG_PRINT_ERROR("Color format not recognized\n"); 1140 rc = OMX_ErrorUndefined; 1141 return rc; 1142 } 1143 1144 rc = update_resolution(width, height, 1145 VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height)); 1146 if (rc < 0) { 1147 DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height); 1148 return rc; 1149 } 1150 } else { 1151 1152 rc = disable_downscalar(); 1153 if (rc < 0) { 1154 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__); 1155 return rc; 1156 } 1157 1158 rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, 1159 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]); 1160 if (rc < 0) { 1161 DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width, 1162 fmt.fmt.pix_mp.height); 1163 return rc; 1164 } 1165 } 1166 1167 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 1168 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1169 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 1170 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 1171 fmt.fmt.pix_mp.pixelformat = capture_capability; 1172 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 1173 if (rc) { 1174 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__); 1175 return rc; 1176 } 1177 1178 rc = get_buffer_req(&drv_ctx.op_buf); 1179 if (rc) { 1180 DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__); 1181 return rc; 1182 } 1183 1184 return rc; 1185 } 1186 1187 /* ====================================================================== 1188 FUNCTION 1189 omx_vdec::OMXCntrlProcessMsgCb 1190 1191 DESCRIPTION 1192 IL Client callbacks are generated through this routine. The decoder 1193 provides the thread context for this routine. 1194 1195 PARAMETERS 1196 ctxt -- Context information related to the self. 1197 id -- Event identifier. This could be any of the following: 1198 1. Command completion event 1199 2. Buffer done callback event 1200 3. Frame done callback event 1201 1202 RETURN VALUE 1203 None. 1204 1205 ========================================================================== */ 1206 void omx_vdec::process_event_cb(void *ctxt, unsigned char id) 1207 { 1208 unsigned long p1; // Parameter - 1 1209 unsigned long p2; // Parameter - 2 1210 unsigned long ident; 1211 unsigned qsize=0; // qsize 1212 omx_vdec *pThis = (omx_vdec *) ctxt; 1213 1214 if (!pThis) { 1215 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out", 1216 __func__); 1217 return; 1218 } 1219 1220 // Protect the shared queue data structure 1221 do { 1222 /*Read the message id's from the queue*/ 1223 pthread_mutex_lock(&pThis->m_lock); 1224 qsize = pThis->m_cmd_q.m_size; 1225 if (qsize) { 1226 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident); 1227 } 1228 1229 if (qsize == 0 && pThis->m_state != OMX_StatePause) { 1230 qsize = pThis->m_ftb_q.m_size; 1231 if (qsize) { 1232 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident); 1233 } 1234 } 1235 1236 if (qsize == 0 && pThis->m_state != OMX_StatePause) { 1237 qsize = pThis->m_etb_q.m_size; 1238 if (qsize) { 1239 pThis->m_etb_q.pop_entry(&p1, &p2, &ident); 1240 } 1241 } 1242 pthread_mutex_unlock(&pThis->m_lock); 1243 1244 /*process message if we have one*/ 1245 if (qsize > 0) { 1246 id = ident; 1247 switch (id) { 1248 case OMX_COMPONENT_GENERATE_EVENT: 1249 if (pThis->m_cb.EventHandler) { 1250 switch (p1) { 1251 case OMX_CommandStateSet: 1252 pThis->m_state = (OMX_STATETYPE) p2; 1253 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d", 1254 pThis->m_state); 1255 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1256 OMX_EventCmdComplete, p1, p2, NULL); 1257 break; 1258 1259 case OMX_EventError: 1260 if (p2 == OMX_StateInvalid) { 1261 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid"); 1262 pThis->m_state = (OMX_STATETYPE) p2; 1263 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1264 OMX_EventError, OMX_ErrorInvalidState, p2, NULL); 1265 } else if (p2 == (unsigned long)OMX_ErrorHardware) { 1266 pThis->omx_report_error(); 1267 } else { 1268 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1269 OMX_EventError, p2, (OMX_U32)NULL, NULL ); 1270 } 1271 break; 1272 1273 case OMX_CommandPortDisable: 1274 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2); 1275 if (BITMASK_PRESENT(&pThis->m_flags, 1276 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) { 1277 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 1278 break; 1279 } 1280 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) { 1281 OMX_ERRORTYPE eRet = OMX_ErrorNone; 1282 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 1283 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT)) 1284 DEBUG_PRINT_HIGH("Failed to release output buffers"); 1285 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf); 1286 pThis->in_reconfig = false; 1287 if (eRet != OMX_ErrorNone) { 1288 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet); 1289 pThis->omx_report_error(); 1290 break; 1291 } 1292 } 1293 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1294 OMX_EventCmdComplete, p1, p2, NULL ); 1295 break; 1296 case OMX_CommandPortEnable: 1297 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2); 1298 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ 1299 OMX_EventCmdComplete, p1, p2, NULL ); 1300 break; 1301 1302 default: 1303 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1304 OMX_EventCmdComplete, p1, p2, NULL ); 1305 break; 1306 1307 } 1308 } else { 1309 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1310 } 1311 break; 1312 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: 1313 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 1314 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) { 1315 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure"); 1316 pThis->omx_report_error (); 1317 } 1318 break; 1319 case OMX_COMPONENT_GENERATE_ETB: { 1320 OMX_ERRORTYPE iret; 1321 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2); 1322 if (iret == OMX_ErrorInsufficientResources) { 1323 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload"); 1324 pThis->omx_report_hw_overload (); 1325 } else if (iret != OMX_ErrorNone) { 1326 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); 1327 pThis->omx_report_error (); 1328 } 1329 } 1330 break; 1331 1332 case OMX_COMPONENT_GENERATE_FTB: 1333 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\ 1334 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) { 1335 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure"); 1336 pThis->omx_report_error (); 1337 } 1338 break; 1339 1340 case OMX_COMPONENT_GENERATE_COMMAND: 1341 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ 1342 (OMX_U32)p2,(OMX_PTR)NULL); 1343 break; 1344 1345 case OMX_COMPONENT_GENERATE_EBD: 1346 1347 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) { 1348 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure"); 1349 pThis->omx_report_error (); 1350 } else { 1351 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) { 1352 pThis->time_stamp_dts.remove_time_stamp( 1353 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp, 1354 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1355 ?true:false); 1356 } 1357 1358 if ( pThis->empty_buffer_done(&pThis->m_cmp, 1359 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) { 1360 DEBUG_PRINT_ERROR("empty_buffer_done failure"); 1361 pThis->omx_report_error (); 1362 } 1363 } 1364 break; 1365 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: { 1366 int64_t *timestamp = (int64_t *)(intptr_t)p1; 1367 if (p1) { 1368 pThis->time_stamp_dts.remove_time_stamp(*timestamp, 1369 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 1370 ?true:false); 1371 free(timestamp); 1372 } 1373 } 1374 break; 1375 case OMX_COMPONENT_GENERATE_FBD: 1376 if (p2 != VDEC_S_SUCCESS) { 1377 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure"); 1378 pThis->omx_report_error (); 1379 } else if ( pThis->fill_buffer_done(&pThis->m_cmp, 1380 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) { 1381 DEBUG_PRINT_ERROR("fill_buffer_done failure"); 1382 pThis->omx_report_error (); 1383 } 1384 break; 1385 1386 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: 1387 DEBUG_PRINT_HIGH("Driver flush i/p Port complete"); 1388 if (!pThis->input_flush_progress) { 1389 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver"); 1390 } else { 1391 pThis->execute_input_flush(); 1392 if (pThis->m_cb.EventHandler) { 1393 if (p2 != VDEC_S_SUCCESS) { 1394 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); 1395 pThis->omx_report_error (); 1396 } else { 1397 /*Check if we need generate event for Flush done*/ 1398 pThis->notify_flush_done(ctxt); 1399 1400 if (BITMASK_PRESENT(&pThis->m_flags, 1401 OMX_COMPONENT_IDLE_PENDING)) { 1402 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) { 1403 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port"); 1404 pThis->omx_report_error (); 1405 } else { 1406 pThis->streaming[OUTPUT_PORT] = false; 1407 } 1408 if (!pThis->output_flush_progress) { 1409 DEBUG_PRINT_LOW("Input flush done hence issue stop"); 1410 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\ 1411 OMX_COMPONENT_GENERATE_STOP_DONE); 1412 } 1413 } 1414 } 1415 } else { 1416 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1417 } 1418 } 1419 break; 1420 1421 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: 1422 DEBUG_PRINT_HIGH("Driver flush o/p Port complete"); 1423 if (!pThis->output_flush_progress) { 1424 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver"); 1425 } else { 1426 pThis->execute_output_flush(); 1427 if (pThis->m_cb.EventHandler) { 1428 if (p2 != VDEC_S_SUCCESS) { 1429 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); 1430 pThis->omx_report_error (); 1431 } else { 1432 /*Check if we need generate event for Flush done*/ 1433 pThis->notify_flush_done(ctxt); 1434 1435 if (BITMASK_PRESENT(&pThis->m_flags, 1436 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) { 1437 DEBUG_PRINT_LOW("Internal flush complete"); 1438 BITMASK_CLEAR (&pThis->m_flags, 1439 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 1440 if (BITMASK_PRESENT(&pThis->m_flags, 1441 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) { 1442 pThis->post_event(OMX_CommandPortDisable, 1443 OMX_CORE_OUTPUT_PORT_INDEX, 1444 OMX_COMPONENT_GENERATE_EVENT); 1445 BITMASK_CLEAR (&pThis->m_flags, 1446 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); 1447 BITMASK_CLEAR (&pThis->m_flags, 1448 OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 1449 1450 } 1451 } 1452 1453 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) { 1454 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) { 1455 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port"); 1456 pThis->omx_report_error (); 1457 break; 1458 } 1459 pThis->streaming[CAPTURE_PORT] = false; 1460 if (!pThis->input_flush_progress) { 1461 DEBUG_PRINT_LOW("Output flush done hence issue stop"); 1462 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\ 1463 OMX_COMPONENT_GENERATE_STOP_DONE); 1464 } 1465 } 1466 } 1467 } else { 1468 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1469 } 1470 } 1471 break; 1472 1473 case OMX_COMPONENT_GENERATE_START_DONE: 1474 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE"); 1475 1476 if (pThis->m_cb.EventHandler) { 1477 if (p2 != VDEC_S_SUCCESS) { 1478 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure"); 1479 pThis->omx_report_error (); 1480 } else { 1481 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success"); 1482 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) { 1483 DEBUG_PRINT_LOW("Move to executing"); 1484 // Send the callback now 1485 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1486 pThis->m_state = OMX_StateExecuting; 1487 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1488 OMX_EventCmdComplete,OMX_CommandStateSet, 1489 OMX_StateExecuting, NULL); 1490 } else if (BITMASK_PRESENT(&pThis->m_flags, 1491 OMX_COMPONENT_PAUSE_PENDING)) { 1492 if (/*ioctl (pThis->drv_ctx.video_driver_fd, 1493 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) { 1494 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed"); 1495 pThis->omx_report_error (); 1496 } 1497 } 1498 } 1499 } else { 1500 DEBUG_PRINT_LOW("Event Handler callback is NULL"); 1501 } 1502 break; 1503 1504 case OMX_COMPONENT_GENERATE_PAUSE_DONE: 1505 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); 1506 if (pThis->m_cb.EventHandler) { 1507 if (p2 != VDEC_S_SUCCESS) { 1508 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); 1509 pThis->omx_report_error (); 1510 } else { 1511 pThis->complete_pending_buffer_done_cbs(); 1512 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) { 1513 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); 1514 //Send the callback now 1515 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); 1516 pThis->m_state = OMX_StatePause; 1517 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1518 OMX_EventCmdComplete,OMX_CommandStateSet, 1519 OMX_StatePause, NULL); 1520 } 1521 } 1522 } else { 1523 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1524 } 1525 1526 break; 1527 1528 case OMX_COMPONENT_GENERATE_RESUME_DONE: 1529 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); 1530 if (pThis->m_cb.EventHandler) { 1531 if (p2 != VDEC_S_SUCCESS) { 1532 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed"); 1533 pThis->omx_report_error (); 1534 } else { 1535 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) { 1536 DEBUG_PRINT_LOW("Moving the decoder to execute state"); 1537 // Send the callback now 1538 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); 1539 pThis->m_state = OMX_StateExecuting; 1540 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1541 OMX_EventCmdComplete,OMX_CommandStateSet, 1542 OMX_StateExecuting,NULL); 1543 } 1544 } 1545 } else { 1546 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1547 } 1548 1549 break; 1550 1551 case OMX_COMPONENT_GENERATE_STOP_DONE: 1552 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); 1553 if (pThis->m_cb.EventHandler) { 1554 if (p2 != VDEC_S_SUCCESS) { 1555 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); 1556 pThis->omx_report_error (); 1557 } else { 1558 pThis->complete_pending_buffer_done_cbs(); 1559 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) { 1560 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success"); 1561 // Send the callback now 1562 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); 1563 pThis->m_state = OMX_StateIdle; 1564 DEBUG_PRINT_LOW("Move to Idle State"); 1565 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, 1566 OMX_EventCmdComplete,OMX_CommandStateSet, 1567 OMX_StateIdle,NULL); 1568 } 1569 } 1570 } else { 1571 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1572 } 1573 1574 break; 1575 1576 case OMX_COMPONENT_GENERATE_PORT_RECONFIG: 1577 if (p2 == OMX_IndexParamPortDefinition) { 1578 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition"); 1579 pThis->in_reconfig = true; 1580 } else if (p2 == OMX_IndexConfigCommonOutputCrop) { 1581 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop"); 1582 1583 /* Check if resolution is changed in smooth streaming mode */ 1584 if (pThis->m_smoothstreaming_mode && 1585 (pThis->framesize.nWidth != 1586 pThis->drv_ctx.video_resolution.frame_width) || 1587 (pThis->framesize.nHeight != 1588 pThis->drv_ctx.video_resolution.frame_height)) { 1589 1590 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d", 1591 pThis->framesize.nWidth, 1592 pThis->framesize.nHeight, 1593 pThis->drv_ctx.video_resolution.frame_width, 1594 pThis->drv_ctx.video_resolution.frame_height); 1595 1596 /* Update new resolution */ 1597 pThis->framesize.nWidth = 1598 pThis->drv_ctx.video_resolution.frame_width; 1599 pThis->framesize.nHeight = 1600 pThis->drv_ctx.video_resolution.frame_height; 1601 1602 /* Update C2D with new resolution */ 1603 if (!pThis->client_buffers.update_buffer_req()) { 1604 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed"); 1605 } 1606 } 1607 1608 /* Update new crop information */ 1609 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left; 1610 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top; 1611 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right; 1612 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom; 1613 1614 /* Validate the new crop information */ 1615 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth > 1616 pThis->drv_ctx.video_resolution.frame_width) { 1617 1618 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]", 1619 pThis->rectangle.nLeft, pThis->rectangle.nWidth, 1620 pThis->drv_ctx.video_resolution.frame_width); 1621 pThis->rectangle.nLeft = 0; 1622 1623 if (pThis->rectangle.nWidth > 1624 pThis->drv_ctx.video_resolution.frame_width) { 1625 1626 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]", 1627 pThis->rectangle.nWidth, 1628 pThis->drv_ctx.video_resolution.frame_width); 1629 pThis->rectangle.nWidth = 1630 pThis->drv_ctx.video_resolution.frame_width; 1631 } 1632 } 1633 if (pThis->rectangle.nTop + pThis->rectangle.nHeight > 1634 pThis->drv_ctx.video_resolution.frame_height) { 1635 1636 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]", 1637 pThis->rectangle.nTop, pThis->rectangle.nHeight, 1638 pThis->drv_ctx.video_resolution.frame_height); 1639 pThis->rectangle.nTop = 0; 1640 1641 if (pThis->rectangle.nHeight > 1642 pThis->drv_ctx.video_resolution.frame_height) { 1643 1644 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]", 1645 pThis->rectangle.nHeight, 1646 pThis->drv_ctx.video_resolution.frame_height); 1647 pThis->rectangle.nHeight = 1648 pThis->drv_ctx.video_resolution.frame_height; 1649 } 1650 } 1651 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u", 1652 pThis->rectangle.nLeft, pThis->rectangle.nTop, 1653 pThis->rectangle.nWidth, pThis->rectangle.nHeight); 1654 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) { 1655 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects"); 1656 } else { 1657 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2); 1658 break; 1659 } 1660 if (pThis->m_debug.outfile) { 1661 fclose(pThis->m_debug.outfile); 1662 pThis->m_debug.outfile = NULL; 1663 } 1664 if (pThis->m_debug.out_ymeta_file) { 1665 fclose(pThis->m_debug.out_ymeta_file); 1666 pThis->m_debug.out_ymeta_file = NULL; 1667 } 1668 if (pThis->m_debug.out_uvmeta_file) { 1669 fclose(pThis->m_debug.out_uvmeta_file); 1670 pThis->m_debug.out_uvmeta_file = NULL; 1671 } 1672 1673 if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) { 1674 pThis->prefetchNewBuffers(); 1675 } 1676 1677 if (pThis->m_cb.EventHandler) { 1678 uint32_t frame_data[2]; 1679 frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ? 1680 pThis->m_reconfig_height : pThis->rectangle.nHeight; 1681 frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ? 1682 pThis->m_reconfig_width : pThis->rectangle.nWidth; 1683 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 1684 OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data ); 1685 } else { 1686 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1687 } 1688 break; 1689 1690 case OMX_COMPONENT_GENERATE_EOS_DONE: 1691 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); 1692 if (pThis->m_cb.EventHandler) { 1693 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, 1694 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); 1695 } else { 1696 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); 1697 } 1698 pThis->prev_ts = LLONG_MAX; 1699 pThis->rst_prev_ts = true; 1700 break; 1701 1702 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: 1703 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); 1704 pThis->omx_report_error(); 1705 break; 1706 1707 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING: 1708 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING"); 1709 pThis->omx_report_unsupported_setting(); 1710 break; 1711 1712 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD: 1713 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD"); 1714 pThis->omx_report_hw_overload(); 1715 break; 1716 1717 default: 1718 break; 1719 } 1720 } 1721 pthread_mutex_lock(&pThis->m_lock); 1722 qsize = pThis->m_cmd_q.m_size; 1723 if (pThis->m_state != OMX_StatePause) 1724 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size); 1725 pthread_mutex_unlock(&pThis->m_lock); 1726 } while (qsize>0); 1727 1728 } 1729 1730 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines) 1731 { 1732 int format_changed = 0; 1733 if ((height != (int)drv_ctx.video_resolution.frame_height) || 1734 (width != (int)drv_ctx.video_resolution.frame_width)) { 1735 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)", 1736 width, drv_ctx.video_resolution.frame_width, 1737 height,drv_ctx.video_resolution.frame_height); 1738 format_changed = 1; 1739 } 1740 drv_ctx.video_resolution.frame_height = height; 1741 drv_ctx.video_resolution.frame_width = width; 1742 drv_ctx.video_resolution.scan_lines = scan_lines; 1743 drv_ctx.video_resolution.stride = stride; 1744 if(!is_down_scalar_enabled) { 1745 rectangle.nLeft = 0; 1746 rectangle.nTop = 0; 1747 rectangle.nWidth = drv_ctx.video_resolution.frame_width; 1748 rectangle.nHeight = drv_ctx.video_resolution.frame_height; 1749 } 1750 return format_changed; 1751 } 1752 1753 OMX_ERRORTYPE omx_vdec::is_video_session_supported() 1754 { 1755 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", 1756 OMX_MAX_STRINGNAME_SIZE) && 1757 (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) { 1758 m_decoder_capability.max_width = 1280; 1759 m_decoder_capability.max_height = 720; 1760 DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP"); 1761 } 1762 1763 if ((drv_ctx.video_resolution.frame_width * 1764 drv_ctx.video_resolution.frame_height > 1765 m_decoder_capability.max_width * 1766 m_decoder_capability.max_height) || 1767 (drv_ctx.video_resolution.frame_width* 1768 drv_ctx.video_resolution.frame_height < 1769 m_decoder_capability.min_width * 1770 m_decoder_capability.min_height)) { 1771 DEBUG_PRINT_ERROR( 1772 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)", 1773 drv_ctx.video_resolution.frame_width, 1774 drv_ctx.video_resolution.frame_height, 1775 m_decoder_capability.min_width, 1776 m_decoder_capability.min_height, 1777 m_decoder_capability.max_width, 1778 m_decoder_capability.max_height); 1779 return OMX_ErrorUnsupportedSetting; 1780 } 1781 DEBUG_PRINT_HIGH("video session supported"); 1782 return OMX_ErrorNone; 1783 } 1784 1785 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) 1786 { 1787 if (m_debug.in_buffer_log && !m_debug.infile) { 1788 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 1789 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v", 1790 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1791 } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 1792 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc, 1793 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1794 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 1795 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263", 1796 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1797 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) || 1798 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 1799 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264", 1800 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1801 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 1802 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265", 1803 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1804 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) { 1805 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1", 1806 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1807 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) { 1808 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1", 1809 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1810 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) { 1811 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf", 1812 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1813 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 1814 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf", 1815 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1816 } else { 1817 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx", 1818 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1819 } 1820 m_debug.infile = fopen (m_debug.infile_name, "ab"); 1821 if (!m_debug.infile) { 1822 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name); 1823 m_debug.infile_name[0] = '\0'; 1824 return -1; 1825 } 1826 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 1827 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 1828 struct ivf_file_header { 1829 OMX_U8 signature[4]; //='DKIF'; 1830 OMX_U8 version ; //= 0; 1831 OMX_U8 headersize ; //= 32; 1832 OMX_U32 FourCC; 1833 OMX_U8 width; 1834 OMX_U8 height; 1835 OMX_U32 rate; 1836 OMX_U32 scale; 1837 OMX_U32 length; 1838 OMX_U8 unused[4]; 1839 } file_header; 1840 1841 memset((void *)&file_header,0,sizeof(file_header)); 1842 file_header.signature[0] = 'D'; 1843 file_header.signature[1] = 'K'; 1844 file_header.signature[2] = 'I'; 1845 file_header.signature[3] = 'F'; 1846 file_header.version = 0; 1847 file_header.headersize = 32; 1848 switch (drv_ctx.decoder_format) { 1849 case VDEC_CODECTYPE_VP8: 1850 file_header.FourCC = 0x30385056; 1851 break; 1852 case VDEC_CODECTYPE_VP9: 1853 file_header.FourCC = 0x30395056; 1854 break; 1855 default: 1856 DEBUG_PRINT_ERROR("unsupported format for VP8/VP9"); 1857 break; 1858 } 1859 fwrite((const char *)&file_header, 1860 sizeof(file_header),1,m_debug.infile); 1861 } 1862 } 1863 if (m_debug.infile && buffer_addr && buffer_len) { 1864 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 1865 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 1866 struct vpx_ivf_frame_header { 1867 OMX_U32 framesize; 1868 OMX_U32 timestamp_lo; 1869 OMX_U32 timestamp_hi; 1870 } vpx_frame_header; 1871 vpx_frame_header.framesize = buffer_len; 1872 /* Currently FW doesn't use timestamp values */ 1873 vpx_frame_header.timestamp_lo = 0; 1874 vpx_frame_header.timestamp_hi = 0; 1875 fwrite((const char *)&vpx_frame_header, 1876 sizeof(vpx_frame_header),1,m_debug.infile); 1877 } 1878 fwrite(buffer_addr, buffer_len, 1, m_debug.infile); 1879 } 1880 return 0; 1881 } 1882 1883 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) { 1884 int buf_index = 0; 1885 char *temp = NULL; 1886 1887 if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) { 1888 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv", 1889 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1890 m_debug.outfile = fopen (m_debug.outfile_name, "ab"); 1891 if (!m_debug.outfile) { 1892 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc); 1893 m_debug.outfile_name[0] = '\0'; 1894 return -1; 1895 } 1896 } 1897 1898 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file 1899 && buffer->nFilledLen) { 1900 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta", 1901 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1902 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta", 1903 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); 1904 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab"); 1905 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab"); 1906 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) { 1907 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc); 1908 m_debug.out_ymetafile_name[0] = '\0'; 1909 m_debug.out_uvmetafile_name[0] = '\0'; 1910 return -1; 1911 } 1912 } 1913 1914 if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen) 1915 return 0; 1916 1917 buf_index = buffer - m_out_mem_ptr; 1918 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; 1919 1920 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 1921 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)", 1922 drv_ctx.video_resolution.frame_width, 1923 drv_ctx.video_resolution.frame_height); 1924 1925 if (m_debug.outfile) 1926 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile); 1927 1928 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) { 1929 unsigned int width = 0, height = 0; 1930 unsigned int y_plane, y_meta_plane; 1931 int y_stride = 0, y_sclines = 0; 1932 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0; 1933 int color_fmt = COLOR_FMT_NV12_UBWC; 1934 int i; 1935 int bytes_written = 0; 1936 1937 width = drv_ctx.video_resolution.frame_width; 1938 height = drv_ctx.video_resolution.frame_height; 1939 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width); 1940 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height); 1941 y_stride = VENUS_Y_STRIDE(color_fmt, width); 1942 y_sclines = VENUS_Y_SCANLINES(color_fmt, height); 1943 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width); 1944 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height); 1945 1946 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096); 1947 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096); 1948 1949 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; 1950 for (i = 0; i < y_meta_scanlines; i++) { 1951 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file); 1952 temp += y_meta_stride; 1953 } 1954 1955 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane; 1956 for(i = 0; i < uv_meta_scanlines; i++) { 1957 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file); 1958 temp += uv_meta_stride; 1959 } 1960 } 1961 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) { 1962 int stride = drv_ctx.video_resolution.stride; 1963 int scanlines = drv_ctx.video_resolution.scan_lines; 1964 if (m_smoothstreaming_mode) { 1965 stride = drv_ctx.video_resolution.frame_width; 1966 scanlines = drv_ctx.video_resolution.frame_height; 1967 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1)); 1968 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1)); 1969 } 1970 unsigned i; 1971 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)", 1972 drv_ctx.video_resolution.frame_width, 1973 drv_ctx.video_resolution.frame_height, stride, scanlines); 1974 int bytes_written = 0; 1975 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) { 1976 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 1977 temp += stride; 1978 } 1979 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines; 1980 int stride_c = stride; 1981 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) { 1982 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile); 1983 temp += stride_c; 1984 } 1985 } 1986 return 0; 1987 } 1988 1989 /* ====================================================================== 1990 FUNCTION 1991 omx_vdec::ComponentInit 1992 1993 DESCRIPTION 1994 Initialize the component. 1995 1996 PARAMETERS 1997 ctxt -- Context information related to the self. 1998 id -- Event identifier. This could be any of the following: 1999 1. Command completion event 2000 2. Buffer done callback event 2001 3. Frame done callback event 2002 2003 RETURN VALUE 2004 None. 2005 2006 ========================================================================== */ 2007 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) 2008 { 2009 2010 OMX_ERRORTYPE eRet = OMX_ErrorNone; 2011 struct v4l2_fmtdesc fdesc; 2012 struct v4l2_format fmt; 2013 struct v4l2_requestbuffers bufreq; 2014 struct v4l2_control control; 2015 struct v4l2_frmsizeenum frmsize; 2016 unsigned int alignment = 0,buffer_size = 0; 2017 int fds[2]; 2018 int r,ret=0; 2019 bool codec_ambiguous = false; 2020 OMX_STRING device_name = (OMX_STRING)"/dev/video32"; 2021 char property_value[PROPERTY_VALUE_MAX] = {0}; 2022 FILE *soc_file = NULL; 2023 char buffer[10]; 2024 2025 #ifdef _ANDROID_ 2026 char platform_name[PROPERTY_VALUE_MAX]; 2027 property_get("ro.board.platform", platform_name, "0"); 2028 if (!strncmp(platform_name, "msm8610", 7)) { 2029 device_name = (OMX_STRING)"/dev/video/q6_dec"; 2030 is_q6_platform = true; 2031 maxSmoothStreamingWidth = 1280; 2032 maxSmoothStreamingHeight = 720; 2033 } 2034 #endif 2035 2036 is_thulium_v1 = false; 2037 soc_file = fopen("/sys/devices/soc0/soc_id", "r"); 2038 if (soc_file) { 2039 fread(buffer, 1, 4, soc_file); 2040 fclose(soc_file); 2041 if (atoi(buffer) == 246) { 2042 soc_file = fopen("/sys/devices/soc0/revision", "r"); 2043 if (soc_file) { 2044 fread(buffer, 1, 4, soc_file); 2045 fclose(soc_file); 2046 if (atoi(buffer) == 1) { 2047 is_thulium_v1 = true; 2048 DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE"); 2049 } 2050 } 2051 } 2052 } 2053 2054 #ifdef _ANDROID_ 2055 /* 2056 * turn off frame parsing for Android by default. 2057 * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode 2058 */ 2059 arbitrary_bytes = false; 2060 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); 2061 if (atoi(property_value)) { 2062 DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command"); 2063 arbitrary_bytes = true; 2064 } 2065 #endif 2066 2067 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure", 2068 OMX_MAX_STRINGNAME_SIZE)) { 2069 secure_mode = true; 2070 arbitrary_bytes = false; 2071 role = (OMX_STRING)"OMX.qcom.video.decoder.avc"; 2072 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure", 2073 OMX_MAX_STRINGNAME_SIZE)) { 2074 secure_mode = true; 2075 arbitrary_bytes = false; 2076 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2"; 2077 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure", 2078 OMX_MAX_STRINGNAME_SIZE)) { 2079 secure_mode = true; 2080 arbitrary_bytes = false; 2081 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc"; 2082 } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure", 2083 OMX_MAX_STRINGNAME_SIZE)) { 2084 secure_mode = true; 2085 arbitrary_bytes = false; 2086 role = (OMX_STRING)"OMX.qcom.video.decoder.vc1"; 2087 } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure", 2088 OMX_MAX_STRINGNAME_SIZE)) { 2089 secure_mode = true; 2090 arbitrary_bytes = false; 2091 role = (OMX_STRING)"OMX.qcom.video.decoder.wmv"; 2092 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure", 2093 OMX_MAX_STRINGNAME_SIZE)) { 2094 secure_mode = true; 2095 arbitrary_bytes = false; 2096 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4"; 2097 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure", 2098 OMX_MAX_STRINGNAME_SIZE)) { 2099 secure_mode = true; 2100 arbitrary_bytes = false; 2101 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9"; 2102 } 2103 2104 drv_ctx.video_driver_fd = open(device_name, O_RDWR); 2105 2106 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd); 2107 2108 if (drv_ctx.video_driver_fd < 0) { 2109 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno); 2110 return OMX_ErrorInsufficientResources; 2111 } 2112 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; 2113 drv_ctx.frame_rate.fps_denominator = 1; 2114 m_poll_efd = eventfd(0, 0); 2115 if (m_poll_efd < 0) { 2116 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno)); 2117 return OMX_ErrorInsufficientResources; 2118 } 2119 ret = subscribe_to_events(drv_ctx.video_driver_fd); 2120 if (!ret) { 2121 async_thread_created = true; 2122 ret = pthread_create(&async_thread_id,0,async_message_thread,this); 2123 } 2124 if (ret) { 2125 DEBUG_PRINT_ERROR("Failed to create async_message_thread"); 2126 async_thread_created = false; 2127 return OMX_ErrorInsufficientResources; 2128 } 2129 2130 #ifdef OUTPUT_EXTRADATA_LOG 2131 outputExtradataFile = fopen (output_extradata_filename, "ab"); 2132 #endif 2133 2134 // Copy the role information which provides the decoder kind 2135 strlcpy(drv_ctx.kind,role,128); 2136 2137 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\ 2138 OMX_MAX_STRINGNAME_SIZE)) { 2139 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\ 2140 OMX_MAX_STRINGNAME_SIZE); 2141 drv_ctx.timestamp_adjust = true; 2142 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4; 2143 eCompressionFormat = OMX_VIDEO_CodingMPEG4; 2144 output_capability=V4L2_PIX_FMT_MPEG4; 2145 /*Initialize Start Code for MPEG4*/ 2146 codec_type_parse = CODEC_TYPE_MPEG4; 2147 m_frame_parser.init_start_codes(codec_type_parse); 2148 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\ 2149 OMX_MAX_STRINGNAME_SIZE)) { 2150 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\ 2151 OMX_MAX_STRINGNAME_SIZE); 2152 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2; 2153 output_capability = V4L2_PIX_FMT_MPEG2; 2154 eCompressionFormat = OMX_VIDEO_CodingMPEG2; 2155 /*Initialize Start Code for MPEG2*/ 2156 codec_type_parse = CODEC_TYPE_MPEG2; 2157 m_frame_parser.init_start_codes(codec_type_parse); 2158 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\ 2159 OMX_MAX_STRINGNAME_SIZE)) { 2160 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 2161 DEBUG_PRINT_LOW("H263 Decoder selected"); 2162 drv_ctx.decoder_format = VDEC_CODECTYPE_H263; 2163 eCompressionFormat = OMX_VIDEO_CodingH263; 2164 output_capability = V4L2_PIX_FMT_H263; 2165 codec_type_parse = CODEC_TYPE_H263; 2166 m_frame_parser.init_start_codes(codec_type_parse); 2167 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\ 2168 OMX_MAX_STRINGNAME_SIZE)) { 2169 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2170 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected"); 2171 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3; 2172 output_capability = V4L2_PIX_FMT_DIVX_311; 2173 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2174 codec_type_parse = CODEC_TYPE_DIVX; 2175 m_frame_parser.init_start_codes(codec_type_parse); 2176 2177 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ 2178 OMX_MAX_STRINGNAME_SIZE)) { 2179 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2180 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected"); 2181 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4; 2182 output_capability = V4L2_PIX_FMT_DIVX; 2183 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2184 codec_type_parse = CODEC_TYPE_DIVX; 2185 codec_ambiguous = true; 2186 m_frame_parser.init_start_codes(codec_type_parse); 2187 2188 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\ 2189 OMX_MAX_STRINGNAME_SIZE)) { 2190 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 2191 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected"); 2192 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6; 2193 output_capability = V4L2_PIX_FMT_DIVX; 2194 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; 2195 codec_type_parse = CODEC_TYPE_DIVX; 2196 codec_ambiguous = true; 2197 m_frame_parser.init_start_codes(codec_type_parse); 2198 2199 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\ 2200 OMX_MAX_STRINGNAME_SIZE)) { 2201 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 2202 drv_ctx.decoder_format = VDEC_CODECTYPE_H264; 2203 output_capability=V4L2_PIX_FMT_H264; 2204 eCompressionFormat = OMX_VIDEO_CodingAVC; 2205 codec_type_parse = CODEC_TYPE_H264; 2206 m_frame_parser.init_start_codes(codec_type_parse); 2207 m_frame_parser.init_nal_length(nal_length); 2208 if (is_thulium_v1) { 2209 arbitrary_bytes = true; 2210 DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264"); 2211 } 2212 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\ 2213 OMX_MAX_STRINGNAME_SIZE)) { 2214 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 2215 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC; 2216 output_capability = V4L2_PIX_FMT_H264_MVC; 2217 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC; 2218 codec_type_parse = CODEC_TYPE_H264; 2219 m_frame_parser.init_start_codes(codec_type_parse); 2220 m_frame_parser.init_nal_length(nal_length); 2221 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\ 2222 OMX_MAX_STRINGNAME_SIZE)) { 2223 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); 2224 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC; 2225 output_capability = V4L2_PIX_FMT_HEVC; 2226 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc; 2227 codec_type_parse = CODEC_TYPE_HEVC; 2228 m_frame_parser.init_start_codes(codec_type_parse); 2229 m_frame_parser.init_nal_length(nal_length); 2230 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\ 2231 OMX_MAX_STRINGNAME_SIZE)) { 2232 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 2233 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1; 2234 eCompressionFormat = OMX_VIDEO_CodingWMV; 2235 codec_type_parse = CODEC_TYPE_VC1; 2236 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G; 2237 m_frame_parser.init_start_codes(codec_type_parse); 2238 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\ 2239 OMX_MAX_STRINGNAME_SIZE)) { 2240 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 2241 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV; 2242 eCompressionFormat = OMX_VIDEO_CodingWMV; 2243 codec_type_parse = CODEC_TYPE_VC1; 2244 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L; 2245 m_frame_parser.init_start_codes(codec_type_parse); 2246 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \ 2247 OMX_MAX_STRINGNAME_SIZE)) { 2248 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 2249 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8; 2250 output_capability = V4L2_PIX_FMT_VP8; 2251 eCompressionFormat = OMX_VIDEO_CodingVP8; 2252 codec_type_parse = CODEC_TYPE_VP8; 2253 arbitrary_bytes = false; 2254 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \ 2255 OMX_MAX_STRINGNAME_SIZE)) { 2256 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE); 2257 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9; 2258 output_capability = V4L2_PIX_FMT_VP9; 2259 eCompressionFormat = OMX_VIDEO_CodingVP9; 2260 codec_type_parse = CODEC_TYPE_VP9; 2261 arbitrary_bytes = false; 2262 } else { 2263 DEBUG_PRINT_ERROR("ERROR:Unknown Component"); 2264 eRet = OMX_ErrorInvalidComponentName; 2265 } 2266 2267 if (eRet == OMX_ErrorNone) { 2268 OMX_COLOR_FORMATTYPE dest_color_format; 2269 if (m_disable_ubwc_mode) { 2270 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; 2271 } else { 2272 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC; 2273 } 2274 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC) 2275 dest_color_format = (OMX_COLOR_FORMATTYPE) 2276 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 2277 else 2278 dest_color_format = (OMX_COLOR_FORMATTYPE) 2279 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 2280 if (!client_buffers.set_color_format(dest_color_format)) { 2281 DEBUG_PRINT_ERROR("Setting color format failed"); 2282 eRet = OMX_ErrorInsufficientResources; 2283 } 2284 2285 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8; 2286 2287 if (m_disable_ubwc_mode) { 2288 capture_capability = V4L2_PIX_FMT_NV12; 2289 } else { 2290 capture_capability = V4L2_PIX_FMT_NV12_UBWC; 2291 } 2292 2293 struct v4l2_capability cap; 2294 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap); 2295 if (ret) { 2296 DEBUG_PRINT_ERROR("Failed to query capabilities"); 2297 /*TODO: How to handle this case */ 2298 } else { 2299 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s," 2300 " version = %d, capabilities = %x", cap.driver, cap.card, 2301 cap.bus_info, cap.version, cap.capabilities); 2302 } 2303 ret=0; 2304 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2305 fdesc.index=0; 2306 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 2307 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 2308 fdesc.pixelformat, fdesc.flags); 2309 fdesc.index++; 2310 } 2311 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2312 fdesc.index=0; 2313 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { 2314 2315 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description, 2316 fdesc.pixelformat, fdesc.flags); 2317 fdesc.index++; 2318 } 2319 update_resolution(320, 240, 320, 240); 2320 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2321 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 2322 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 2323 fmt.fmt.pix_mp.pixelformat = output_capability; 2324 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 2325 if (ret) { 2326 /*TODO: How to handle this case */ 2327 DEBUG_PRINT_ERROR("Failed to set format on output port"); 2328 return OMX_ErrorInsufficientResources; 2329 } 2330 DEBUG_PRINT_HIGH("Set Format was successful"); 2331 if (codec_ambiguous) { 2332 if (output_capability == V4L2_PIX_FMT_DIVX) { 2333 struct v4l2_control divx_ctrl; 2334 2335 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) { 2336 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4; 2337 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) { 2338 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5; 2339 } else { 2340 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6; 2341 } 2342 2343 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT; 2344 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl); 2345 if (ret) { 2346 DEBUG_PRINT_ERROR("Failed to set divx version"); 2347 } 2348 } else { 2349 DEBUG_PRINT_ERROR("Codec should not be ambiguous"); 2350 } 2351 } 2352 2353 property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR); 2354 m_conceal_color= atoi(property_value); 2355 DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color); 2356 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR; 2357 control.value = m_conceal_color; 2358 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2359 if (ret) { 2360 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret); 2361 } 2362 2363 //Get the hardware capabilities 2364 memset((void *)&frmsize,0,sizeof(frmsize)); 2365 frmsize.index = 0; 2366 frmsize.pixel_format = output_capability; 2367 ret = ioctl(drv_ctx.video_driver_fd, 2368 VIDIOC_ENUM_FRAMESIZES, &frmsize); 2369 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) { 2370 DEBUG_PRINT_ERROR("Failed to get framesizes"); 2371 return OMX_ErrorHardware; 2372 } 2373 2374 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 2375 m_decoder_capability.min_width = frmsize.stepwise.min_width; 2376 m_decoder_capability.max_width = frmsize.stepwise.max_width; 2377 m_decoder_capability.min_height = frmsize.stepwise.min_height; 2378 m_decoder_capability.max_height = frmsize.stepwise.max_height; 2379 } 2380 2381 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 2382 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2383 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 2384 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 2385 fmt.fmt.pix_mp.pixelformat = capture_capability; 2386 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 2387 if (ret) { 2388 /*TODO: How to handle this case */ 2389 DEBUG_PRINT_ERROR("Failed to set format on capture port"); 2390 } 2391 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE)); 2392 framesize.nWidth = drv_ctx.video_resolution.frame_width; 2393 framesize.nHeight = drv_ctx.video_resolution.frame_height; 2394 2395 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE)); 2396 rectangle.nWidth = drv_ctx.video_resolution.frame_width; 2397 rectangle.nHeight = drv_ctx.video_resolution.frame_height; 2398 2399 DEBUG_PRINT_HIGH("Set Format was successful"); 2400 if (secure_mode) { 2401 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE; 2402 control.value = 1; 2403 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret); 2404 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 2405 if (ret) { 2406 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret); 2407 return OMX_ErrorInsufficientResources; 2408 } 2409 } 2410 if (output_capability == V4L2_PIX_FMT_H264_MVC) { 2411 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT; 2412 control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM; 2413 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2414 if (ret) { 2415 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout"); 2416 return OMX_ErrorInsufficientResources; 2417 } 2418 } 2419 2420 if (is_thulium_v1) { 2421 eRet = enable_smoothstreaming(); 2422 if (eRet != OMX_ErrorNone) { 2423 DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver"); 2424 return eRet; 2425 } 2426 } 2427 2428 /*Get the Buffer requirements for input and output ports*/ 2429 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; 2430 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 2431 2432 if (secure_mode) { 2433 drv_ctx.op_buf.alignment = SECURE_ALIGN; 2434 drv_ctx.ip_buf.alignment = SECURE_ALIGN; 2435 } else { 2436 drv_ctx.op_buf.alignment = SZ_4K; 2437 drv_ctx.ip_buf.alignment = SZ_4K; 2438 } 2439 2440 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 2441 drv_ctx.extradata = 0; 2442 drv_ctx.picture_order = VDEC_ORDER_DISPLAY; 2443 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 2444 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 2445 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 2446 drv_ctx.idr_only_decoding = 0; 2447 2448 #ifdef _ANDROID_ 2449 property_get("vidc.dec.downscalar_width",property_value,"0"); 2450 if (atoi(property_value)) { 2451 m_downscalar_width = atoi(property_value); 2452 } 2453 property_get("vidc.dec.downscalar_height",property_value,"0"); 2454 if (atoi(property_value)) { 2455 m_downscalar_height = atoi(property_value); 2456 } 2457 2458 if (m_downscalar_width < m_decoder_capability.min_width || 2459 m_downscalar_height < m_decoder_capability.min_height) { 2460 m_downscalar_width = 0; 2461 m_downscalar_height = 0; 2462 } 2463 2464 DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n", 2465 m_downscalar_width, m_downscalar_height); 2466 #endif 2467 m_state = OMX_StateLoaded; 2468 #ifdef DEFAULT_EXTRADATA 2469 if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", 2470 OMX_MAX_STRINGNAME_SIZE) && 2471 strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", 2472 OMX_MAX_STRINGNAME_SIZE)) && 2473 (eRet == OMX_ErrorNone)) 2474 enable_extradata(DEFAULT_EXTRADATA, true, true); 2475 #endif 2476 eRet = get_buffer_req(&drv_ctx.ip_buf); 2477 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size); 2478 get_buffer_req(&drv_ctx.op_buf); 2479 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 || 2480 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC || 2481 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) { 2482 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size; 2483 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size); 2484 h264_scratch.nFilledLen = 0; 2485 h264_scratch.nOffset = 0; 2486 2487 if (h264_scratch.pBuffer == NULL) { 2488 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed "); 2489 return OMX_ErrorInsufficientResources; 2490 } 2491 } 2492 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 || 2493 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) { 2494 if (m_frame_parser.mutils == NULL) { 2495 m_frame_parser.mutils = new H264_Utils(); 2496 if (m_frame_parser.mutils == NULL) { 2497 DEBUG_PRINT_ERROR("parser utils Allocation failed "); 2498 eRet = OMX_ErrorInsufficientResources; 2499 } else { 2500 m_frame_parser.mutils->initialize_frame_checking_environment(); 2501 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size); 2502 } 2503 } 2504 2505 h264_parser = new h264_stream_parser(); 2506 if (!h264_parser) { 2507 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!"); 2508 eRet = OMX_ErrorInsufficientResources; 2509 } 2510 } 2511 2512 if (pipe(fds)) { 2513 DEBUG_PRINT_ERROR("pipe creation failed"); 2514 eRet = OMX_ErrorInsufficientResources; 2515 } else { 2516 m_pipe_in = fds[0]; 2517 m_pipe_out = fds[1]; 2518 msg_thread_created = true; 2519 r = pthread_create(&msg_thread_id,0,message_thread,this); 2520 2521 if (r < 0) { 2522 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed"); 2523 msg_thread_created = false; 2524 eRet = OMX_ErrorInsufficientResources; 2525 } 2526 } 2527 } 2528 2529 { 2530 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore); 2531 init_vendor_extensions(*extStore); 2532 mVendorExtensionStore.dumpExtensions((const char *)role); 2533 } 2534 2535 if (eRet != OMX_ErrorNone) { 2536 DEBUG_PRINT_ERROR("Component Init Failed"); 2537 } else { 2538 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d", 2539 drv_ctx.video_driver_fd); 2540 } 2541 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); 2542 return eRet; 2543 } 2544 2545 /* ====================================================================== 2546 FUNCTION 2547 omx_vdec::GetComponentVersion 2548 2549 DESCRIPTION 2550 Returns the component version. 2551 2552 PARAMETERS 2553 TBD. 2554 2555 RETURN VALUE 2556 OMX_ErrorNone. 2557 2558 ========================================================================== */ 2559 OMX_ERRORTYPE omx_vdec::get_component_version 2560 ( 2561 OMX_IN OMX_HANDLETYPE hComp, 2562 OMX_OUT OMX_STRING componentName, 2563 OMX_OUT OMX_VERSIONTYPE* componentVersion, 2564 OMX_OUT OMX_VERSIONTYPE* specVersion, 2565 OMX_OUT OMX_UUIDTYPE* componentUUID 2566 ) 2567 { 2568 (void) hComp; 2569 (void) componentName; 2570 (void) componentVersion; 2571 (void) componentUUID; 2572 if (m_state == OMX_StateInvalid) { 2573 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State"); 2574 return OMX_ErrorInvalidState; 2575 } 2576 /* TBD -- Return the proper version */ 2577 if (specVersion) { 2578 specVersion->nVersion = OMX_SPEC_VERSION; 2579 } 2580 return OMX_ErrorNone; 2581 } 2582 /* ====================================================================== 2583 FUNCTION 2584 omx_vdec::SendCommand 2585 2586 DESCRIPTION 2587 Returns zero if all the buffers released.. 2588 2589 PARAMETERS 2590 None. 2591 2592 RETURN VALUE 2593 true/false 2594 2595 ========================================================================== */ 2596 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, 2597 OMX_IN OMX_COMMANDTYPE cmd, 2598 OMX_IN OMX_U32 param1, 2599 OMX_IN OMX_PTR cmdData 2600 ) 2601 { 2602 (void) hComp; 2603 (void) cmdData; 2604 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client"); 2605 if (m_state == OMX_StateInvalid) { 2606 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State"); 2607 return OMX_ErrorInvalidState; 2608 } 2609 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX 2610 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) { 2611 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush " 2612 "to invalid port: %u", (unsigned int)param1); 2613 return OMX_ErrorBadPortIndex; 2614 } 2615 2616 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); 2617 sem_wait(&m_cmd_lock); 2618 DEBUG_PRINT_LOW("send_command: Command Processed"); 2619 return OMX_ErrorNone; 2620 } 2621 2622 /* ====================================================================== 2623 FUNCTION 2624 omx_vdec::SendCommand 2625 2626 DESCRIPTION 2627 Returns zero if all the buffers released.. 2628 2629 PARAMETERS 2630 None. 2631 2632 RETURN VALUE 2633 true/false 2634 2635 ========================================================================== */ 2636 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, 2637 OMX_IN OMX_COMMANDTYPE cmd, 2638 OMX_IN OMX_U32 param1, 2639 OMX_IN OMX_PTR cmdData 2640 ) 2641 { 2642 (void) hComp; 2643 (void) cmdData; 2644 OMX_ERRORTYPE eRet = OMX_ErrorNone; 2645 OMX_STATETYPE eState = (OMX_STATETYPE) param1; 2646 int bFlag = 1,sem_posted = 0,ret=0; 2647 2648 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd); 2649 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d", 2650 m_state, eState); 2651 2652 if (cmd == OMX_CommandStateSet) { 2653 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued"); 2654 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState); 2655 /***************************/ 2656 /* Current State is Loaded */ 2657 /***************************/ 2658 if (m_state == OMX_StateLoaded) { 2659 if (eState == OMX_StateIdle) { 2660 //if all buffers are allocated or all ports disabled 2661 if (allocate_done() || 2662 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) { 2663 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle"); 2664 } else { 2665 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending"); 2666 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); 2667 // Skip the event notification 2668 bFlag = 0; 2669 } 2670 } 2671 /* Requesting transition from Loaded to Loaded */ 2672 else if (eState == OMX_StateLoaded) { 2673 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded"); 2674 post_event(OMX_EventError,OMX_ErrorSameState,\ 2675 OMX_COMPONENT_GENERATE_EVENT); 2676 eRet = OMX_ErrorSameState; 2677 } 2678 /* Requesting transition from Loaded to WaitForResources */ 2679 else if (eState == OMX_StateWaitForResources) { 2680 /* Since error is None , we will post an event 2681 at the end of this function definition */ 2682 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources"); 2683 } 2684 /* Requesting transition from Loaded to Executing */ 2685 else if (eState == OMX_StateExecuting) { 2686 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing"); 2687 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2688 OMX_COMPONENT_GENERATE_EVENT); 2689 eRet = OMX_ErrorIncorrectStateTransition; 2690 } 2691 /* Requesting transition from Loaded to Pause */ 2692 else if (eState == OMX_StatePause) { 2693 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause"); 2694 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2695 OMX_COMPONENT_GENERATE_EVENT); 2696 eRet = OMX_ErrorIncorrectStateTransition; 2697 } 2698 /* Requesting transition from Loaded to Invalid */ 2699 else if (eState == OMX_StateInvalid) { 2700 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid"); 2701 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2702 eRet = OMX_ErrorInvalidState; 2703 } else { 2704 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\ 2705 eState); 2706 eRet = OMX_ErrorBadParameter; 2707 } 2708 } 2709 2710 /***************************/ 2711 /* Current State is IDLE */ 2712 /***************************/ 2713 else if (m_state == OMX_StateIdle) { 2714 if (eState == OMX_StateLoaded) { 2715 if (release_done()) { 2716 /* 2717 Since error is None , we will post an event at the end 2718 of this function definition 2719 */ 2720 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded"); 2721 } else { 2722 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending"); 2723 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); 2724 // Skip the event notification 2725 bFlag = 0; 2726 } 2727 } 2728 /* Requesting transition from Idle to Executing */ 2729 else if (eState == OMX_StateExecuting) { 2730 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2731 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); 2732 bFlag = 1; 2733 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 2734 m_state=OMX_StateExecuting; 2735 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful"); 2736 } 2737 /* Requesting transition from Idle to Idle */ 2738 else if (eState == OMX_StateIdle) { 2739 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle"); 2740 post_event(OMX_EventError,OMX_ErrorSameState,\ 2741 OMX_COMPONENT_GENERATE_EVENT); 2742 eRet = OMX_ErrorSameState; 2743 } 2744 /* Requesting transition from Idle to WaitForResources */ 2745 else if (eState == OMX_StateWaitForResources) { 2746 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources"); 2747 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2748 OMX_COMPONENT_GENERATE_EVENT); 2749 eRet = OMX_ErrorIncorrectStateTransition; 2750 } 2751 /* Requesting transition from Idle to Pause */ 2752 else if (eState == OMX_StatePause) { 2753 /*To pause the Video core we need to start the driver*/ 2754 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, 2755 NULL) < */0) { 2756 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED"); 2757 omx_report_error (); 2758 eRet = OMX_ErrorHardware; 2759 } else { 2760 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); 2761 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause"); 2762 bFlag = 0; 2763 } 2764 } 2765 /* Requesting transition from Idle to Invalid */ 2766 else if (eState == OMX_StateInvalid) { 2767 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid"); 2768 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2769 eRet = OMX_ErrorInvalidState; 2770 } else { 2771 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState); 2772 eRet = OMX_ErrorBadParameter; 2773 } 2774 } 2775 2776 /******************************/ 2777 /* Current State is Executing */ 2778 /******************************/ 2779 else if (m_state == OMX_StateExecuting) { 2780 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting"); 2781 /* Requesting transition from Executing to Idle */ 2782 if (eState == OMX_StateIdle) { 2783 /* Since error is None , we will post an event 2784 at the end of this function definition 2785 */ 2786 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle"); 2787 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 2788 if (!sem_posted) { 2789 sem_posted = 1; 2790 sem_post (&m_cmd_lock); 2791 execute_omx_flush(OMX_ALL); 2792 } 2793 bFlag = 0; 2794 } 2795 /* Requesting transition from Executing to Paused */ 2796 else if (eState == OMX_StatePause) { 2797 DEBUG_PRINT_LOW("PAUSE Command Issued"); 2798 m_state = OMX_StatePause; 2799 bFlag = 1; 2800 } 2801 /* Requesting transition from Executing to Loaded */ 2802 else if (eState == OMX_StateLoaded) { 2803 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded"); 2804 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2805 OMX_COMPONENT_GENERATE_EVENT); 2806 eRet = OMX_ErrorIncorrectStateTransition; 2807 } 2808 /* Requesting transition from Executing to WaitForResources */ 2809 else if (eState == OMX_StateWaitForResources) { 2810 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources"); 2811 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2812 OMX_COMPONENT_GENERATE_EVENT); 2813 eRet = OMX_ErrorIncorrectStateTransition; 2814 } 2815 /* Requesting transition from Executing to Executing */ 2816 else if (eState == OMX_StateExecuting) { 2817 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing"); 2818 post_event(OMX_EventError,OMX_ErrorSameState,\ 2819 OMX_COMPONENT_GENERATE_EVENT); 2820 eRet = OMX_ErrorSameState; 2821 } 2822 /* Requesting transition from Executing to Invalid */ 2823 else if (eState == OMX_StateInvalid) { 2824 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid"); 2825 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2826 eRet = OMX_ErrorInvalidState; 2827 } else { 2828 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState); 2829 eRet = OMX_ErrorBadParameter; 2830 } 2831 } 2832 /***************************/ 2833 /* Current State is Pause */ 2834 /***************************/ 2835 else if (m_state == OMX_StatePause) { 2836 /* Requesting transition from Pause to Executing */ 2837 if (eState == OMX_StateExecuting) { 2838 DEBUG_PRINT_LOW("Pause --> Executing"); 2839 m_state = OMX_StateExecuting; 2840 bFlag = 1; 2841 } 2842 /* Requesting transition from Pause to Idle */ 2843 else if (eState == OMX_StateIdle) { 2844 /* Since error is None , we will post an event 2845 at the end of this function definition */ 2846 DEBUG_PRINT_LOW("Pause --> Idle"); 2847 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); 2848 if (!sem_posted) { 2849 sem_posted = 1; 2850 sem_post (&m_cmd_lock); 2851 execute_omx_flush(OMX_ALL); 2852 } 2853 bFlag = 0; 2854 } 2855 /* Requesting transition from Pause to loaded */ 2856 else if (eState == OMX_StateLoaded) { 2857 DEBUG_PRINT_ERROR("Pause --> loaded"); 2858 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2859 OMX_COMPONENT_GENERATE_EVENT); 2860 eRet = OMX_ErrorIncorrectStateTransition; 2861 } 2862 /* Requesting transition from Pause to WaitForResources */ 2863 else if (eState == OMX_StateWaitForResources) { 2864 DEBUG_PRINT_ERROR("Pause --> WaitForResources"); 2865 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2866 OMX_COMPONENT_GENERATE_EVENT); 2867 eRet = OMX_ErrorIncorrectStateTransition; 2868 } 2869 /* Requesting transition from Pause to Pause */ 2870 else if (eState == OMX_StatePause) { 2871 DEBUG_PRINT_ERROR("Pause --> Pause"); 2872 post_event(OMX_EventError,OMX_ErrorSameState,\ 2873 OMX_COMPONENT_GENERATE_EVENT); 2874 eRet = OMX_ErrorSameState; 2875 } 2876 /* Requesting transition from Pause to Invalid */ 2877 else if (eState == OMX_StateInvalid) { 2878 DEBUG_PRINT_ERROR("Pause --> Invalid"); 2879 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2880 eRet = OMX_ErrorInvalidState; 2881 } else { 2882 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState); 2883 eRet = OMX_ErrorBadParameter; 2884 } 2885 } 2886 /***************************/ 2887 /* Current State is WaitForResources */ 2888 /***************************/ 2889 else if (m_state == OMX_StateWaitForResources) { 2890 /* Requesting transition from WaitForResources to Loaded */ 2891 if (eState == OMX_StateLoaded) { 2892 /* Since error is None , we will post an event 2893 at the end of this function definition */ 2894 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded"); 2895 } 2896 /* Requesting transition from WaitForResources to WaitForResources */ 2897 else if (eState == OMX_StateWaitForResources) { 2898 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources"); 2899 post_event(OMX_EventError,OMX_ErrorSameState, 2900 OMX_COMPONENT_GENERATE_EVENT); 2901 eRet = OMX_ErrorSameState; 2902 } 2903 /* Requesting transition from WaitForResources to Executing */ 2904 else if (eState == OMX_StateExecuting) { 2905 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing"); 2906 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2907 OMX_COMPONENT_GENERATE_EVENT); 2908 eRet = OMX_ErrorIncorrectStateTransition; 2909 } 2910 /* Requesting transition from WaitForResources to Pause */ 2911 else if (eState == OMX_StatePause) { 2912 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause"); 2913 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ 2914 OMX_COMPONENT_GENERATE_EVENT); 2915 eRet = OMX_ErrorIncorrectStateTransition; 2916 } 2917 /* Requesting transition from WaitForResources to Invalid */ 2918 else if (eState == OMX_StateInvalid) { 2919 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid"); 2920 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); 2921 eRet = OMX_ErrorInvalidState; 2922 } 2923 /* Requesting transition from WaitForResources to Loaded - 2924 is NOT tested by Khronos TS */ 2925 2926 } else { 2927 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState); 2928 eRet = OMX_ErrorBadParameter; 2929 } 2930 } 2931 /********************************/ 2932 /* Current State is Invalid */ 2933 /*******************************/ 2934 else if (m_state == OMX_StateInvalid) { 2935 /* State Transition from Inavlid to any state */ 2936 if (eState == (OMX_StateLoaded || OMX_StateWaitForResources 2937 || OMX_StateIdle || OMX_StateExecuting 2938 || OMX_StatePause || OMX_StateInvalid)) { 2939 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded"); 2940 post_event(OMX_EventError,OMX_ErrorInvalidState,\ 2941 OMX_COMPONENT_GENERATE_EVENT); 2942 eRet = OMX_ErrorInvalidState; 2943 } 2944 } else if (cmd == OMX_CommandFlush) { 2945 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued" 2946 "with param1: %u", (unsigned int)param1); 2947 #ifdef _MSM8974_ 2948 send_codec_config(); 2949 #endif 2950 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX || 2951 param1 == OMX_ALL)) { 2952 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) { 2953 struct timespec ts; 2954 2955 clock_gettime(CLOCK_REALTIME, &ts); 2956 ts.tv_sec += 2; 2957 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ", 2958 m_queued_codec_config_count); 2959 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED); 2960 if (sem_timedwait(&m_safe_flush, &ts)) { 2961 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers"); 2962 } 2963 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED); 2964 } 2965 } 2966 2967 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) { 2968 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); 2969 } 2970 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) { 2971 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 2972 } 2973 if (!sem_posted) { 2974 sem_posted = 1; 2975 DEBUG_PRINT_LOW("Set the Semaphore"); 2976 sem_post (&m_cmd_lock); 2977 execute_omx_flush(param1); 2978 } 2979 bFlag = 0; 2980 } else if ( cmd == OMX_CommandPortEnable) { 2981 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued" 2982 "with param1: %u", (unsigned int)param1); 2983 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { 2984 m_inp_bEnabled = OMX_TRUE; 2985 2986 if ( (m_state == OMX_StateLoaded && 2987 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 2988 || allocate_input_done()) { 2989 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, 2990 OMX_COMPONENT_GENERATE_EVENT); 2991 } else { 2992 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 2993 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); 2994 // Skip the event notification 2995 bFlag = 0; 2996 } 2997 } 2998 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) { 2999 DEBUG_PRINT_LOW("Enable output Port command recieved"); 3000 m_out_bEnabled = OMX_TRUE; 3001 3002 if ( (m_state == OMX_StateLoaded && 3003 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) 3004 || (allocate_output_done())) { 3005 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, 3006 OMX_COMPONENT_GENERATE_EVENT); 3007 3008 } else { 3009 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending"); 3010 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 3011 // Skip the event notification 3012 bFlag = 0; 3013 /* enable/disable downscaling if required */ 3014 ret = decide_downscalar(); 3015 if (ret) { 3016 DEBUG_PRINT_LOW("decide_downscalar failed\n"); 3017 } 3018 } 3019 } 3020 } else if (cmd == OMX_CommandPortDisable) { 3021 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued" 3022 "with param1: %u", (unsigned int)param1); 3023 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { 3024 codec_config_flag = false; 3025 m_inp_bEnabled = OMX_FALSE; 3026 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 3027 && release_input_done()) { 3028 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, 3029 OMX_COMPONENT_GENERATE_EVENT); 3030 } else { 3031 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); 3032 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) { 3033 if (!sem_posted) { 3034 sem_posted = 1; 3035 sem_post (&m_cmd_lock); 3036 } 3037 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); 3038 } 3039 3040 // Skip the event notification 3041 bFlag = 0; 3042 } 3043 } 3044 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) { 3045 m_out_bEnabled = OMX_FALSE; 3046 DEBUG_PRINT_LOW("Disable output Port command recieved"); 3047 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) 3048 && release_output_done()) { 3049 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ 3050 OMX_COMPONENT_GENERATE_EVENT); 3051 } else { 3052 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 3053 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) { 3054 if (!sem_posted) { 3055 sem_posted = 1; 3056 sem_post (&m_cmd_lock); 3057 } 3058 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); 3059 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); 3060 } 3061 // Skip the event notification 3062 bFlag = 0; 3063 3064 } 3065 } 3066 } else { 3067 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd); 3068 eRet = OMX_ErrorNotImplemented; 3069 } 3070 if (eRet == OMX_ErrorNone && bFlag) { 3071 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); 3072 } 3073 if (!sem_posted) { 3074 sem_post(&m_cmd_lock); 3075 } 3076 3077 return eRet; 3078 } 3079 3080 /* ====================================================================== 3081 FUNCTION 3082 omx_vdec::ExecuteOmxFlush 3083 3084 DESCRIPTION 3085 Executes the OMX flush. 3086 3087 PARAMETERS 3088 flushtype - input flush(1)/output flush(0)/ both. 3089 3090 RETURN VALUE 3091 true/false 3092 3093 ========================================================================== */ 3094 bool omx_vdec::execute_omx_flush(OMX_U32 flushType) 3095 { 3096 bool bRet = false; 3097 struct v4l2_plane plane; 3098 struct v4l2_buffer v4l2_buf; 3099 struct v4l2_decoder_cmd dec; 3100 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType); 3101 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf)); 3102 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH; 3103 3104 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig); 3105 3106 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) { 3107 output_flush_progress = true; 3108 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 3109 } else { 3110 /* XXX: The driver/hardware does not support flushing of individual ports 3111 * in all states. So we pretty much need to flush both ports internally, 3112 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it 3113 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set, 3114 * we automatically omit sending the FLUSH done for the "opposite" port. */ 3115 input_flush_progress = true; 3116 output_flush_progress = true; 3117 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; 3118 request_perf_level(VIDC_TURBO); 3119 } 3120 3121 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { 3122 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType); 3123 bRet = false; 3124 } 3125 3126 return bRet; 3127 } 3128 /*========================================================================= 3129 FUNCTION : execute_output_flush 3130 3131 DESCRIPTION 3132 Executes the OMX flush at OUTPUT PORT. 3133 3134 PARAMETERS 3135 None. 3136 3137 RETURN VALUE 3138 true/false 3139 ==========================================================================*/ 3140 bool omx_vdec::execute_output_flush() 3141 { 3142 unsigned long p1 = 0; // Parameter - 1 3143 unsigned long p2 = 0; // Parameter - 2 3144 unsigned long ident = 0; 3145 bool bRet = true; 3146 3147 /*Generate FBD for all Buffers in the FTBq*/ 3148 pthread_mutex_lock(&m_lock); 3149 DEBUG_PRINT_LOW("Initiate Output Flush"); 3150 3151 //reset last render TS 3152 if(m_last_rendered_TS > 0) { 3153 m_last_rendered_TS = 0; 3154 } 3155 3156 while (m_ftb_q.m_size) { 3157 DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d", 3158 m_ftb_q.m_size,pending_output_buffers); 3159 m_ftb_q.pop_entry(&p1,&p2,&ident); 3160 DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2); 3161 if (ident == m_fill_output_msg ) { 3162 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2); 3163 } else if (ident == OMX_COMPONENT_GENERATE_FBD) { 3164 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1); 3165 } 3166 } 3167 pthread_mutex_unlock(&m_lock); 3168 output_flush_progress = false; 3169 3170 if (arbitrary_bytes) { 3171 prev_ts = LLONG_MAX; 3172 rst_prev_ts = true; 3173 } 3174 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); 3175 return bRet; 3176 } 3177 /*========================================================================= 3178 FUNCTION : execute_input_flush 3179 3180 DESCRIPTION 3181 Executes the OMX flush at INPUT PORT. 3182 3183 PARAMETERS 3184 None. 3185 3186 RETURN VALUE 3187 true/false 3188 ==========================================================================*/ 3189 bool omx_vdec::execute_input_flush() 3190 { 3191 unsigned i =0; 3192 unsigned long p1 = 0; // Parameter - 1 3193 unsigned long p2 = 0; // Parameter - 2 3194 unsigned long ident = 0; 3195 bool bRet = true; 3196 3197 /*Generate EBD for all Buffers in the ETBq*/ 3198 DEBUG_PRINT_LOW("Initiate Input Flush"); 3199 3200 pthread_mutex_lock(&m_lock); 3201 DEBUG_PRINT_LOW("Check if the Queue is empty"); 3202 while (m_etb_q.m_size) { 3203 m_etb_q.pop_entry(&p1,&p2,&ident); 3204 3205 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { 3206 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 3207 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 3208 } else if (ident == OMX_COMPONENT_GENERATE_ETB) { 3209 pending_input_buffers++; 3210 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 3211 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 3212 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 3213 } else if (ident == OMX_COMPONENT_GENERATE_EBD) { 3214 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p", 3215 (OMX_BUFFERHEADERTYPE *)p1); 3216 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 3217 } 3218 } 3219 time_stamp_dts.flush_timestamp(); 3220 /*Check if Heap Buffers are to be flushed*/ 3221 if (arbitrary_bytes && !(codec_config_flag)) { 3222 DEBUG_PRINT_LOW("Reset all the variables before flusing"); 3223 h264_scratch.nFilledLen = 0; 3224 nal_count = 0; 3225 look_ahead_nal = false; 3226 frame_count = 0; 3227 h264_last_au_ts = LLONG_MAX; 3228 h264_last_au_flags = 0; 3229 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 3230 m_demux_entries = 0; 3231 DEBUG_PRINT_LOW("Initialize parser"); 3232 if (m_frame_parser.mutils) { 3233 m_frame_parser.mutils->initialize_frame_checking_environment(); 3234 } 3235 3236 while (m_input_pending_q.m_size) { 3237 m_input_pending_q.pop_entry(&p1,&p2,&ident); 3238 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); 3239 } 3240 3241 if (psource_frame) { 3242 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); 3243 psource_frame = NULL; 3244 } 3245 3246 if (pdest_frame) { 3247 pdest_frame->nFilledLen = 0; 3248 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL, 3249 (unsigned int)NULL); 3250 pdest_frame = NULL; 3251 } 3252 m_frame_parser.flush(); 3253 } else if (codec_config_flag) { 3254 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer " 3255 "is not sent to the driver yet"); 3256 } 3257 pthread_mutex_unlock(&m_lock); 3258 input_flush_progress = false; 3259 if (!arbitrary_bytes) { 3260 prev_ts = LLONG_MAX; 3261 rst_prev_ts = true; 3262 } 3263 #ifdef _ANDROID_ 3264 if (m_debug_timestamp) { 3265 m_timestamp_list.reset_ts_list(); 3266 } 3267 #endif 3268 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); 3269 return bRet; 3270 } 3271 3272 /*========================================================================= 3273 FUNCTION : notify_flush_done 3274 DESCRIPTION 3275 Notifies flush done to the OMX Client. 3276 PARAMETERS 3277 ctxt -- Context information related to the self.. 3278 RETURN VALUE 3279 NONE 3280 ==========================================================================*/ 3281 void omx_vdec::notify_flush_done(void *ctxt) { 3282 omx_vdec *pThis = (omx_vdec *) ctxt; 3283 if (!pThis->input_flush_progress && !pThis->output_flush_progress) { 3284 if (BITMASK_PRESENT(&pThis->m_flags, 3285 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) { 3286 DEBUG_PRINT_LOW("Notify Output Flush done"); 3287 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); 3288 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 3289 OMX_EventCmdComplete,OMX_CommandFlush, 3290 OMX_CORE_OUTPUT_PORT_INDEX,NULL ); 3291 } 3292 3293 if (BITMASK_PRESENT(&pThis->m_flags, 3294 OMX_COMPONENT_INPUT_FLUSH_PENDING)) { 3295 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); 3296 DEBUG_PRINT_LOW("Input Flush completed - Notify Client"); 3297 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, 3298 OMX_EventCmdComplete,OMX_CommandFlush, 3299 OMX_CORE_INPUT_PORT_INDEX,NULL ); 3300 } 3301 } 3302 } 3303 3304 /* ====================================================================== 3305 FUNCTION 3306 omx_vdec::SendCommandEvent 3307 3308 DESCRIPTION 3309 Send the event to decoder pipe. This is needed to generate the callbacks 3310 in decoder thread context. 3311 3312 PARAMETERS 3313 None. 3314 3315 RETURN VALUE 3316 true/false 3317 3318 ========================================================================== */ 3319 bool omx_vdec::post_event(unsigned long p1, 3320 unsigned long p2, 3321 unsigned long id) 3322 { 3323 bool bRet = false; 3324 3325 /* Just drop messages typically generated by hardware (w/o client request), 3326 * if we've reported an error to client. */ 3327 if (m_error_propogated) { 3328 switch (id) { 3329 case OMX_COMPONENT_GENERATE_PORT_RECONFIG: 3330 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: 3331 DEBUG_PRINT_ERROR("Dropping message %lx " 3332 "since client expected to be in error state", id); 3333 return false; 3334 default: 3335 /* whatever */ 3336 break; 3337 } 3338 } 3339 3340 pthread_mutex_lock(&m_lock); 3341 3342 if (id == m_fill_output_msg || 3343 id == OMX_COMPONENT_GENERATE_FBD || 3344 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG || 3345 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) { 3346 m_ftb_q.insert_entry(p1,p2,id); 3347 } else if (id == OMX_COMPONENT_GENERATE_ETB || 3348 id == OMX_COMPONENT_GENERATE_EBD || 3349 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY || 3350 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) { 3351 m_etb_q.insert_entry(p1,p2,id); 3352 } else { 3353 m_cmd_q.insert_entry(p1,p2,id); 3354 } 3355 3356 bRet = true; 3357 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this); 3358 post_message(this, id); 3359 3360 pthread_mutex_unlock(&m_lock); 3361 3362 return bRet; 3363 } 3364 3365 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) 3366 { 3367 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3368 if (!profileLevelType) 3369 return OMX_ErrorBadParameter; 3370 3371 if (profileLevelType->nPortIndex == 0) { 3372 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 3373 if (profileLevelType->nProfileIndex == 0) { 3374 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; 3375 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; 3376 3377 } else if (profileLevelType->nProfileIndex == 1) { 3378 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; 3379 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; 3380 } else if (profileLevelType->nProfileIndex == 2) { 3381 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; 3382 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; 3383 } else { 3384 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3385 (unsigned int)profileLevelType->nProfileIndex); 3386 eRet = OMX_ErrorNoMore; 3387 } 3388 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 3389 if (profileLevelType->nProfileIndex == 0) { 3390 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh; 3391 profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51; 3392 } else { 3393 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3394 (unsigned int)profileLevelType->nProfileIndex); 3395 eRet = OMX_ErrorNoMore; 3396 } 3397 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 3398 if (profileLevelType->nProfileIndex == 0) { 3399 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; 3400 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; 3401 } else if (profileLevelType->nProfileIndex == 1) { 3402 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; 3403 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; 3404 } else { 3405 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3406 (unsigned int)profileLevelType->nProfileIndex); 3407 eRet = OMX_ErrorNoMore; 3408 } 3409 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) { 3410 if (profileLevelType->nProfileIndex == 0) { 3411 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; 3412 profileLevelType->eLevel = OMX_VIDEO_H263Level70; 3413 } else { 3414 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3415 (unsigned int)profileLevelType->nProfileIndex); 3416 eRet = OMX_ErrorNoMore; 3417 } 3418 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 3419 if (profileLevelType->nProfileIndex == 0) { 3420 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; 3421 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; 3422 } else if (profileLevelType->nProfileIndex == 1) { 3423 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; 3424 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; 3425 } else { 3426 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3427 (unsigned int)profileLevelType->nProfileIndex); 3428 eRet = OMX_ErrorNoMore; 3429 } 3430 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) || 3431 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) { 3432 eRet = OMX_ErrorNoMore; 3433 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 3434 if (profileLevelType->nProfileIndex == 0) { 3435 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; 3436 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; 3437 } else if (profileLevelType->nProfileIndex == 1) { 3438 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; 3439 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; 3440 } else { 3441 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", 3442 (unsigned int)profileLevelType->nProfileIndex); 3443 eRet = OMX_ErrorNoMore; 3444 } 3445 } else { 3446 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind); 3447 eRet = OMX_ErrorNoMore; 3448 } 3449 } else { 3450 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u", 3451 (unsigned int)profileLevelType->nPortIndex); 3452 eRet = OMX_ErrorBadPortIndex; 3453 } 3454 return eRet; 3455 } 3456 3457 /* ====================================================================== 3458 FUNCTION 3459 omx_vdec::GetParameter 3460 3461 DESCRIPTION 3462 OMX Get Parameter method implementation 3463 3464 PARAMETERS 3465 <TBD>. 3466 3467 RETURN VALUE 3468 Error None if successful. 3469 3470 ========================================================================== */ 3471 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, 3472 OMX_IN OMX_INDEXTYPE paramIndex, 3473 OMX_INOUT OMX_PTR paramData) 3474 { 3475 (void) hComp; 3476 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3477 3478 DEBUG_PRINT_LOW("get_parameter:"); 3479 if (m_state == OMX_StateInvalid) { 3480 DEBUG_PRINT_ERROR("Get Param in Invalid State"); 3481 return OMX_ErrorInvalidState; 3482 } 3483 if (paramData == NULL) { 3484 DEBUG_PRINT_LOW("Get Param in Invalid paramData"); 3485 return OMX_ErrorBadParameter; 3486 } 3487 switch ((unsigned long)paramIndex) { 3488 case OMX_IndexParamPortDefinition: { 3489 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); 3490 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = 3491 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3492 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); 3493 decide_dpb_buffer_mode(is_down_scalar_enabled); 3494 eRet = update_portdef(portDefn); 3495 if (eRet == OMX_ErrorNone) 3496 m_port_def = *portDefn; 3497 break; 3498 } 3499 case OMX_IndexParamVideoInit: { 3500 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3501 OMX_PORT_PARAM_TYPE *portParamType = 3502 (OMX_PORT_PARAM_TYPE *) paramData; 3503 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); 3504 3505 portParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3506 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3507 portParamType->nPorts = 2; 3508 portParamType->nStartPortNumber = 0; 3509 break; 3510 } 3511 case OMX_IndexParamVideoPortFormat: { 3512 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); 3513 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3514 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3515 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); 3516 3517 portFmt->nVersion.nVersion = OMX_SPEC_VERSION; 3518 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 3519 3520 if (0 == portFmt->nPortIndex) { 3521 if (0 == portFmt->nIndex) { 3522 portFmt->eColorFormat = OMX_COLOR_FormatUnused; 3523 portFmt->eCompressionFormat = eCompressionFormat; 3524 } else { 3525 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3526 " NoMore compression formats"); 3527 eRet = OMX_ErrorNoMore; 3528 } 3529 } else if (1 == portFmt->nPortIndex) { 3530 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; 3531 3532 // Distinguish non-surface mode from normal playback use-case based on 3533 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2" 3534 // For non-android, use the default list 3535 // Also use default format-list if FLEXIBLE YUV is supported, 3536 // as the client negotiates the standard color-format if it needs to 3537 bool useNonSurfaceMode = false; 3538 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) 3539 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE); 3540 #endif 3541 if (is_thulium_v1) { 3542 portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex); 3543 } else { 3544 portFmt->eColorFormat = useNonSurfaceMode ? 3545 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) : 3546 getPreferredColorFormatDefaultMode(portFmt->nIndex); 3547 } 3548 3549 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) { 3550 eRet = OMX_ErrorNoMore; 3551 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3552 " NoMore Color formats"); 3553 } 3554 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat); 3555 } else { 3556 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d", 3557 (int)portFmt->nPortIndex); 3558 eRet = OMX_ErrorBadPortIndex; 3559 } 3560 break; 3561 } 3562 /*Component should support this port definition*/ 3563 case OMX_IndexParamAudioInit: { 3564 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3565 OMX_PORT_PARAM_TYPE *audioPortParamType = 3566 (OMX_PORT_PARAM_TYPE *) paramData; 3567 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); 3568 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3569 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3570 audioPortParamType->nPorts = 0; 3571 audioPortParamType->nStartPortNumber = 0; 3572 break; 3573 } 3574 /*Component should support this port definition*/ 3575 case OMX_IndexParamImageInit: { 3576 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); 3577 OMX_PORT_PARAM_TYPE *imagePortParamType = 3578 (OMX_PORT_PARAM_TYPE *) paramData; 3579 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); 3580 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3581 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); 3582 imagePortParamType->nPorts = 0; 3583 imagePortParamType->nStartPortNumber = 0; 3584 break; 3585 3586 } 3587 /*Component should support this port definition*/ 3588 case OMX_IndexParamOtherInit: { 3589 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x", 3590 paramIndex); 3591 eRet =OMX_ErrorUnsupportedIndex; 3592 break; 3593 } 3594 case OMX_IndexParamStandardComponentRole: { 3595 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); 3596 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3597 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3598 comp_role->nVersion.nVersion = OMX_SPEC_VERSION; 3599 comp_role->nSize = sizeof(*comp_role); 3600 3601 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d", 3602 paramIndex); 3603 strlcpy((char*)comp_role->cRole,(const char*)m_cRole, 3604 OMX_MAX_STRINGNAME_SIZE); 3605 break; 3606 } 3607 /* Added for parameter test */ 3608 case OMX_IndexParamPriorityMgmt: { 3609 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); 3610 OMX_PRIORITYMGMTTYPE *priorityMgmType = 3611 (OMX_PRIORITYMGMTTYPE *) paramData; 3612 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); 3613 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; 3614 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE); 3615 3616 break; 3617 } 3618 /* Added for parameter test */ 3619 case OMX_IndexParamCompBufferSupplier: { 3620 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); 3621 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = 3622 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3623 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); 3624 3625 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE); 3626 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; 3627 if (0 == bufferSupplierType->nPortIndex) 3628 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3629 else if (1 == bufferSupplierType->nPortIndex) 3630 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3631 else 3632 eRet = OMX_ErrorBadPortIndex; 3633 3634 3635 break; 3636 } 3637 case OMX_IndexParamVideoAvc: { 3638 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x", 3639 paramIndex); 3640 break; 3641 } 3642 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 3643 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x", 3644 paramIndex); 3645 break; 3646 } 3647 case OMX_IndexParamVideoH263: { 3648 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x", 3649 paramIndex); 3650 break; 3651 } 3652 case OMX_IndexParamVideoMpeg4: { 3653 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x", 3654 paramIndex); 3655 break; 3656 } 3657 case OMX_IndexParamVideoMpeg2: { 3658 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x", 3659 paramIndex); 3660 break; 3661 } 3662 case OMX_IndexParamVideoProfileLevelQuerySupported: { 3663 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 3664 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex); 3665 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = 3666 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; 3667 eRet = get_supported_profile_level(profileLevelType); 3668 break; 3669 } 3670 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3671 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: { 3672 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams); 3673 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); 3674 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; 3675 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3676 3677 if (secure_mode && !secure_scaling_to_non_secure_opb) { 3678 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | 3679 GRALLOC_USAGE_PRIVATE_UNCACHED); 3680 } else { 3681 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED; 3682 } 3683 } else { 3684 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!"); 3685 eRet = OMX_ErrorBadParameter; 3686 } 3687 } 3688 break; 3689 #endif 3690 3691 #ifdef FLEXYUV_SUPPORTED 3692 case OMX_QcomIndexFlexibleYUVDescription: { 3693 DEBUG_PRINT_LOW("get_parameter: describeColorFormat"); 3694 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams); 3695 eRet = describeColorFormat(paramData); 3696 break; 3697 } 3698 #endif 3699 case OMX_IndexParamVideoProfileLevelCurrent: { 3700 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 3701 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; 3702 struct v4l2_control profile_control, level_control; 3703 3704 switch (drv_ctx.decoder_format) { 3705 case VDEC_CODECTYPE_H264: 3706 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; 3707 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; 3708 break; 3709 default: 3710 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264"); 3711 eRet = OMX_ErrorNotImplemented; 3712 break; 3713 } 3714 3715 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) { 3716 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) { 3717 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: 3718 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: 3719 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline; 3720 break; 3721 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: 3722 pParam->eProfile = OMX_VIDEO_AVCProfileMain; 3723 break; 3724 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: 3725 pParam->eProfile = OMX_VIDEO_AVCProfileExtended; 3726 break; 3727 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: 3728 pParam->eProfile = OMX_VIDEO_AVCProfileHigh; 3729 break; 3730 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10: 3731 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10; 3732 break; 3733 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422: 3734 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422; 3735 break; 3736 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: 3737 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA: 3738 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA: 3739 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA: 3740 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA: 3741 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE: 3742 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH: 3743 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA: 3744 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH: 3745 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH: 3746 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH: 3747 eRet = OMX_ErrorUnsupportedIndex; 3748 break; 3749 } 3750 } else { 3751 eRet = OMX_ErrorUnsupportedIndex; 3752 } 3753 3754 3755 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) { 3756 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) { 3757 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: 3758 pParam->eLevel = OMX_VIDEO_AVCLevel1; 3759 break; 3760 case V4L2_MPEG_VIDEO_H264_LEVEL_1B: 3761 pParam->eLevel = OMX_VIDEO_AVCLevel1b; 3762 break; 3763 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: 3764 pParam->eLevel = OMX_VIDEO_AVCLevel11; 3765 break; 3766 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: 3767 pParam->eLevel = OMX_VIDEO_AVCLevel12; 3768 break; 3769 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: 3770 pParam->eLevel = OMX_VIDEO_AVCLevel13; 3771 break; 3772 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: 3773 pParam->eLevel = OMX_VIDEO_AVCLevel2; 3774 break; 3775 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: 3776 pParam->eLevel = OMX_VIDEO_AVCLevel21; 3777 break; 3778 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: 3779 pParam->eLevel = OMX_VIDEO_AVCLevel22; 3780 break; 3781 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: 3782 pParam->eLevel = OMX_VIDEO_AVCLevel3; 3783 break; 3784 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: 3785 pParam->eLevel = OMX_VIDEO_AVCLevel31; 3786 break; 3787 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: 3788 pParam->eLevel = OMX_VIDEO_AVCLevel32; 3789 break; 3790 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: 3791 pParam->eLevel = OMX_VIDEO_AVCLevel4; 3792 break; 3793 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: 3794 pParam->eLevel = OMX_VIDEO_AVCLevel41; 3795 break; 3796 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: 3797 pParam->eLevel = OMX_VIDEO_AVCLevel42; 3798 break; 3799 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: 3800 pParam->eLevel = OMX_VIDEO_AVCLevel5; 3801 break; 3802 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: 3803 pParam->eLevel = OMX_VIDEO_AVCLevel51; 3804 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2: 3805 pParam->eLevel = OMX_VIDEO_AVCLevel52; 3806 break; 3807 } 3808 } else { 3809 eRet = OMX_ErrorUnsupportedIndex; 3810 } 3811 3812 break; 3813 3814 } 3815 default: { 3816 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex); 3817 eRet =OMX_ErrorUnsupportedIndex; 3818 } 3819 3820 } 3821 3822 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)", 3823 drv_ctx.video_resolution.frame_width, 3824 drv_ctx.video_resolution.frame_height, 3825 drv_ctx.video_resolution.stride, 3826 drv_ctx.video_resolution.scan_lines); 3827 3828 return eRet; 3829 } 3830 3831 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3832 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) 3833 { 3834 DEBUG_PRINT_LOW("Inside use_android_native_buffer"); 3835 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3836 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; 3837 3838 if ((params == NULL) || 3839 (params->nativeBuffer == NULL) || 3840 (params->nativeBuffer->handle == NULL) || 3841 !m_enable_android_native_buffers) 3842 return OMX_ErrorBadParameter; 3843 m_use_android_native_buffers = OMX_TRUE; 3844 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 3845 private_handle_t *handle = (private_handle_t *)nBuf->handle; 3846 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port 3847 OMX_U8 *buffer = NULL; 3848 if (!secure_mode) { 3849 buffer = (OMX_U8*)mmap(0, handle->size, 3850 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 3851 if (buffer == MAP_FAILED) { 3852 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 3853 return OMX_ErrorInsufficientResources; 3854 } 3855 } 3856 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); 3857 } else { 3858 eRet = OMX_ErrorBadParameter; 3859 } 3860 return eRet; 3861 } 3862 #endif 3863 3864 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() { 3865 struct v4l2_control control; 3866 struct v4l2_format fmt; 3867 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER; 3868 control.value = 1; 3869 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 3870 if (rc < 0) { 3871 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); 3872 return OMX_ErrorHardware; 3873 } 3874 m_smoothstreaming_mode = true; 3875 return OMX_ErrorNone; 3876 } 3877 3878 /* ====================================================================== 3879 FUNCTION 3880 omx_vdec::Setparameter 3881 3882 DESCRIPTION 3883 OMX Set Parameter method implementation. 3884 3885 PARAMETERS 3886 <TBD>. 3887 3888 RETURN VALUE 3889 OMX Error None if successful. 3890 3891 ========================================================================== */ 3892 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, 3893 OMX_IN OMX_INDEXTYPE paramIndex, 3894 OMX_IN OMX_PTR paramData) 3895 { 3896 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3897 int ret=0; 3898 struct v4l2_format fmt; 3899 #ifdef _ANDROID_ 3900 char property_value[PROPERTY_VALUE_MAX] = {0}; 3901 #endif 3902 if (m_state == OMX_StateInvalid) { 3903 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3904 return OMX_ErrorInvalidState; 3905 } 3906 if (paramData == NULL) { 3907 DEBUG_PRINT_ERROR("Get Param in Invalid paramData"); 3908 return OMX_ErrorBadParameter; 3909 } 3910 if ((m_state != OMX_StateLoaded) && 3911 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && 3912 (m_out_bEnabled == OMX_TRUE) && 3913 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && 3914 (m_inp_bEnabled == OMX_TRUE)) { 3915 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3916 return OMX_ErrorIncorrectStateOperation; 3917 } 3918 switch ((unsigned long)paramIndex) { 3919 case OMX_IndexParamPortDefinition: { 3920 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); 3921 OMX_PARAM_PORTDEFINITIONTYPE *portDefn; 3922 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3923 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has 3924 //been called. 3925 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", 3926 (int)portDefn->format.video.nFrameHeight, 3927 (int)portDefn->format.video.nFrameWidth); 3928 3929 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 3930 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d", 3931 portDefn->nBufferCountActual); 3932 eRet = OMX_ErrorBadParameter; 3933 break; 3934 } 3935 if (OMX_DirOutput == portDefn->eDir) { 3936 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); 3937 bool port_format_changed = false; 3938 m_display_id = portDefn->format.video.pNativeWindow; 3939 unsigned int buffer_size; 3940 /* update output port resolution with client supplied dimensions 3941 in case scaling is enabled, else it follows input resolution set 3942 */ 3943 decide_dpb_buffer_mode(is_down_scalar_enabled); 3944 if (is_down_scalar_enabled) { 3945 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)", 3946 (unsigned int)portDefn->format.video.nFrameWidth, 3947 (unsigned int)portDefn->format.video.nFrameHeight); 3948 if (portDefn->format.video.nFrameHeight != 0x0 && 3949 portDefn->format.video.nFrameWidth != 0x0) { 3950 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3951 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3952 fmt.fmt.pix_mp.pixelformat = capture_capability; 3953 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 3954 if (ret) { 3955 DEBUG_PRINT_ERROR("Get Resolution failed"); 3956 eRet = OMX_ErrorHardware; 3957 break; 3958 } 3959 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) || 3960 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) { 3961 port_format_changed = true; 3962 } 3963 update_resolution(portDefn->format.video.nFrameWidth, 3964 portDefn->format.video.nFrameHeight, 3965 portDefn->format.video.nFrameWidth, 3966 portDefn->format.video.nFrameHeight); 3967 3968 /* set crop info */ 3969 rectangle.nLeft = 0; 3970 rectangle.nTop = 0; 3971 rectangle.nWidth = portDefn->format.video.nFrameWidth; 3972 rectangle.nHeight = portDefn->format.video.nFrameHeight; 3973 3974 eRet = is_video_session_supported(); 3975 if (eRet) 3976 break; 3977 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3978 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3979 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3980 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3981 fmt.fmt.pix_mp.pixelformat = capture_capability; 3982 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", 3983 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width); 3984 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3985 if (ret) { 3986 DEBUG_PRINT_ERROR("Set Resolution failed"); 3987 eRet = OMX_ErrorUnsupportedSetting; 3988 } else 3989 eRet = get_buffer_req(&drv_ctx.op_buf); 3990 } 3991 3992 if (eRet) { 3993 break; 3994 } 3995 3996 if (secure_mode) { 3997 struct v4l2_control control; 3998 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD; 3999 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 4000 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id); 4001 eRet = OMX_ErrorHardware; 4002 } else { 4003 /* This is a workaround for a bug in fw which uses stride 4004 * and slice instead of width and height to check against 4005 * the threshold. 4006 */ 4007 OMX_U32 stride, slice; 4008 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 4009 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth); 4010 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight); 4011 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 4012 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth); 4013 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight); 4014 } else { 4015 stride = portDefn->format.video.nFrameWidth; 4016 slice = portDefn->format.video.nFrameHeight; 4017 } 4018 4019 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice); 4020 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value); 4021 4022 if (stride * slice <= (OMX_U32)control.value) { 4023 secure_scaling_to_non_secure_opb = true; 4024 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ"); 4025 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2; 4026 control.value = 1; 4027 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) { 4028 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed"); 4029 eRet = OMX_ErrorUnsupportedSetting; 4030 } 4031 } 4032 } 4033 } 4034 } 4035 4036 if (eRet) { 4037 break; 4038 } 4039 4040 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 4041 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)", 4042 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); 4043 eRet = OMX_ErrorBadParameter; 4044 } else if (!client_buffers.get_buffer_req(buffer_size)) { 4045 DEBUG_PRINT_ERROR("Error in getting buffer requirements"); 4046 eRet = OMX_ErrorBadParameter; 4047 } else if (!port_format_changed) { 4048 4049 // Buffer count can change only when port is unallocated 4050 if (m_out_mem_ptr && 4051 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount || 4052 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) { 4053 4054 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !"); 4055 eRet = OMX_ErrorInvalidState; 4056 break; 4057 } 4058 4059 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && 4060 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) { 4061 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; 4062 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize; 4063 drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount; 4064 drv_ctx.extradata_info.size = drv_ctx.extradata_info.count * 4065 drv_ctx.extradata_info.buffer_size; 4066 eRet = set_buffer_req(&drv_ctx.op_buf); 4067 if (eRet == OMX_ErrorNone) 4068 m_port_def = *portDefn; 4069 } else { 4070 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)", 4071 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size, 4072 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 4073 eRet = OMX_ErrorBadParameter; 4074 } 4075 } 4076 } else if (OMX_DirInput == portDefn->eDir) { 4077 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port"); 4078 bool port_format_changed = false; 4079 if ((portDefn->format.video.xFramerate >> 16) > 0 && 4080 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) { 4081 // Frame rate only should be set if this is a "known value" or to 4082 // activate ts prediction logic (arbitrary mode only) sending input 4083 // timestamps with max value (LLONG_MAX). 4084 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u", 4085 (unsigned int)portDefn->format.video.xFramerate >> 16); 4086 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, 4087 drv_ctx.frame_rate.fps_denominator); 4088 if (!drv_ctx.frame_rate.fps_numerator) { 4089 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 4090 drv_ctx.frame_rate.fps_numerator = 30; 4091 } 4092 if (drv_ctx.frame_rate.fps_denominator) 4093 drv_ctx.frame_rate.fps_numerator = (int) 4094 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 4095 drv_ctx.frame_rate.fps_denominator = 1; 4096 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 4097 drv_ctx.frame_rate.fps_numerator; 4098 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", 4099 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 4100 (float)drv_ctx.frame_rate.fps_denominator); 4101 4102 struct v4l2_outputparm oparm; 4103 /*XXX: we're providing timing info as seconds per frame rather than frames 4104 * per second.*/ 4105 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 4106 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 4107 4108 struct v4l2_streamparm sparm; 4109 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4110 sparm.parm.output = oparm; 4111 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 4112 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected"); 4113 eRet = OMX_ErrorHardware; 4114 break; 4115 } 4116 m_perf_control.request_cores(frm_int); 4117 } 4118 4119 if (drv_ctx.video_resolution.frame_height != 4120 portDefn->format.video.nFrameHeight || 4121 drv_ctx.video_resolution.frame_width != 4122 portDefn->format.video.nFrameWidth) { 4123 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)", 4124 (unsigned int)portDefn->format.video.nFrameWidth, 4125 (unsigned int)portDefn->format.video.nFrameHeight); 4126 port_format_changed = true; 4127 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth; 4128 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight; 4129 if (frameHeight != 0x0 && frameWidth != 0x0) { 4130 if (m_smoothstreaming_mode && 4131 ((frameWidth * frameHeight) < 4132 (m_smoothstreaming_width * m_smoothstreaming_height))) { 4133 frameWidth = m_smoothstreaming_width; 4134 frameHeight = m_smoothstreaming_height; 4135 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u " 4136 "for adaptive-playback/smooth-streaming", 4137 (unsigned int)frameWidth, (unsigned int)frameHeight); 4138 } 4139 update_resolution(frameWidth, frameHeight, 4140 frameWidth, frameHeight); 4141 eRet = is_video_session_supported(); 4142 if (eRet) 4143 break; 4144 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4145 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4146 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 4147 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 4148 fmt.fmt.pix_mp.pixelformat = output_capability; 4149 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); 4150 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4151 if (ret) { 4152 DEBUG_PRINT_ERROR("Set Resolution failed"); 4153 eRet = OMX_ErrorUnsupportedSetting; 4154 } else { 4155 if (!is_down_scalar_enabled) 4156 eRet = get_buffer_req(&drv_ctx.op_buf); 4157 } 4158 } 4159 } 4160 if (m_custom_buffersize.input_buffersize 4161 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) { 4162 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d", 4163 m_custom_buffersize.input_buffersize, portDefn->nBufferSize); 4164 eRet = OMX_ErrorBadParameter; 4165 break; 4166 } 4167 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { 4168 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)", 4169 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); 4170 eRet = OMX_ErrorBadParameter; 4171 break; 4172 } 4173 // Buffer count can change only when port is unallocated 4174 if (m_inp_mem_ptr && 4175 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount || 4176 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) { 4177 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !"); 4178 eRet = OMX_ErrorInvalidState; 4179 break; 4180 } 4181 4182 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount 4183 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) { 4184 port_format_changed = true; 4185 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf; 4186 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; 4187 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) & 4188 (~(buffer_prop->alignment - 1)); 4189 eRet = set_buffer_req(buffer_prop); 4190 } 4191 if (false == port_format_changed) { 4192 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)", 4193 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size, 4194 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 4195 eRet = OMX_ErrorBadParameter; 4196 } 4197 } else if (portDefn->eDir == OMX_DirMax) { 4198 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", 4199 (int)portDefn->nPortIndex); 4200 eRet = OMX_ErrorBadPortIndex; 4201 } 4202 } 4203 break; 4204 case OMX_IndexParamVideoPortFormat: { 4205 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); 4206 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 4207 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 4208 int ret=0; 4209 struct v4l2_format fmt; 4210 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u", 4211 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex); 4212 4213 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 4214 if (1 == portFmt->nPortIndex) { 4215 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4216 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 4217 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 4218 enum vdec_output_fromat op_format; 4219 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4220 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m || 4221 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4222 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView || 4223 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar || 4224 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 4225 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12; 4226 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4227 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 4228 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC; 4229 } else 4230 eRet = OMX_ErrorBadParameter; 4231 4232 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 4233 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 4234 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC; 4235 } else { 4236 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12; 4237 } 4238 4239 if (eRet == OMX_ErrorNone) { 4240 drv_ctx.output_format = op_format; 4241 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 4242 if (ret) { 4243 DEBUG_PRINT_ERROR("Set output format failed"); 4244 eRet = OMX_ErrorUnsupportedSetting; 4245 /*TODO: How to handle this case */ 4246 } else { 4247 eRet = get_buffer_req(&drv_ctx.op_buf); 4248 } 4249 } 4250 if (eRet == OMX_ErrorNone) { 4251 if (!client_buffers.set_color_format(portFmt->eColorFormat)) { 4252 DEBUG_PRINT_ERROR("Set color format failed"); 4253 eRet = OMX_ErrorBadParameter; 4254 } 4255 } 4256 } 4257 } 4258 break; 4259 4260 case OMX_QcomIndexPortDefn: { 4261 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE); 4262 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = 4263 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; 4264 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u", 4265 (unsigned int)portFmt->nFramePackingFormat); 4266 4267 /* Input port */ 4268 if (portFmt->nPortIndex == 0) { 4269 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how: 4270 // - headers are allocated and 4271 // - headers-indices are derived 4272 // Avoid changing arbitrary_bytes when the port is already allocated 4273 if (m_inp_mem_ptr) { 4274 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!"); 4275 return OMX_ErrorUnsupportedSetting; 4276 } 4277 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) { 4278 if (secure_mode || m_input_pass_buffer_fd) { 4279 arbitrary_bytes = false; 4280 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode"); 4281 eRet = OMX_ErrorUnsupportedSetting; 4282 } else { 4283 arbitrary_bytes = true; 4284 } 4285 } else if (portFmt->nFramePackingFormat == 4286 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) { 4287 arbitrary_bytes = false; 4288 #ifdef _ANDROID_ 4289 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); 4290 if (atoi(property_value)) { 4291 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command"); 4292 arbitrary_bytes = true; 4293 } 4294 #endif 4295 } else { 4296 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u", 4297 (unsigned int)portFmt->nFramePackingFormat); 4298 eRet = OMX_ErrorUnsupportedSetting; 4299 } 4300 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 4301 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port"); 4302 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && 4303 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && 4304 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) { 4305 m_out_mem_region_smi = OMX_TRUE; 4306 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 4307 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set"); 4308 m_use_output_pmem = OMX_TRUE; 4309 } 4310 } 4311 } 4312 } 4313 if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", 4314 OMX_MAX_STRINGNAME_SIZE)) { 4315 arbitrary_bytes = true; 4316 DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264"); 4317 } 4318 break; 4319 4320 case OMX_IndexParamStandardComponentRole: { 4321 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); 4322 OMX_PARAM_COMPONENTROLETYPE *comp_role; 4323 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 4324 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", 4325 comp_role->cRole); 4326 4327 if ((m_state == OMX_StateLoaded)&& 4328 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) { 4329 DEBUG_PRINT_LOW("Set Parameter called in valid state"); 4330 } else { 4331 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 4332 return OMX_ErrorIncorrectStateOperation; 4333 } 4334 4335 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) { 4336 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) { 4337 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE); 4338 } else { 4339 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4340 eRet =OMX_ErrorUnsupportedSetting; 4341 } 4342 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 4343 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 4344 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 4345 } else { 4346 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4347 eRet = OMX_ErrorUnsupportedSetting; 4348 } 4349 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 4350 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) { 4351 strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE); 4352 } else { 4353 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4354 eRet = OMX_ErrorUnsupportedSetting; 4355 } 4356 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 4357 if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) { 4358 strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE); 4359 } else { 4360 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4361 eRet =OMX_ErrorUnsupportedSetting; 4362 } 4363 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 4364 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) { 4365 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE); 4366 } else { 4367 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4368 eRet = OMX_ErrorUnsupportedSetting; 4369 } 4370 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) || 4371 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) || 4372 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE)) 4373 ) { 4374 if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) { 4375 strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE); 4376 } else { 4377 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4378 eRet =OMX_ErrorUnsupportedSetting; 4379 } 4380 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) || 4381 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) 4382 ) { 4383 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) { 4384 strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE); 4385 } else { 4386 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4387 eRet =OMX_ErrorUnsupportedSetting; 4388 } 4389 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) { 4390 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) || 4391 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) { 4392 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE); 4393 } else { 4394 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4395 eRet = OMX_ErrorUnsupportedSetting; 4396 } 4397 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) { 4398 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) || 4399 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) { 4400 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE); 4401 } else { 4402 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4403 eRet = OMX_ErrorUnsupportedSetting; 4404 } 4405 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 4406 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 4407 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 4408 } else { 4409 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 4410 eRet = OMX_ErrorUnsupportedSetting; 4411 } 4412 } else { 4413 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind); 4414 eRet = OMX_ErrorInvalidComponentName; 4415 } 4416 break; 4417 } 4418 4419 case OMX_IndexParamPriorityMgmt: { 4420 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); 4421 if (m_state != OMX_StateLoaded) { 4422 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 4423 return OMX_ErrorIncorrectStateOperation; 4424 } 4425 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; 4426 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u", 4427 (unsigned int)priorityMgmtype->nGroupID); 4428 4429 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u", 4430 (unsigned int)priorityMgmtype->nGroupPriority); 4431 4432 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; 4433 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; 4434 4435 break; 4436 } 4437 4438 case OMX_IndexParamCompBufferSupplier: { 4439 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); 4440 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 4441 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", 4442 bufferSupplierType->eBufferSupplier); 4443 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) 4444 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; 4445 4446 else 4447 4448 eRet = OMX_ErrorBadPortIndex; 4449 4450 break; 4451 4452 } 4453 case OMX_IndexParamVideoAvc: { 4454 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d", 4455 paramIndex); 4456 break; 4457 } 4458 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 4459 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d", 4460 paramIndex); 4461 break; 4462 } 4463 case OMX_IndexParamVideoH263: { 4464 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d", 4465 paramIndex); 4466 break; 4467 } 4468 case OMX_IndexParamVideoMpeg4: { 4469 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d", 4470 paramIndex); 4471 break; 4472 } 4473 case OMX_IndexParamVideoMpeg2: { 4474 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d", 4475 paramIndex); 4476 break; 4477 } 4478 case OMX_QcomIndexParamVideoDecoderPictureOrder: { 4479 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER); 4480 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = 4481 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; 4482 struct v4l2_control control; 4483 int pic_order,rc=0; 4484 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d", 4485 pictureOrder->eOutputPictureOrder); 4486 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) { 4487 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 4488 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) { 4489 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 4490 time_stamp_dts.set_timestamp_reorder_mode(false); 4491 } else 4492 eRet = OMX_ErrorBadParameter; 4493 if (eRet == OMX_ErrorNone) { 4494 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 4495 control.value = pic_order; 4496 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4497 if (rc) { 4498 DEBUG_PRINT_ERROR("Set picture order failed"); 4499 eRet = OMX_ErrorUnsupportedSetting; 4500 } 4501 } 4502 m_decode_order_mode = 4503 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER; 4504 break; 4505 } 4506 case OMX_QcomIndexParamConcealMBMapExtraData: 4507 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4508 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false, 4509 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4510 break; 4511 case OMX_QcomIndexParamFrameInfoExtraData: 4512 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4513 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, 4514 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4515 break; 4516 case OMX_ExtraDataFrameDimension: 4517 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4518 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false, 4519 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4520 break; 4521 case OMX_QcomIndexParamInterlaceExtraData: 4522 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4523 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false, 4524 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4525 break; 4526 case OMX_QcomIndexParamH264TimeInfo: 4527 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4528 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false, 4529 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4530 break; 4531 case OMX_QcomIndexParamVideoFramePackingExtradata: 4532 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4533 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false, 4534 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4535 break; 4536 case OMX_QcomIndexParamVideoQPExtraData: 4537 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4538 eRet = enable_extradata(OMX_QP_EXTRADATA, false, 4539 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4540 break; 4541 case OMX_QcomIndexParamVideoInputBitsInfoExtraData: 4542 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4543 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false, 4544 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4545 break; 4546 case OMX_QcomIndexEnableExtnUserData: 4547 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4548 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false, 4549 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4550 break; 4551 case OMX_QTIIndexParamVQZipSEIExtraData: 4552 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4553 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false, 4554 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4555 break; 4556 case OMX_QcomIndexParamVideoDivx: { 4557 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; 4558 } 4559 break; 4560 case OMX_QcomIndexPlatformPvt: { 4561 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN); 4562 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); 4563 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; 4564 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 4565 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); 4566 eRet = OMX_ErrorUnsupportedSetting; 4567 } else { 4568 m_out_pvt_entry_pmem = OMX_TRUE; 4569 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 4570 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set"); 4571 m_use_output_pmem = OMX_TRUE; 4572 } 4573 } 4574 4575 } 4576 break; 4577 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: { 4578 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); 4579 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); 4580 struct v4l2_control control; 4581 int rc; 4582 drv_ctx.idr_only_decoding = 1; 4583 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 4584 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 4585 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4586 if (rc) { 4587 DEBUG_PRINT_ERROR("Set picture order failed"); 4588 eRet = OMX_ErrorUnsupportedSetting; 4589 } else { 4590 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE; 4591 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE; 4592 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4593 if (rc) { 4594 DEBUG_PRINT_ERROR("Sync frame setting failed"); 4595 eRet = OMX_ErrorUnsupportedSetting; 4596 } 4597 /*Setting sync frame decoding on driver might change buffer 4598 * requirements so update them here*/ 4599 if (get_buffer_req(&drv_ctx.ip_buf)) { 4600 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements"); 4601 eRet = OMX_ErrorUnsupportedSetting; 4602 } 4603 if (get_buffer_req(&drv_ctx.op_buf)) { 4604 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements"); 4605 eRet = OMX_ErrorUnsupportedSetting; 4606 } 4607 } 4608 } 4609 break; 4610 4611 case OMX_QcomIndexParamIndexExtraDataType: { 4612 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); 4613 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; 4614 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && 4615 (extradataIndexType->bEnabled == OMX_TRUE) && 4616 (extradataIndexType->nPortIndex == 1)) { 4617 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming"); 4618 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled); 4619 4620 } 4621 } 4622 break; 4623 case OMX_QcomIndexParamEnableSmoothStreaming: { 4624 #ifndef SMOOTH_STREAMING_DISABLED 4625 eRet = enable_smoothstreaming(); 4626 #else 4627 eRet = OMX_ErrorUnsupportedSetting; 4628 #endif 4629 } 4630 break; 4631 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 4632 /* Need to allow following two set_parameters even in Idle 4633 * state. This is ANDROID architecture which is not in sync 4634 * with openmax standard. */ 4635 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: { 4636 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams); 4637 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; 4638 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { 4639 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!"); 4640 eRet = OMX_ErrorUnsupportedSetting; 4641 break; 4642 } else if (m_out_mem_ptr) { 4643 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !"); 4644 eRet = OMX_ErrorInvalidState; 4645 break; 4646 } 4647 if (enableNativeBuffers) { 4648 m_enable_android_native_buffers = enableNativeBuffers->enable; 4649 } 4650 #if !defined(FLEXYUV_SUPPORTED) 4651 if (m_enable_android_native_buffers) { 4652 // Use the most-preferred-native-color-format as surface-mode is hinted here 4653 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) { 4654 DEBUG_PRINT_ERROR("Failed to set native color format!"); 4655 eRet = OMX_ErrorUnsupportedSetting; 4656 } 4657 } 4658 #endif 4659 } 4660 break; 4661 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: { 4662 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams); 4663 eRet = use_android_native_buffer(hComp, paramData); 4664 } 4665 break; 4666 case OMX_GoogleAndroidIndexAllocateNativeHandle: { 4667 4668 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData; 4669 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams); 4670 4671 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) { 4672 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!"); 4673 eRet = OMX_ErrorUnsupportedSetting; 4674 break; 4675 } else if (m_inp_mem_ptr) { 4676 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !"); 4677 eRet = OMX_ErrorInvalidState; 4678 break; 4679 } 4680 4681 if (allocateNativeHandleParams != NULL) { 4682 allocate_native_handle = allocateNativeHandleParams->enable; 4683 } 4684 } 4685 break; 4686 #endif 4687 case OMX_QcomIndexParamEnableTimeStampReorder: { 4688 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER); 4689 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; 4690 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) { 4691 if (reorder->bEnable == OMX_TRUE) { 4692 frm_int =0; 4693 time_stamp_dts.set_timestamp_reorder_mode(true); 4694 } else 4695 time_stamp_dts.set_timestamp_reorder_mode(false); 4696 } else { 4697 time_stamp_dts.set_timestamp_reorder_mode(false); 4698 if (reorder->bEnable == OMX_TRUE) { 4699 eRet = OMX_ErrorUnsupportedSetting; 4700 } 4701 } 4702 } 4703 break; 4704 case OMX_IndexParamVideoProfileLevelCurrent: { 4705 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); 4706 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = 4707 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; 4708 if (pParam) { 4709 m_profile_lvl.eProfile = pParam->eProfile; 4710 m_profile_lvl.eLevel = pParam->eLevel; 4711 } 4712 break; 4713 4714 } 4715 case OMX_QcomIndexParamVideoMetaBufferMode: 4716 { 4717 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams); 4718 StoreMetaDataInBuffersParams *metabuffer = 4719 (StoreMetaDataInBuffersParams *)paramData; 4720 if (!metabuffer) { 4721 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer); 4722 eRet = OMX_ErrorBadParameter; 4723 break; 4724 } 4725 if (m_disable_dynamic_buf_mode) { 4726 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled"); 4727 eRet = OMX_ErrorUnsupportedSetting; 4728 break; 4729 } 4730 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 4731 4732 if (m_out_mem_ptr) { 4733 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !"); 4734 eRet = OMX_ErrorInvalidState; 4735 break; 4736 } 4737 //set property dynamic buffer mode to driver. 4738 struct v4l2_control control; 4739 struct v4l2_format fmt; 4740 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT; 4741 if (metabuffer->bStoreMetaData == true) { 4742 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC; 4743 } else { 4744 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC; 4745 } 4746 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 4747 if (!rc) { 4748 DEBUG_PRINT_HIGH("%s buffer mode", 4749 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic"); 4750 } else { 4751 DEBUG_PRINT_ERROR("Failed to %s buffer mode", 4752 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic"); 4753 } 4754 dynamic_buf_mode = metabuffer->bStoreMetaData; 4755 } else { 4756 DEBUG_PRINT_ERROR( 4757 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u", 4758 (unsigned int)metabuffer->nPortIndex); 4759 eRet = OMX_ErrorUnsupportedSetting; 4760 } 4761 break; 4762 } 4763 case OMX_QcomIndexParamVideoDownScalar: 4764 { 4765 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR); 4766 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData; 4767 struct v4l2_control control; 4768 int rc; 4769 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable); 4770 4771 if (pParam && pParam->bEnable) { 4772 rc = enable_downscalar(); 4773 if (rc < 0) { 4774 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__); 4775 return OMX_ErrorUnsupportedSetting; 4776 } 4777 m_force_down_scalar = pParam->bEnable; 4778 } else { 4779 rc = disable_downscalar(); 4780 if (rc < 0) { 4781 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__); 4782 return OMX_ErrorUnsupportedSetting; 4783 } 4784 m_force_down_scalar = pParam->bEnable; 4785 } 4786 break; 4787 } 4788 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 4789 case OMX_QcomIndexParamVideoAdaptivePlaybackMode: 4790 { 4791 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams); 4792 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback"); 4793 PrepareForAdaptivePlaybackParams* pParams = 4794 (PrepareForAdaptivePlaybackParams *) paramData; 4795 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 4796 if (!pParams->bEnable) { 4797 return OMX_ErrorNone; 4798 } 4799 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth 4800 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) { 4801 DEBUG_PRINT_ERROR( 4802 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]", 4803 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight, 4804 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight); 4805 eRet = OMX_ErrorBadParameter; 4806 } else { 4807 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight); 4808 } 4809 } else { 4810 DEBUG_PRINT_ERROR( 4811 "Prepare for adaptive playback supported only on output port"); 4812 eRet = OMX_ErrorBadParameter; 4813 } 4814 break; 4815 } 4816 4817 case OMX_QTIIndexParamVideoPreferAdaptivePlayback: 4818 { 4819 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4820 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback"); 4821 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable; 4822 if (m_disable_dynamic_buf_mode) { 4823 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set"); 4824 } 4825 break; 4826 } 4827 #endif 4828 case OMX_QcomIndexParamVideoCustomBufferSize: 4829 { 4830 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE); 4831 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize"); 4832 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData; 4833 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 4834 struct v4l2_control control; 4835 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT; 4836 control.value = pParam->nBufferSize; 4837 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 4838 DEBUG_PRINT_ERROR("Failed to set input buffer size"); 4839 eRet = OMX_ErrorUnsupportedSetting; 4840 } else { 4841 eRet = get_buffer_req(&drv_ctx.ip_buf); 4842 if (eRet == OMX_ErrorNone) { 4843 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size; 4844 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d", 4845 m_custom_buffersize.input_buffersize); 4846 } else { 4847 DEBUG_PRINT_ERROR("Failed to get buffer requirement"); 4848 } 4849 } 4850 } else { 4851 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port"); 4852 eRet = OMX_ErrorBadParameter; 4853 } 4854 break; 4855 } 4856 case OMX_QTIIndexParamVQZIPSEIType: 4857 { 4858 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE); 4859 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType"); 4860 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam = 4861 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData; 4862 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable); 4863 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false, 4864 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4865 if (eRet != OMX_ErrorNone) { 4866 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata"); 4867 eRet = OMX_ErrorBadParameter; 4868 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA; 4869 } else { 4870 eRet = enable_extradata(OMX_QP_EXTRADATA, false, 4871 ((QOMX_ENABLETYPE *)paramData)->bEnable); 4872 if (eRet != OMX_ErrorNone) { 4873 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata"); 4874 eRet = OMX_ErrorBadParameter; 4875 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA; 4876 client_extradata = client_extradata & ~OMX_QP_EXTRADATA; 4877 } 4878 } 4879 break; 4880 } 4881 4882 case OMX_QTIIndexParamPassInputBufferFd: 4883 { 4884 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); 4885 if (arbitrary_bytes) { 4886 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode"); 4887 eRet = OMX_ErrorUnsupportedSetting; 4888 break; 4889 } 4890 4891 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable; 4892 if (m_input_pass_buffer_fd) 4893 DEBUG_PRINT_LOW("Enable passing input buffer FD"); 4894 break; 4895 } 4896 case OMX_QTIIndexParamForceCompressedForDPB: 4897 { 4898 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE); 4899 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB"); 4900 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam = 4901 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData; 4902 if (m_disable_ubwc_mode) { 4903 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled"); 4904 eRet = OMX_ErrorUnsupportedSetting; 4905 break; 4906 } 4907 if (!paramData) { 4908 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL"); 4909 eRet = OMX_ErrorBadParameter; 4910 break; 4911 } 4912 4913 m_force_compressed_for_dpb = pParam->bEnable; 4914 break; 4915 } 4916 case OMX_QTIIndexParamForceUnCompressedForOPB: 4917 { 4918 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE); 4919 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB"); 4920 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam = 4921 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData; 4922 if (!paramData) { 4923 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL"); 4924 eRet = OMX_ErrorBadParameter; 4925 break; 4926 } 4927 m_disable_ubwc_mode = pParam->bEnable; 4928 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled"); 4929 break; 4930 } 4931 4932 4933 default: { 4934 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex); 4935 eRet = OMX_ErrorUnsupportedIndex; 4936 } 4937 } 4938 if (eRet != OMX_ErrorNone) 4939 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex); 4940 return eRet; 4941 } 4942 4943 /* ====================================================================== 4944 FUNCTION 4945 omx_vdec::GetConfig 4946 4947 DESCRIPTION 4948 OMX Get Config Method implementation. 4949 4950 PARAMETERS 4951 <TBD>. 4952 4953 RETURN VALUE 4954 OMX Error None if successful. 4955 4956 ========================================================================== */ 4957 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, 4958 OMX_IN OMX_INDEXTYPE configIndex, 4959 OMX_INOUT OMX_PTR configData) 4960 { 4961 (void) hComp; 4962 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4963 4964 if (m_state == OMX_StateInvalid) { 4965 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 4966 return OMX_ErrorInvalidState; 4967 } 4968 4969 switch ((unsigned long)configIndex) { 4970 case OMX_QcomIndexConfigInterlaced: { 4971 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE); 4972 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = 4973 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; 4974 if (configFmt->nPortIndex == 1) { 4975 if (configFmt->nIndex == 0) { 4976 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; 4977 } else if (configFmt->nIndex == 1) { 4978 configFmt->eInterlaceType = 4979 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 4980 } else if (configFmt->nIndex == 2) { 4981 configFmt->eInterlaceType = 4982 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 4983 } else { 4984 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" 4985 " NoMore Interlaced formats"); 4986 eRet = OMX_ErrorNoMore; 4987 } 4988 4989 } else { 4990 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port", 4991 (int)configFmt->nPortIndex); 4992 eRet = OMX_ErrorBadPortIndex; 4993 } 4994 break; 4995 } 4996 case OMX_QcomIndexQueryNumberOfVideoDecInstance: { 4997 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES); 4998 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = 4999 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; 5000 decoderinstances->nNumOfInstances = 16; 5001 /*TODO: How to handle this case */ 5002 break; 5003 } 5004 case OMX_QcomIndexConfigVideoFramePackingArrangement: { 5005 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) { 5006 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT); 5007 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = 5008 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; 5009 memcpy(configFmt, &m_frame_pack_arrangement, 5010 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 5011 } else { 5012 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); 5013 } 5014 break; 5015 } 5016 case OMX_IndexConfigCommonOutputCrop: { 5017 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE); 5018 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData; 5019 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE)); 5020 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u", 5021 rectangle.nLeft, rectangle.nTop, 5022 rectangle.nWidth, rectangle.nHeight); 5023 break; 5024 } 5025 case OMX_QcomIndexConfigPerfLevel: { 5026 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL); 5027 struct v4l2_control control; 5028 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 5029 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 5030 5031 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 5032 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 5033 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno); 5034 eRet = OMX_ErrorHardware; 5035 } 5036 5037 if (eRet == OMX_ErrorNone) { 5038 switch (control.value) { 5039 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: 5040 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo; 5041 break; 5042 default: 5043 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value); 5044 /* Fall through */ 5045 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: 5046 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal; 5047 break; 5048 } 5049 } 5050 5051 break; 5052 } 5053 case OMX_QcomIndexConfigH264EntropyCodingCabac: { 5054 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE); 5055 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData; 5056 struct v4l2_control control; 5057 5058 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) { 5059 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264"); 5060 eRet = OMX_ErrorNotImplemented; 5061 break; 5062 } 5063 5064 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; 5065 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) { 5066 coding->bCabac = (OMX_BOOL) 5067 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC); 5068 /* We can't query driver at the moment for the cabac mode, so 5069 * just use 0xff...f as a place holder for future improvement */ 5070 coding->nCabacInitIdc = ~0; 5071 } else { 5072 eRet = OMX_ErrorUnsupportedIndex; 5073 } 5074 5075 break; 5076 } 5077 case OMX_QTIIndexConfigDescribeColorAspects: 5078 { 5079 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); 5080 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; 5081 5082 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client"); 5083 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal"); 5084 5085 if (params->bRequestingDataSpace) { 5086 DEBUG_PRINT_ERROR("Does not handle dataspace request"); 5087 return OMX_ErrorUnsupportedSetting; 5088 } 5089 if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) { 5090 DEBUG_PRINT_LOW("Updating Client's color aspects with internal"); 5091 memcpy(&(m_client_color_space.sAspects), 5092 &(m_internal_color_space.sAspects), sizeof(ColorAspects)); 5093 m_internal_color_space.bDataSpaceChanged = OMX_FALSE; 5094 } 5095 memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects)); 5096 5097 break; 5098 } 5099 case OMX_IndexConfigAndroidVendorExtension: 5100 { 5101 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); 5102 5103 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext = 5104 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData); 5105 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext); 5106 return get_vendor_extension_config(ext); 5107 } 5108 default: 5109 { 5110 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); 5111 eRet = OMX_ErrorBadParameter; 5112 } 5113 5114 } 5115 5116 return eRet; 5117 } 5118 5119 /* ====================================================================== 5120 FUNCTION 5121 omx_vdec::SetConfig 5122 5123 DESCRIPTION 5124 OMX Set Config method implementation 5125 5126 PARAMETERS 5127 <TBD>. 5128 5129 RETURN VALUE 5130 OMX Error None if successful. 5131 ========================================================================== */ 5132 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, 5133 OMX_IN OMX_INDEXTYPE configIndex, 5134 OMX_IN OMX_PTR configData) 5135 { 5136 (void) hComp; 5137 if (m_state == OMX_StateInvalid) { 5138 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 5139 return OMX_ErrorInvalidState; 5140 } 5141 5142 OMX_ERRORTYPE ret = OMX_ErrorNone; 5143 OMX_VIDEO_CONFIG_NALSIZE *pNal; 5144 5145 DEBUG_PRINT_LOW("Set Config Called"); 5146 5147 if (configIndex == OMX_IndexConfigVideoNalSize) { 5148 struct v4l2_control temp; 5149 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT; 5150 5151 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE); 5152 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); 5153 switch (pNal->nNaluBytes) { 5154 case 0: 5155 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES; 5156 break; 5157 case 2: 5158 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH; 5159 break; 5160 case 4: 5161 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH; 5162 break; 5163 default: 5164 return OMX_ErrorUnsupportedSetting; 5165 } 5166 5167 if (!arbitrary_bytes) { 5168 /* In arbitrary bytes mode, the assembler strips out nal size and replaces 5169 * with start code, so only need to notify driver in frame by frame mode */ 5170 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) { 5171 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT"); 5172 return OMX_ErrorHardware; 5173 } 5174 } 5175 5176 nal_length = pNal->nNaluBytes; 5177 m_frame_parser.init_nal_length(nal_length); 5178 5179 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length); 5180 return ret; 5181 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) { 5182 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData; 5183 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps); 5184 5185 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 5186 if (config->bEnabled) { 5187 if ((config->nFps >> 16) > 0) { 5188 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u", 5189 (unsigned int)config->nFps >> 16); 5190 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator, 5191 drv_ctx.frame_rate.fps_denominator); 5192 5193 if (!drv_ctx.frame_rate.fps_numerator) { 5194 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 5195 drv_ctx.frame_rate.fps_numerator = 30; 5196 } 5197 5198 if (drv_ctx.frame_rate.fps_denominator) { 5199 drv_ctx.frame_rate.fps_numerator = (int) 5200 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 5201 } 5202 5203 drv_ctx.frame_rate.fps_denominator = 1; 5204 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 5205 drv_ctx.frame_rate.fps_numerator; 5206 5207 struct v4l2_outputparm oparm; 5208 /*XXX: we're providing timing info as seconds per frame rather than frames 5209 * per second.*/ 5210 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 5211 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 5212 5213 struct v4l2_streamparm sparm; 5214 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 5215 sparm.parm.output = oparm; 5216 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 5217 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 5218 performance might be affected"); 5219 ret = OMX_ErrorHardware; 5220 } 5221 client_set_fps = true; 5222 } else { 5223 DEBUG_PRINT_ERROR("Frame rate not supported."); 5224 ret = OMX_ErrorUnsupportedSetting; 5225 } 5226 } else { 5227 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate"); 5228 client_set_fps = false; 5229 } 5230 } else { 5231 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d", 5232 (int)config->nPortIndex); 5233 ret = OMX_ErrorBadPortIndex; 5234 } 5235 5236 return ret; 5237 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) { 5238 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 5239 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 5240 struct v4l2_control control; 5241 5242 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel); 5243 5244 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 5245 5246 switch (perf->ePerfLevel) { 5247 case OMX_QCOM_PerfLevelNominal: 5248 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; 5249 break; 5250 case OMX_QCOM_PerfLevelTurbo: 5251 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 5252 break; 5253 default: 5254 ret = OMX_ErrorUnsupportedSetting; 5255 break; 5256 } 5257 5258 if (ret == OMX_ErrorNone) { 5259 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? 5260 OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 5261 } 5262 5263 return ret; 5264 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) { 5265 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config = 5266 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData; 5267 struct v4l2_control control; 5268 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType); 5269 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE; 5270 5271 switch (config->eDecodeType) { 5272 case OMX_QCOM_PictypeDecode_I: 5273 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON; 5274 break; 5275 case OMX_QCOM_PictypeDecode_IPB: 5276 default: 5277 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF; 5278 break; 5279 } 5280 5281 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? 5282 OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 5283 if (ret) 5284 DEBUG_PRINT_ERROR("Failed to set picture type decode"); 5285 5286 return ret; 5287 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) { 5288 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData; 5289 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32); 5290 5291 struct v4l2_control control; 5292 5293 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; 5294 if (priority->nU32 == 0) 5295 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE; 5296 else 5297 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; 5298 5299 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 5300 DEBUG_PRINT_ERROR("Failed to set Priority"); 5301 ret = OMX_ErrorUnsupportedSetting; 5302 } 5303 return ret; 5304 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) { 5305 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData; 5306 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16); 5307 5308 struct v4l2_control control; 5309 5310 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE; 5311 control.value = rate->nU32; 5312 5313 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 5314 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources : 5315 OMX_ErrorUnsupportedSetting; 5316 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)", 5317 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno)); 5318 } 5319 return ret; 5320 5321 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) { 5322 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); 5323 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; 5324 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) { 5325 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true); 5326 } 5327 5328 print_debug_color_aspects(&(params->sAspects), "Set Config"); 5329 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams)); 5330 return ret; 5331 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) { 5332 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); 5333 5334 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext = 5335 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData); 5336 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext); 5337 5338 return set_vendor_extension_config(ext); 5339 } 5340 5341 return OMX_ErrorNotImplemented; 5342 } 5343 5344 #define extn_equals(param, extn) (!strcmp(param, extn)) 5345 5346 /* ====================================================================== 5347 FUNCTION 5348 omx_vdec::GetExtensionIndex 5349 5350 DESCRIPTION 5351 OMX GetExtensionIndex method implementaion. <TBD> 5352 5353 PARAMETERS 5354 <TBD>. 5355 5356 RETURN VALUE 5357 OMX Error None if everything successful. 5358 5359 ========================================================================== */ 5360 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, 5361 OMX_IN OMX_STRING paramName, 5362 OMX_OUT OMX_INDEXTYPE* indexType) 5363 { 5364 (void) hComp; 5365 if (m_state == OMX_StateInvalid) { 5366 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State"); 5367 return OMX_ErrorInvalidState; 5368 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) { 5369 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; 5370 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) { 5371 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; 5372 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) { 5373 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata; 5374 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) { 5375 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement; 5376 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) { 5377 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData; 5378 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) { 5379 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData; 5380 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) { 5381 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData; 5382 } 5383 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 5384 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) { 5385 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; 5386 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) { 5387 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; 5388 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) { 5389 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName); 5390 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; 5391 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) { 5392 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; 5393 } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) { 5394 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle; 5395 } 5396 #endif 5397 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { 5398 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; 5399 } 5400 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 5401 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) { 5402 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode; 5403 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) { 5404 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback; 5405 } 5406 #endif 5407 #ifdef FLEXYUV_SUPPORTED 5408 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) { 5409 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription; 5410 } 5411 #endif 5412 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) { 5413 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd; 5414 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) { 5415 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB; 5416 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) { 5417 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB; 5418 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { 5419 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; 5420 } else { 5421 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); 5422 return OMX_ErrorNotImplemented; 5423 } 5424 return OMX_ErrorNone; 5425 } 5426 5427 /* ====================================================================== 5428 FUNCTION 5429 omx_vdec::GetState 5430 5431 DESCRIPTION 5432 Returns the state information back to the caller.<TBD> 5433 5434 PARAMETERS 5435 <TBD>. 5436 5437 RETURN VALUE 5438 Error None if everything is successful. 5439 ========================================================================== */ 5440 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, 5441 OMX_OUT OMX_STATETYPE* state) 5442 { 5443 (void) hComp; 5444 *state = m_state; 5445 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state); 5446 return OMX_ErrorNone; 5447 } 5448 5449 /* ====================================================================== 5450 FUNCTION 5451 omx_vdec::ComponentTunnelRequest 5452 5453 DESCRIPTION 5454 OMX Component Tunnel Request method implementation. <TBD> 5455 5456 PARAMETERS 5457 None. 5458 5459 RETURN VALUE 5460 OMX Error None if everything successful. 5461 5462 ========================================================================== */ 5463 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, 5464 OMX_IN OMX_U32 port, 5465 OMX_IN OMX_HANDLETYPE peerComponent, 5466 OMX_IN OMX_U32 peerPort, 5467 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) 5468 { 5469 (void) hComp; 5470 (void) port; 5471 (void) peerComponent; 5472 (void) peerPort; 5473 (void) tunnelSetup; 5474 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented"); 5475 return OMX_ErrorNotImplemented; 5476 } 5477 5478 /* ====================================================================== 5479 FUNCTION 5480 omx_vdec::UseOutputBuffer 5481 5482 DESCRIPTION 5483 Helper function for Use buffer in the input pin 5484 5485 PARAMETERS 5486 None. 5487 5488 RETURN VALUE 5489 true/false 5490 5491 ========================================================================== */ 5492 OMX_ERRORTYPE omx_vdec::allocate_extradata() 5493 { 5494 #ifdef USE_ION 5495 if (drv_ctx.extradata_info.buffer_size) { 5496 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { 5497 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 5498 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5499 free_ion_memory(&drv_ctx.extradata_info.ion); 5500 } 5501 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); 5502 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( 5503 drv_ctx.extradata_info.size, 4096, 5504 &drv_ctx.extradata_info.ion.ion_alloc_data, 5505 &drv_ctx.extradata_info.ion.fd_ion_data, 0); 5506 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) { 5507 DEBUG_PRINT_ERROR("Failed to alloc extradata memory"); 5508 return OMX_ErrorInsufficientResources; 5509 } 5510 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL, 5511 drv_ctx.extradata_info.size, 5512 PROT_READ|PROT_WRITE, MAP_SHARED, 5513 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0); 5514 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) { 5515 DEBUG_PRINT_ERROR("Failed to map extradata memory"); 5516 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5517 free_ion_memory(&drv_ctx.extradata_info.ion); 5518 return OMX_ErrorInsufficientResources; 5519 } 5520 } 5521 #endif 5522 if (!m_other_extradata) { 5523 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size); 5524 if (!m_other_extradata) { 5525 DEBUG_PRINT_ERROR("Failed to alloc memory\n"); 5526 return OMX_ErrorInsufficientResources; 5527 } 5528 } 5529 return OMX_ErrorNone; 5530 } 5531 5532 void omx_vdec::free_extradata() 5533 { 5534 #ifdef USE_ION 5535 if (drv_ctx.extradata_info.uaddr) { 5536 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 5537 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 5538 free_ion_memory(&drv_ctx.extradata_info.ion); 5539 } 5540 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 5541 #endif 5542 if (m_other_extradata) { 5543 free(m_other_extradata); 5544 m_other_extradata = NULL; 5545 } 5546 } 5547 5548 OMX_ERRORTYPE omx_vdec::use_output_buffer( 5549 OMX_IN OMX_HANDLETYPE hComp, 5550 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5551 OMX_IN OMX_U32 port, 5552 OMX_IN OMX_PTR appData, 5553 OMX_IN OMX_U32 bytes, 5554 OMX_IN OMX_U8* buffer) 5555 { 5556 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5557 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 5558 unsigned i= 0; // Temporary counter 5559 struct vdec_setbuffer_cmd setbuffers; 5560 OMX_PTR privateAppData = NULL; 5561 private_handle_t *handle = NULL; 5562 OMX_U8 *buff = buffer; 5563 struct v4l2_buffer buf; 5564 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 5565 int extra_idx = 0; 5566 (void) hComp; 5567 (void) port; 5568 5569 if (!m_out_mem_ptr) { 5570 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); 5571 eRet = allocate_output_headers(); 5572 if (eRet == OMX_ErrorNone) 5573 eRet = allocate_extradata(); 5574 } 5575 5576 if (eRet == OMX_ErrorNone) { 5577 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 5578 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 5579 break; 5580 } 5581 } 5582 } 5583 5584 if (i >= drv_ctx.op_buf.actualcount) { 5585 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount); 5586 eRet = OMX_ErrorInsufficientResources; 5587 } 5588 5589 if (eRet != OMX_ErrorNone) 5590 return eRet; 5591 5592 if (dynamic_buf_mode) { 5593 *bufferHdr = (m_out_mem_ptr + i ); 5594 (*bufferHdr)->pBuffer = NULL; 5595 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) { 5596 enum v4l2_buf_type buf_type; 5597 int rr = 0; 5598 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5599 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) { 5600 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr); 5601 return OMX_ErrorInsufficientResources; 5602 } else { 5603 streaming[CAPTURE_PORT] = true; 5604 DEBUG_PRINT_LOW("STREAMON Successful"); 5605 } 5606 5607 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 5608 request_perf_level(VIDC_TURBO); 5609 } 5610 BITMASK_SET(&m_out_bm_count,i); 5611 (*bufferHdr)->pAppPrivate = appData; 5612 (*bufferHdr)->pBuffer = buffer; 5613 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 5614 return eRet; 5615 } 5616 5617 if (eRet == OMX_ErrorNone) { 5618 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) 5619 if (m_enable_android_native_buffers) { 5620 if (m_use_android_native_buffers) { 5621 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; 5622 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 5623 handle = (private_handle_t *)nBuf->handle; 5624 privateAppData = params->pAppPrivate; 5625 } else { 5626 handle = (private_handle_t *)buff; 5627 privateAppData = appData; 5628 } 5629 if (!handle) { 5630 DEBUG_PRINT_ERROR("handle is invalid"); 5631 return OMX_ErrorBadParameter; 5632 } 5633 5634 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { 5635 if (secure_mode && secure_scaling_to_non_secure_opb) { 5636 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it", 5637 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 5638 } else { 5639 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," 5640 " expected %u, got %u", 5641 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 5642 return OMX_ErrorBadParameter; 5643 } 5644 } 5645 5646 drv_ctx.op_buf.buffer_size = handle->size; 5647 5648 if (!m_use_android_native_buffers) { 5649 if (!secure_mode) { 5650 buff = (OMX_U8*)mmap(0, handle->size, 5651 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 5652 if (buff == MAP_FAILED) { 5653 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 5654 return OMX_ErrorInsufficientResources; 5655 } 5656 } 5657 } 5658 #if defined(_ANDROID_ICS_) 5659 native_buffer[i].nativehandle = handle; 5660 native_buffer[i].privatehandle = handle; 5661 #endif 5662 if (!handle) { 5663 DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); 5664 return OMX_ErrorBadParameter; 5665 } 5666 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; 5667 drv_ctx.ptr_outputbuffer[i].offset = 0; 5668 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 5669 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 5670 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size; 5671 } else 5672 #endif 5673 5674 if (!ouput_egl_buffers && !m_use_output_pmem) { 5675 #ifdef USE_ION 5676 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 5677 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, 5678 &drv_ctx.op_buf_ion_info[i].ion_alloc_data, 5679 &drv_ctx.op_buf_ion_info[i].fd_ion_data, 5680 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0); 5681 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { 5682 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd); 5683 return OMX_ErrorInsufficientResources; 5684 } 5685 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 5686 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 5687 #else 5688 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 5689 open (MEM_DEVICE,O_RDWR); 5690 5691 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 5692 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 5693 return OMX_ErrorInsufficientResources; 5694 } 5695 5696 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */ 5697 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) { 5698 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 5699 open (MEM_DEVICE,O_RDWR); 5700 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 5701 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 5702 return OMX_ErrorInsufficientResources; 5703 } 5704 } 5705 5706 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, 5707 drv_ctx.op_buf.buffer_size, 5708 drv_ctx.op_buf.alignment)) { 5709 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 5710 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 5711 return OMX_ErrorInsufficientResources; 5712 } 5713 #endif 5714 if (!secure_mode) { 5715 drv_ctx.ptr_outputbuffer[i].bufferaddr = 5716 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, 5717 PROT_READ|PROT_WRITE, MAP_SHARED, 5718 drv_ctx.ptr_outputbuffer[i].pmem_fd,0); 5719 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { 5720 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 5721 #ifdef USE_ION 5722 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 5723 #endif 5724 DEBUG_PRINT_ERROR("Unable to mmap output buffer"); 5725 return OMX_ErrorInsufficientResources; 5726 } 5727 } 5728 drv_ctx.ptr_outputbuffer[i].offset = 0; 5729 privateAppData = appData; 5730 } else { 5731 5732 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem); 5733 if (!appData || !bytes ) { 5734 if (!secure_mode && !buffer) { 5735 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case"); 5736 return OMX_ErrorBadParameter; 5737 } 5738 } 5739 5740 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; 5741 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; 5742 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; 5743 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry || 5744 !pmem_list->nEntries || 5745 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 5746 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer"); 5747 return OMX_ErrorBadParameter; 5748 } 5749 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 5750 pmem_list->entryList->entry; 5751 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx", 5752 pmem_info->pmem_fd); 5753 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; 5754 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; 5755 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 5756 drv_ctx.ptr_outputbuffer[i].mmaped_size = 5757 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 5758 privateAppData = appData; 5759 } 5760 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 5761 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; 5762 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 5763 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 5764 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 5765 5766 *bufferHdr = (m_out_mem_ptr + i ); 5767 if (secure_mode) 5768 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 5769 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 5770 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], 5771 sizeof (vdec_bufferpayload)); 5772 5773 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i, 5774 drv_ctx.ptr_outputbuffer[i].bufferaddr, 5775 drv_ctx.ptr_outputbuffer[i].pmem_fd ); 5776 5777 buf.index = i; 5778 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5779 buf.memory = V4L2_MEMORY_USERPTR; 5780 plane[0].length = drv_ctx.op_buf.buffer_size; 5781 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 5782 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 5783 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd; 5784 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 5785 plane[0].data_offset = 0; 5786 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 5787 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 5788 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 5789 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 5790 #ifdef USE_ION 5791 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 5792 #endif 5793 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 5794 plane[extra_idx].data_offset = 0; 5795 } else if (extra_idx >= VIDEO_MAX_PLANES) { 5796 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 5797 return OMX_ErrorBadParameter; 5798 } 5799 buf.m.planes = plane; 5800 buf.length = drv_ctx.num_planes; 5801 5802 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) { 5803 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 5804 /*TODO: How to handle this case */ 5805 return OMX_ErrorInsufficientResources; 5806 } 5807 5808 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 5809 enum v4l2_buf_type buf_type; 5810 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5811 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 5812 return OMX_ErrorInsufficientResources; 5813 } else { 5814 streaming[CAPTURE_PORT] = true; 5815 DEBUG_PRINT_LOW("STREAMON Successful"); 5816 } 5817 5818 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 5819 request_perf_level(VIDC_TURBO); 5820 } 5821 5822 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; 5823 if (m_enable_android_native_buffers) { 5824 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle); 5825 (*bufferHdr)->pBuffer = (OMX_U8 *)handle; 5826 } else { 5827 (*bufferHdr)->pBuffer = buff; 5828 } 5829 (*bufferHdr)->pAppPrivate = privateAppData; 5830 BITMASK_SET(&m_out_bm_count,i); 5831 } 5832 return eRet; 5833 } 5834 5835 /* ====================================================================== 5836 FUNCTION 5837 omx_vdec::use_input_heap_buffers 5838 5839 DESCRIPTION 5840 OMX Use Buffer Heap allocation method implementation. 5841 5842 PARAMETERS 5843 <TBD>. 5844 5845 RETURN VALUE 5846 OMX Error None , if everything successful. 5847 5848 ========================================================================== */ 5849 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( 5850 OMX_IN OMX_HANDLETYPE hComp, 5851 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5852 OMX_IN OMX_U32 port, 5853 OMX_IN OMX_PTR appData, 5854 OMX_IN OMX_U32 bytes, 5855 OMX_IN OMX_U8* buffer) 5856 { 5857 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer); 5858 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5859 5860 if (secure_mode) { 5861 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode"); 5862 return OMX_ErrorUndefined; 5863 } 5864 5865 if (!m_inp_heap_ptr) 5866 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) 5867 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 5868 drv_ctx.ip_buf.actualcount); 5869 if (!m_phdr_pmem_ptr) 5870 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) 5871 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 5872 drv_ctx.ip_buf.actualcount); 5873 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) { 5874 DEBUG_PRINT_ERROR("Insufficent memory"); 5875 eRet = OMX_ErrorInsufficientResources; 5876 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) { 5877 input_use_buffer = true; 5878 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); 5879 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; 5880 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; 5881 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; 5882 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; 5883 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; 5884 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; 5885 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); 5886 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); 5887 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt], 5888 (unsigned)NULL, (unsigned)NULL)) { 5889 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 5890 return OMX_ErrorInsufficientResources; 5891 } 5892 m_in_alloc_cnt++; 5893 } else { 5894 DEBUG_PRINT_ERROR("All i/p buffers have been set!"); 5895 eRet = OMX_ErrorInsufficientResources; 5896 } 5897 return eRet; 5898 } 5899 5900 /* ====================================================================== 5901 FUNCTION 5902 omx_vdec::UseBuffer 5903 5904 DESCRIPTION 5905 OMX Use Buffer method implementation. 5906 5907 PARAMETERS 5908 <TBD>. 5909 5910 RETURN VALUE 5911 OMX Error None , if everything successful. 5912 5913 ========================================================================== */ 5914 OMX_ERRORTYPE omx_vdec::use_buffer( 5915 OMX_IN OMX_HANDLETYPE hComp, 5916 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5917 OMX_IN OMX_U32 port, 5918 OMX_IN OMX_PTR appData, 5919 OMX_IN OMX_U32 bytes, 5920 OMX_IN OMX_U8* buffer) 5921 { 5922 OMX_ERRORTYPE error = OMX_ErrorNone; 5923 struct vdec_setbuffer_cmd setbuffers; 5924 5925 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) { 5926 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer); 5927 return OMX_ErrorBadParameter; 5928 } 5929 if (m_state == OMX_StateInvalid) { 5930 DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); 5931 return OMX_ErrorInvalidState; 5932 } 5933 if (port == OMX_CORE_INPUT_PORT_INDEX) { 5934 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), 5935 // ensure that use-buffer was called for previous allocation. 5936 // Mix-and-match of useBuffer and allocateBuffer is not allowed 5937 if (m_inp_mem_ptr && !input_use_buffer) { 5938 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !"); 5939 return OMX_ErrorUndefined; 5940 } 5941 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); 5942 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) 5943 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested 5944 else { 5945 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 5946 error = OMX_ErrorBadPortIndex; 5947 } 5948 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error); 5949 if (error == OMX_ErrorNone) { 5950 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 5951 // Send the callback now 5952 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 5953 post_event(OMX_CommandStateSet,OMX_StateIdle, 5954 OMX_COMPONENT_GENERATE_EVENT); 5955 } 5956 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && 5957 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 5958 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 5959 post_event(OMX_CommandPortEnable, 5960 OMX_CORE_INPUT_PORT_INDEX, 5961 OMX_COMPONENT_GENERATE_EVENT); 5962 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && 5963 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 5964 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 5965 post_event(OMX_CommandPortEnable, 5966 OMX_CORE_OUTPUT_PORT_INDEX, 5967 OMX_COMPONENT_GENERATE_EVENT); 5968 } 5969 } 5970 return error; 5971 } 5972 5973 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, 5974 OMX_BUFFERHEADERTYPE *pmem_bufferHdr) 5975 { 5976 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) { 5977 if (m_inp_heap_ptr[bufferindex].pBuffer) 5978 free(m_inp_heap_ptr[bufferindex].pBuffer); 5979 m_inp_heap_ptr[bufferindex].pBuffer = NULL; 5980 } 5981 if (pmem_bufferHdr) 5982 free_input_buffer(pmem_bufferHdr); 5983 return OMX_ErrorNone; 5984 } 5985 5986 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 5987 { 5988 unsigned int index = 0; 5989 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) { 5990 return OMX_ErrorBadParameter; 5991 } 5992 5993 index = bufferHdr - m_inp_mem_ptr; 5994 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 5995 5996 auto_lock l(buf_lock); 5997 bufferHdr->pInputPortPrivate = NULL; 5998 5999 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) { 6000 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 6001 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) { 6002 struct vdec_setbuffer_cmd setbuffers; 6003 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; 6004 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], 6005 sizeof (vdec_bufferpayload)); 6006 if (!secure_mode) { 6007 DEBUG_PRINT_LOW("unmap the input buffer fd=%d", 6008 drv_ctx.ptr_inputbuffer[index].pmem_fd); 6009 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p", 6010 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size, 6011 drv_ctx.ptr_inputbuffer[index].bufferaddr); 6012 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, 6013 drv_ctx.ptr_inputbuffer[index].mmaped_size); 6014 close (drv_ctx.ptr_inputbuffer[index].pmem_fd); 6015 } else if (allocate_native_handle){ 6016 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer; 6017 native_handle_close(nh); 6018 native_handle_delete(nh); 6019 } 6020 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; 6021 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) { 6022 free(m_desc_buffer_ptr[index].buf_addr); 6023 m_desc_buffer_ptr[index].buf_addr = NULL; 6024 m_desc_buffer_ptr[index].desc_data_size = 0; 6025 } 6026 #ifdef USE_ION 6027 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); 6028 #endif 6029 } 6030 } 6031 6032 return OMX_ErrorNone; 6033 } 6034 6035 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 6036 { 6037 unsigned int index = 0; 6038 6039 if (bufferHdr == NULL || m_out_mem_ptr == NULL) { 6040 return OMX_ErrorBadParameter; 6041 } 6042 6043 index = bufferHdr - m_out_mem_ptr; 6044 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index); 6045 6046 if (index < drv_ctx.op_buf.actualcount 6047 && drv_ctx.ptr_outputbuffer) { 6048 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index, 6049 drv_ctx.ptr_outputbuffer[index].bufferaddr); 6050 6051 struct vdec_setbuffer_cmd setbuffers; 6052 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 6053 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], 6054 sizeof (vdec_bufferpayload)); 6055 6056 if (!dynamic_buf_mode) { 6057 if (streaming[CAPTURE_PORT] && 6058 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) { 6059 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) { 6060 DEBUG_PRINT_ERROR("STREAMOFF Failed"); 6061 } else { 6062 DEBUG_PRINT_LOW("STREAMOFF Successful"); 6063 } 6064 } 6065 #ifdef _ANDROID_ 6066 if (m_enable_android_native_buffers) { 6067 if (!secure_mode) { 6068 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { 6069 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, 6070 drv_ctx.ptr_outputbuffer[index].mmaped_size); 6071 } 6072 } 6073 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; 6074 } else { 6075 #endif 6076 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { 6077 if (!secure_mode) { 6078 DEBUG_PRINT_LOW("unmap the output buffer fd = %d", 6079 drv_ctx.ptr_outputbuffer[0].pmem_fd); 6080 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p", 6081 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, 6082 drv_ctx.ptr_outputbuffer[0].bufferaddr); 6083 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, 6084 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); 6085 } 6086 close (drv_ctx.ptr_outputbuffer[0].pmem_fd); 6087 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; 6088 #ifdef USE_ION 6089 free_ion_memory(&drv_ctx.op_buf_ion_info[0]); 6090 #endif 6091 } 6092 #ifdef _ANDROID_ 6093 } 6094 #endif 6095 } //!dynamic_buf_mode 6096 if (release_output_done()) { 6097 free_extradata(); 6098 } 6099 } 6100 6101 return OMX_ErrorNone; 6102 6103 } 6104 6105 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, 6106 OMX_BUFFERHEADERTYPE **bufferHdr, 6107 OMX_U32 port, 6108 OMX_PTR appData, 6109 OMX_U32 bytes) 6110 { 6111 OMX_BUFFERHEADERTYPE *input = NULL; 6112 unsigned char *buf_addr = NULL; 6113 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6114 unsigned i = 0; 6115 6116 /* Sanity Check*/ 6117 if (bufferHdr == NULL) { 6118 return OMX_ErrorBadParameter; 6119 } 6120 6121 if (m_inp_heap_ptr == NULL) { 6122 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ 6123 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 6124 drv_ctx.ip_buf.actualcount); 6125 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ 6126 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 6127 drv_ctx.ip_buf.actualcount); 6128 6129 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) { 6130 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed "); 6131 return OMX_ErrorInsufficientResources; 6132 } 6133 } 6134 6135 /*Find a Free index*/ 6136 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 6137 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) { 6138 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 6139 break; 6140 } 6141 } 6142 6143 if (i < drv_ctx.ip_buf.actualcount) { 6144 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); 6145 6146 if (buf_addr == NULL) { 6147 return OMX_ErrorInsufficientResources; 6148 } 6149 6150 *bufferHdr = (m_inp_heap_ptr + i); 6151 input = *bufferHdr; 6152 BITMASK_SET(&m_heap_inp_bm_count,i); 6153 6154 input->pBuffer = (OMX_U8 *)buf_addr; 6155 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6156 input->nVersion.nVersion = OMX_SPEC_VERSION; 6157 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 6158 input->pAppPrivate = appData; 6159 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 6160 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr ); 6161 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); 6162 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]); 6163 /*Add the Buffers to freeq*/ 6164 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i], 6165 (unsigned)NULL, (unsigned)NULL)) { 6166 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 6167 return OMX_ErrorInsufficientResources; 6168 } 6169 } else { 6170 return OMX_ErrorBadParameter; 6171 } 6172 6173 return eRet; 6174 6175 } 6176 6177 6178 /* ====================================================================== 6179 FUNCTION 6180 omx_vdec::AllocateInputBuffer 6181 6182 DESCRIPTION 6183 Helper function for allocate buffer in the input pin 6184 6185 PARAMETERS 6186 None. 6187 6188 RETURN VALUE 6189 true/false 6190 6191 ========================================================================== */ 6192 OMX_ERRORTYPE omx_vdec::allocate_input_buffer( 6193 OMX_IN OMX_HANDLETYPE hComp, 6194 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6195 OMX_IN OMX_U32 port, 6196 OMX_IN OMX_PTR appData, 6197 OMX_IN OMX_U32 bytes) 6198 { 6199 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6200 struct vdec_setbuffer_cmd setbuffers; 6201 OMX_BUFFERHEADERTYPE *input = NULL; 6202 unsigned i = 0; 6203 unsigned char *buf_addr = NULL; 6204 int pmem_fd = -1, ret = 0; 6205 6206 (void) hComp; 6207 (void) port; 6208 6209 6210 if (bytes != drv_ctx.ip_buf.buffer_size) { 6211 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u", 6212 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size); 6213 return OMX_ErrorBadParameter; 6214 } 6215 6216 if (!m_inp_mem_ptr) { 6217 struct v4l2_requestbuffers bufreq; 6218 bufreq.memory = V4L2_MEMORY_USERPTR; 6219 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6220 bufreq.count = drv_ctx.ip_buf.actualcount; 6221 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 6222 if (ret) { 6223 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %s", strerror(errno)); 6224 /*TODO: How to handle this case */ 6225 eRet = OMX_ErrorInsufficientResources; 6226 } else if (bufreq.count != drv_ctx.ip_buf.actualcount) { 6227 DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d", 6228 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count); 6229 eRet = OMX_ErrorInsufficientResources; 6230 } 6231 6232 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)", 6233 drv_ctx.ip_buf.actualcount, 6234 (unsigned int)drv_ctx.ip_buf.buffer_size); 6235 6236 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ 6237 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); 6238 6239 if (m_inp_mem_ptr == NULL) { 6240 return OMX_ErrorInsufficientResources; 6241 } 6242 6243 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ 6244 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); 6245 6246 if (drv_ctx.ptr_inputbuffer == NULL) { 6247 return OMX_ErrorInsufficientResources; 6248 } 6249 #ifdef USE_ION 6250 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ 6251 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); 6252 6253 if (drv_ctx.ip_buf_ion_info == NULL) { 6254 return OMX_ErrorInsufficientResources; 6255 } 6256 #endif 6257 6258 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) { 6259 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; 6260 #ifdef USE_ION 6261 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; 6262 #endif 6263 } 6264 } 6265 6266 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 6267 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 6268 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 6269 break; 6270 } 6271 } 6272 6273 if (i < drv_ctx.ip_buf.actualcount) { 6274 struct v4l2_buffer buf; 6275 struct v4l2_plane plane; 6276 int rc; 6277 DEBUG_PRINT_LOW("Allocate input Buffer"); 6278 #ifdef USE_ION 6279 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 6280 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, 6281 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, 6282 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? 6283 SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED); 6284 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { 6285 return OMX_ErrorInsufficientResources; 6286 } 6287 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; 6288 #else 6289 pmem_fd = open (MEM_DEVICE,O_RDWR); 6290 6291 if (pmem_fd < 0) { 6292 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 6293 return OMX_ErrorInsufficientResources; 6294 } 6295 6296 if (pmem_fd == 0) { 6297 pmem_fd = open (MEM_DEVICE,O_RDWR); 6298 6299 if (pmem_fd < 0) { 6300 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 6301 return OMX_ErrorInsufficientResources; 6302 } 6303 } 6304 6305 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, 6306 drv_ctx.ip_buf.alignment)) { 6307 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 6308 close(pmem_fd); 6309 return OMX_ErrorInsufficientResources; 6310 } 6311 #endif 6312 if (!secure_mode) { 6313 buf_addr = (unsigned char *)mmap(NULL, 6314 drv_ctx.ip_buf.buffer_size, 6315 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); 6316 6317 if (buf_addr == MAP_FAILED) { 6318 close(pmem_fd); 6319 #ifdef USE_ION 6320 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); 6321 #endif 6322 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer"); 6323 return OMX_ErrorInsufficientResources; 6324 } 6325 } 6326 *bufferHdr = (m_inp_mem_ptr + i); 6327 if (secure_mode) 6328 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; 6329 else 6330 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; 6331 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; 6332 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; 6333 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; 6334 drv_ctx.ptr_inputbuffer [i].offset = 0; 6335 6336 6337 buf.index = i; 6338 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6339 buf.memory = V4L2_MEMORY_USERPTR; 6340 plane.bytesused = 0; 6341 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size; 6342 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr; 6343 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd; 6344 plane.reserved[1] = 0; 6345 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset; 6346 buf.m.planes = &plane; 6347 buf.length = 1; 6348 6349 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i, 6350 drv_ctx.ptr_inputbuffer[i].bufferaddr); 6351 6352 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 6353 6354 if (rc) { 6355 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 6356 /*TODO: How to handle this case */ 6357 return OMX_ErrorInsufficientResources; 6358 } 6359 6360 input = *bufferHdr; 6361 BITMASK_SET(&m_inp_bm_count,i); 6362 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr); 6363 if (allocate_native_handle) { 6364 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/); 6365 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd; 6366 input->pBuffer = (OMX_U8 *)nh; 6367 } else if (secure_mode || m_input_pass_buffer_fd) { 6368 /*Legacy method, pass ion fd stashed directly in pBuffer*/ 6369 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd; 6370 } else { 6371 input->pBuffer = (OMX_U8 *)buf_addr; 6372 } 6373 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6374 input->nVersion.nVersion = OMX_SPEC_VERSION; 6375 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 6376 input->pAppPrivate = appData; 6377 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 6378 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; 6379 6380 if (drv_ctx.disable_dmx) { 6381 eRet = allocate_desc_buffer(i); 6382 } 6383 } else { 6384 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found"); 6385 eRet = OMX_ErrorInsufficientResources; 6386 } 6387 return eRet; 6388 } 6389 6390 6391 /* ====================================================================== 6392 FUNCTION 6393 omx_vdec::AllocateOutputBuffer 6394 6395 DESCRIPTION 6396 Helper fn for AllocateBuffer in the output pin 6397 6398 PARAMETERS 6399 <TBD>. 6400 6401 RETURN VALUE 6402 OMX Error None if everything went well. 6403 6404 ========================================================================== */ 6405 OMX_ERRORTYPE omx_vdec::allocate_output_buffer( 6406 OMX_IN OMX_HANDLETYPE hComp, 6407 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6408 OMX_IN OMX_U32 port, 6409 OMX_IN OMX_PTR appData, 6410 OMX_IN OMX_U32 bytes) 6411 { 6412 (void)hComp; 6413 (void)port; 6414 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6415 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 6416 unsigned i= 0; // Temporary counter 6417 struct vdec_setbuffer_cmd setbuffers; 6418 int extra_idx = 0; 6419 #ifdef USE_ION 6420 int ion_device_fd =-1; 6421 struct ion_allocation_data ion_alloc_data; 6422 struct ion_fd_data fd_ion_data; 6423 #endif 6424 if (!m_out_mem_ptr) { 6425 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)", 6426 drv_ctx.op_buf.actualcount, 6427 (unsigned int)drv_ctx.op_buf.buffer_size); 6428 int nBufHdrSize = 0; 6429 int nPlatformEntrySize = 0; 6430 int nPlatformListSize = 0; 6431 int nPMEMInfoSize = 0; 6432 int pmem_fd = -1; 6433 unsigned char *pmem_baseaddress = NULL; 6434 6435 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 6436 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 6437 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 6438 6439 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)", 6440 drv_ctx.op_buf.actualcount); 6441 nBufHdrSize = drv_ctx.op_buf.actualcount * 6442 sizeof(OMX_BUFFERHEADERTYPE); 6443 6444 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 6445 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 6446 nPlatformListSize = drv_ctx.op_buf.actualcount * 6447 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 6448 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 6449 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 6450 6451 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 6452 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 6453 nPMEMInfoSize, 6454 nPlatformListSize); 6455 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, 6456 drv_ctx.op_buf.actualcount); 6457 #ifdef USE_ION 6458 // Allocate output buffers as cached to improve performance of software-reading 6459 // of the YUVs. Output buffers are cache-invalidated in driver. 6460 // If color-conversion is involved, Only the C2D output buffers are cached, no 6461 // need to cache the decoder's output buffers 6462 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED; 6463 ion_device_fd = alloc_map_ion_memory( 6464 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount, 6465 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment, 6466 &ion_alloc_data, &fd_ion_data, 6467 (secure_mode && !secure_scaling_to_non_secure_opb) ? 6468 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag); 6469 if (ion_device_fd < 0) { 6470 return OMX_ErrorInsufficientResources; 6471 } 6472 pmem_fd = fd_ion_data.fd; 6473 #else 6474 pmem_fd = open (MEM_DEVICE,O_RDWR); 6475 6476 if (pmem_fd < 0) { 6477 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 6478 drv_ctx.op_buf.buffer_size); 6479 return OMX_ErrorInsufficientResources; 6480 } 6481 6482 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size * 6483 drv_ctx.op_buf.actualcount, 6484 drv_ctx.op_buf.alignment)) { 6485 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 6486 close(pmem_fd); 6487 return OMX_ErrorInsufficientResources; 6488 } 6489 #endif 6490 if (!secure_mode) { 6491 pmem_baseaddress = (unsigned char *)mmap(NULL, 6492 (drv_ctx.op_buf.buffer_size * 6493 drv_ctx.op_buf.actualcount), 6494 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); 6495 if (pmem_baseaddress == MAP_FAILED) { 6496 DEBUG_PRINT_ERROR("MMAP failed for Size %u", 6497 (unsigned int)drv_ctx.op_buf.buffer_size); 6498 close(pmem_fd); 6499 #ifdef USE_ION 6500 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 6501 #endif 6502 return OMX_ErrorInsufficientResources; 6503 } 6504 } 6505 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 6506 // Alloc mem for platform specific info 6507 char *pPtr=NULL; 6508 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 6509 nPMEMInfoSize,1); 6510 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ 6511 calloc (sizeof(struct vdec_bufferpayload), 6512 drv_ctx.op_buf.actualcount); 6513 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 6514 calloc (sizeof (struct vdec_output_frameinfo), 6515 drv_ctx.op_buf.actualcount); 6516 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 6517 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer "); 6518 return OMX_ErrorInsufficientResources; 6519 } 6520 6521 #ifdef USE_ION 6522 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ 6523 calloc (sizeof(struct vdec_ion), 6524 drv_ctx.op_buf.actualcount); 6525 if (!drv_ctx.op_buf_ion_info) { 6526 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 6527 return OMX_ErrorInsufficientResources; 6528 } 6529 #endif 6530 6531 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 6532 && drv_ctx.ptr_respbuffer) { 6533 drv_ctx.ptr_outputbuffer[0].mmaped_size = 6534 (drv_ctx.op_buf.buffer_size * 6535 drv_ctx.op_buf.actualcount); 6536 bufHdr = m_out_mem_ptr; 6537 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 6538 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 6539 (((char *) m_platform_list) + nPlatformListSize); 6540 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 6541 (((char *) m_platform_entry) + nPlatformEntrySize); 6542 pPlatformList = m_platform_list; 6543 pPlatformEntry = m_platform_entry; 6544 pPMEMInfo = m_pmem_info; 6545 6546 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 6547 6548 // Settting the entire storage nicely 6549 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry); 6550 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 6551 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 6552 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 6553 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 6554 // Set the values when we determine the right HxW param 6555 bufHdr->nAllocLen = bytes; 6556 bufHdr->nFilledLen = 0; 6557 bufHdr->pAppPrivate = appData; 6558 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 6559 // Platform specific PMEM Information 6560 // Initialize the Platform Entry 6561 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i); 6562 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 6563 pPlatformEntry->entry = pPMEMInfo; 6564 // Initialize the Platform List 6565 pPlatformList->nEntries = 1; 6566 pPlatformList->entryList = pPlatformEntry; 6567 // Keep pBuffer NULL till vdec is opened 6568 bufHdr->pBuffer = NULL; 6569 bufHdr->nOffset = 0; 6570 6571 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i; 6572 pPMEMInfo->pmem_fd = -1; 6573 bufHdr->pPlatformPrivate = pPlatformList; 6574 6575 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd; 6576 m_pmem_info[i].pmem_fd = pmem_fd; 6577 #ifdef USE_ION 6578 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd; 6579 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data; 6580 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data; 6581 #endif 6582 6583 /*Create a mapping between buffers*/ 6584 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 6585 drv_ctx.ptr_respbuffer[i].client_data = (void *)\ 6586 &drv_ctx.ptr_outputbuffer[i]; 6587 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i; 6588 drv_ctx.ptr_outputbuffer[i].bufferaddr = 6589 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i); 6590 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 6591 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 6592 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 6593 6594 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p", 6595 pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset, 6596 drv_ctx.ptr_outputbuffer[i].bufferaddr); 6597 // Move the buffer and buffer header pointers 6598 bufHdr++; 6599 pPMEMInfo++; 6600 pPlatformEntry++; 6601 pPlatformList++; 6602 } 6603 } else { 6604 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 6605 m_out_mem_ptr, pPtr); 6606 if (m_out_mem_ptr) { 6607 free(m_out_mem_ptr); 6608 m_out_mem_ptr = NULL; 6609 } 6610 if (pPtr) { 6611 free(pPtr); 6612 pPtr = NULL; 6613 } 6614 if (drv_ctx.ptr_outputbuffer) { 6615 free(drv_ctx.ptr_outputbuffer); 6616 drv_ctx.ptr_outputbuffer = NULL; 6617 } 6618 if (drv_ctx.ptr_respbuffer) { 6619 free(drv_ctx.ptr_respbuffer); 6620 drv_ctx.ptr_respbuffer = NULL; 6621 } 6622 #ifdef USE_ION 6623 if (drv_ctx.op_buf_ion_info) { 6624 DEBUG_PRINT_LOW("Free o/p ion context"); 6625 free(drv_ctx.op_buf_ion_info); 6626 drv_ctx.op_buf_ion_info = NULL; 6627 } 6628 #endif 6629 eRet = OMX_ErrorInsufficientResources; 6630 } 6631 if (eRet == OMX_ErrorNone) 6632 eRet = allocate_extradata(); 6633 } 6634 6635 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 6636 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 6637 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i); 6638 break; 6639 } 6640 } 6641 6642 if (eRet == OMX_ErrorNone) { 6643 if (i < drv_ctx.op_buf.actualcount) { 6644 struct v4l2_buffer buf; 6645 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 6646 int rc; 6647 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 6648 6649 drv_ctx.ptr_outputbuffer[i].buffer_len = 6650 drv_ctx.op_buf.buffer_size; 6651 6652 *bufferHdr = (m_out_mem_ptr + i ); 6653 if (secure_mode) { 6654 #ifdef USE_ION 6655 drv_ctx.ptr_outputbuffer[i].bufferaddr = 6656 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 6657 #else 6658 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 6659 #endif 6660 } 6661 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; 6662 6663 buf.index = i; 6664 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6665 buf.memory = V4L2_MEMORY_USERPTR; 6666 plane[0].length = drv_ctx.op_buf.buffer_size; 6667 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 6668 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 6669 #ifdef USE_ION 6670 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 6671 #endif 6672 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 6673 plane[0].data_offset = 0; 6674 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 6675 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 6676 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 6677 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 6678 #ifdef USE_ION 6679 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 6680 #endif 6681 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 6682 plane[extra_idx].data_offset = 0; 6683 } else if (extra_idx >= VIDEO_MAX_PLANES) { 6684 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx); 6685 return OMX_ErrorBadParameter; 6686 } 6687 buf.m.planes = plane; 6688 buf.length = drv_ctx.num_planes; 6689 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr); 6690 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 6691 if (rc) { 6692 /*TODO: How to handle this case */ 6693 return OMX_ErrorInsufficientResources; 6694 } 6695 6696 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { 6697 enum v4l2_buf_type buf_type; 6698 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6699 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 6700 if (rc) { 6701 return OMX_ErrorInsufficientResources; 6702 } else { 6703 streaming[CAPTURE_PORT] = true; 6704 DEBUG_PRINT_LOW("STREAMON Successful"); 6705 } 6706 6707 DEBUG_PRINT_HIGH("Enabling Turbo mode"); 6708 request_perf_level(VIDC_TURBO); 6709 } 6710 6711 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 6712 (*bufferHdr)->pAppPrivate = appData; 6713 BITMASK_SET(&m_out_bm_count,i); 6714 } else { 6715 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient"); 6716 eRet = OMX_ErrorInsufficientResources; 6717 } 6718 } 6719 6720 return eRet; 6721 } 6722 6723 6724 // AllocateBuffer -- API Call 6725 /* ====================================================================== 6726 FUNCTION 6727 omx_vdec::AllocateBuffer 6728 6729 DESCRIPTION 6730 Returns zero if all the buffers released.. 6731 6732 PARAMETERS 6733 None. 6734 6735 RETURN VALUE 6736 true/false 6737 6738 ========================================================================== */ 6739 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, 6740 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6741 OMX_IN OMX_U32 port, 6742 OMX_IN OMX_PTR appData, 6743 OMX_IN OMX_U32 bytes) 6744 { 6745 unsigned i = 0; 6746 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type 6747 6748 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port); 6749 if (m_state == OMX_StateInvalid) { 6750 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State"); 6751 return OMX_ErrorInvalidState; 6752 } 6753 6754 if (port == OMX_CORE_INPUT_PORT_INDEX) { 6755 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), 6756 // ensure that use-buffer was never called. 6757 // Mix-and-match of useBuffer and allocateBuffer is not allowed 6758 if (m_inp_mem_ptr && input_use_buffer) { 6759 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !"); 6760 return OMX_ErrorUndefined; 6761 } 6762 if (arbitrary_bytes) { 6763 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); 6764 } else { 6765 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); 6766 } 6767 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 6768 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port, 6769 appData,bytes); 6770 } else { 6771 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 6772 eRet = OMX_ErrorBadPortIndex; 6773 } 6774 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); 6775 if (eRet == OMX_ErrorNone) { 6776 if (allocate_done()) { 6777 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 6778 // Send the callback now 6779 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 6780 post_event(OMX_CommandStateSet,OMX_StateIdle, 6781 OMX_COMPONENT_GENERATE_EVENT); 6782 } 6783 } 6784 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) { 6785 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 6786 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 6787 post_event(OMX_CommandPortEnable, 6788 OMX_CORE_INPUT_PORT_INDEX, 6789 OMX_COMPONENT_GENERATE_EVENT); 6790 } 6791 } 6792 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) { 6793 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 6794 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 6795 post_event(OMX_CommandPortEnable, 6796 OMX_CORE_OUTPUT_PORT_INDEX, 6797 OMX_COMPONENT_GENERATE_EVENT); 6798 } 6799 } 6800 } 6801 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet); 6802 return eRet; 6803 } 6804 6805 // Free Buffer - API call 6806 /* ====================================================================== 6807 FUNCTION 6808 omx_vdec::FreeBuffer 6809 6810 DESCRIPTION 6811 6812 PARAMETERS 6813 None. 6814 6815 RETURN VALUE 6816 true/false 6817 6818 ========================================================================== */ 6819 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, 6820 OMX_IN OMX_U32 port, 6821 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6822 { 6823 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6824 unsigned int nPortIndex; 6825 (void) hComp; 6826 DEBUG_PRINT_LOW("In for decoder free_buffer"); 6827 6828 if (m_state == OMX_StateIdle && 6829 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 6830 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); 6831 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| 6832 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) { 6833 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port); 6834 } else if ((port == OMX_CORE_INPUT_PORT_INDEX && 6835 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) || 6836 (port == OMX_CORE_OUTPUT_PORT_INDEX && 6837 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) { 6838 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port); 6839 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) { 6840 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled"); 6841 post_event(OMX_EventError, 6842 OMX_ErrorPortUnpopulated, 6843 OMX_COMPONENT_GENERATE_EVENT); 6844 6845 return OMX_ErrorIncorrectStateOperation; 6846 } else if (m_state != OMX_StateInvalid) { 6847 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers"); 6848 post_event(OMX_EventError, 6849 OMX_ErrorPortUnpopulated, 6850 OMX_COMPONENT_GENERATE_EVENT); 6851 } 6852 6853 if (port == OMX_CORE_INPUT_PORT_INDEX) { 6854 /*Check if arbitrary bytes*/ 6855 if (!arbitrary_bytes && !input_use_buffer) 6856 nPortIndex = buffer - m_inp_mem_ptr; 6857 else 6858 nPortIndex = buffer - m_inp_heap_ptr; 6859 6860 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); 6861 if (nPortIndex < drv_ctx.ip_buf.actualcount && 6862 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { 6863 // Clear the bit associated with it. 6864 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); 6865 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); 6866 if (input_use_buffer == true) { 6867 6868 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex); 6869 if (m_phdr_pmem_ptr) 6870 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); 6871 } else { 6872 if (arbitrary_bytes) { 6873 if (m_phdr_pmem_ptr) 6874 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); 6875 else 6876 free_input_buffer(nPortIndex,NULL); 6877 } else 6878 free_input_buffer(buffer); 6879 } 6880 m_inp_bPopulated = OMX_FALSE; 6881 if(release_input_done()) 6882 release_buffers(this, VDEC_BUFFER_TYPE_INPUT); 6883 /*Free the Buffer Header*/ 6884 if (release_input_done()) { 6885 DEBUG_PRINT_HIGH("ALL input buffers are freed/released"); 6886 free_input_buffer_header(); 6887 } 6888 } else { 6889 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid"); 6890 eRet = OMX_ErrorBadPortIndex; 6891 } 6892 6893 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) 6894 && release_input_done()) { 6895 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 6896 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); 6897 post_event(OMX_CommandPortDisable, 6898 OMX_CORE_INPUT_PORT_INDEX, 6899 OMX_COMPONENT_GENERATE_EVENT); 6900 } 6901 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 6902 // check if the buffer is valid 6903 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 6904 if (nPortIndex < drv_ctx.op_buf.actualcount && 6905 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { 6906 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); 6907 // Clear the bit associated with it. 6908 BITMASK_CLEAR(&m_out_bm_count,nPortIndex); 6909 m_out_bPopulated = OMX_FALSE; 6910 client_buffers.free_output_buffer (buffer); 6911 6912 if(release_output_done()) { 6913 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT); 6914 } 6915 if (release_output_done()) { 6916 free_output_buffer_header(); 6917 } 6918 } else { 6919 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid"); 6920 eRet = OMX_ErrorBadPortIndex; 6921 } 6922 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) 6923 && release_output_done()) { 6924 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it"); 6925 6926 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 6927 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 6928 #ifdef _ANDROID_ICS_ 6929 if (m_enable_android_native_buffers) { 6930 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); 6931 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 6932 } 6933 #endif 6934 6935 post_event(OMX_CommandPortDisable, 6936 OMX_CORE_OUTPUT_PORT_INDEX, 6937 OMX_COMPONENT_GENERATE_EVENT); 6938 } 6939 } else { 6940 eRet = OMX_ErrorBadPortIndex; 6941 } 6942 if ((eRet == OMX_ErrorNone) && 6943 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 6944 if (release_done()) { 6945 // Send the callback now 6946 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); 6947 post_event(OMX_CommandStateSet, OMX_StateLoaded, 6948 OMX_COMPONENT_GENERATE_EVENT); 6949 } 6950 } 6951 return eRet; 6952 } 6953 6954 6955 /* ====================================================================== 6956 FUNCTION 6957 omx_vdec::EmptyThisBuffer 6958 6959 DESCRIPTION 6960 This routine is used to push the encoded video frames to 6961 the video decoder. 6962 6963 PARAMETERS 6964 None. 6965 6966 RETURN VALUE 6967 OMX Error None if everything went successful. 6968 6969 ========================================================================== */ 6970 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 6971 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6972 { 6973 OMX_ERRORTYPE ret1 = OMX_ErrorNone; 6974 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; 6975 6976 if (m_state != OMX_StateExecuting && 6977 m_state != OMX_StatePause && 6978 m_state != OMX_StateIdle) { 6979 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State"); 6980 return OMX_ErrorInvalidState; 6981 } 6982 6983 if (buffer == NULL) { 6984 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL"); 6985 return OMX_ErrorBadParameter; 6986 } 6987 6988 if (!m_inp_bEnabled) { 6989 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled."); 6990 return OMX_ErrorIncorrectStateOperation; 6991 } 6992 6993 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) { 6994 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex); 6995 return OMX_ErrorBadPortIndex; 6996 } 6997 6998 if (perf_flag) { 6999 if (!latency) { 7000 dec_time.stop(); 7001 latency = dec_time.processing_time_us(); 7002 dec_time.start(); 7003 } 7004 } 7005 7006 if (arbitrary_bytes) { 7007 nBufferIndex = buffer - m_inp_heap_ptr; 7008 } else { 7009 if (input_use_buffer == true) { 7010 nBufferIndex = buffer - m_inp_heap_ptr; 7011 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { 7012 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode"); 7013 return OMX_ErrorBadParameter; 7014 } 7015 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; 7016 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; 7017 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; 7018 buffer = &m_inp_mem_ptr[nBufferIndex]; 7019 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u", 7020 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen); 7021 } else { 7022 nBufferIndex = buffer - m_inp_mem_ptr; 7023 } 7024 } 7025 7026 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { 7027 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); 7028 return OMX_ErrorBadParameter; 7029 } 7030 7031 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 7032 codec_config_flag = true; 7033 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); 7034 } 7035 7036 /* The client should not set this when codec is in arbitrary bytes mode */ 7037 if (m_input_pass_buffer_fd) { 7038 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr; 7039 } 7040 7041 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)", 7042 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen); 7043 if (arbitrary_bytes) { 7044 post_event ((unsigned long)hComp,(unsigned long)buffer, 7045 OMX_COMPONENT_GENERATE_ETB_ARBITRARY); 7046 } else { 7047 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB); 7048 } 7049 time_stamp_dts.insert_timestamp(buffer); 7050 return OMX_ErrorNone; 7051 } 7052 7053 /* ====================================================================== 7054 FUNCTION 7055 omx_vdec::empty_this_buffer_proxy 7056 7057 DESCRIPTION 7058 This routine is used to push the encoded video frames to 7059 the video decoder. 7060 7061 PARAMETERS 7062 None. 7063 7064 RETURN VALUE 7065 OMX Error None if everything went successful. 7066 7067 ========================================================================== */ 7068 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, 7069 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7070 { 7071 (void) hComp; 7072 int push_cnt = 0,i=0; 7073 unsigned nPortIndex = 0; 7074 OMX_ERRORTYPE ret = OMX_ErrorNone; 7075 struct vdec_input_frameinfo frameinfo; 7076 struct vdec_bufferpayload *temp_buffer; 7077 struct vdec_seqheader seq_header; 7078 bool port_setting_changed = true; 7079 7080 /*Should we generate a Aync error event*/ 7081 if (buffer == NULL || buffer->pInputPortPrivate == NULL) { 7082 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid"); 7083 return OMX_ErrorBadParameter; 7084 } 7085 7086 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 7087 7088 if (nPortIndex >= drv_ctx.ip_buf.actualcount) { 7089 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", 7090 nPortIndex); 7091 return OMX_ErrorBadParameter; 7092 } 7093 7094 pending_input_buffers++; 7095 7096 /* return zero length and not an EOS buffer */ 7097 if (!arbitrary_bytes && (buffer->nFilledLen == 0) && 7098 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) { 7099 DEBUG_PRINT_HIGH("return zero legth buffer"); 7100 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 7101 OMX_COMPONENT_GENERATE_EBD); 7102 return OMX_ErrorNone; 7103 } 7104 7105 if (input_flush_progress == true) { 7106 DEBUG_PRINT_LOW("Flush in progress return buffer "); 7107 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 7108 OMX_COMPONENT_GENERATE_EBD); 7109 return OMX_ErrorNone; 7110 } 7111 7112 auto_lock l(buf_lock); 7113 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; 7114 7115 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) { 7116 return OMX_ErrorBadParameter; 7117 } 7118 /* If its first frame, H264 codec and reject is true, then parse the nal 7119 and get the profile. Based on this, reject the clip playback */ 7120 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 && 7121 m_reject_avc_1080p_mp) { 7122 first_frame = 1; 7123 DEBUG_PRINT_ERROR("Parse nal to get the profile"); 7124 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen, 7125 NALU_TYPE_SPS); 7126 m_profile = h264_parser->get_profile(); 7127 ret = is_video_session_supported(); 7128 if (ret) { 7129 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD); 7130 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT); 7131 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */ 7132 m_state = OMX_StateInvalid; 7133 return OMX_ErrorNone; 7134 } 7135 } 7136 7137 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7138 /*for use buffer we need to memcpy the data*/ 7139 temp_buffer->buffer_len = buffer->nFilledLen; 7140 7141 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) { 7142 if (buffer->nFilledLen <= temp_buffer->buffer_len) { 7143 if (arbitrary_bytes) { 7144 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); 7145 } else { 7146 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), 7147 buffer->nFilledLen); 7148 } 7149 } else { 7150 return OMX_ErrorBadParameter; 7151 } 7152 7153 } 7154 7155 frameinfo.bufferaddr = temp_buffer->bufferaddr; 7156 frameinfo.client_data = (void *) buffer; 7157 frameinfo.datalen = temp_buffer->buffer_len; 7158 frameinfo.flags = 0; 7159 frameinfo.offset = buffer->nOffset; 7160 frameinfo.pmem_fd = temp_buffer->pmem_fd; 7161 frameinfo.pmem_offset = temp_buffer->offset; 7162 frameinfo.timestamp = buffer->nTimeStamp; 7163 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) { 7164 DEBUG_PRINT_LOW("ETB: dmx enabled"); 7165 if (m_demux_entries == 0) { 7166 extract_demux_addr_offsets(buffer); 7167 } 7168 7169 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries); 7170 handle_demux_data(buffer); 7171 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; 7172 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; 7173 } else { 7174 frameinfo.desc_addr = NULL; 7175 frameinfo.desc_size = 0; 7176 } 7177 if (!arbitrary_bytes) { 7178 frameinfo.flags |= buffer->nFlags; 7179 } 7180 7181 #ifdef _ANDROID_ 7182 if (m_debug_timestamp) { 7183 if (arbitrary_bytes) { 7184 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 7185 m_timestamp_list.insert_ts(buffer->nTimeStamp); 7186 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 7187 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 7188 m_timestamp_list.insert_ts(buffer->nTimeStamp); 7189 } 7190 } 7191 #endif 7192 7193 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); 7194 7195 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 7196 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7197 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7198 } 7199 7200 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 7201 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached"); 7202 frameinfo.flags |= VDEC_BUFFERFLAG_EOS; 7203 h264_scratch.nFilledLen = 0; 7204 nal_count = 0; 7205 look_ahead_nal = false; 7206 frame_count = 0; 7207 if (m_frame_parser.mutils) 7208 m_frame_parser.mutils->initialize_frame_checking_environment(); 7209 m_frame_parser.flush(); 7210 h264_last_au_ts = LLONG_MAX; 7211 h264_last_au_flags = 0; 7212 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 7213 m_demux_entries = 0; 7214 } 7215 struct v4l2_buffer buf; 7216 struct v4l2_plane plane; 7217 memset( (void *)&buf, 0, sizeof(buf)); 7218 memset( (void *)&plane, 0, sizeof(plane)); 7219 int rc; 7220 unsigned long print_count; 7221 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 7222 buf.flags = V4L2_QCOM_BUF_FLAG_EOS; 7223 DEBUG_PRINT_HIGH("INPUT EOS reached") ; 7224 } 7225 OMX_ERRORTYPE eRet = OMX_ErrorNone; 7226 buf.index = nPortIndex; 7227 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 7228 buf.memory = V4L2_MEMORY_USERPTR; 7229 plane.bytesused = temp_buffer->buffer_len; 7230 plane.length = drv_ctx.ip_buf.buffer_size; 7231 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr - 7232 (unsigned long)temp_buffer->offset; 7233 plane.reserved[0] = temp_buffer->pmem_fd; 7234 plane.reserved[1] = temp_buffer->offset; 7235 plane.data_offset = 0; 7236 buf.m.planes = &plane; 7237 buf.length = 1; 7238 if (frameinfo.timestamp >= LLONG_MAX) { 7239 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID; 7240 } 7241 //assumption is that timestamp is in milliseconds 7242 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000; 7243 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000); 7244 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0; 7245 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0; 7246 7247 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 7248 DEBUG_PRINT_LOW("Increment codec_config buffer counter"); 7249 android_atomic_inc(&m_queued_codec_config_count); 7250 } 7251 7252 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 7253 if (rc) { 7254 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver"); 7255 return OMX_ErrorHardware; 7256 } 7257 7258 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 7259 codec_config_flag = false; 7260 } 7261 if (!streaming[OUTPUT_PORT]) { 7262 enum v4l2_buf_type buf_type; 7263 int ret,r; 7264 7265 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 7266 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 7267 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 7268 if (!ret) { 7269 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful"); 7270 streaming[OUTPUT_PORT] = true; 7271 } else if (errno == EBUSY) { 7272 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD"); 7273 post_event ((unsigned long)buffer, VDEC_S_SUCCESS, 7274 OMX_COMPONENT_GENERATE_EBD); 7275 return OMX_ErrorInsufficientResources; 7276 } else { 7277 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT"); 7278 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued"); 7279 post_event ((unsigned long)buffer, VDEC_S_SUCCESS, 7280 OMX_COMPONENT_GENERATE_EBD); 7281 return OMX_ErrorBadParameter; 7282 } 7283 } 7284 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)", 7285 frameinfo.bufferaddr, (long long)frameinfo.timestamp, 7286 (unsigned int)frameinfo.datalen); 7287 7288 return ret; 7289 } 7290 7291 /* ====================================================================== 7292 FUNCTION 7293 omx_vdec::FillThisBuffer 7294 7295 DESCRIPTION 7296 IL client uses this method to release the frame buffer 7297 after displaying them. 7298 7299 PARAMETERS 7300 None. 7301 7302 RETURN VALUE 7303 true/false 7304 7305 ========================================================================== */ 7306 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 7307 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 7308 { 7309 if (m_state != OMX_StateExecuting && 7310 m_state != OMX_StatePause && 7311 m_state != OMX_StateIdle) { 7312 DEBUG_PRINT_ERROR("FTB in Invalid State"); 7313 return OMX_ErrorInvalidState; 7314 } 7315 7316 if (!m_out_bEnabled) { 7317 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); 7318 return OMX_ErrorIncorrectStateOperation; 7319 } 7320 7321 unsigned nPortIndex = 0; 7322 if (dynamic_buf_mode) { 7323 private_handle_t *handle = NULL; 7324 struct VideoDecoderOutputMetaData *meta; 7325 unsigned int nPortIndex = 0; 7326 7327 if (!buffer || !buffer->pBuffer) { 7328 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer); 7329 return OMX_ErrorBadParameter; 7330 } 7331 7332 //get the buffer type and fd info 7333 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer; 7334 handle = (private_handle_t *)meta->pHandle; 7335 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle); 7336 7337 if (!handle) { 7338 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle); 7339 return OMX_ErrorBadParameter; 7340 } 7341 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF 7342 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 7343 if (nPortIndex < drv_ctx.op_buf.actualcount && 7344 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 7345 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd; 7346 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer; 7347 7348 //Store private handle from GraphicBuffer 7349 native_buffer[nPortIndex].privatehandle = handle; 7350 native_buffer[nPortIndex].nativehandle = handle; 7351 } else { 7352 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex); 7353 return OMX_ErrorBadParameter; 7354 } 7355 7356 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite 7357 //this with a more sane size so that we don't compensate in rest of code 7358 //We'll restore this size later on, so that it's transparent to client 7359 buffer->nFilledLen = 0; 7360 buffer->nAllocLen = handle->size; 7361 drv_ctx.op_buf.buffer_size = handle->size; 7362 } 7363 7364 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 7365 if (buffer == NULL || 7366 (nPortIndex >= drv_ctx.op_buf.actualcount)) { 7367 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 7368 nPortIndex, drv_ctx.op_buf.actualcount); 7369 return OMX_ErrorBadParameter; 7370 } 7371 7372 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { 7373 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex); 7374 return OMX_ErrorBadPortIndex; 7375 } 7376 7377 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7378 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg); 7379 return OMX_ErrorNone; 7380 } 7381 /* ====================================================================== 7382 FUNCTION 7383 omx_vdec::fill_this_buffer_proxy 7384 7385 DESCRIPTION 7386 IL client uses this method to release the frame buffer 7387 after displaying them. 7388 7389 PARAMETERS 7390 None. 7391 7392 RETURN VALUE 7393 true/false 7394 7395 ========================================================================== */ 7396 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( 7397 OMX_IN OMX_HANDLETYPE hComp, 7398 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) 7399 { 7400 OMX_ERRORTYPE nRet = OMX_ErrorNone; 7401 OMX_BUFFERHEADERTYPE *buffer = bufferAdd; 7402 unsigned nPortIndex = 0; 7403 struct vdec_fillbuffer_cmd fillbuffer; 7404 struct vdec_bufferpayload *ptr_outputbuffer = NULL; 7405 struct vdec_output_frameinfo *ptr_respbuffer = NULL; 7406 7407 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 7408 7409 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) { 7410 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 7411 nPortIndex, drv_ctx.op_buf.actualcount); 7412 return OMX_ErrorBadParameter; 7413 } 7414 7415 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", 7416 bufferAdd, bufferAdd->pBuffer); 7417 /*Return back the output buffer to client*/ 7418 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) { 7419 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition"); 7420 buffer->nFilledLen = 0; 7421 m_cb.FillBufferDone (hComp,m_app_data,buffer); 7422 return OMX_ErrorNone; 7423 } 7424 7425 if (dynamic_buf_mode) { 7426 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0; 7427 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen; 7428 buf_ref_add(nPortIndex); 7429 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen; 7430 } 7431 7432 pending_output_buffers++; 7433 buffer = client_buffers.get_dr_buf_hdr(bufferAdd); 7434 if (!buffer) { 7435 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid"); 7436 return OMX_ErrorBadParameter; 7437 } 7438 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; 7439 if (ptr_respbuffer) { 7440 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; 7441 } 7442 7443 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) { 7444 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); 7445 buffer->nFilledLen = 0; 7446 m_cb.FillBufferDone (hComp,m_app_data,buffer); 7447 pending_output_buffers--; 7448 return OMX_ErrorBadParameter; 7449 } 7450 7451 int rc = 0; 7452 struct v4l2_buffer buf; 7453 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 7454 memset( (void *)&buf, 0, sizeof(buf)); 7455 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); 7456 unsigned int extra_idx = 0; 7457 7458 buf.index = nPortIndex; 7459 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 7460 buf.memory = V4L2_MEMORY_USERPTR; 7461 plane[0].bytesused = buffer->nFilledLen; 7462 plane[0].length = buffer->nAllocLen; 7463 plane[0].m.userptr = 7464 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr - 7465 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset; 7466 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 7467 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 7468 plane[0].data_offset = 0; 7469 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 7470 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 7471 plane[extra_idx].bytesused = 0; 7472 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 7473 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size); 7474 #ifdef USE_ION 7475 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 7476 #endif 7477 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; 7478 plane[extra_idx].data_offset = 0; 7479 } else if (extra_idx >= VIDEO_MAX_PLANES) { 7480 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx); 7481 return OMX_ErrorBadParameter; 7482 } 7483 buf.m.planes = plane; 7484 buf.length = drv_ctx.num_planes; 7485 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d", 7486 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress); 7487 7488 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 7489 if (rc) { 7490 /*TODO: How to handle this case */ 7491 DEBUG_PRINT_ERROR("Failed to qbuf to driver"); 7492 } 7493 return OMX_ErrorNone; 7494 } 7495 7496 /* ====================================================================== 7497 FUNCTION 7498 omx_vdec::SetCallbacks 7499 7500 DESCRIPTION 7501 Set the callbacks. 7502 7503 PARAMETERS 7504 None. 7505 7506 RETURN VALUE 7507 OMX Error None if everything successful. 7508 7509 ========================================================================== */ 7510 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, 7511 OMX_IN OMX_CALLBACKTYPE* callbacks, 7512 OMX_IN OMX_PTR appData) 7513 { 7514 (void) hComp; 7515 m_cb = *callbacks; 7516 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ 7517 m_cb.EventHandler,m_cb.FillBufferDone); 7518 m_app_data = appData; 7519 return OMX_ErrorNotImplemented; 7520 } 7521 7522 /* ====================================================================== 7523 FUNCTION 7524 omx_vdec::ComponentDeInit 7525 7526 DESCRIPTION 7527 Destroys the component and release memory allocated to the heap. 7528 7529 PARAMETERS 7530 <TBD>. 7531 7532 RETURN VALUE 7533 OMX Error None if everything successful. 7534 7535 ========================================================================== */ 7536 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) 7537 { 7538 (void) hComp; 7539 7540 unsigned i = 0; 7541 if (OMX_StateLoaded != m_state) { 7542 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\ 7543 m_state); 7544 DEBUG_PRINT_ERROR("Playback Ended - FAILED"); 7545 } else { 7546 DEBUG_PRINT_HIGH("Playback Ended - PASSED"); 7547 } 7548 7549 /*Check if the output buffers have to be cleaned up*/ 7550 if (m_out_mem_ptr) { 7551 DEBUG_PRINT_LOW("Freeing the Output Memory"); 7552 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) { 7553 if (BITMASK_PRESENT(&m_out_bm_count, i)) { 7554 BITMASK_CLEAR(&m_out_bm_count, i); 7555 client_buffers.free_output_buffer (&m_out_mem_ptr[i]); 7556 } 7557 7558 if (release_output_done()) { 7559 break; 7560 } 7561 } 7562 #ifdef _ANDROID_ICS_ 7563 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 7564 #endif 7565 } 7566 7567 /*Check if the input buffers have to be cleaned up*/ 7568 if (m_inp_mem_ptr || m_inp_heap_ptr) { 7569 DEBUG_PRINT_LOW("Freeing the Input Memory"); 7570 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) { 7571 7572 if (BITMASK_PRESENT(&m_inp_bm_count, i)) { 7573 BITMASK_CLEAR(&m_inp_bm_count, i); 7574 if (m_inp_mem_ptr) 7575 free_input_buffer (i,&m_inp_mem_ptr[i]); 7576 else 7577 free_input_buffer (i,NULL); 7578 } 7579 7580 if (release_input_done()) { 7581 break; 7582 } 7583 } 7584 } 7585 free_input_buffer_header(); 7586 free_output_buffer_header(); 7587 if (h264_scratch.pBuffer) { 7588 free(h264_scratch.pBuffer); 7589 h264_scratch.pBuffer = NULL; 7590 } 7591 7592 if (h264_parser) { 7593 delete h264_parser; 7594 h264_parser = NULL; 7595 } 7596 7597 if (m_frame_parser.mutils) { 7598 DEBUG_PRINT_LOW("Free utils parser"); 7599 delete (m_frame_parser.mutils); 7600 m_frame_parser.mutils = NULL; 7601 } 7602 7603 if (m_platform_list) { 7604 free(m_platform_list); 7605 m_platform_list = NULL; 7606 } 7607 if (m_vendor_config.pData) { 7608 free(m_vendor_config.pData); 7609 m_vendor_config.pData = NULL; 7610 } 7611 7612 // Reset counters in mesg queues 7613 m_ftb_q.m_size=0; 7614 m_cmd_q.m_size=0; 7615 m_etb_q.m_size=0; 7616 m_ftb_q.m_read = m_ftb_q.m_write =0; 7617 m_cmd_q.m_read = m_cmd_q.m_write =0; 7618 m_etb_q.m_read = m_etb_q.m_write =0; 7619 #ifdef _ANDROID_ 7620 if (m_debug_timestamp) { 7621 m_timestamp_list.reset_ts_list(); 7622 } 7623 #endif 7624 7625 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG"); 7626 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, 7627 // NULL); 7628 DEBUG_PRINT_HIGH("Close the driver instance"); 7629 7630 if (m_debug.infile) { 7631 fclose(m_debug.infile); 7632 m_debug.infile = NULL; 7633 } 7634 if (m_debug.outfile) { 7635 fclose(m_debug.outfile); 7636 m_debug.outfile = NULL; 7637 } 7638 if (m_debug.out_ymeta_file) { 7639 fclose(m_debug.out_ymeta_file); 7640 m_debug.out_ymeta_file = NULL; 7641 } 7642 if (m_debug.out_uvmeta_file) { 7643 fclose(m_debug.out_uvmeta_file); 7644 m_debug.out_uvmeta_file = NULL; 7645 } 7646 #ifdef OUTPUT_EXTRADATA_LOG 7647 if (outputExtradataFile) 7648 fclose (outputExtradataFile); 7649 #endif 7650 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete"); 7651 return OMX_ErrorNone; 7652 } 7653 7654 /* ====================================================================== 7655 FUNCTION 7656 omx_vdec::UseEGLImage 7657 7658 DESCRIPTION 7659 OMX Use EGL Image method implementation <TBD>. 7660 7661 PARAMETERS 7662 <TBD>. 7663 7664 RETURN VALUE 7665 Not Implemented error. 7666 7667 ========================================================================== */ 7668 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, 7669 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 7670 OMX_IN OMX_U32 port, 7671 OMX_IN OMX_PTR appData, 7672 OMX_IN void* eglImage) 7673 { 7674 (void) appData; 7675 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; 7676 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; 7677 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; 7678 7679 #ifdef USE_EGL_IMAGE_GPU 7680 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; 7681 EGLint fd = -1, offset = 0,pmemPtr = 0; 7682 #else 7683 int fd = -1, offset = 0; 7684 #endif 7685 DEBUG_PRINT_HIGH("use EGL image support for decoder"); 7686 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { 7687 DEBUG_PRINT_ERROR("Invalid EGL image"); 7688 } 7689 #ifdef USE_EGL_IMAGE_GPU 7690 if (m_display_id == NULL) { 7691 DEBUG_PRINT_ERROR("Display ID is not set by IL client"); 7692 return OMX_ErrorInsufficientResources; 7693 } 7694 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) 7695 eglGetProcAddress("eglQueryImageKHR"); 7696 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd); 7697 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset); 7698 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr); 7699 #else //with OMX test app 7700 struct temp_egl { 7701 int pmem_fd; 7702 int offset; 7703 }; 7704 struct temp_egl *temp_egl_id = NULL; 7705 void * pmemPtr = (void *) eglImage; 7706 temp_egl_id = (struct temp_egl *)eglImage; 7707 if (temp_egl_id != NULL) { 7708 fd = temp_egl_id->pmem_fd; 7709 offset = temp_egl_id->offset; 7710 } 7711 #endif 7712 if (fd < 0) { 7713 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd); 7714 return OMX_ErrorInsufficientResources; 7715 } 7716 pmem_info.pmem_fd = (OMX_U32) fd; 7717 pmem_info.offset = (OMX_U32) offset; 7718 pmem_entry.entry = (void *) &pmem_info; 7719 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 7720 pmem_list.entryList = &pmem_entry; 7721 pmem_list.nEntries = 1; 7722 ouput_egl_buffers = true; 7723 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, 7724 (void *)&pmem_list, drv_ctx.op_buf.buffer_size, 7725 (OMX_U8 *)pmemPtr)) { 7726 DEBUG_PRINT_ERROR("use buffer call failed for egl image"); 7727 return OMX_ErrorInsufficientResources; 7728 } 7729 return OMX_ErrorNone; 7730 } 7731 7732 /* ====================================================================== 7733 FUNCTION 7734 omx_vdec::ComponentRoleEnum 7735 7736 DESCRIPTION 7737 OMX Component Role Enum method implementation. 7738 7739 PARAMETERS 7740 <TBD>. 7741 7742 RETURN VALUE 7743 OMX Error None if everything is successful. 7744 ========================================================================== */ 7745 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, 7746 OMX_OUT OMX_U8* role, 7747 OMX_IN OMX_U32 index) 7748 { 7749 (void) hComp; 7750 OMX_ERRORTYPE eRet = OMX_ErrorNone; 7751 7752 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 7753 if ((0 == index) && role) { 7754 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); 7755 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7756 } else { 7757 eRet = OMX_ErrorNoMore; 7758 } 7759 } 7760 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 7761 if ((0 == index) && role) { 7762 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); 7763 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7764 } else { 7765 eRet = OMX_ErrorNoMore; 7766 } 7767 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) { 7768 if ((0 == index) && role) { 7769 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 7770 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7771 } else { 7772 DEBUG_PRINT_LOW("No more roles"); 7773 eRet = OMX_ErrorNoMore; 7774 } 7775 } 7776 7777 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || 7778 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) { 7779 if ((0 == index) && role) { 7780 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 7781 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7782 } else { 7783 DEBUG_PRINT_LOW("No more roles"); 7784 eRet = OMX_ErrorNoMore; 7785 } 7786 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 7787 if ((0 == index) && role) { 7788 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 7789 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7790 } else { 7791 DEBUG_PRINT_LOW("No more roles"); 7792 eRet = OMX_ErrorNoMore; 7793 } 7794 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 7795 if ((0 == index) && role) { 7796 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 7797 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7798 } else { 7799 DEBUG_PRINT_LOW("No more roles"); 7800 eRet = OMX_ErrorNoMore; 7801 } 7802 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 7803 if ((0 == index) && role) { 7804 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 7805 DEBUG_PRINT_LOW("component_role_enum: role %s", role); 7806 } else { 7807 DEBUG_PRINT_LOW("No more roles"); 7808 eRet = OMX_ErrorNoMore; 7809 } 7810 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || 7811 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) 7812 ) { 7813 if ((0 == index) && role) { 7814 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 7815 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7816 } else { 7817 DEBUG_PRINT_LOW("No more roles"); 7818 eRet = OMX_ErrorNoMore; 7819 } 7820 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) { 7821 if ((0 == index) && role) { 7822 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 7823 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7824 } else { 7825 DEBUG_PRINT_LOW("No more roles"); 7826 eRet = OMX_ErrorNoMore; 7827 } 7828 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) { 7829 if ((0 == index) && role) { 7830 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE); 7831 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 7832 } else { 7833 DEBUG_PRINT_LOW("No more roles"); 7834 eRet = OMX_ErrorNoMore; 7835 } 7836 } else { 7837 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component"); 7838 eRet = OMX_ErrorInvalidComponentName; 7839 } 7840 return eRet; 7841 } 7842 7843 7844 7845 7846 /* ====================================================================== 7847 FUNCTION 7848 omx_vdec::AllocateDone 7849 7850 DESCRIPTION 7851 Checks if entire buffer pool is allocated by IL Client or not. 7852 Need this to move to IDLE state. 7853 7854 PARAMETERS 7855 None. 7856 7857 RETURN VALUE 7858 true/false. 7859 7860 ========================================================================== */ 7861 bool omx_vdec::allocate_done(void) 7862 { 7863 bool bRet = false; 7864 bool bRet_In = false; 7865 bool bRet_Out = false; 7866 7867 bRet_In = allocate_input_done(); 7868 bRet_Out = allocate_output_done(); 7869 7870 if (bRet_In && bRet_Out) { 7871 bRet = true; 7872 } 7873 7874 return bRet; 7875 } 7876 /* ====================================================================== 7877 FUNCTION 7878 omx_vdec::AllocateInputDone 7879 7880 DESCRIPTION 7881 Checks if I/P buffer pool is allocated by IL Client or not. 7882 7883 PARAMETERS 7884 None. 7885 7886 RETURN VALUE 7887 true/false. 7888 7889 ========================================================================== */ 7890 bool omx_vdec::allocate_input_done(void) 7891 { 7892 bool bRet = false; 7893 unsigned i=0; 7894 7895 if (m_inp_mem_ptr == NULL) { 7896 return bRet; 7897 } 7898 if (m_inp_mem_ptr ) { 7899 for (; i<drv_ctx.ip_buf.actualcount; i++) { 7900 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 7901 break; 7902 } 7903 } 7904 } 7905 if (i == drv_ctx.ip_buf.actualcount) { 7906 bRet = true; 7907 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers"); 7908 } 7909 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) { 7910 m_inp_bPopulated = OMX_TRUE; 7911 } 7912 return bRet; 7913 } 7914 /* ====================================================================== 7915 FUNCTION 7916 omx_vdec::AllocateOutputDone 7917 7918 DESCRIPTION 7919 Checks if entire O/P buffer pool is allocated by IL Client or not. 7920 7921 PARAMETERS 7922 None. 7923 7924 RETURN VALUE 7925 true/false. 7926 7927 ========================================================================== */ 7928 bool omx_vdec::allocate_output_done(void) 7929 { 7930 bool bRet = false; 7931 unsigned j=0; 7932 7933 if (m_out_mem_ptr == NULL) { 7934 return bRet; 7935 } 7936 7937 if (m_out_mem_ptr) { 7938 for (; j < drv_ctx.op_buf.actualcount; j++) { 7939 if (BITMASK_ABSENT(&m_out_bm_count,j)) { 7940 break; 7941 } 7942 } 7943 } 7944 7945 if (j == drv_ctx.op_buf.actualcount) { 7946 bRet = true; 7947 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers"); 7948 if (m_out_bEnabled) 7949 m_out_bPopulated = OMX_TRUE; 7950 } 7951 7952 return bRet; 7953 } 7954 7955 /* ====================================================================== 7956 FUNCTION 7957 omx_vdec::ReleaseDone 7958 7959 DESCRIPTION 7960 Checks if IL client has released all the buffers. 7961 7962 PARAMETERS 7963 None. 7964 7965 RETURN VALUE 7966 true/false 7967 7968 ========================================================================== */ 7969 bool omx_vdec::release_done(void) 7970 { 7971 bool bRet = false; 7972 7973 if (release_input_done()) { 7974 if (release_output_done()) { 7975 bRet = true; 7976 } 7977 } 7978 return bRet; 7979 } 7980 7981 7982 /* ====================================================================== 7983 FUNCTION 7984 omx_vdec::ReleaseOutputDone 7985 7986 DESCRIPTION 7987 Checks if IL client has released all the buffers. 7988 7989 PARAMETERS 7990 None. 7991 7992 RETURN VALUE 7993 true/false 7994 7995 ========================================================================== */ 7996 bool omx_vdec::release_output_done(void) 7997 { 7998 bool bRet = false; 7999 unsigned i=0,j=0; 8000 8001 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr); 8002 if (m_out_mem_ptr) { 8003 for (; j < drv_ctx.op_buf.actualcount ; j++) { 8004 if (BITMASK_PRESENT(&m_out_bm_count,j)) { 8005 break; 8006 } 8007 } 8008 if (j == drv_ctx.op_buf.actualcount) { 8009 m_out_bm_count = 0; 8010 bRet = true; 8011 } 8012 } else { 8013 m_out_bm_count = 0; 8014 bRet = true; 8015 } 8016 return bRet; 8017 } 8018 /* ====================================================================== 8019 FUNCTION 8020 omx_vdec::ReleaseInputDone 8021 8022 DESCRIPTION 8023 Checks if IL client has released all the buffers. 8024 8025 PARAMETERS 8026 None. 8027 8028 RETURN VALUE 8029 true/false 8030 8031 ========================================================================== */ 8032 bool omx_vdec::release_input_done(void) 8033 { 8034 bool bRet = false; 8035 unsigned i=0,j=0; 8036 8037 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr); 8038 if (m_inp_mem_ptr) { 8039 for (; j<drv_ctx.ip_buf.actualcount; j++) { 8040 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) { 8041 break; 8042 } 8043 } 8044 if (j==drv_ctx.ip_buf.actualcount) { 8045 bRet = true; 8046 } 8047 } else { 8048 bRet = true; 8049 } 8050 return bRet; 8051 } 8052 8053 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, 8054 OMX_BUFFERHEADERTYPE * buffer) 8055 { 8056 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; 8057 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) { 8058 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer); 8059 return OMX_ErrorBadParameter; 8060 } else if (output_flush_progress) { 8061 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); 8062 buffer->nFilledLen = 0; 8063 buffer->nTimeStamp = 0; 8064 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 8065 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 8066 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 8067 } 8068 8069 if (m_debug_extradata) { 8070 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 8071 DEBUG_PRINT_HIGH("***************************************************"); 8072 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received"); 8073 DEBUG_PRINT_HIGH("***************************************************"); 8074 } 8075 8076 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) { 8077 DEBUG_PRINT_HIGH("***************************************************"); 8078 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 8079 DEBUG_PRINT_HIGH("***************************************************"); 8080 } 8081 } 8082 8083 8084 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld", 8085 buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp); 8086 pending_output_buffers --; 8087 8088 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8089 DEBUG_PRINT_HIGH("Output EOS has been reached"); 8090 if (!output_flush_progress) 8091 post_event((unsigned)NULL, (unsigned)NULL, 8092 OMX_COMPONENT_GENERATE_EOS_DONE); 8093 8094 if (psource_frame) { 8095 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); 8096 psource_frame = NULL; 8097 } 8098 if (pdest_frame) { 8099 pdest_frame->nFilledLen = 0; 8100 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL, 8101 (unsigned)NULL); 8102 pdest_frame = NULL; 8103 } 8104 } 8105 8106 if (!output_flush_progress && (buffer->nFilledLen > 0)) { 8107 // set the default colorspace advised by client, since the bitstream may be 8108 // devoid of colorspace-info. 8109 if (m_enable_android_native_buffers) { 8110 ColorSpace_t color_space = ITU_R_601; 8111 8112 // Disabled ? 8113 // WA for VP8. Vp8 encoder does not embed color-info (yet!). 8114 // Encoding RGBA results in 601-LR for all resolutions. 8115 // This conflicts with the client't defaults which are based on resolution. 8116 // Eg: 720p will be encoded as 601-LR. Client will say 709. 8117 // Re-enable this code once vp8 encoder generates color-info and hence the 8118 // decoder will be able to override with the correct source color. 8119 #if 0 8120 switch (m_client_color_space.sAspects.mPrimaries) { 8121 case ColorAspects::PrimariesBT601_6_625: 8122 case ColorAspects::PrimariesBT601_6_525: 8123 { 8124 color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ? 8125 ITU_R_601_FR : ITU_R_601; 8126 break; 8127 } 8128 case ColorAspects::PrimariesBT709_5: 8129 { 8130 color_space = ITU_R_709; 8131 break; 8132 } 8133 default: 8134 { 8135 break; 8136 } 8137 } 8138 #endif 8139 DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)", 8140 color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709); 8141 set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr); 8142 } 8143 DEBUG_PRINT_LOW("Processing extradata"); 8144 handle_extradata(buffer); 8145 } 8146 8147 #ifdef OUTPUT_EXTRADATA_LOG 8148 if (outputExtradataFile) { 8149 int buf_index = buffer - m_out_mem_ptr; 8150 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr); 8151 8152 OMX_OTHER_EXTRADATATYPE *p_extra = NULL; 8153 p_extra = (OMX_OTHER_EXTRADATATYPE *) 8154 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3)); 8155 8156 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) { 8157 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x", 8158 p_extra->nSize, p_extra->eType); 8159 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); 8160 8161 if (p_extra->eType == OMX_ExtraDataNone) { 8162 break; 8163 } 8164 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 8165 } 8166 } 8167 #endif 8168 8169 /* For use buffer we need to copy the data */ 8170 if (!output_flush_progress) { 8171 /* This is the error check for non-recoverable errros */ 8172 bool is_duplicate_ts_valid = true; 8173 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive); 8174 8175 if (output_capability == V4L2_PIX_FMT_MPEG4 || 8176 output_capability == V4L2_PIX_FMT_MPEG2 || 8177 output_capability == V4L2_PIX_FMT_DIVX || 8178 output_capability == V4L2_PIX_FMT_DIVX_311) 8179 is_duplicate_ts_valid = false; 8180 8181 if ((output_capability == V4L2_PIX_FMT_H264 || 8182 output_capability == V4L2_PIX_FMT_H264_MVC) && 8183 is_interlaced) { 8184 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) { 8185 is_interlaced = false; 8186 } 8187 } 8188 8189 if (buffer->nFilledLen > 0) { 8190 time_stamp_dts.get_next_timestamp(buffer, 8191 is_interlaced && is_duplicate_ts_valid); 8192 if (m_debug_timestamp) { 8193 { 8194 OMX_TICKS expected_ts = 0; 8195 m_timestamp_list.pop_min_ts(expected_ts); 8196 if (is_interlaced && is_duplicate_ts_valid) { 8197 m_timestamp_list.pop_min_ts(expected_ts); 8198 } 8199 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", 8200 buffer->nTimeStamp, expected_ts); 8201 8202 if (buffer->nTimeStamp != expected_ts) { 8203 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check"); 8204 } 8205 } 8206 } 8207 } 8208 } 8209 8210 if (m_cb.FillBufferDone) { 8211 if (buffer->nFilledLen > 0) { 8212 if (arbitrary_bytes) 8213 adjust_timestamp(buffer->nTimeStamp); 8214 else 8215 set_frame_rate(buffer->nTimeStamp); 8216 8217 if (perf_flag) { 8218 if (!proc_frms) { 8219 dec_time.stop(); 8220 latency = dec_time.processing_time_us() - latency; 8221 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); 8222 dec_time.start(); 8223 fps_metrics.start(); 8224 } 8225 proc_frms++; 8226 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8227 OMX_U64 proc_time = 0; 8228 fps_metrics.stop(); 8229 proc_time = fps_metrics.processing_time_us(); 8230 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)", 8231 (unsigned int)proc_frms, (float)proc_time / 1e6, 8232 (float)(1e6 * proc_frms) / proc_time); 8233 proc_frms = 0; 8234 } 8235 } 8236 } 8237 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 8238 prev_ts = LLONG_MAX; 8239 rst_prev_ts = true; 8240 } 8241 8242 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 8243 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) 8244 buffer->pPlatformPrivate)->entryList->entry; 8245 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd); 8246 OMX_BUFFERHEADERTYPE *il_buffer; 8247 il_buffer = client_buffers.get_il_buf_hdr(buffer); 8248 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator); 8249 8250 if (il_buffer && m_last_rendered_TS >= 0) { 8251 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS); 8252 8253 // Current frame can be send for rendering if 8254 // (a) current FPS is <= 60 8255 // (b) is the next frame after the frame with TS 0 8256 // (c) is the first frame after seek 8257 // (d) the delta TS b\w two consecutive frames is > 16 ms 8258 // (e) its TS is equal to previous frame TS 8259 // (f) if marked EOS 8260 8261 if(current_framerate <= 60 || m_last_rendered_TS == 0 || 8262 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 || 8263 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 8264 m_last_rendered_TS = il_buffer->nTimeStamp; 8265 } else { 8266 //mark for droping 8267 buffer->nFilledLen = 0; 8268 } 8269 8270 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)", 8271 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS, 8272 il_buffer->nTimeStamp,ts_delta); 8273 8274 //above code makes sure that delta b\w two consecutive frames is not 8275 //greater than 16ms, slow-mo feature, so cap fps to max 60 8276 if (current_framerate > 60 ) { 8277 current_framerate = 60; 8278 } 8279 } 8280 8281 // add current framerate to gralloc meta data 8282 if (m_enable_android_native_buffers && m_out_mem_ptr) { 8283 OMX_U32 buf_index = buffer - m_out_mem_ptr; 8284 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 8285 UPDATE_REFRESH_RATE, (void*)¤t_framerate); 8286 } 8287 8288 if (il_buffer) { 8289 log_output_buffers(il_buffer); 8290 if (dynamic_buf_mode) { 8291 unsigned int nPortIndex = 0; 8292 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 8293 8294 // Since we're passing around handles, adjust nFilledLen and nAllocLen 8295 // to size of the handle. Do it _after_ log_output_buffers which 8296 // requires the respective sizes to be accurate. 8297 8298 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 8299 buffer->nFilledLen = buffer->nFilledLen ? 8300 sizeof(struct VideoDecoderOutputMetaData) : 0; 8301 8302 //Clear graphic buffer handles in dynamic mode 8303 if (nPortIndex < drv_ctx.op_buf.actualcount && 8304 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 8305 native_buffer[nPortIndex].privatehandle = NULL; 8306 native_buffer[nPortIndex].nativehandle = NULL; 8307 } else { 8308 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex); 8309 return OMX_ErrorBadParameter; 8310 } 8311 } 8312 m_cb.FillBufferDone (hComp,m_app_data,il_buffer); 8313 } else { 8314 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr"); 8315 return OMX_ErrorBadParameter; 8316 } 8317 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd); 8318 } else { 8319 return OMX_ErrorBadParameter; 8320 } 8321 8322 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED 8323 if (m_smoothstreaming_mode && m_out_mem_ptr) { 8324 OMX_U32 buf_index = buffer - m_out_mem_ptr; 8325 BufferDim_t dim; 8326 private_handle_t *private_handle = NULL; 8327 dim.sliceWidth = framesize.nWidth; 8328 dim.sliceHeight = framesize.nHeight; 8329 if (buf_index < drv_ctx.op_buf.actualcount && 8330 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 8331 native_buffer[buf_index].privatehandle) 8332 private_handle = native_buffer[buf_index].privatehandle; 8333 if (private_handle) { 8334 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d", 8335 dim.sliceWidth, dim.sliceHeight); 8336 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim); 8337 } 8338 } 8339 #endif 8340 8341 return OMX_ErrorNone; 8342 } 8343 8344 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, 8345 OMX_BUFFERHEADERTYPE* buffer) 8346 { 8347 8348 int nBufferIndex = buffer - m_inp_mem_ptr; 8349 8350 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) { 8351 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); 8352 return OMX_ErrorBadParameter; 8353 } 8354 8355 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x", 8356 buffer, buffer->pBuffer, buffer->nFlags); 8357 pending_input_buffers--; 8358 8359 if (arbitrary_bytes) { 8360 if (pdest_frame == NULL && input_flush_progress == false) { 8361 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer); 8362 pdest_frame = buffer; 8363 buffer->nFilledLen = 0; 8364 buffer->nTimeStamp = LLONG_MAX; 8365 push_input_buffer (hComp); 8366 } else { 8367 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer); 8368 buffer->nFilledLen = 0; 8369 if (!m_input_free_q.insert_entry((unsigned long)buffer, 8370 (unsigned)NULL, (unsigned)NULL)) { 8371 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error"); 8372 } 8373 } 8374 } else if (m_cb.EmptyBufferDone) { 8375 buffer->nFilledLen = 0; 8376 if (input_use_buffer == true) { 8377 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; 8378 } 8379 8380 /* Restore the FD that we over-wrote in ETB */ 8381 if (m_input_pass_buffer_fd) { 8382 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd; 8383 } 8384 8385 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); 8386 } 8387 return OMX_ErrorNone; 8388 } 8389 8390 int omx_vdec::async_message_process (void *context, void* message) 8391 { 8392 omx_vdec* omx = NULL; 8393 struct vdec_msginfo *vdec_msg = NULL; 8394 OMX_BUFFERHEADERTYPE* omxhdr = NULL; 8395 struct v4l2_buffer *v4l2_buf_ptr = NULL; 8396 struct vdec_output_frameinfo *output_respbuf = NULL; 8397 int rc=1; 8398 if (context == NULL || message == NULL) { 8399 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check"); 8400 return -1; 8401 } 8402 vdec_msg = (struct vdec_msginfo *)message; 8403 8404 omx = reinterpret_cast<omx_vdec*>(context); 8405 8406 switch (vdec_msg->msgcode) { 8407 8408 case VDEC_MSG_EVT_HW_ERROR: 8409 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8410 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 8411 break; 8412 8413 case VDEC_MSG_EVT_HW_OVERLOAD: 8414 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8415 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD); 8416 break; 8417 8418 case VDEC_MSG_EVT_HW_UNSUPPORTED: 8419 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8420 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); 8421 break; 8422 8423 case VDEC_MSG_RESP_START_DONE: 8424 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8425 OMX_COMPONENT_GENERATE_START_DONE); 8426 break; 8427 8428 case VDEC_MSG_RESP_STOP_DONE: 8429 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8430 OMX_COMPONENT_GENERATE_STOP_DONE); 8431 break; 8432 8433 case VDEC_MSG_RESP_RESUME_DONE: 8434 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8435 OMX_COMPONENT_GENERATE_RESUME_DONE); 8436 break; 8437 8438 case VDEC_MSG_RESP_PAUSE_DONE: 8439 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8440 OMX_COMPONENT_GENERATE_PAUSE_DONE); 8441 break; 8442 8443 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 8444 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8445 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); 8446 break; 8447 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 8448 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8449 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); 8450 break; 8451 case VDEC_MSG_RESP_INPUT_FLUSHED: 8452 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 8453 8454 /* omxhdr = (OMX_BUFFERHEADERTYPE* ) 8455 vdec_msg->msgdata.input_frame_clientdata; */ 8456 8457 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata; 8458 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL || 8459 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) { 8460 omxhdr = NULL; 8461 vdec_msg->status_code = VDEC_S_EFATAL; 8462 break; 8463 8464 } 8465 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index; 8466 8467 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) { 8468 DEBUG_PRINT_HIGH("Unsupported input"); 8469 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 8470 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 8471 } 8472 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 8473 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 8474 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR; 8475 } 8476 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 8477 8478 DEBUG_PRINT_LOW("Decrement codec_config buffer counter"); 8479 android_atomic_dec(&omx->m_queued_codec_config_count); 8480 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) && 8481 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) { 8482 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer"); 8483 sem_post(&omx->m_safe_flush); 8484 } 8485 } 8486 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || 8487 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 8488 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 8489 } 8490 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code, 8491 OMX_COMPONENT_GENERATE_EBD); 8492 break; 8493 case VDEC_MSG_EVT_INFO_FIELD_DROPPED: 8494 int64_t *timestamp; 8495 timestamp = (int64_t *) malloc(sizeof(int64_t)); 8496 if (timestamp) { 8497 *timestamp = vdec_msg->msgdata.output_frame.time_stamp; 8498 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code, 8499 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); 8500 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", 8501 (long long)vdec_msg->msgdata.output_frame.time_stamp); 8502 } 8503 break; 8504 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 8505 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 8506 8507 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; 8508 8509 if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL || 8510 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) { 8511 omxhdr = NULL; 8512 vdec_msg->status_code = VDEC_S_EFATAL; 8513 break; 8514 } 8515 8516 omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index; 8517 8518 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)", 8519 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp, 8520 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags, 8521 (unsigned int)vdec_msg->msgdata.output_frame.len, 8522 vdec_msg->msgdata.output_frame.framesize.left, 8523 vdec_msg->msgdata.output_frame.framesize.top, 8524 vdec_msg->msgdata.output_frame.framesize.right, 8525 vdec_msg->msgdata.output_frame.framesize.bottom); 8526 8527 if (omxhdr && omxhdr->pOutputPortPrivate && 8528 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) && 8529 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate 8530 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) { 8531 8532 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) { 8533 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; 8534 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; 8535 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp; 8536 omxhdr->nFlags = 0; 8537 8538 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) { 8539 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS; 8540 //rc = -1; 8541 } 8542 if (omxhdr->nFilledLen) { 8543 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 8544 } 8545 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 8546 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 8547 } else { 8548 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME; 8549 } 8550 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) { 8551 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 8552 } 8553 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) { 8554 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY; 8555 } 8556 8557 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) { 8558 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF; 8559 } 8560 8561 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) { 8562 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY; 8563 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d", 8564 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd); 8565 } 8566 8567 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) && 8568 !omx->output_flush_progress && 8569 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) && 8570 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) { 8571 unsigned int index = v4l2_buf_ptr->index; 8572 unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes); 8573 struct v4l2_plane *plane = v4l2_buf_ptr->m.planes; 8574 omx->time_stamp_dts.remove_time_stamp( 8575 omxhdr->nTimeStamp, 8576 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 8577 ?true:false); 8578 plane[0].bytesused = 0; 8579 plane[0].m.userptr = 8580 (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr - 8581 (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset; 8582 plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd; 8583 plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset; 8584 plane[0].data_offset = 0; 8585 v4l2_buf_ptr->flags = 0x0; 8586 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 8587 plane[extra_idx].bytesused = 0; 8588 plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size; 8589 plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size); 8590 #ifdef USE_ION 8591 plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd; 8592 #endif 8593 plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size; 8594 plane[extra_idx].data_offset = 0; 8595 } else if (extra_idx >= VIDEO_MAX_PLANES) { 8596 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx); 8597 return -1; 8598 } 8599 8600 DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d", 8601 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress); 8602 if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) { 8603 DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]); 8604 return -1; 8605 } 8606 break; 8607 } 8608 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 8609 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 8610 } 8611 vdec_msg->msgdata.output_frame.bufferaddr = 8612 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; 8613 8614 /* Post event if resolution OR crop changed */ 8615 /* filled length will be changed if resolution changed */ 8616 /* Crop parameters can be changed even without resolution change */ 8617 if (omxhdr->nFilledLen 8618 && ((omx->prev_n_filled_len != omxhdr->nFilledLen) 8619 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left) 8620 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top) 8621 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right) 8622 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom) 8623 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width) 8624 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) { 8625 8626 DEBUG_PRINT_HIGH("Paramters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u", 8627 omx->prev_n_filled_len, 8628 omx->drv_ctx.video_resolution.frame_width, 8629 omx->drv_ctx.video_resolution.frame_height, 8630 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top, 8631 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom, 8632 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width, 8633 vdec_msg->msgdata.output_frame.picsize.frame_height, 8634 vdec_msg->msgdata.output_frame.framesize.left, 8635 vdec_msg->msgdata.output_frame.framesize.top, 8636 vdec_msg->msgdata.output_frame.framesize.right, 8637 vdec_msg->msgdata.output_frame.framesize.bottom); 8638 8639 omx->drv_ctx.video_resolution.frame_width = 8640 vdec_msg->msgdata.output_frame.picsize.frame_width; 8641 omx->drv_ctx.video_resolution.frame_height = 8642 vdec_msg->msgdata.output_frame.picsize.frame_height; 8643 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 8644 omx->drv_ctx.video_resolution.stride = 8645 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width); 8646 omx->drv_ctx.video_resolution.scan_lines = 8647 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height); 8648 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 8649 omx->drv_ctx.video_resolution.stride = 8650 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width); 8651 omx->drv_ctx.video_resolution.scan_lines = 8652 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height); 8653 } 8654 8655 memcpy(&omx->drv_ctx.frame_size, 8656 &vdec_msg->msgdata.output_frame.framesize, 8657 sizeof(struct vdec_framesize)); 8658 8659 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX, 8660 OMX_IndexConfigCommonOutputCrop, 8661 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 8662 } 8663 8664 if (omxhdr->nFilledLen) 8665 omx->prev_n_filled_len = omxhdr->nFilledLen; 8666 8667 output_respbuf = (struct vdec_output_frameinfo *)\ 8668 omxhdr->pOutputPortPrivate; 8669 if (!output_respbuf) { 8670 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received"); 8671 return -1; 8672 } 8673 output_respbuf->len = vdec_msg->msgdata.output_frame.len; 8674 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; 8675 8676 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) { 8677 output_respbuf->pic_type = PICTURE_TYPE_I; 8678 } 8679 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) { 8680 output_respbuf->pic_type = PICTURE_TYPE_P; 8681 } 8682 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) { 8683 output_respbuf->pic_type = PICTURE_TYPE_B; 8684 } 8685 if (omxhdr && omxhdr->nFilledLen) { 8686 omx->request_perf_level(VIDC_NOMINAL); 8687 } 8688 if (omx->output_use_buffer && omxhdr->pBuffer && 8689 vdec_msg->msgdata.output_frame.bufferaddr) 8690 memcpy ( omxhdr->pBuffer, (void *) 8691 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr + 8692 (unsigned long)vdec_msg->msgdata.output_frame.offset), 8693 vdec_msg->msgdata.output_frame.len); 8694 } else { 8695 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u", 8696 (unsigned int)vdec_msg->msgdata.output_frame.len, 8697 omxhdr->nAllocLen, omx->prev_n_filled_len); 8698 omxhdr->nFilledLen = 0; 8699 } 8700 8701 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code, 8702 OMX_COMPONENT_GENERATE_FBD); 8703 8704 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) { 8705 omx->post_event ((unsigned long)NULL, vdec_msg->status_code, 8706 OMX_COMPONENT_GENERATE_EOS_DONE); 8707 } else { 8708 omx->post_event ((unsigned int)NULL, vdec_msg->status_code, 8709 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 8710 } 8711 break; 8712 case VDEC_MSG_EVT_CONFIG_CHANGED: 8713 DEBUG_PRINT_HIGH("Port settings changed"); 8714 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width; 8715 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height; 8716 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition, 8717 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 8718 omx->request_perf_level(VIDC_NOMINAL); 8719 break; 8720 default: 8721 break; 8722 } 8723 return rc; 8724 } 8725 8726 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( 8727 OMX_HANDLETYPE hComp, 8728 OMX_BUFFERHEADERTYPE *buffer 8729 ) 8730 { 8731 unsigned address,p2,id; 8732 DEBUG_PRINT_LOW("Empty this arbitrary"); 8733 8734 if (buffer == NULL) { 8735 return OMX_ErrorBadParameter; 8736 } 8737 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 8738 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld", 8739 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp); 8740 8741 /* return zero length and not an EOS buffer */ 8742 /* return buffer if input flush in progress */ 8743 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && 8744 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) { 8745 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress"); 8746 m_cb.EmptyBufferDone (hComp,m_app_data,buffer); 8747 return OMX_ErrorNone; 8748 } 8749 8750 if (psource_frame == NULL) { 8751 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp); 8752 psource_frame = buffer; 8753 DEBUG_PRINT_LOW("Try to Push One Input Buffer "); 8754 push_input_buffer (hComp); 8755 } else { 8756 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer); 8757 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL, 8758 (unsigned)NULL)) { 8759 return OMX_ErrorBadParameter; 8760 } 8761 } 8762 8763 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 8764 codec_config_flag = false; 8765 } 8766 return OMX_ErrorNone; 8767 } 8768 8769 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) 8770 { 8771 unsigned long address,p2,id; 8772 OMX_ERRORTYPE ret = OMX_ErrorNone; 8773 8774 if (pdest_frame == NULL || psource_frame == NULL) { 8775 /*Check if we have a destination buffer*/ 8776 if (pdest_frame == NULL) { 8777 DEBUG_PRINT_LOW("Get a Destination buffer from the queue"); 8778 if (m_input_free_q.m_size) { 8779 m_input_free_q.pop_entry(&address,&p2,&id); 8780 pdest_frame = (OMX_BUFFERHEADERTYPE *)address; 8781 pdest_frame->nFilledLen = 0; 8782 pdest_frame->nTimeStamp = LLONG_MAX; 8783 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame); 8784 } 8785 } 8786 8787 /*Check if we have a destination buffer*/ 8788 if (psource_frame == NULL) { 8789 DEBUG_PRINT_LOW("Get a source buffer from the queue"); 8790 if (m_input_pending_q.m_size) { 8791 m_input_pending_q.pop_entry(&address,&p2,&id); 8792 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 8793 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 8794 psource_frame->nTimeStamp); 8795 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 8796 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 8797 8798 } 8799 } 8800 8801 } 8802 8803 while ((pdest_frame != NULL) && (psource_frame != NULL)) { 8804 switch (codec_type_parse) { 8805 case CODEC_TYPE_MPEG4: 8806 case CODEC_TYPE_H263: 8807 case CODEC_TYPE_MPEG2: 8808 ret = push_input_sc_codec(hComp); 8809 break; 8810 case CODEC_TYPE_H264: 8811 ret = push_input_h264(hComp); 8812 break; 8813 case CODEC_TYPE_HEVC: 8814 ret = push_input_hevc(hComp); 8815 break; 8816 case CODEC_TYPE_VC1: 8817 ret = push_input_vc1(hComp); 8818 break; 8819 default: 8820 break; 8821 } 8822 if (ret != OMX_ErrorNone) { 8823 DEBUG_PRINT_ERROR("Pushing input Buffer Failed"); 8824 omx_report_error (); 8825 break; 8826 } 8827 } 8828 8829 return ret; 8830 } 8831 8832 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp) 8833 { 8834 OMX_U32 partial_frame = 1; 8835 OMX_BOOL generate_ebd = OMX_TRUE; 8836 unsigned long address = 0, p2 = 0, id = 0; 8837 8838 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld", 8839 psource_frame,psource_frame->nTimeStamp); 8840 if (m_frame_parser.parse_sc_frame(psource_frame, 8841 pdest_frame,&partial_frame) == -1) { 8842 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 8843 return OMX_ErrorBadParameter; 8844 } 8845 8846 if (partial_frame == 0) { 8847 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d", 8848 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count); 8849 8850 8851 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp); 8852 /*First Parsed buffer will have only header Hence skip*/ 8853 if (frame_count == 0) { 8854 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame "); 8855 8856 if (codec_type_parse == CODEC_TYPE_MPEG4 || 8857 codec_type_parse == CODEC_TYPE_DIVX) { 8858 mp4StreamType psBits; 8859 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset; 8860 psBits.numBytes = pdest_frame->nFilledLen; 8861 mp4_headerparser.parseHeader(&psBits); 8862 } 8863 8864 frame_count++; 8865 } else { 8866 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 8867 if (pdest_frame->nFilledLen) { 8868 /*Push the frame to the Decoder*/ 8869 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 8870 return OMX_ErrorBadParameter; 8871 } 8872 frame_count++; 8873 pdest_frame = NULL; 8874 8875 if (m_input_free_q.m_size) { 8876 m_input_free_q.pop_entry(&address,&p2,&id); 8877 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 8878 pdest_frame->nFilledLen = 0; 8879 } 8880 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) { 8881 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL"); 8882 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL, 8883 (unsigned)NULL); 8884 pdest_frame = NULL; 8885 } 8886 } 8887 } else { 8888 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen); 8889 /*Check if Destination Buffer is full*/ 8890 if (pdest_frame->nAllocLen == 8891 pdest_frame->nFilledLen + pdest_frame->nOffset) { 8892 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled"); 8893 return OMX_ErrorStreamCorrupt; 8894 } 8895 } 8896 8897 if (psource_frame->nFilledLen == 0) { 8898 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 8899 if (pdest_frame) { 8900 pdest_frame->nFlags |= psource_frame->nFlags; 8901 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld", 8902 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 8903 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 8904 (unsigned int)pdest_frame->nFilledLen,frame_count++); 8905 /*Push the frame to the Decoder*/ 8906 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 8907 return OMX_ErrorBadParameter; 8908 } 8909 frame_count++; 8910 pdest_frame = NULL; 8911 } else { 8912 DEBUG_PRINT_LOW("Last frame in else dest addr") ; 8913 generate_ebd = OMX_FALSE; 8914 } 8915 } 8916 if (generate_ebd) { 8917 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame); 8918 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 8919 psource_frame = NULL; 8920 8921 if (m_input_pending_q.m_size) { 8922 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 8923 m_input_pending_q.pop_entry(&address,&p2,&id); 8924 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 8925 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 8926 psource_frame->nTimeStamp); 8927 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 8928 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 8929 } 8930 } 8931 } 8932 return OMX_ErrorNone; 8933 } 8934 8935 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) 8936 { 8937 OMX_U32 partial_frame = 1; 8938 unsigned long address = 0, p2 = 0, id = 0; 8939 OMX_BOOL isNewFrame = OMX_FALSE; 8940 OMX_BOOL generate_ebd = OMX_TRUE; 8941 8942 if (h264_scratch.pBuffer == NULL) { 8943 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated"); 8944 return OMX_ErrorBadParameter; 8945 } 8946 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u " 8947 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal); 8948 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen); 8949 if (h264_scratch.nFilledLen && look_ahead_nal) { 8950 look_ahead_nal = false; 8951 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 8952 h264_scratch.nFilledLen) { 8953 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 8954 h264_scratch.pBuffer,h264_scratch.nFilledLen); 8955 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 8956 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame"); 8957 h264_scratch.nFilledLen = 0; 8958 } else { 8959 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264"); 8960 return OMX_ErrorBadParameter; 8961 } 8962 } 8963 8964 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result 8965 in EOS flag getting associated with the destination 8966 */ 8967 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) && 8968 pdest_frame->nFilledLen) { 8969 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'"); 8970 generate_ebd = OMX_FALSE; 8971 } 8972 8973 if (nal_length == 0) { 8974 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code"); 8975 if (m_frame_parser.parse_sc_frame(psource_frame, 8976 &h264_scratch,&partial_frame) == -1) { 8977 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 8978 return OMX_ErrorBadParameter; 8979 } 8980 } else { 8981 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length); 8982 if (m_frame_parser.parse_h264_nallength(psource_frame, 8983 &h264_scratch,&partial_frame) == -1) { 8984 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 8985 return OMX_ErrorBadParameter; 8986 } 8987 } 8988 8989 if (partial_frame == 0) { 8990 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 8991 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 8992 nal_count++; 8993 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 8994 h264_scratch.nFlags = psource_frame->nFlags; 8995 } else { 8996 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen); 8997 if (h264_scratch.nFilledLen) { 8998 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen, 8999 NALU_TYPE_SPS); 9000 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9001 if (client_extradata & OMX_TIMEINFO_EXTRADATA) 9002 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 9003 h264_scratch.nFilledLen, NALU_TYPE_SEI); 9004 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 9005 // If timeinfo is present frame info from SEI is already processed 9006 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 9007 h264_scratch.nFilledLen, NALU_TYPE_SEI); 9008 #endif 9009 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 9010 nal_count++; 9011 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) { 9012 pdest_frame->nTimeStamp = h264_last_au_ts; 9013 pdest_frame->nFlags = h264_last_au_flags; 9014 #ifdef PANSCAN_HDLR 9015 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 9016 h264_parser->update_panscan_data(h264_last_au_ts); 9017 #endif 9018 } 9019 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR || 9020 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) { 9021 h264_last_au_ts = h264_scratch.nTimeStamp; 9022 h264_last_au_flags = h264_scratch.nFlags; 9023 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9024 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 9025 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts); 9026 if (!VALID_TS(h264_last_au_ts)) 9027 h264_last_au_ts = ts_in_sei; 9028 } 9029 #endif 9030 } else 9031 h264_last_au_ts = LLONG_MAX; 9032 } 9033 9034 if (!isNewFrame) { 9035 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9036 h264_scratch.nFilledLen) { 9037 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u", 9038 (unsigned int)h264_scratch.nFilledLen); 9039 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9040 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9041 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9042 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ) 9043 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 9044 h264_scratch.nFilledLen = 0; 9045 } else { 9046 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264"); 9047 return OMX_ErrorBadParameter; 9048 } 9049 } else if(h264_scratch.nFilledLen) { 9050 look_ahead_nal = true; 9051 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu", 9052 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 9053 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 9054 (unsigned int)pdest_frame->nFilledLen,frame_count++); 9055 9056 if (pdest_frame->nFilledLen == 0) { 9057 DEBUG_PRINT_LOW("Copy the Current Frame since and push it"); 9058 look_ahead_nal = false; 9059 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9060 h264_scratch.nFilledLen) { 9061 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9062 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9063 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9064 h264_scratch.nFilledLen = 0; 9065 } else { 9066 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264"); 9067 return OMX_ErrorBadParameter; 9068 } 9069 } else { 9070 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 9071 DEBUG_PRINT_LOW("Reset the EOS Flag"); 9072 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 9073 } 9074 /*Push the frame to the Decoder*/ 9075 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9076 return OMX_ErrorBadParameter; 9077 } 9078 //frame_count++; 9079 pdest_frame = NULL; 9080 if (m_input_free_q.m_size) { 9081 m_input_free_q.pop_entry(&address,&p2,&id); 9082 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 9083 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame); 9084 pdest_frame->nFilledLen = 0; 9085 pdest_frame->nFlags = 0; 9086 pdest_frame->nTimeStamp = LLONG_MAX; 9087 } 9088 } 9089 } 9090 } 9091 } else { 9092 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen); 9093 /*Check if Destination Buffer is full*/ 9094 if (h264_scratch.nAllocLen == 9095 h264_scratch.nFilledLen + h264_scratch.nOffset) { 9096 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 9097 return OMX_ErrorStreamCorrupt; 9098 } 9099 } 9100 9101 if (!psource_frame->nFilledLen) { 9102 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame); 9103 9104 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 9105 if (pdest_frame) { 9106 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 9107 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 9108 h264_scratch.nFilledLen) { 9109 if(pdest_frame->nFilledLen == 0) { 9110 /* No residual frame from before, send whatever 9111 * we have left */ 9112 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9113 h264_scratch.pBuffer, h264_scratch.nFilledLen); 9114 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9115 h264_scratch.nFilledLen = 0; 9116 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 9117 } else { 9118 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 9119 if(!isNewFrame) { 9120 /* Have a residual frame, but we know that the 9121 * AU in this frame is belonging to whatever 9122 * frame we had left over. So append it */ 9123 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 9124 h264_scratch.pBuffer,h264_scratch.nFilledLen); 9125 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 9126 h264_scratch.nFilledLen = 0; 9127 if (h264_last_au_ts != LLONG_MAX) 9128 pdest_frame->nTimeStamp = h264_last_au_ts; 9129 } else { 9130 /* Completely new frame, let's just push what 9131 * we have now. The resulting EBD would trigger 9132 * another push */ 9133 generate_ebd = OMX_FALSE; 9134 pdest_frame->nTimeStamp = h264_last_au_ts; 9135 h264_last_au_ts = h264_scratch.nTimeStamp; 9136 } 9137 } 9138 } else { 9139 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264"); 9140 return OMX_ErrorBadParameter; 9141 } 9142 9143 /* Iff we coalesced two buffers, inherit the flags of both bufs */ 9144 if(generate_ebd == OMX_TRUE) { 9145 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 9146 } 9147 9148 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu", 9149 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 9150 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++); 9151 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 9152 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 9153 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp); 9154 if (!VALID_TS(pdest_frame->nTimeStamp)) 9155 pdest_frame->nTimeStamp = ts_in_sei; 9156 } 9157 #endif 9158 /*Push the frame to the Decoder*/ 9159 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 9160 return OMX_ErrorBadParameter; 9161 } 9162 frame_count++; 9163 pdest_frame = NULL; 9164 } else { 9165 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 9166 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 9167 generate_ebd = OMX_FALSE; 9168 } 9169 } 9170 } 9171 if (generate_ebd && !psource_frame->nFilledLen) { 9172 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 9173 psource_frame = NULL; 9174 if (m_input_pending_q.m_size) { 9175 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 9176 m_input_pending_q.pop_entry(&address,&p2,&id); 9177 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 9178 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u", 9179 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 9180 } 9181 } 9182 return OMX_ErrorNone; 9183 } 9184 9185 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc) 9186 { 9187 OMX_ERRORTYPE rc = OMX_ErrorNone; 9188 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) { 9189 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen); 9190 if (pDst->nTimeStamp == LLONG_MAX) { 9191 pDst->nTimeStamp = pSrc->nTimeStamp; 9192 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp); 9193 } 9194 pDst->nFilledLen += pSrc->nFilledLen; 9195 pSrc->nFilledLen = 0; 9196 } else { 9197 DEBUG_PRINT_ERROR("Error: Destination buffer overflow"); 9198 rc = OMX_ErrorBadParameter; 9199 } 9200 return rc; 9201 } 9202 9203 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp) 9204 { 9205 OMX_U32 partial_frame = 1; 9206 unsigned long address,p2,id; 9207 OMX_BOOL isNewFrame = OMX_FALSE; 9208 OMX_BOOL generate_ebd = OMX_TRUE; 9209 OMX_ERRORTYPE rc = OMX_ErrorNone; 9210 if (h264_scratch.pBuffer == NULL) { 9211 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated"); 9212 return OMX_ErrorBadParameter; 9213 } 9214 9215 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \ 9216 pdest_frame nFilledLen %u nTimeStamp %lld", 9217 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 9218 9219 if (h264_scratch.nFilledLen && look_ahead_nal) { 9220 look_ahead_nal = false; 9221 rc = copy_buffer(pdest_frame, &h264_scratch); 9222 if (rc != OMX_ErrorNone) { 9223 return rc; 9224 } 9225 } 9226 9227 if (nal_length == 0) { 9228 if (m_frame_parser.parse_sc_frame(psource_frame, 9229 &h264_scratch,&partial_frame) == -1) { 9230 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 9231 return OMX_ErrorBadParameter; 9232 } 9233 } else { 9234 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length); 9235 if (m_frame_parser.parse_h264_nallength(psource_frame, 9236 &h264_scratch,&partial_frame) == -1) { 9237 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 9238 return OMX_ErrorBadParameter; 9239 } 9240 } 9241 9242 if (partial_frame == 0) { 9243 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 9244 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 9245 nal_count++; 9246 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 9247 h264_scratch.nFlags = psource_frame->nFlags; 9248 } else { 9249 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen); 9250 if (h264_scratch.nFilledLen) { 9251 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame); 9252 nal_count++; 9253 } 9254 9255 if (!isNewFrame) { 9256 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \ 9257 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld", 9258 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp, 9259 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 9260 rc = copy_buffer(pdest_frame, &h264_scratch); 9261 if (rc != OMX_ErrorNone) { 9262 return rc; 9263 } 9264 } else { 9265 look_ahead_nal = true; 9266 if (pdest_frame->nFilledLen == 0) { 9267 look_ahead_nal = false; 9268 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer"); 9269 rc = copy_buffer(pdest_frame, &h264_scratch); 9270 if (rc != OMX_ErrorNone) { 9271 return OMX_ErrorBadParameter; 9272 } 9273 } else { 9274 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 9275 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 9276 } 9277 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \ 9278 nTimeStamp %lld, look_ahead_nal in h264_scratch \ 9279 nFilledLen %u nTimeStamp %lld", 9280 frame_count++, (unsigned int)pdest_frame->nFilledLen, 9281 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen, 9282 h264_scratch.nTimeStamp); 9283 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 9284 return OMX_ErrorBadParameter; 9285 } 9286 pdest_frame = NULL; 9287 if (m_input_free_q.m_size) { 9288 m_input_free_q.pop_entry(&address, &p2, &id); 9289 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 9290 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame); 9291 pdest_frame->nFilledLen = 0; 9292 pdest_frame->nFlags = 0; 9293 pdest_frame->nTimeStamp = LLONG_MAX; 9294 } 9295 } 9296 } 9297 } 9298 } else { 9299 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \ 9300 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \ 9301 nFilledLen %u nTimeStamp %lld", 9302 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp, 9303 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp, 9304 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp); 9305 9306 if (h264_scratch.nAllocLen == 9307 h264_scratch.nFilledLen + h264_scratch.nOffset) { 9308 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 9309 return OMX_ErrorStreamCorrupt; 9310 } 9311 } 9312 9313 if (!psource_frame->nFilledLen) { 9314 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame); 9315 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 9316 if (pdest_frame) { 9317 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 9318 rc = copy_buffer(pdest_frame, &h264_scratch); 9319 if ( rc != OMX_ErrorNone ) { 9320 return rc; 9321 } 9322 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 9323 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 9324 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld", 9325 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 9326 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 9327 return OMX_ErrorBadParameter; 9328 } 9329 frame_count++; 9330 pdest_frame = NULL; 9331 } else { 9332 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 9333 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 9334 generate_ebd = OMX_FALSE; 9335 } 9336 } 9337 } 9338 9339 if (generate_ebd && !psource_frame->nFilledLen) { 9340 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame); 9341 psource_frame = NULL; 9342 if (m_input_pending_q.m_size) { 9343 m_input_pending_q.pop_entry(&address, &p2, &id); 9344 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 9345 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld", 9346 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp); 9347 } 9348 } 9349 return OMX_ErrorNone; 9350 } 9351 9352 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp) 9353 { 9354 OMX_U8 *buf, *pdest; 9355 OMX_U32 partial_frame = 1; 9356 OMX_U32 buf_len, dest_len; 9357 9358 if (first_frame == 0) { 9359 first_frame = 1; 9360 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes"); 9361 if (!m_vendor_config.pData) { 9362 DEBUG_PRINT_LOW("Check profile type in 1st source buffer"); 9363 buf = psource_frame->pBuffer; 9364 buf_len = psource_frame->nFilledLen; 9365 9366 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) == 9367 VC1_SP_MP_START_CODE) { 9368 m_vc1_profile = VC1_SP_MP_RCV; 9369 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) { 9370 m_vc1_profile = VC1_AP; 9371 } else { 9372 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer"); 9373 return OMX_ErrorStreamCorrupt; 9374 } 9375 } else { 9376 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen + 9377 pdest_frame->nOffset; 9378 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen + 9379 pdest_frame->nOffset); 9380 9381 if (dest_len < m_vendor_config.nDataSize) { 9382 DEBUG_PRINT_ERROR("Destination buffer full"); 9383 return OMX_ErrorBadParameter; 9384 } else { 9385 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize); 9386 pdest_frame->nFilledLen += m_vendor_config.nDataSize; 9387 } 9388 } 9389 } 9390 9391 switch (m_vc1_profile) { 9392 case VC1_AP: 9393 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code"); 9394 if (push_input_sc_codec(hComp) != OMX_ErrorNone) { 9395 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code"); 9396 return OMX_ErrorBadParameter; 9397 } 9398 break; 9399 9400 case VC1_SP_MP_RCV: 9401 default: 9402 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode"); 9403 return OMX_ErrorBadParameter; 9404 } 9405 return OMX_ErrorNone; 9406 } 9407 9408 #ifndef USE_ION 9409 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, 9410 OMX_U32 alignment) 9411 { 9412 struct pmem_allocation allocation; 9413 allocation.size = buffer_size; 9414 allocation.align = clip2(alignment); 9415 if (allocation.align < 4096) { 9416 allocation.align = 4096; 9417 } 9418 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) { 9419 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)", 9420 allocation.align, allocation.size); 9421 return false; 9422 } 9423 return true; 9424 } 9425 #endif 9426 #ifdef USE_ION 9427 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, 9428 OMX_U32 alignment, struct ion_allocation_data *alloc_data, 9429 struct ion_fd_data *fd_data, int flag) 9430 { 9431 int fd = -EINVAL; 9432 int rc = -EINVAL; 9433 int ion_dev_flag; 9434 struct vdec_ion ion_buf_info; 9435 if (!alloc_data || buffer_size <= 0 || !fd_data) { 9436 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory"); 9437 return -EINVAL; 9438 } 9439 ion_dev_flag = O_RDONLY; 9440 fd = open (MEM_DEVICE, ion_dev_flag); 9441 if (fd < 0) { 9442 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd); 9443 return fd; 9444 } 9445 9446 alloc_data->flags = flag; 9447 alloc_data->len = buffer_size; 9448 alloc_data->align = clip2(alignment); 9449 if (alloc_data->align < 4096) { 9450 alloc_data->align = 4096; 9451 } 9452 9453 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID); 9454 if (secure_mode && (alloc_data->flags & ION_SECURE)) { 9455 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID); 9456 } 9457 9458 /* Use secure display cma heap for obvious reasons. */ 9459 if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) { 9460 alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); 9461 } 9462 9463 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); 9464 if (rc || !alloc_data->handle) { 9465 DEBUG_PRINT_ERROR("ION ALLOC memory failed"); 9466 alloc_data->handle = 0; 9467 close(fd); 9468 fd = -ENOMEM; 9469 return fd; 9470 } 9471 fd_data->handle = alloc_data->handle; 9472 rc = ioctl(fd,ION_IOC_MAP,fd_data); 9473 if (rc) { 9474 DEBUG_PRINT_ERROR("ION MAP failed "); 9475 ion_buf_info.ion_alloc_data = *alloc_data; 9476 ion_buf_info.ion_device_fd = fd; 9477 ion_buf_info.fd_ion_data = *fd_data; 9478 free_ion_memory(&ion_buf_info); 9479 fd_data->fd =-1; 9480 fd = -ENOMEM; 9481 } 9482 9483 return fd; 9484 } 9485 9486 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) 9487 { 9488 9489 if (!buf_ion_info) { 9490 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata"); 9491 return; 9492 } 9493 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, 9494 &buf_ion_info->ion_alloc_data.handle)) { 9495 DEBUG_PRINT_ERROR("ION: free failed" ); 9496 } 9497 close(buf_ion_info->ion_device_fd); 9498 buf_ion_info->ion_device_fd = -1; 9499 buf_ion_info->ion_alloc_data.handle = 0; 9500 buf_ion_info->fd_ion_data.fd = -1; 9501 } 9502 #endif 9503 void omx_vdec::free_output_buffer_header() 9504 { 9505 DEBUG_PRINT_HIGH("ALL output buffers are freed/released"); 9506 output_use_buffer = false; 9507 ouput_egl_buffers = false; 9508 9509 if (m_out_mem_ptr) { 9510 free (m_out_mem_ptr); 9511 m_out_mem_ptr = NULL; 9512 } 9513 9514 if (m_platform_list) { 9515 free(m_platform_list); 9516 m_platform_list = NULL; 9517 } 9518 9519 if (drv_ctx.ptr_respbuffer) { 9520 free (drv_ctx.ptr_respbuffer); 9521 drv_ctx.ptr_respbuffer = NULL; 9522 } 9523 if (drv_ctx.ptr_outputbuffer) { 9524 free (drv_ctx.ptr_outputbuffer); 9525 drv_ctx.ptr_outputbuffer = NULL; 9526 } 9527 #ifdef USE_ION 9528 if (drv_ctx.op_buf_ion_info) { 9529 DEBUG_PRINT_LOW("Free o/p ion context"); 9530 free(drv_ctx.op_buf_ion_info); 9531 drv_ctx.op_buf_ion_info = NULL; 9532 } 9533 #endif 9534 buf_ref_remove(); 9535 } 9536 9537 void omx_vdec::free_input_buffer_header() 9538 { 9539 input_use_buffer = false; 9540 if (arbitrary_bytes) { 9541 if (m_inp_heap_ptr) { 9542 DEBUG_PRINT_LOW("Free input Heap Pointer"); 9543 free (m_inp_heap_ptr); 9544 m_inp_heap_ptr = NULL; 9545 } 9546 9547 if (m_phdr_pmem_ptr) { 9548 DEBUG_PRINT_LOW("Free input pmem header Pointer"); 9549 free (m_phdr_pmem_ptr); 9550 m_phdr_pmem_ptr = NULL; 9551 } 9552 } 9553 if (m_inp_mem_ptr) { 9554 DEBUG_PRINT_LOW("Free input pmem Pointer area"); 9555 free (m_inp_mem_ptr); 9556 m_inp_mem_ptr = NULL; 9557 } 9558 /* We just freed all the buffer headers, every thing in m_input_free_q, 9559 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */ 9560 while (m_input_free_q.m_size) { 9561 unsigned long address, p2, id; 9562 m_input_free_q.pop_entry(&address, &p2, &id); 9563 } 9564 while (m_input_pending_q.m_size) { 9565 unsigned long address, p2, id; 9566 m_input_pending_q.pop_entry(&address, &p2, &id); 9567 } 9568 pdest_frame = NULL; 9569 psource_frame = NULL; 9570 if (drv_ctx.ptr_inputbuffer) { 9571 DEBUG_PRINT_LOW("Free Driver Context pointer"); 9572 free (drv_ctx.ptr_inputbuffer); 9573 drv_ctx.ptr_inputbuffer = NULL; 9574 } 9575 #ifdef USE_ION 9576 if (drv_ctx.ip_buf_ion_info) { 9577 DEBUG_PRINT_LOW("Free ion context"); 9578 free(drv_ctx.ip_buf_ion_info); 9579 drv_ctx.ip_buf_ion_info = NULL; 9580 } 9581 #endif 9582 } 9583 9584 int omx_vdec::stream_off(OMX_U32 port) 9585 { 9586 enum v4l2_buf_type btype; 9587 int rc = 0; 9588 enum v4l2_ports v4l2_port = OUTPUT_PORT; 9589 9590 if (port == OMX_CORE_INPUT_PORT_INDEX) { 9591 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9592 v4l2_port = OUTPUT_PORT; 9593 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 9594 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9595 v4l2_port = CAPTURE_PORT; 9596 } else if (port == OMX_ALL) { 9597 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX); 9598 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 9599 9600 if (!rc_input) 9601 return rc_input; 9602 else 9603 return rc_output; 9604 } 9605 9606 if (!streaming[v4l2_port]) { 9607 // already streamed off, warn and move on 9608 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port," 9609 " which is already streamed off", v4l2_port); 9610 return 0; 9611 } 9612 9613 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port); 9614 9615 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); 9616 if (rc) { 9617 /*TODO: How to handle this case */ 9618 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port); 9619 } else { 9620 streaming[v4l2_port] = false; 9621 } 9622 9623 return rc; 9624 } 9625 9626 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) 9627 { 9628 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9629 struct v4l2_requestbuffers bufreq; 9630 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0; 9631 unsigned int final_extra_data_size = 0; 9632 struct v4l2_format fmt; 9633 int ret = 0; 9634 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 9635 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 9636 bufreq.memory = V4L2_MEMORY_USERPTR; 9637 bufreq.count = 1; 9638 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 9639 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9640 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9641 fmt.fmt.pix_mp.pixelformat = output_capability; 9642 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 9643 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9644 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9645 fmt.fmt.pix_mp.pixelformat = capture_capability; 9646 } else { 9647 eRet = OMX_ErrorBadParameter; 9648 } 9649 if (eRet==OMX_ErrorNone) { 9650 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 9651 } 9652 if (ret) { 9653 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 9654 /*TODO: How to handle this case */ 9655 eRet = OMX_ErrorInsufficientResources; 9656 return eRet; 9657 } else { 9658 buffer_prop->actualcount = bufreq.count; 9659 buffer_prop->mincount = bufreq.count; 9660 DEBUG_PRINT_HIGH("Count = %d",bufreq.count); 9661 } 9662 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 9663 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 9664 9665 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 9666 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 9667 9668 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 9669 9670 update_resolution(fmt.fmt.pix_mp.width, 9671 fmt.fmt.pix_mp.height, 9672 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, 9673 fmt.fmt.pix_mp.plane_fmt[0].reserved[0]); 9674 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 9675 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes; 9676 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage); 9677 9678 if (ret) { 9679 /*TODO: How to handle this case */ 9680 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 9681 eRet = OMX_ErrorInsufficientResources; 9682 } else { 9683 int extra_idx = 0; 9684 9685 eRet = is_video_session_supported(); 9686 if (eRet) 9687 return eRet; 9688 9689 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; 9690 buf_size = buffer_prop->buffer_size; 9691 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 9692 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 9693 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage; 9694 } else if (extra_idx >= VIDEO_MAX_PLANES) { 9695 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 9696 return OMX_ErrorBadParameter; 9697 } 9698 9699 default_extra_data_size = VENUS_EXTRADATA_SIZE( 9700 drv_ctx.video_resolution.frame_height, 9701 drv_ctx.video_resolution.frame_width); 9702 final_extra_data_size = extra_data_size > default_extra_data_size ? 9703 extra_data_size : default_extra_data_size; 9704 9705 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) & 9706 (~(buffer_prop->alignment - 1)); 9707 9708 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size; 9709 drv_ctx.extradata_info.count = buffer_prop->actualcount; 9710 drv_ctx.extradata_info.buffer_size = final_extra_data_size; 9711 if (!secure_mode) 9712 buf_size += final_extra_data_size; 9713 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 9714 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)", 9715 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size); 9716 if (extra_data_size) 9717 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)", 9718 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size); 9719 9720 if (in_reconfig) // BufReq will be set to driver when port is disabled 9721 buffer_prop->buffer_size = buf_size; 9722 else if (buf_size != buffer_prop->buffer_size) { 9723 buffer_prop->buffer_size = buf_size; 9724 eRet = set_buffer_req(buffer_prop); 9725 } 9726 } 9727 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)", 9728 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 9729 return eRet; 9730 } 9731 9732 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) 9733 { 9734 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9735 unsigned buf_size = 0; 9736 struct v4l2_format fmt; 9737 struct v4l2_requestbuffers bufreq; 9738 int ret; 9739 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)", 9740 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 9741 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 9742 if (buf_size != buffer_prop->buffer_size) { 9743 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)", 9744 (unsigned int)buffer_prop->buffer_size, buf_size); 9745 eRet = OMX_ErrorBadParameter; 9746 } else { 9747 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 9748 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 9749 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 9750 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size; 9751 9752 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 9753 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9754 fmt.fmt.pix_mp.pixelformat = output_capability; 9755 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 9756 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9757 fmt.fmt.pix_mp.pixelformat = capture_capability; 9758 } else { 9759 eRet = OMX_ErrorBadParameter; 9760 } 9761 9762 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 9763 if (ret) { 9764 /*TODO: How to handle this case */ 9765 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret); 9766 eRet = OMX_ErrorInsufficientResources; 9767 } 9768 9769 bufreq.memory = V4L2_MEMORY_USERPTR; 9770 bufreq.count = buffer_prop->actualcount; 9771 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 9772 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9773 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 9774 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9775 } else { 9776 eRet = OMX_ErrorBadParameter; 9777 } 9778 9779 if (eRet==OMX_ErrorNone) { 9780 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 9781 } 9782 9783 if (ret) { 9784 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret); 9785 /*TODO: How to handle this case */ 9786 eRet = OMX_ErrorInsufficientResources; 9787 } else if (bufreq.count < buffer_prop->actualcount) { 9788 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers" 9789 " on v4l2 port %d to %d (prefers %d)", bufreq.type, 9790 buffer_prop->actualcount, bufreq.count); 9791 eRet = OMX_ErrorInsufficientResources; 9792 } else { 9793 if (!client_buffers.update_buffer_req()) { 9794 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); 9795 eRet = OMX_ErrorInsufficientResources; 9796 } 9797 } 9798 } 9799 return eRet; 9800 } 9801 9802 OMX_ERRORTYPE omx_vdec::update_picture_resolution() 9803 { 9804 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9805 return eRet; 9806 } 9807 9808 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) 9809 { 9810 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9811 struct v4l2_format fmt; 9812 if (!portDefn) { 9813 return OMX_ErrorBadParameter; 9814 } 9815 DEBUG_PRINT_LOW("omx_vdec::update_portdef"); 9816 portDefn->nVersion.nVersion = OMX_SPEC_VERSION; 9817 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 9818 portDefn->eDomain = OMX_PortDomainVideo; 9819 if (drv_ctx.frame_rate.fps_denominator > 0) 9820 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator / 9821 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format 9822 else { 9823 DEBUG_PRINT_ERROR("Error: Divide by zero"); 9824 return OMX_ErrorBadParameter; 9825 } 9826 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 9827 if (0 == portDefn->nPortIndex) { 9828 portDefn->eDir = OMX_DirInput; 9829 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; 9830 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; 9831 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size; 9832 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; 9833 portDefn->format.video.eCompressionFormat = eCompressionFormat; 9834 portDefn->bEnabled = m_inp_bEnabled; 9835 portDefn->bPopulated = m_inp_bPopulated; 9836 9837 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9838 fmt.fmt.pix_mp.pixelformat = output_capability; 9839 } else if (1 == portDefn->nPortIndex) { 9840 unsigned int buf_size = 0; 9841 if (!client_buffers.update_buffer_req()) { 9842 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed"); 9843 return OMX_ErrorHardware; 9844 } 9845 if (!client_buffers.get_buffer_req(buf_size)) { 9846 DEBUG_PRINT_ERROR("update buffer requirements"); 9847 return OMX_ErrorHardware; 9848 } 9849 portDefn->nBufferSize = buf_size; 9850 portDefn->eDir = OMX_DirOutput; 9851 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; 9852 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; 9853 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 9854 portDefn->bEnabled = m_out_bEnabled; 9855 portDefn->bPopulated = m_out_bPopulated; 9856 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) { 9857 DEBUG_PRINT_ERROR("Error in getting color format"); 9858 return OMX_ErrorHardware; 9859 } 9860 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 9861 fmt.fmt.pix_mp.pixelformat = capture_capability; 9862 } else { 9863 portDefn->eDir = OMX_DirMax; 9864 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", 9865 (int)portDefn->nPortIndex); 9866 eRet = OMX_ErrorBadPortIndex; 9867 } 9868 if (is_down_scalar_enabled) { 9869 int ret = 0; 9870 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 9871 if (ret) { 9872 DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution"); 9873 return OMX_ErrorHardware; 9874 } else { 9875 portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width; 9876 portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height; 9877 portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; 9878 portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0]; 9879 } 9880 } else { 9881 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; 9882 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; 9883 portDefn->format.video.nStride = drv_ctx.video_resolution.stride; 9884 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; 9885 } 9886 9887 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) || 9888 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) { 9889 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16); 9890 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height; 9891 } 9892 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d " 9893 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u", 9894 (unsigned int)portDefn->nPortIndex, 9895 (unsigned int)portDefn->format.video.nFrameWidth, 9896 (unsigned int)portDefn->format.video.nFrameHeight, 9897 (int)portDefn->format.video.nStride, 9898 (unsigned int)portDefn->format.video.nSliceHeight, 9899 (unsigned int)portDefn->format.video.eColorFormat, 9900 (unsigned int)portDefn->nBufferSize, 9901 (unsigned int)portDefn->nBufferCountActual); 9902 9903 return eRet; 9904 } 9905 9906 OMX_ERRORTYPE omx_vdec::allocate_output_headers() 9907 { 9908 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9909 OMX_BUFFERHEADERTYPE *bufHdr = NULL; 9910 unsigned i= 0; 9911 9912 if (!m_out_mem_ptr) { 9913 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation"); 9914 int nBufHdrSize = 0; 9915 int nPlatformEntrySize = 0; 9916 int nPlatformListSize = 0; 9917 int nPMEMInfoSize = 0; 9918 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 9919 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 9920 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 9921 9922 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)", 9923 drv_ctx.op_buf.actualcount); 9924 nBufHdrSize = drv_ctx.op_buf.actualcount * 9925 sizeof(OMX_BUFFERHEADERTYPE); 9926 9927 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 9928 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 9929 nPlatformListSize = drv_ctx.op_buf.actualcount * 9930 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 9931 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 9932 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 9933 9934 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 9935 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 9936 nPMEMInfoSize, 9937 nPlatformListSize); 9938 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize, 9939 m_out_bm_count); 9940 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 9941 // Alloc mem for platform specific info 9942 char *pPtr=NULL; 9943 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 9944 nPMEMInfoSize,1); 9945 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ 9946 calloc (sizeof(struct vdec_bufferpayload), 9947 drv_ctx.op_buf.actualcount); 9948 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 9949 calloc (sizeof (struct vdec_output_frameinfo), 9950 drv_ctx.op_buf.actualcount); 9951 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 9952 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer"); 9953 return OMX_ErrorInsufficientResources; 9954 } 9955 9956 #ifdef USE_ION 9957 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ 9958 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); 9959 if (!drv_ctx.op_buf_ion_info) { 9960 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 9961 return OMX_ErrorInsufficientResources; 9962 } 9963 #endif 9964 if (dynamic_buf_mode) { 9965 out_dynamic_list = (struct dynamic_buf_list *) \ 9966 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount); 9967 if (out_dynamic_list) { 9968 for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++) 9969 out_dynamic_list[i].dup_fd = -1; 9970 } 9971 } 9972 9973 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 9974 && drv_ctx.ptr_respbuffer) { 9975 bufHdr = m_out_mem_ptr; 9976 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 9977 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 9978 (((char *) m_platform_list) + nPlatformListSize); 9979 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 9980 (((char *) m_platform_entry) + nPlatformEntrySize); 9981 pPlatformList = m_platform_list; 9982 pPlatformEntry = m_platform_entry; 9983 pPMEMInfo = m_pmem_info; 9984 9985 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 9986 9987 // Settting the entire storage nicely 9988 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, 9989 m_out_mem_ptr,pPlatformEntry); 9990 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 9991 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 9992 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 9993 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 9994 // Set the values when we determine the right HxW param 9995 bufHdr->nAllocLen = 0; 9996 bufHdr->nFilledLen = 0; 9997 bufHdr->pAppPrivate = NULL; 9998 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9999 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 10000 pPlatformEntry->entry = pPMEMInfo; 10001 // Initialize the Platform List 10002 pPlatformList->nEntries = 1; 10003 pPlatformList->entryList = pPlatformEntry; 10004 // Keep pBuffer NULL till vdec is opened 10005 bufHdr->pBuffer = NULL; 10006 pPMEMInfo->offset = 0; 10007 pPMEMInfo->pmem_fd = -1; 10008 bufHdr->pPlatformPrivate = pPlatformList; 10009 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; 10010 #ifdef USE_ION 10011 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; 10012 #endif 10013 /*Create a mapping between buffers*/ 10014 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 10015 drv_ctx.ptr_respbuffer[i].client_data = (void *) \ 10016 &drv_ctx.ptr_outputbuffer[i]; 10017 // Move the buffer and buffer header pointers 10018 bufHdr++; 10019 pPMEMInfo++; 10020 pPlatformEntry++; 10021 pPlatformList++; 10022 } 10023 } else { 10024 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 10025 m_out_mem_ptr, pPtr); 10026 if (m_out_mem_ptr) { 10027 free(m_out_mem_ptr); 10028 m_out_mem_ptr = NULL; 10029 } 10030 if (pPtr) { 10031 free(pPtr); 10032 pPtr = NULL; 10033 } 10034 if (drv_ctx.ptr_outputbuffer) { 10035 free(drv_ctx.ptr_outputbuffer); 10036 drv_ctx.ptr_outputbuffer = NULL; 10037 } 10038 if (drv_ctx.ptr_respbuffer) { 10039 free(drv_ctx.ptr_respbuffer); 10040 drv_ctx.ptr_respbuffer = NULL; 10041 } 10042 #ifdef USE_ION 10043 if (drv_ctx.op_buf_ion_info) { 10044 DEBUG_PRINT_LOW("Free o/p ion context"); 10045 free(drv_ctx.op_buf_ion_info); 10046 drv_ctx.op_buf_ion_info = NULL; 10047 } 10048 #endif 10049 eRet = OMX_ErrorInsufficientResources; 10050 } 10051 } else { 10052 eRet = OMX_ErrorInsufficientResources; 10053 } 10054 return eRet; 10055 } 10056 10057 void omx_vdec::complete_pending_buffer_done_cbs() 10058 { 10059 unsigned long p1, p2, ident; 10060 omx_cmd_queue tmp_q, pending_bd_q; 10061 pthread_mutex_lock(&m_lock); 10062 // pop all pending GENERATE FDB from ftb queue 10063 while (m_ftb_q.m_size) { 10064 m_ftb_q.pop_entry(&p1,&p2,&ident); 10065 if (ident == OMX_COMPONENT_GENERATE_FBD) { 10066 pending_bd_q.insert_entry(p1,p2,ident); 10067 } else { 10068 tmp_q.insert_entry(p1,p2,ident); 10069 } 10070 } 10071 //return all non GENERATE FDB to ftb queue 10072 while (tmp_q.m_size) { 10073 tmp_q.pop_entry(&p1,&p2,&ident); 10074 m_ftb_q.insert_entry(p1,p2,ident); 10075 } 10076 // pop all pending GENERATE EDB from etb queue 10077 while (m_etb_q.m_size) { 10078 m_etb_q.pop_entry(&p1,&p2,&ident); 10079 if (ident == OMX_COMPONENT_GENERATE_EBD) { 10080 pending_bd_q.insert_entry(p1,p2,ident); 10081 } else { 10082 tmp_q.insert_entry(p1,p2,ident); 10083 } 10084 } 10085 //return all non GENERATE FDB to etb queue 10086 while (tmp_q.m_size) { 10087 tmp_q.pop_entry(&p1,&p2,&ident); 10088 m_etb_q.insert_entry(p1,p2,ident); 10089 } 10090 pthread_mutex_unlock(&m_lock); 10091 // process all pending buffer dones 10092 while (pending_bd_q.m_size) { 10093 pending_bd_q.pop_entry(&p1,&p2,&ident); 10094 switch (ident) { 10095 case OMX_COMPONENT_GENERATE_EBD: 10096 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) { 10097 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!"); 10098 omx_report_error (); 10099 } 10100 break; 10101 10102 case OMX_COMPONENT_GENERATE_FBD: 10103 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) { 10104 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!"); 10105 omx_report_error (); 10106 } 10107 break; 10108 } 10109 } 10110 } 10111 10112 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) 10113 { 10114 OMX_U32 new_frame_interval = 0; 10115 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts 10116 && llabs(act_timestamp - prev_ts) > 2000) { 10117 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ? 10118 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual); 10119 if (new_frame_interval != frm_int || frm_int == 0) { 10120 frm_int = new_frame_interval; 10121 if (frm_int) { 10122 drv_ctx.frame_rate.fps_numerator = 1e6; 10123 drv_ctx.frame_rate.fps_denominator = frm_int; 10124 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", 10125 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 10126 (float)drv_ctx.frame_rate.fps_denominator); 10127 m_perf_control.request_cores(frm_int); 10128 /* We need to report the difference between this FBD and the previous FBD 10129 * back to the driver for clock scaling purposes. */ 10130 struct v4l2_outputparm oparm; 10131 /*XXX: we're providing timing info as seconds per frame rather than frames 10132 * per second.*/ 10133 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 10134 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 10135 10136 struct v4l2_streamparm sparm; 10137 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10138 sparm.parm.output = oparm; 10139 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 10140 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 10141 performance might be affected"); 10142 } 10143 10144 } 10145 } 10146 } 10147 prev_ts = act_timestamp; 10148 } 10149 10150 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) 10151 { 10152 if (rst_prev_ts && VALID_TS(act_timestamp)) { 10153 prev_ts = act_timestamp; 10154 prev_ts_actual = act_timestamp; 10155 rst_prev_ts = false; 10156 } else if (VALID_TS(prev_ts)) { 10157 bool codec_cond = (drv_ctx.timestamp_adjust)? 10158 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) : 10159 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual); 10160 prev_ts_actual = act_timestamp; //unadjusted previous timestamp 10161 if (frm_int > 0 && codec_cond) { 10162 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); 10163 act_timestamp = prev_ts + frm_int; 10164 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); 10165 prev_ts = act_timestamp; 10166 } else { 10167 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) { 10168 // ensure that timestamps can never step backwards when in display order 10169 act_timestamp = prev_ts; 10170 } 10171 set_frame_rate(act_timestamp); 10172 } 10173 } else if (frm_int > 0) // In this case the frame rate was set along 10174 { // with the port definition, start ts with 0 10175 act_timestamp = prev_ts = 0; // and correct if a valid ts is received. 10176 rst_prev_ts = true; 10177 } 10178 } 10179 10180 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range, 10181 OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects) 10182 { 10183 switch (primaries) { 10184 case MSM_VIDC_BT709_5: 10185 *color_space = ITU_R_709; 10186 aspects->mPrimaries = ColorAspects::PrimariesBT709_5; 10187 break; 10188 case MSM_VIDC_BT470_6_M: 10189 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M; 10190 break; 10191 case MSM_VIDC_BT601_6_625: 10192 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; 10193 break; 10194 case MSM_VIDC_BT601_6_525: 10195 *color_space = range ? ITU_R_601_FR : ITU_R_601; 10196 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525; 10197 break; 10198 case MSM_VIDC_GENERIC_FILM: 10199 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm; 10200 break; 10201 case MSM_VIDC_BT2020: 10202 aspects->mPrimaries = ColorAspects::PrimariesBT2020; 10203 break; 10204 case MSM_VIDC_UNSPECIFIED: 10205 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default 10206 default: 10207 //aspects->mPrimaries = ColorAspects::PrimariesOther; 10208 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 10209 break; 10210 } 10211 10212 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited; 10213 10214 switch (transfer) { 10215 case MSM_VIDC_TRANSFER_BT709_5: 10216 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625: 10217 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 10218 break; 10219 case MSM_VIDC_TRANSFER_BT_470_6_M: 10220 aspects->mTransfer = ColorAspects::TransferGamma22; 10221 break; 10222 case MSM_VIDC_TRANSFER_BT_470_6_BG: 10223 aspects->mTransfer = ColorAspects::TransferGamma28; 10224 break; 10225 case MSM_VIDC_TRANSFER_SMPTE_240M: 10226 aspects->mTransfer = ColorAspects::TransferSMPTE240M; 10227 break; 10228 case MSM_VIDC_TRANSFER_LINEAR: 10229 aspects->mTransfer = ColorAspects::TransferLinear; 10230 break; 10231 case MSM_VIDC_TRANSFER_IEC_61966: 10232 aspects->mTransfer = ColorAspects::TransferXvYCC; 10233 break; 10234 case MSM_VIDC_TRANSFER_BT_1361: 10235 aspects->mTransfer = ColorAspects::TransferBT1361; 10236 break; 10237 case MSM_VIDC_TRANSFER_SRGB: 10238 aspects->mTransfer = ColorAspects::TransferSRGB; 10239 break; 10240 default: 10241 //aspects->mTransfer = ColorAspects::TransferOther; 10242 aspects->mTransfer = m_client_color_space.sAspects.mTransfer; 10243 break; 10244 } 10245 10246 switch (matrix) { 10247 case MSM_VIDC_MATRIX_BT_709_5: 10248 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 10249 break; 10250 case MSM_VIDC_MATRIX_FCC_47: 10251 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M; 10252 break; 10253 case MSM_VIDC_MATRIX_601_6_625: 10254 case MSM_VIDC_MATRIX_601_6_525: 10255 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; 10256 break; 10257 case MSM_VIDC_MATRIX_SMPTE_240M: 10258 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M; 10259 break; 10260 case MSM_VIDC_MATRIX_BT_2020: 10261 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; 10262 break; 10263 case MSM_VIDC_MATRIX_BT_2020_CONST: 10264 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant; 10265 break; 10266 default: 10267 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther; 10268 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; 10269 break; 10270 } 10271 } 10272 10273 void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) { 10274 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d", 10275 prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs); 10276 } 10277 10278 void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index) 10279 { 10280 ColorSpace_t color_space = ITU_R_601; 10281 ColorAspects tempAspects; 10282 memset(&tempAspects, 0x0, sizeof(ColorAspects)); 10283 ColorAspects *aspects = &tempAspects; 10284 10285 switch(output_capability) { 10286 case V4L2_PIX_FMT_MPEG2: 10287 { 10288 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload; 10289 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data; 10290 10291 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to 10292 * understand this code */ 10293 10294 if (seqdisp_payload && seqdisp_payload->color_descp) { 10295 10296 convert_color_space_info(seqdisp_payload->color_primaries, 1, 10297 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs, 10298 &color_space,aspects); 10299 m_disp_hor_size = seqdisp_payload->disp_width; 10300 m_disp_vert_size = seqdisp_payload->disp_height; 10301 } 10302 } 10303 break; 10304 case V4L2_PIX_FMT_H264: 10305 case V4L2_PIX_FMT_HEVC: 10306 { 10307 struct msm_vidc_vui_display_info_payload *display_info_payload; 10308 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data; 10309 10310 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */ 10311 10312 if (display_info_payload->video_signal_present_flag && 10313 display_info_payload->color_description_present_flag) { 10314 convert_color_space_info(display_info_payload->color_primaries, 10315 display_info_payload->video_full_range_flag, 10316 display_info_payload->transfer_characteristics, 10317 display_info_payload->matrix_coefficients, 10318 &color_space,aspects); 10319 } 10320 } 10321 break; 10322 case V4L2_PIX_FMT_VC1_ANNEX_G: 10323 case V4L2_PIX_FMT_VC1_ANNEX_L: 10324 { 10325 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload; 10326 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data; 10327 10328 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23 10329 * SMPTE 421M to understand this code */ 10330 10331 if (m_enable_android_native_buffers && 10332 vc1_seq_disp_payload->color_primaries) { 10333 10334 convert_color_space_info(vc1_seq_disp_payload->color_primaries, 10335 1, 10336 vc1_seq_disp_payload->transfer_char, 10337 vc1_seq_disp_payload->matrix_coeffs, 10338 &color_space,aspects); 10339 } 10340 } 10341 break; 10342 case V4L2_PIX_FMT_VP8: 10343 { 10344 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; 10345 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; 10346 10347 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011 10348 * to understand this code */ 10349 10350 if (vpx_color_space_payload->color_space == 0) { 10351 color_space = ITU_R_601; 10352 } else { 10353 DEBUG_PRINT_ERROR("Unsupported Color space for VP8"); 10354 break; 10355 } 10356 } 10357 break; 10358 case V4L2_PIX_FMT_VP9: 10359 { 10360 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; 10361 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; 10362 10363 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016 10364 * to understand this code */ 10365 10366 switch(vpx_color_space_payload->color_space) { 10367 case MSM_VIDC_CS_BT_601: 10368 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; 10369 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 10370 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; 10371 aspects->mRange = m_client_color_space.sAspects.mRange; 10372 break; 10373 case MSM_VIDC_CS_BT_709: 10374 color_space = ITU_R_709; 10375 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 10376 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 10377 aspects->mPrimaries = ColorAspects::PrimariesBT709_5; 10378 aspects->mRange = m_client_color_space.sAspects.mRange; 10379 break; 10380 case MSM_VIDC_CS_SMPTE_170: 10381 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 10382 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 10383 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 10384 aspects->mRange = m_client_color_space.sAspects.mRange; 10385 break; 10386 case MSM_VIDC_CS_SMPTE_240: 10387 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; 10388 aspects->mTransfer = ColorAspects::TransferSMPTE240M; 10389 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; 10390 aspects->mRange = m_client_color_space.sAspects.mRange; 10391 break; 10392 case MSM_VIDC_CS_BT_2020: 10393 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; 10394 aspects->mTransfer = ColorAspects:: TransferSMPTE170M; 10395 aspects->mPrimaries = ColorAspects::PrimariesBT2020; 10396 aspects->mRange = m_client_color_space.sAspects.mRange; 10397 break; 10398 case MSM_VIDC_CS_RESERVED: 10399 aspects->mMatrixCoeffs = ColorAspects::MatrixOther; 10400 aspects->mTransfer = ColorAspects::TransferOther; 10401 aspects->mPrimaries = ColorAspects::PrimariesOther; 10402 aspects->mRange = m_client_color_space.sAspects.mRange; 10403 break; 10404 case MSM_VIDC_CS_RGB: 10405 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; 10406 aspects->mTransfer = ColorAspects::TransferSMPTE170M; 10407 aspects->mPrimaries = ColorAspects::PrimariesOther; 10408 aspects->mRange = m_client_color_space.sAspects.mRange; 10409 break; 10410 default: 10411 break; 10412 } 10413 } 10414 break; 10415 default: 10416 break; 10417 } 10418 if (m_enable_android_native_buffers) { 10419 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); 10420 set_colorspace_in_handle(color_space, buf_index); 10421 } 10422 print_debug_color_aspects(aspects, "Bitstream"); 10423 10424 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries || 10425 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer || 10426 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs || 10427 m_internal_color_space.sAspects.mRange != aspects->mRange) { 10428 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects)); 10429 m_internal_color_space.bDataSpaceChanged = OMX_TRUE; 10430 10431 DEBUG_PRINT_HIGH("Initiating PORT Reconfig"); 10432 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal"); 10433 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client"); 10434 10435 post_event(OMX_CORE_OUTPUT_PORT_INDEX, 10436 OMX_QTIIndexConfigDescribeColorAspects, 10437 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 10438 } 10439 } 10440 10441 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) { 10442 private_handle_t *private_handle = NULL; 10443 if (buf_index < drv_ctx.op_buf.actualcount && 10444 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 10445 native_buffer[buf_index].privatehandle) { 10446 private_handle = native_buffer[buf_index].privatehandle; 10447 } 10448 if (private_handle) { 10449 setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space); 10450 } 10451 } 10452 10453 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) 10454 { 10455 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; 10456 OMX_U32 num_conceal_MB = 0; 10457 OMX_TICKS time_stamp = 0; 10458 OMX_U32 frame_rate = 0; 10459 unsigned long consumed_len = 0; 10460 OMX_U32 num_MB_in_frame; 10461 OMX_U32 recovery_sei_flags = 1; 10462 int enable = 0; 10463 10464 int buf_index = p_buf_hdr - m_out_mem_ptr; 10465 if (buf_index >= drv_ctx.extradata_info.count) { 10466 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", 10467 buf_index, drv_ctx.extradata_info.count); 10468 return; 10469 } 10470 struct msm_vidc_panscan_window_payload *panscan_payload = NULL; 10471 10472 if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) { 10473 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL"); 10474 return; 10475 } 10476 10477 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) + 10478 p_buf_hdr->nOffset; 10479 10480 if (!drv_ctx.extradata_info.uaddr) { 10481 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr"); 10482 return; 10483 } 10484 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) { 10485 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data"); 10486 p_extra = NULL; 10487 return; 10488 } 10489 if (!secure_mode) 10490 p_extra = (OMX_OTHER_EXTRADATATYPE *) 10491 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3)); 10492 else 10493 p_extra = m_other_extradata; 10494 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size; 10495 10496 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { 10497 p_extra = NULL; 10498 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); 10499 return; 10500 } 10501 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; 10502 if (data && p_extra) { 10503 while ((consumed_len < drv_ctx.extradata_info.buffer_size) 10504 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) { 10505 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) { 10506 DEBUG_PRINT_LOW("Invalid extra data size"); 10507 break; 10508 } 10509 10510 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { 10511 p_extra = NULL; 10512 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); 10513 return; 10514 } 10515 10516 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType); 10517 switch ((unsigned long)data->eType) { 10518 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO: 10519 struct msm_vidc_interlace_payload *payload; 10520 OMX_U32 interlace_color_format; 10521 payload = (struct msm_vidc_interlace_payload *)(void *)data->data; 10522 if (payload) { 10523 enable = 1; 10524 switch (payload->format) { 10525 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE: 10526 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 10527 enable = 0; 10528 break; 10529 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST: 10530 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 10531 break; 10532 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST: 10533 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst; 10534 break; 10535 default: 10536 DEBUG_PRINT_LOW("default case - set interlace to topfield"); 10537 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 10538 } 10539 switch (payload->color_format) { 10540 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12: 10541 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 10542 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; 10543 break; 10544 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC: 10545 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 10546 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC; 10547 break; 10548 default: 10549 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 10550 DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame"); 10551 } 10552 } 10553 10554 if (m_enable_android_native_buffers) { 10555 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d", 10556 payload->format, interlace_color_format ,enable, 10557 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false); 10558 10559 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 10560 PP_PARAM_INTERLACED, (void*)&enable); 10561 10562 if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) { 10563 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 10564 LINEAR_FORMAT, (void*)&interlace_color_format); 10565 } 10566 } 10567 if (client_extradata & OMX_INTERLACE_EXTRADATA) { 10568 append_interlace_extradata(p_extra, payload->format, 10569 p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF); 10570 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10571 } 10572 break; 10573 case MSM_VIDC_EXTRADATA_FRAME_RATE: 10574 struct msm_vidc_framerate_payload *frame_rate_payload; 10575 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data; 10576 frame_rate = frame_rate_payload->frame_rate; 10577 break; 10578 case MSM_VIDC_EXTRADATA_TIMESTAMP: 10579 struct msm_vidc_ts_payload *time_stamp_payload; 10580 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data; 10581 time_stamp = time_stamp_payload->timestamp_lo; 10582 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32); 10583 p_buf_hdr->nTimeStamp = time_stamp; 10584 break; 10585 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB: 10586 struct msm_vidc_concealmb_payload *conceal_mb_payload; 10587 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data; 10588 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 10589 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 10590 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0); 10591 break; 10592 case MSM_VIDC_EXTRADATA_INDEX: 10593 int *etype; 10594 etype = (int *)(void *)data->data; 10595 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) { 10596 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload; 10597 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype); 10598 if (aspect_ratio_payload) { 10599 ((struct vdec_output_frameinfo *) 10600 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width; 10601 ((struct vdec_output_frameinfo *) 10602 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height; 10603 } 10604 } 10605 break; 10606 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI: 10607 struct msm_vidc_recoverysei_payload *recovery_sei_payload; 10608 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data; 10609 recovery_sei_flags = recovery_sei_payload->flags; 10610 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) { 10611 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 10612 DEBUG_PRINT_HIGH("***************************************************"); 10613 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 10614 DEBUG_PRINT_HIGH("***************************************************"); 10615 } 10616 break; 10617 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW: 10618 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data; 10619 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) { 10620 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n"); 10621 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n", 10622 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows); 10623 return; 10624 } 10625 break; 10626 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP: 10627 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO: 10628 case MSM_VIDC_EXTRADATA_VC1_SEQDISP: 10629 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO: 10630 handle_color_space_info((void *)data->data, buf_index); 10631 break; 10632 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING: 10633 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload; 10634 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data; 10635 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) { 10636 append_framepack_extradata(p_extra, s3d_frame_packing_payload); 10637 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10638 } 10639 break; 10640 case MSM_VIDC_EXTRADATA_FRAME_QP: 10641 struct msm_vidc_frame_qp_payload *qp_payload; 10642 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data; 10643 if (client_extradata & OMX_QP_EXTRADATA) { 10644 append_qp_extradata(p_extra, qp_payload); 10645 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10646 } 10647 break; 10648 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO: 10649 struct msm_vidc_frame_bits_info_payload *bits_info_payload; 10650 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data; 10651 if (client_extradata & OMX_BITSINFO_EXTRADATA) { 10652 append_bitsinfo_extradata(p_extra, bits_info_payload); 10653 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10654 } 10655 break; 10656 case MSM_VIDC_EXTRADATA_STREAM_USERDATA: 10657 if (client_extradata & OMX_EXTNUSER_EXTRADATA) { 10658 append_user_extradata(p_extra, data); 10659 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10660 } 10661 break; 10662 case MSM_VIDC_EXTRADATA_VQZIP_SEI: 10663 struct msm_vidc_vqzip_sei_payload *vqzip_payload; 10664 vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data; 10665 if (client_extradata & OMX_VQZIPSEI_EXTRADATA) { 10666 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 10667 append_vqzip_extradata(p_extra, vqzip_payload); 10668 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10669 } 10670 break; 10671 default: 10672 DEBUG_PRINT_LOW("Unrecognized extradata"); 10673 goto unrecognized_extradata; 10674 } 10675 consumed_len += data->nSize; 10676 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); 10677 } 10678 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) { 10679 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 10680 append_frame_info_extradata(p_extra, 10681 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate, 10682 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *) 10683 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info); 10684 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10685 } 10686 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) { 10687 append_frame_dimension_extradata(p_extra); 10688 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 10689 } 10690 } 10691 unrecognized_extradata: 10692 if (client_extradata && p_extra) { 10693 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 10694 append_terminator_extradata(p_extra); 10695 } 10696 if (secure_mode && p_extradata && m_other_extradata) { 10697 struct vdec_output_frameinfo *ptr_extradatabuff = NULL; 10698 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size); 10699 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate; 10700 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata; 10701 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size; 10702 } 10703 return; 10704 } 10705 10706 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, 10707 bool is_internal, bool enable) 10708 { 10709 OMX_ERRORTYPE ret = OMX_ErrorNone; 10710 struct v4l2_control control; 10711 if (m_state != OMX_StateLoaded) { 10712 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); 10713 return OMX_ErrorIncorrectStateOperation; 10714 } 10715 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d", 10716 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal); 10717 10718 if (!is_internal) { 10719 if (enable) 10720 client_extradata |= requested_extradata; 10721 else 10722 client_extradata = client_extradata & ~requested_extradata; 10723 } 10724 10725 if (enable) { 10726 if (requested_extradata & OMX_INTERLACE_EXTRADATA) { 10727 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10728 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO; 10729 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10730 DEBUG_PRINT_HIGH("Failed to set interlaced extradata." 10731 " Quality of interlaced clips might be impacted."); 10732 } 10733 } 10734 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) { 10735 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10736 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE; 10737 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10738 DEBUG_PRINT_HIGH("Failed to set framerate extradata"); 10739 } 10740 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10741 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB; 10742 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10743 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata"); 10744 } 10745 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10746 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI; 10747 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10748 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata"); 10749 } 10750 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10751 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW; 10752 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10753 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 10754 } 10755 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10756 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO; 10757 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10758 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 10759 } 10760 if (output_capability == V4L2_PIX_FMT_MPEG2) { 10761 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10762 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; 10763 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10764 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 10765 } 10766 } 10767 } 10768 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) { 10769 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10770 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP; 10771 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10772 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata"); 10773 } 10774 } 10775 if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) { 10776 if (output_capability == V4L2_PIX_FMT_H264) { 10777 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA"); 10778 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10779 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING; 10780 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10781 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata"); 10782 } 10783 } else { 10784 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only"); 10785 } 10786 } 10787 if (requested_extradata & OMX_QP_EXTRADATA) { 10788 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10789 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP; 10790 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10791 DEBUG_PRINT_HIGH("Failed to set QP extradata"); 10792 } 10793 } 10794 if (requested_extradata & OMX_BITSINFO_EXTRADATA) { 10795 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10796 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO; 10797 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10798 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata"); 10799 } 10800 } 10801 if (requested_extradata & OMX_EXTNUSER_EXTRADATA) { 10802 if (secure_mode) { 10803 DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions"); 10804 return OMX_ErrorUnsupportedSetting; 10805 } 10806 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10807 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA; 10808 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10809 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata"); 10810 } 10811 } 10812 if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) { 10813 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10814 control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI; 10815 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10816 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata"); 10817 } 10818 client_extradata |= OMX_VQZIPSEI_EXTRADATA; 10819 10820 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10821 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP; 10822 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10823 DEBUG_PRINT_HIGH("Failed to set QP extradata"); 10824 } 10825 client_extradata |= OMX_QP_EXTRADATA; 10826 } 10827 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) { 10828 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 10829 switch(output_capability) { 10830 case V4L2_PIX_FMT_H264: 10831 case V4L2_PIX_FMT_HEVC: 10832 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY; 10833 break; 10834 case CODEC_TYPE_MPEG2: 10835 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; 10836 break; 10837 case V4L2_PIX_FMT_VP8: 10838 case V4L2_PIX_FMT_VP9: 10839 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE; 10840 break; 10841 case V4L2_PIX_FMT_VC1_ANNEX_G: 10842 case V4L2_PIX_FMT_VC1_ANNEX_L: 10843 control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP; 10844 break; 10845 default: 10846 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind); 10847 return ret; 10848 } 10849 10850 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 10851 DEBUG_PRINT_HIGH("Failed to set Display info extradata"); 10852 } 10853 } 10854 } 10855 ret = get_buffer_req(&drv_ctx.op_buf); 10856 return ret; 10857 } 10858 10859 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) 10860 { 10861 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; 10862 OMX_U8 *data_ptr = extra->data, data = 0; 10863 while (byte_count < extra->nDataSize) { 10864 data = *data_ptr; 10865 while (data) { 10866 num_MB += (data&0x01); 10867 data >>= 1; 10868 } 10869 data_ptr++; 10870 byte_count++; 10871 } 10872 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 10873 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 10874 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); 10875 } 10876 10877 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) 10878 { 10879 if (!m_debug_extradata || !extra) 10880 return; 10881 10882 10883 DEBUG_PRINT_HIGH( 10884 "============== Extra Data ==============\n" 10885 " Size: %u\n" 10886 " Version: %u\n" 10887 " PortIndex: %u\n" 10888 " Type: %x\n" 10889 " DataSize: %u", 10890 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion, 10891 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize); 10892 10893 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) { 10894 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 10895 DEBUG_PRINT_HIGH( 10896 "------ Interlace Format ------\n" 10897 " Size: %u\n" 10898 " Version: %u\n" 10899 " PortIndex: %u\n" 10900 " Is Interlace Format: %d\n" 10901 " Interlace Formats: %u\n" 10902 "=========== End of Interlace ===========", 10903 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex, 10904 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats); 10905 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) { 10906 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 10907 10908 DEBUG_PRINT_HIGH( 10909 "-------- Frame Format --------\n" 10910 " Picture Type: %d\n" 10911 " Interlace Type: %d\n" 10912 " Pan Scan Total Frame Num: %u\n" 10913 " Concealed Macro Blocks: %u\n" 10914 " frame rate: %u\n" 10915 " Time Stamp: %llu\n" 10916 " Aspect Ratio X: %u\n" 10917 " Aspect Ratio Y: %u", 10918 fminfo->ePicType, 10919 fminfo->interlaceType, 10920 (unsigned int)fminfo->panScan.numWindows, 10921 (unsigned int)fminfo->nConcealedMacroblocks, 10922 (unsigned int)fminfo->nFrameRate, 10923 fminfo->nTimeStamp, 10924 (unsigned int)fminfo->aspectRatio.aspectRatioX, 10925 (unsigned int)fminfo->aspectRatio.aspectRatioY); 10926 10927 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) { 10928 DEBUG_PRINT_HIGH( 10929 "------------------------------" 10930 " Pan Scan Frame Num: %u\n" 10931 " Rectangle x: %d\n" 10932 " Rectangle y: %d\n" 10933 " Rectangle dx: %d\n" 10934 " Rectangle dy: %d", 10935 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y, 10936 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy); 10937 } 10938 10939 DEBUG_PRINT_HIGH("========= End of Frame Format =========="); 10940 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) { 10941 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 10942 DEBUG_PRINT_HIGH( 10943 "------------------ Framepack Format ----------\n" 10944 " id: %u \n" 10945 " cancel_flag: %u \n" 10946 " type: %u \n" 10947 " quincunx_sampling_flagFormat: %u \n" 10948 " content_interpretation_type: %u \n" 10949 " spatial_flipping_flag: %u \n" 10950 " frame0_flipped_flag: %u \n" 10951 " field_views_flag: %u \n" 10952 " current_frame_is_frame0_flag: %u \n" 10953 " frame0_self_contained_flag: %u \n" 10954 " frame1_self_contained_flag: %u \n" 10955 " frame0_grid_position_x: %u \n" 10956 " frame0_grid_position_y: %u \n" 10957 " frame1_grid_position_x: %u \n" 10958 " frame1_grid_position_y: %u \n" 10959 " reserved_byte: %u \n" 10960 " repetition_period: %u \n" 10961 " extension_flag: %u \n" 10962 "================== End of Framepack ===========", 10963 (unsigned int)framepack->id, 10964 (unsigned int)framepack->cancel_flag, 10965 (unsigned int)framepack->type, 10966 (unsigned int)framepack->quincunx_sampling_flag, 10967 (unsigned int)framepack->content_interpretation_type, 10968 (unsigned int)framepack->spatial_flipping_flag, 10969 (unsigned int)framepack->frame0_flipped_flag, 10970 (unsigned int)framepack->field_views_flag, 10971 (unsigned int)framepack->current_frame_is_frame0_flag, 10972 (unsigned int)framepack->frame0_self_contained_flag, 10973 (unsigned int)framepack->frame1_self_contained_flag, 10974 (unsigned int)framepack->frame0_grid_position_x, 10975 (unsigned int)framepack->frame0_grid_position_y, 10976 (unsigned int)framepack->frame1_grid_position_x, 10977 (unsigned int)framepack->frame1_grid_position_y, 10978 (unsigned int)framepack->reserved_byte, 10979 (unsigned int)framepack->repetition_period, 10980 (unsigned int)framepack->extension_flag); 10981 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) { 10982 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 10983 DEBUG_PRINT_HIGH( 10984 "---- QP (Frame quantization parameter) ----\n" 10985 " Frame QP: %u \n" 10986 "================ End of QP ================\n", 10987 (unsigned int)qp->nQP); 10988 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) { 10989 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data; 10990 DEBUG_PRINT_HIGH( 10991 "--------- Input bits information --------\n" 10992 " Header bits: %u \n" 10993 " Frame bits: %u \n" 10994 "===== End of Input bits information =====\n", 10995 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits); 10996 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) { 10997 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data; 10998 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data; 10999 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type); 11000 OMX_U32 i = 0; 11001 DEBUG_PRINT_HIGH( 11002 "-------------- Userdata -------------\n" 11003 " Stream userdata type: %u\n" 11004 " userdata size: %u\n" 11005 " STREAM_USERDATA:", 11006 (unsigned int)userdata->type, (unsigned int)userdata_size); 11007 for (i = 0; i < userdata_size; i+=4) { 11008 DEBUG_PRINT_HIGH(" %x %x %x %x", 11009 data_ptr[i], data_ptr[i+1], 11010 data_ptr[i+2], data_ptr[i+3]); 11011 } 11012 DEBUG_PRINT_HIGH( 11013 "=========== End of Userdata ==========="); 11014 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) { 11015 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data; 11016 DEBUG_PRINT_HIGH( 11017 "-------------- VQZip -------------\n" 11018 " Size: %u\n", 11019 (unsigned int)vq->nSize); 11020 DEBUG_PRINT_HIGH( "=========== End of VQZip ==========="); 11021 } else if (extra->eType == OMX_ExtraDataNone) { 11022 DEBUG_PRINT_HIGH("========== End of Terminator ==========="); 11023 } else { 11024 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); 11025 } 11026 } 11027 11028 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11029 OMX_U32 interlaced_format_type, bool is_mbaff) 11030 { 11031 OMX_STREAMINTERLACEFORMAT *interlace_format; 11032 11033 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) { 11034 return; 11035 } 11036 if (!extra) { 11037 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input"); 11038 return; 11039 } 11040 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; 11041 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11042 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11043 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; 11044 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); 11045 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 11046 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); 11047 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; 11048 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11049 11050 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) { 11051 interlace_format->bInterlaceFormat = OMX_FALSE; 11052 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; 11053 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 11054 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) { 11055 interlace_format->bInterlaceFormat = OMX_TRUE; 11056 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 11057 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 11058 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) { 11059 interlace_format->bInterlaceFormat = OMX_TRUE; 11060 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst; 11061 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 11062 } else { 11063 interlace_format->bInterlaceFormat = OMX_TRUE; 11064 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 11065 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 11066 } 11067 print_debug_extradata(extra); 11068 } 11069 11070 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra) 11071 { 11072 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension; 11073 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) { 11074 return; 11075 } 11076 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE; 11077 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11078 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11079 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension; 11080 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION); 11081 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data; 11082 frame_dimension->nDecWidth = rectangle.nLeft; 11083 frame_dimension->nDecHeight = rectangle.nTop; 11084 frame_dimension->nActualWidth = rectangle.nWidth; 11085 frame_dimension->nActualHeight = rectangle.nHeight; 11086 } 11087 11088 void omx_vdec::fill_aspect_ratio_info( 11089 struct vdec_aspectratioinfo *aspect_ratio_info, 11090 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info) 11091 { 11092 m_extradata = frame_info; 11093 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width; 11094 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height; 11095 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX, 11096 (unsigned int)m_extradata->aspectRatio.aspectRatioY); 11097 } 11098 11099 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11100 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate, 11101 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload, 11102 struct vdec_aspectratioinfo *aspect_ratio_info) 11103 { 11104 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; 11105 struct msm_vidc_panscan_window *panscan_window; 11106 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) { 11107 return; 11108 } 11109 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; 11110 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11111 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11112 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; 11113 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); 11114 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 11115 switch (picture_type) { 11116 case PICTURE_TYPE_I: 11117 frame_info->ePicType = OMX_VIDEO_PictureTypeI; 11118 break; 11119 case PICTURE_TYPE_P: 11120 frame_info->ePicType = OMX_VIDEO_PictureTypeP; 11121 break; 11122 case PICTURE_TYPE_B: 11123 frame_info->ePicType = OMX_VIDEO_PictureTypeB; 11124 break; 11125 default: 11126 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; 11127 } 11128 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) 11129 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 11130 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) 11131 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 11132 else 11133 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; 11134 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); 11135 frame_info->nConcealedMacroblocks = num_conceal_mb; 11136 frame_info->nFrameRate = frame_rate; 11137 frame_info->nTimeStamp = time_stamp; 11138 frame_info->panScan.numWindows = 0; 11139 if (output_capability == V4L2_PIX_FMT_MPEG2) { 11140 if (m_disp_hor_size && m_disp_vert_size) { 11141 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size; 11142 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size; 11143 } else { 11144 frame_info->displayAspectRatio.displayHorizontalSize = 0; 11145 frame_info->displayAspectRatio.displayVerticalSize = 0; 11146 } 11147 } 11148 11149 if (panscan_payload) { 11150 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows; 11151 panscan_window = &panscan_payload->wnd[0]; 11152 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) { 11153 frame_info->panScan.window[i].x = panscan_window->panscan_window_width; 11154 frame_info->panScan.window[i].y = panscan_window->panscan_window_height; 11155 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset; 11156 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset; 11157 panscan_window++; 11158 } 11159 } 11160 fill_aspect_ratio_info(aspect_ratio_info, frame_info); 11161 print_debug_extradata(extra); 11162 } 11163 11164 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) 11165 { 11166 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; 11167 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; 11168 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11169 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11170 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; 11171 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 11172 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data; 11173 *portDefn = m_port_def; 11174 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u " 11175 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight, 11176 (unsigned int)portDefn->format.video.nFrameWidth, 11177 (unsigned int)portDefn->format.video.nStride, 11178 (unsigned int)portDefn->format.video.nSliceHeight); 11179 } 11180 11181 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11182 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload) 11183 { 11184 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack; 11185 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) { 11186 DEBUG_PRINT_ERROR("frame packing size mismatch"); 11187 return; 11188 } 11189 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE; 11190 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11191 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11192 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement; 11193 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 11194 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 11195 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 11196 framepack->nVersion.nVersion = OMX_SPEC_VERSION; 11197 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11198 memcpy(&framepack->id, s3d_frame_packing_payload, 11199 sizeof(struct msm_vidc_s3d_frame_packing_payload)); 11200 memcpy(&m_frame_pack_arrangement, framepack, 11201 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 11202 print_debug_extradata(extra); 11203 } 11204 11205 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11206 struct msm_vidc_frame_qp_payload *qp_payload) 11207 { 11208 OMX_QCOM_EXTRADATA_QP * qp = NULL; 11209 if (!qp_payload) { 11210 DEBUG_PRINT_ERROR("QP payload is NULL"); 11211 return; 11212 } 11213 extra->nSize = OMX_QP_EXTRADATA_SIZE; 11214 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11215 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11216 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP; 11217 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP); 11218 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 11219 qp->nQP = qp_payload->frame_qp; 11220 print_debug_extradata(extra); 11221 } 11222 11223 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11224 struct msm_vidc_frame_bits_info_payload *bits_payload) 11225 { 11226 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL; 11227 if (!bits_payload) { 11228 DEBUG_PRINT_ERROR("bits info payload is NULL"); 11229 return; 11230 } 11231 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE; 11232 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11233 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11234 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo; 11235 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO); 11236 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data; 11237 bits->frame_bits = bits_payload->frame_bits; 11238 bits->header_bits = bits_payload->header_bits; 11239 print_debug_extradata(extra); 11240 } 11241 11242 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11243 OMX_OTHER_EXTRADATATYPE *p_user) 11244 { 11245 int userdata_size = 0; 11246 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL; 11247 userdata_payload = 11248 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data; 11249 userdata_size = p_user->nDataSize; 11250 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size; 11251 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11252 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11253 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData; 11254 extra->nDataSize = userdata_size; 11255 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize)) 11256 memcpy(extra->data, p_user->data, extra->nDataSize); 11257 print_debug_extradata(extra); 11258 } 11259 11260 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) 11261 { 11262 if (!client_extradata) { 11263 return; 11264 } 11265 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); 11266 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11267 extra->eType = OMX_ExtraDataNone; 11268 extra->nDataSize = 0; 11269 extra->data[0] = 0; 11270 11271 print_debug_extradata(extra); 11272 } 11273 11274 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra, 11275 struct msm_vidc_vqzip_sei_payload *vqzip_payload) 11276 { 11277 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL; 11278 11279 extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size; 11280 extra->nVersion.nVersion = OMX_SPEC_VERSION; 11281 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11282 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI; 11283 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size; 11284 11285 vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data; 11286 vq->nSize = vqzip_payload->size; 11287 memcpy(vq->data, vqzip_payload->data, vqzip_payload->size); 11288 11289 print_debug_extradata(extra); 11290 } 11291 11292 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) 11293 { 11294 OMX_ERRORTYPE eRet = OMX_ErrorNone; 11295 if (index >= drv_ctx.ip_buf.actualcount) { 11296 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found"); 11297 return OMX_ErrorInsufficientResources; 11298 } 11299 if (m_desc_buffer_ptr == NULL) { 11300 m_desc_buffer_ptr = (desc_buffer_hdr*) \ 11301 calloc( (sizeof(desc_buffer_hdr)), 11302 drv_ctx.ip_buf.actualcount); 11303 if (m_desc_buffer_ptr == NULL) { 11304 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed "); 11305 return OMX_ErrorInsufficientResources; 11306 } 11307 } 11308 11309 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); 11310 if (m_desc_buffer_ptr[index].buf_addr == NULL) { 11311 DEBUG_PRINT_ERROR("desc buffer Allocation failed "); 11312 return OMX_ErrorInsufficientResources; 11313 } 11314 11315 return eRet; 11316 } 11317 11318 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) 11319 { 11320 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries); 11321 if (m_demux_entries < 8192) { 11322 m_demux_offsets[m_demux_entries++] = address_offset; 11323 } 11324 return; 11325 } 11326 11327 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) 11328 { 11329 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; 11330 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; 11331 OMX_U32 index = 0; 11332 11333 m_demux_entries = 0; 11334 11335 while (index < bytes_to_parse) { 11336 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 11337 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || 11338 ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 11339 (buf[index+2] == 0x01)) ) { 11340 //Found start code, insert address offset 11341 insert_demux_addr_offset(index); 11342 if (buf[index+2] == 0x01) // 3 byte start code 11343 index += 3; 11344 else //4 byte start code 11345 index += 4; 11346 } else 11347 index++; 11348 } 11349 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries); 11350 return; 11351 } 11352 11353 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) 11354 { 11355 //fix this, handle 3 byte start code, vc1 terminator entry 11356 OMX_U8 *p_demux_data = NULL; 11357 OMX_U32 desc_data = 0; 11358 OMX_U32 start_addr = 0; 11359 OMX_U32 nal_size = 0; 11360 OMX_U32 suffix_byte = 0; 11361 OMX_U32 demux_index = 0; 11362 OMX_U32 buffer_index = 0; 11363 11364 if (m_desc_buffer_ptr == NULL) { 11365 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); 11366 return OMX_ErrorBadParameter; 11367 } 11368 11369 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 11370 if (buffer_index > drv_ctx.ip_buf.actualcount) { 11371 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index); 11372 return OMX_ErrorBadParameter; 11373 } 11374 11375 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; 11376 11377 if ( ((OMX_U8*)p_demux_data == NULL) || 11378 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) { 11379 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); 11380 return OMX_ErrorBadParameter; 11381 } else { 11382 for (; demux_index < m_demux_entries; demux_index++) { 11383 desc_data = 0; 11384 start_addr = m_demux_offsets[demux_index]; 11385 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) { 11386 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; 11387 } else { 11388 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; 11389 } 11390 if (demux_index < (m_demux_entries - 1)) { 11391 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; 11392 } else { 11393 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; 11394 } 11395 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)", 11396 (unsigned int)start_addr, 11397 (unsigned int)suffix_byte, 11398 (unsigned int)nal_size, 11399 (unsigned int)demux_index); 11400 desc_data = (start_addr >> 3) << 1; 11401 desc_data |= (start_addr & 7) << 21; 11402 desc_data |= suffix_byte << 24; 11403 11404 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 11405 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); 11406 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 11407 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 11408 11409 p_demux_data += 16; 11410 } 11411 if (codec_type_parse == CODEC_TYPE_VC1) { 11412 DEBUG_PRINT_LOW("VC1 terminator entry"); 11413 desc_data = 0; 11414 desc_data = 0x82 << 24; 11415 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 11416 memset(p_demux_data + 4, 0, sizeof(OMX_U32)); 11417 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 11418 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 11419 p_demux_data += 16; 11420 m_demux_entries++; 11421 } 11422 //Add zero word to indicate end of descriptors 11423 memset(p_demux_data, 0, sizeof(OMX_U32)); 11424 11425 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); 11426 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size); 11427 } 11428 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 11429 m_demux_entries = 0; 11430 DEBUG_PRINT_LOW("Demux table complete!"); 11431 return OMX_ErrorNone; 11432 } 11433 11434 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level) 11435 { 11436 struct v4l2_control control; 11437 char property_value[PROPERTY_VALUE_MAX] = {0}; 11438 11439 property_get("vidc.debug.turbo", property_value, "0"); 11440 memset(&control, 0, sizeof(v4l2_control)); 11441 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 11442 switch (perf_level) { 11443 case VIDC_NOMINAL: 11444 if (atoi(property_value)) 11445 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 11446 else 11447 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; 11448 break; 11449 case VIDC_TURBO: 11450 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 11451 break; 11452 default: 11453 DEBUG_PRINT_ERROR("Requested PERF level not supported"); 11454 break; 11455 } 11456 if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig) 11457 return; 11458 11459 DEBUG_PRINT_HIGH("changing performance level to %d", control.value); 11460 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 11461 current_perf_level = control.value; 11462 } else { 11463 DEBUG_PRINT_ERROR("Failed to set PERF level"); 11464 } 11465 } 11466 11467 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf() 11468 { 11469 enabled = false; 11470 omx = NULL; 11471 init_members(); 11472 ColorFormat = OMX_COLOR_FormatMax; 11473 dest_format = YCbCr420P; 11474 } 11475 11476 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client) 11477 { 11478 omx = reinterpret_cast<omx_vdec*>(client); 11479 } 11480 11481 void omx_vdec::allocate_color_convert_buf::init_members() 11482 { 11483 allocated_count = 0; 11484 buffer_size_req = 0; 11485 buffer_alignment_req = 0; 11486 memset(m_platform_list_client,0,sizeof(m_platform_list_client)); 11487 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client)); 11488 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client)); 11489 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client)); 11490 #ifdef USE_ION 11491 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client)); 11492 #endif 11493 for (int i = 0; i < MAX_COUNT; i++) 11494 pmem_fd[i] = -1; 11495 } 11496 11497 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf() 11498 { 11499 c2d.destroy(); 11500 } 11501 11502 bool omx_vdec::allocate_color_convert_buf::update_buffer_req() 11503 { 11504 bool status = true; 11505 unsigned int src_size = 0, destination_size = 0; 11506 OMX_COLOR_FORMATTYPE drv_color_format; 11507 if (!omx) { 11508 DEBUG_PRINT_ERROR("Invalid client in color convert"); 11509 return false; 11510 } 11511 if (!enabled) { 11512 DEBUG_PRINT_HIGH("No color conversion required"); 11513 return status; 11514 } 11515 pthread_mutex_lock(&omx->c_lock); 11516 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 && 11517 ColorFormat != OMX_COLOR_FormatYUV420Planar) { 11518 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion"); 11519 status = false; 11520 goto fail_update_buf_req; 11521 } 11522 c2d.close(); 11523 status = c2d.open(omx->drv_ctx.video_resolution.frame_height, 11524 omx->drv_ctx.video_resolution.frame_width, 11525 NV12_128m,dest_format); 11526 if (status) { 11527 status = c2d.get_buffer_size(C2D_INPUT,src_size); 11528 if (status) 11529 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size); 11530 } 11531 if (status) { 11532 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size || 11533 !destination_size) { 11534 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d" 11535 "driver size %u destination size %d", 11536 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size, 11537 destination_size); 11538 status = false; 11539 c2d.close(); 11540 buffer_size_req = 0; 11541 } else { 11542 buffer_size_req = destination_size; 11543 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size) 11544 buffer_size_req = omx->drv_ctx.op_buf.buffer_size; 11545 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 11546 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 11547 } 11548 } 11549 fail_update_buf_req: 11550 pthread_mutex_unlock(&omx->c_lock); 11551 return status; 11552 } 11553 11554 bool omx_vdec::allocate_color_convert_buf::set_color_format( 11555 OMX_COLOR_FORMATTYPE dest_color_format) 11556 { 11557 bool status = true; 11558 OMX_COLOR_FORMATTYPE drv_color_format; 11559 if (!omx) { 11560 DEBUG_PRINT_ERROR("Invalid client in color convert"); 11561 return false; 11562 } 11563 pthread_mutex_lock(&omx->c_lock); 11564 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 11565 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 11566 drv_color_format = (OMX_COLOR_FORMATTYPE) 11567 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 11568 else 11569 drv_color_format = (OMX_COLOR_FORMATTYPE) 11570 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 11571 else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) { 11572 drv_color_format = (OMX_COLOR_FORMATTYPE) 11573 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 11574 } else { 11575 DEBUG_PRINT_ERROR("Incorrect color format"); 11576 status = false; 11577 } 11578 if (status && 11579 drv_color_format != dest_color_format && 11580 drv_color_format != (OMX_COLOR_FORMATTYPE) 11581 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView && 11582 drv_color_format != (OMX_COLOR_FORMATTYPE) 11583 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed && 11584 dest_color_format != (OMX_COLOR_FORMATTYPE) 11585 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) { 11586 DEBUG_PRINT_LOW("Enabling C2D"); 11587 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) && 11588 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) { 11589 DEBUG_PRINT_ERROR("Unsupported color format for c2d"); 11590 status = false; 11591 } else { 11592 ColorFormat = dest_color_format; 11593 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ? 11594 YCbCr420P : YCbCr420SP; 11595 if (enabled) 11596 c2d.destroy(); 11597 enabled = false; 11598 if (!c2d.init()) { 11599 DEBUG_PRINT_ERROR("open failed for c2d"); 11600 status = false; 11601 } else 11602 enabled = true; 11603 } 11604 } else { 11605 if (enabled) 11606 c2d.destroy(); 11607 enabled = false; 11608 } 11609 pthread_mutex_unlock(&omx->c_lock); 11610 return status; 11611 } 11612 11613 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() 11614 { 11615 if (!omx) { 11616 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 11617 return NULL; 11618 } 11619 if (!enabled) 11620 return omx->m_out_mem_ptr; 11621 return m_out_mem_ptr_client; 11622 } 11623 11624 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr 11625 (OMX_BUFFERHEADERTYPE *bufadd) 11626 { 11627 if (!omx) { 11628 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 11629 return NULL; 11630 } 11631 if (!enabled) 11632 return bufadd; 11633 11634 unsigned index = 0; 11635 index = bufadd - omx->m_out_mem_ptr; 11636 if (index < omx->drv_ctx.op_buf.actualcount) { 11637 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS); 11638 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp; 11639 bool status; 11640 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) { 11641 pthread_mutex_lock(&omx->c_lock); 11642 cache_clean_buffer(index); 11643 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd, 11644 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index], 11645 pmem_baseaddress[index], pmem_baseaddress[index]); 11646 if (!status) { 11647 DEBUG_PRINT_ERROR("Failed color conversion %d", status); 11648 m_out_mem_ptr_client[index].nFilledLen = 0; 11649 pthread_mutex_unlock(&omx->c_lock); 11650 return &m_out_mem_ptr_client[index]; 11651 } else { 11652 unsigned int filledLen = 0; 11653 c2d.get_output_filled_length(filledLen); 11654 m_out_mem_ptr_client[index].nFilledLen = filledLen; 11655 cache_clean_invalidate_buffer(index); 11656 } 11657 pthread_mutex_unlock(&omx->c_lock); 11658 } else 11659 m_out_mem_ptr_client[index].nFilledLen = 0; 11660 return &m_out_mem_ptr_client[index]; 11661 } 11662 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr"); 11663 return NULL; 11664 } 11665 11666 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr 11667 (OMX_BUFFERHEADERTYPE *bufadd) 11668 { 11669 if (!omx) { 11670 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 11671 return NULL; 11672 } 11673 if (!enabled) 11674 return bufadd; 11675 unsigned index = 0; 11676 index = bufadd - m_out_mem_ptr_client; 11677 if (index < omx->drv_ctx.op_buf.actualcount) { 11678 return &omx->m_out_mem_ptr[index]; 11679 } 11680 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr"); 11681 return NULL; 11682 } 11683 bool omx_vdec::allocate_color_convert_buf::get_buffer_req 11684 (unsigned int &buffer_size) 11685 { 11686 bool status = true; 11687 pthread_mutex_lock(&omx->c_lock); 11688 if (!enabled) 11689 buffer_size = omx->drv_ctx.op_buf.buffer_size; 11690 else { 11691 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) { 11692 DEBUG_PRINT_ERROR("Get buffer size failed"); 11693 status = false; 11694 goto fail_get_buffer_size; 11695 } 11696 } 11697 if (buffer_size < omx->drv_ctx.op_buf.buffer_size) 11698 buffer_size = omx->drv_ctx.op_buf.buffer_size; 11699 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 11700 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 11701 fail_get_buffer_size: 11702 pthread_mutex_unlock(&omx->c_lock); 11703 return status; 11704 } 11705 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer( 11706 OMX_BUFFERHEADERTYPE *bufhdr) 11707 { 11708 unsigned int index = 0; 11709 11710 if (!enabled) 11711 return omx->free_output_buffer(bufhdr); 11712 if (enabled && omx->is_component_secure()) 11713 return OMX_ErrorNone; 11714 if (!allocated_count || !bufhdr) { 11715 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr); 11716 return OMX_ErrorBadParameter; 11717 } 11718 index = bufhdr - m_out_mem_ptr_client; 11719 if (index >= omx->drv_ctx.op_buf.actualcount) { 11720 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer"); 11721 return OMX_ErrorBadParameter; 11722 } 11723 if (pmem_fd[index] >= 0) { 11724 munmap(pmem_baseaddress[index], buffer_size_req); 11725 close(pmem_fd[index]); 11726 } 11727 pmem_fd[index] = -1; 11728 #ifdef USE_ION 11729 omx->free_ion_memory(&op_buf_ion_info[index]); 11730 #endif 11731 m_heap_ptr[index].video_heap_ptr = NULL; 11732 if (allocated_count > 0) 11733 allocated_count--; 11734 else 11735 allocated_count = 0; 11736 if (!allocated_count) { 11737 pthread_mutex_lock(&omx->c_lock); 11738 c2d.close(); 11739 init_members(); 11740 pthread_mutex_unlock(&omx->c_lock); 11741 } 11742 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]); 11743 } 11744 11745 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp, 11746 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes) 11747 { 11748 OMX_ERRORTYPE eRet = OMX_ErrorNone; 11749 if (!enabled) { 11750 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); 11751 return eRet; 11752 } 11753 if (enabled && omx->is_component_secure()) { 11754 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d", 11755 omx->is_component_secure()); 11756 return OMX_ErrorUnsupportedSetting; 11757 } 11758 if (!bufferHdr || bytes > buffer_size_req) { 11759 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr); 11760 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u", 11761 (unsigned int)buffer_size_req, (unsigned int)bytes); 11762 return OMX_ErrorBadParameter; 11763 } 11764 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) { 11765 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert"); 11766 return OMX_ErrorInsufficientResources; 11767 } 11768 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL; 11769 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr, 11770 port,appData,omx->drv_ctx.op_buf.buffer_size); 11771 if (eRet != OMX_ErrorNone || !temp_bufferHdr) { 11772 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert"); 11773 return eRet; 11774 } 11775 if ((temp_bufferHdr - omx->m_out_mem_ptr) >= 11776 (int)omx->drv_ctx.op_buf.actualcount) { 11777 DEBUG_PRINT_ERROR("Invalid header index %ld", 11778 (long int)(temp_bufferHdr - omx->m_out_mem_ptr)); 11779 return OMX_ErrorUndefined; 11780 } 11781 unsigned int i = allocated_count; 11782 #ifdef USE_ION 11783 // Allocate color-conversion buffers as cached to improve software-reading 11784 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit 11785 // cache invalidation. 11786 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory( 11787 buffer_size_req,buffer_alignment_req, 11788 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data, 11789 ION_FLAG_CACHED); 11790 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd; 11791 if (op_buf_ion_info[i].ion_device_fd < 0) { 11792 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert"); 11793 return OMX_ErrorInsufficientResources; 11794 } 11795 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req, 11796 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0); 11797 11798 if (pmem_baseaddress[i] == MAP_FAILED) { 11799 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req); 11800 close(pmem_fd[i]); 11801 omx->free_ion_memory(&op_buf_ion_info[i]); 11802 return OMX_ErrorInsufficientResources; 11803 } 11804 m_heap_ptr[i].video_heap_ptr = new VideoHeap ( 11805 op_buf_ion_info[i].ion_device_fd,buffer_size_req, 11806 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]); 11807 #endif 11808 m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get(); 11809 m_pmem_info_client[i].offset = 0; 11810 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i]; 11811 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 11812 m_platform_list_client[i].nEntries = 1; 11813 m_platform_list_client[i].entryList = &m_platform_entry_client[i]; 11814 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL; 11815 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req; 11816 m_out_mem_ptr_client[i].nFilledLen = 0; 11817 m_out_mem_ptr_client[i].nFlags = 0; 11818 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 11819 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE); 11820 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION; 11821 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i]; 11822 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i]; 11823 m_out_mem_ptr_client[i].pAppPrivate = appData; 11824 *bufferHdr = &m_out_mem_ptr_client[i]; 11825 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr); 11826 allocated_count++; 11827 return eRet; 11828 } 11829 11830 bool omx_vdec::is_component_secure() 11831 { 11832 return secure_mode; 11833 } 11834 11835 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format) 11836 { 11837 bool status = true; 11838 if (!enabled) { 11839 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 11840 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 11841 dest_color_format = (OMX_COLOR_FORMATTYPE) 11842 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 11843 else 11844 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 11845 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){ 11846 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed; 11847 } else 11848 status = false; 11849 } else { 11850 if (ColorFormat == OMX_COLOR_FormatYUV420Planar || 11851 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 11852 dest_color_format = ColorFormat; 11853 } else 11854 status = false; 11855 } 11856 return status; 11857 } 11858 11859 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops( 11860 unsigned int index, unsigned int cmd) 11861 { 11862 if (!enabled) { 11863 return OMX_ErrorNone; 11864 } 11865 11866 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) { 11867 DEBUG_PRINT_ERROR("%s: Invalid param", __func__); 11868 return OMX_ErrorBadParameter; 11869 } 11870 11871 struct ion_flush_data flush_data; 11872 struct ion_custom_data custom_data; 11873 11874 memset(&flush_data, 0x0, sizeof(flush_data)); 11875 memset(&custom_data, 0x0, sizeof(custom_data)); 11876 11877 flush_data.vaddr = pmem_baseaddress[index]; 11878 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd; 11879 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle; 11880 flush_data.length = buffer_size_req; 11881 custom_data.cmd = cmd; 11882 custom_data.arg = (unsigned long)&flush_data; 11883 11884 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d", 11885 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 11886 flush_data.fd, flush_data.handle, flush_data.vaddr, 11887 flush_data.length); 11888 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data); 11889 if (ret < 0) { 11890 DEBUG_PRINT_ERROR("Cache %s failed: %s\n", 11891 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 11892 strerror(errno)); 11893 return OMX_ErrorUndefined; 11894 } 11895 return OMX_ErrorNone; 11896 } 11897 11898 void omx_vdec::buf_ref_add(int nPortIndex) 11899 { 11900 unsigned long i = 0; 11901 bool buf_present = false; 11902 long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 11903 OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 11904 11905 if (!dynamic_buf_mode || !out_dynamic_list) { 11906 return; 11907 } 11908 11909 pthread_mutex_lock(&m_lock); 11910 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 11911 //check the buffer fd, offset, uv addr with list contents 11912 //If present increment reference. 11913 if ((out_dynamic_list[i].fd == fd) && 11914 (out_dynamic_list[i].offset == offset)) { 11915 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u", 11916 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 11917 if (!secure_mode) { 11918 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr; 11919 } 11920 buf_present = true; 11921 break; 11922 } 11923 } 11924 if (!buf_present) { 11925 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 11926 //search for a entry to insert details of the new buffer 11927 if (out_dynamic_list[i].dup_fd < 0) { 11928 out_dynamic_list[i].fd = fd; 11929 out_dynamic_list[i].offset = offset; 11930 out_dynamic_list[i].dup_fd = dup(fd); 11931 out_dynamic_list[i].ref_count++; 11932 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u", 11933 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 11934 11935 if (!secure_mode) { 11936 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = 11937 (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len, 11938 PROT_READ|PROT_WRITE, MAP_SHARED, 11939 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0); 11940 //mmap returns (void *)-1 on failure and sets error code in errno. 11941 if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) { 11942 DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno); 11943 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL; 11944 break; 11945 } 11946 out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr; 11947 out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len; 11948 DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size); 11949 } 11950 break; 11951 } 11952 } 11953 } 11954 pthread_mutex_unlock(&m_lock); 11955 } 11956 11957 void omx_vdec::buf_ref_remove() 11958 { 11959 unsigned long i = 0; 11960 11961 if (!dynamic_buf_mode || !out_dynamic_list) { 11962 return; 11963 } 11964 11965 pthread_mutex_lock(&m_lock); 11966 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 11967 if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) { 11968 DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size); 11969 munmap(out_dynamic_list[i].buffaddr, 11970 out_dynamic_list[i].mapped_size); 11971 } 11972 11973 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u", 11974 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 11975 close(out_dynamic_list[i].dup_fd); 11976 out_dynamic_list[i].dup_fd = -1; 11977 } 11978 pthread_mutex_unlock(&m_lock); 11979 11980 if (out_dynamic_list) { 11981 free(out_dynamic_list); 11982 out_dynamic_list = NULL; 11983 } 11984 } 11985 11986 #ifdef _MSM8974_ 11987 void omx_vdec::send_codec_config() { 11988 if (codec_config_flag) { 11989 unsigned long p1 = 0; // Parameter - 1 11990 unsigned long p2 = 0; // Parameter - 2 11991 unsigned long ident = 0; 11992 pthread_mutex_lock(&m_lock); 11993 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n"); 11994 while (m_etb_q.m_size) { 11995 m_etb_q.pop_entry(&p1,&p2,&ident); 11996 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { 11997 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 11998 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 11999 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 12000 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); 12001 omx_report_error(); 12002 } 12003 } else { 12004 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 12005 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 12006 } 12007 } else if (ident == OMX_COMPONENT_GENERATE_ETB) { 12008 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 12009 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ 12010 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 12011 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); 12012 omx_report_error (); 12013 } 12014 } else { 12015 pending_input_buffers++; 12016 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 12017 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 12018 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 12019 } 12020 } else if (ident == OMX_COMPONENT_GENERATE_EBD) { 12021 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", 12022 (OMX_BUFFERHEADERTYPE *)p1); 12023 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 12024 } 12025 } 12026 pthread_mutex_unlock(&m_lock); 12027 } 12028 } 12029 #endif 12030 12031 omx_vdec::perf_control::perf_control() 12032 { 12033 m_perf_lib = NULL; 12034 m_perf_handle = 0; 12035 m_perf_lock_acquire = NULL; 12036 m_perf_lock_release = NULL; 12037 } 12038 12039 omx_vdec::perf_control::~perf_control() 12040 { 12041 if (m_perf_handle != 0 && m_perf_lock_release) { 12042 DEBUG_PRINT_LOW("NOTE2: release perf lock"); 12043 m_perf_lock_release(m_perf_handle); 12044 } 12045 if (m_perf_lib) { 12046 dlclose(m_perf_lib); 12047 } 12048 } 12049 12050 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0}; 12051 12052 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock; 12053 12054 void omx_vdec::perf_control::send_hint_to_mpctl(bool state) 12055 { 12056 if (load_lib() == false) { 12057 return; 12058 } 12059 m_perf_lock.lock(); 12060 /* 0x4401 maps to video decode playback hint 12061 * in perflock, enum number is 44 and state 12062 * being sent on perflock acquire is 01 (true) 12063 */ 12064 int arg = 0x4401; 12065 12066 if (state == true) { 12067 mpctl_obj.vid_inst_count++; 12068 } else if (state == false) { 12069 mpctl_obj.vid_inst_count--; 12070 } 12071 12072 if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) { 12073 mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int)); 12074 mpctl_obj.vid_acquired = true; 12075 DEBUG_PRINT_INFO("Video slvp perflock acquired"); 12076 } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) { 12077 m_perf_lock_release(mpctl_obj.vid_disp_handle); 12078 mpctl_obj.vid_acquired = false; 12079 DEBUG_PRINT_INFO("Video slvp perflock released"); 12080 } 12081 m_perf_lock.unlock(); 12082 } 12083 12084 void omx_vdec::perf_control::request_cores(int frame_duration_us) 12085 { 12086 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) { 12087 return; 12088 } 12089 bool retVal = load_lib(); 12090 if (retVal && m_perf_lock_acquire && m_perf_handle == 0) { 12091 int arg = 0x700 /*base value*/ + 2 /*cores*/; 12092 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int)); 12093 if (m_perf_handle) { 12094 DEBUG_PRINT_HIGH("perf lock acquired"); 12095 } 12096 } 12097 } 12098 12099 bool omx_vdec::perf_control::load_lib() 12100 { 12101 char perf_lib_path[PROPERTY_VALUE_MAX] = {0}; 12102 if (m_perf_lib) 12103 return true; 12104 12105 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) { 12106 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library"); 12107 goto handle_err; 12108 } 12109 12110 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) { 12111 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror()); 12112 goto handle_err; 12113 } else { 12114 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq"); 12115 if (m_perf_lock_acquire == NULL) { 12116 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq"); 12117 goto handle_err; 12118 } 12119 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel"); 12120 if (m_perf_lock_release == NULL) { 12121 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel"); 12122 goto handle_err; 12123 } 12124 } 12125 return true; 12126 12127 handle_err: 12128 if (m_perf_lib) { 12129 dlclose(m_perf_lib); 12130 } 12131 m_perf_lib = NULL; 12132 return false; 12133 } 12134 12135 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth, 12136 unsigned long nMaxFrameHeight) 12137 { 12138 12139 OMX_ERRORTYPE eRet = OMX_ErrorNone; 12140 int ret = 0; 12141 unsigned long min_res_buf_count = 0; 12142 12143 eRet = enable_smoothstreaming(); 12144 if (eRet != OMX_ErrorNone) { 12145 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver"); 12146 return eRet; 12147 } 12148 12149 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu", 12150 nMaxFrameWidth, 12151 nMaxFrameHeight); 12152 m_smoothstreaming_mode = true; 12153 m_smoothstreaming_width = nMaxFrameWidth; 12154 m_smoothstreaming_height = nMaxFrameHeight; 12155 12156 //Get upper limit buffer count for min supported resolution 12157 struct v4l2_format fmt; 12158 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 12159 fmt.fmt.pix_mp.height = m_decoder_capability.min_height; 12160 fmt.fmt.pix_mp.width = m_decoder_capability.min_width; 12161 fmt.fmt.pix_mp.pixelformat = output_capability; 12162 12163 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 12164 if (ret) { 12165 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u", 12166 m_decoder_capability.min_height, 12167 m_decoder_capability.min_width); 12168 return OMX_ErrorUnsupportedSetting; 12169 } 12170 12171 eRet = get_buffer_req(&drv_ctx.op_buf); 12172 if (eRet != OMX_ErrorNone) { 12173 DEBUG_PRINT_ERROR("failed to get_buffer_req"); 12174 return eRet; 12175 } 12176 12177 min_res_buf_count = drv_ctx.op_buf.mincount; 12178 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u", 12179 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width); 12180 12181 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, 12182 m_smoothstreaming_width, m_smoothstreaming_height); 12183 eRet = is_video_session_supported(); 12184 if (eRet != OMX_ErrorNone) { 12185 DEBUG_PRINT_ERROR("video session is not supported"); 12186 return eRet; 12187 } 12188 12189 //Get upper limit buffer size for max smooth streaming resolution set 12190 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 12191 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 12192 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 12193 fmt.fmt.pix_mp.pixelformat = output_capability; 12194 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 12195 if (ret) { 12196 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback"); 12197 return OMX_ErrorUnsupportedSetting; 12198 } 12199 12200 eRet = get_buffer_req(&drv_ctx.op_buf); 12201 if (eRet != OMX_ErrorNone) { 12202 DEBUG_PRINT_ERROR("failed to get_buffer_req!!"); 12203 return eRet; 12204 } 12205 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u", 12206 (unsigned int)drv_ctx.op_buf.buffer_size); 12207 12208 drv_ctx.op_buf.mincount = min_res_buf_count; 12209 drv_ctx.op_buf.actualcount = min_res_buf_count; 12210 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size; 12211 eRet = set_buffer_req(&drv_ctx.op_buf); 12212 if (eRet != OMX_ErrorNone) { 12213 DEBUG_PRINT_ERROR("failed to set_buffer_req"); 12214 return eRet; 12215 } 12216 12217 eRet = get_buffer_req(&drv_ctx.op_buf); 12218 if (eRet != OMX_ErrorNone) { 12219 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!"); 12220 return eRet; 12221 } 12222 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u", 12223 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size); 12224 return eRet; 12225 } 12226 12227 //static 12228 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { 12229 12230 #ifndef FLEXYUV_SUPPORTED 12231 return OMX_ErrorUndefined; 12232 #else 12233 12234 if (pParam == NULL) { 12235 DEBUG_PRINT_ERROR("describeColorFormat: invalid params"); 12236 return OMX_ErrorBadParameter; 12237 } 12238 12239 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam; 12240 12241 MediaImage *img = &(params->sMediaImage); 12242 switch(params->eColorFormat) { 12243 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m: 12244 { 12245 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 12246 img->mNumPlanes = 3; 12247 // mWidth and mHeight represent the W x H of the largest plane 12248 // In our case, this happens to be the Stride x Scanlines of Y plane 12249 img->mWidth = params->nFrameWidth; 12250 img->mHeight = params->nFrameHeight; 12251 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 12252 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight); 12253 img->mBitDepth = 8; 12254 //Plane 0 (Y) 12255 img->mPlane[MediaImage::Y].mOffset = 0; 12256 img->mPlane[MediaImage::Y].mColInc = 1; 12257 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride 12258 img->mPlane[MediaImage::Y].mHorizSubsampling = 1; 12259 img->mPlane[MediaImage::Y].mVertSubsampling = 1; 12260 //Plane 1 (U) 12261 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight; 12262 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV 12263 img->mPlane[MediaImage::U].mRowInc = 12264 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 12265 img->mPlane[MediaImage::U].mHorizSubsampling = 2; 12266 img->mPlane[MediaImage::U].mVertSubsampling = 2; 12267 //Plane 2 (V) 12268 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1; 12269 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV 12270 img->mPlane[MediaImage::V].mRowInc = 12271 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 12272 img->mPlane[MediaImage::V].mHorizSubsampling = 2; 12273 img->mPlane[MediaImage::V].mVertSubsampling = 2; 12274 break; 12275 } 12276 12277 case OMX_COLOR_FormatYUV420Planar: 12278 case OMX_COLOR_FormatYUV420SemiPlanar: 12279 // We need not describe the standard OMX linear formats as these are 12280 // understood by client. Fail this deliberately to let client fill-in 12281 return OMX_ErrorUnsupportedSetting; 12282 12283 default: 12284 // Rest all formats which are non-linear cannot be described 12285 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat); 12286 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 12287 return OMX_ErrorNone; 12288 }; 12289 12290 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat); 12291 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight); 12292 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight); 12293 for (size_t i = 0; i < img->mNumPlanes; ++i) { 12294 DEBUG_PRINT_LOW(" Plane[%zd] : offset=%d / xStep=%d / yStep = %d", 12295 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc); 12296 } 12297 return OMX_ErrorNone; 12298 #endif //FLEXYUV_SUPPORTED 12299 } 12300 12301 void omx_vdec::prefetchNewBuffers() { 12302 12303 struct v4l2_decoder_cmd dec; 12304 uint32_t prefetch_count; 12305 uint32_t prefetch_size; 12306 uint32_t want_size; 12307 uint32_t have_size; 12308 int color_fmt, rc; 12309 uint32_t new_calculated_size; 12310 uint32_t new_buffer_size; 12311 uint32_t new_buffer_count; 12312 uint32_t old_buffer_size; 12313 uint32_t old_buffer_count; 12314 12315 memset((void *)&dec, 0 , sizeof(dec)); 12316 DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n", 12317 (int)drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount, 12318 drv_ctx.video_resolution.frame_width, 12319 drv_ctx.video_resolution.frame_height); 12320 dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT; 12321 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { 12322 DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno); 12323 } else { 12324 DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n", 12325 dec.raw.data[0], dec.raw.data[1]); 12326 } 12327 12328 switch ((int)drv_ctx.output_format) { 12329 case VDEC_YUV_FORMAT_NV12: 12330 color_fmt = COLOR_FMT_NV12; 12331 break; 12332 case VDEC_YUV_FORMAT_NV12_UBWC: 12333 color_fmt = COLOR_FMT_NV12_UBWC; 12334 break; 12335 default: 12336 color_fmt = -1; 12337 } 12338 12339 new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height); 12340 DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n", 12341 m_reconfig_width, m_reconfig_height, new_calculated_size); 12342 new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size; 12343 new_buffer_count = dec.raw.data[1]; 12344 old_buffer_size = drv_ctx.op_buf.buffer_size; 12345 old_buffer_count = drv_ctx.op_buf.actualcount; 12346 12347 new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count; 12348 12349 prefetch_count = new_buffer_count; 12350 prefetch_size = new_buffer_size - old_buffer_size; 12351 want_size = new_buffer_size * new_buffer_count; 12352 have_size = old_buffer_size * old_buffer_count; 12353 12354 if (want_size > have_size) { 12355 DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size); 12356 DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size); 12357 12358 int ion_fd = open(MEM_DEVICE, O_RDONLY); 12359 if (ion_fd < 0) { 12360 DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd); 12361 return; 12362 } 12363 12364 struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data)); 12365 struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data)); 12366 struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions)); 12367 size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count); 12368 12369 if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) { 12370 DEBUG_PRINT_ERROR("prefetch data allocation failed"); 12371 goto prefetch_exit; 12372 } 12373 12374 for (uint32_t i = 0; i < prefetch_count; i++) { 12375 sizes[i] = prefetch_size; 12376 } 12377 12378 regions[0].nr_sizes = prefetch_count; 12379 regions[0].sizes = sizes; 12380 regions[0].vmid = ION_FLAG_CP_PIXEL; 12381 12382 prefetch_data->nr_regions = 1; 12383 prefetch_data->regions = regions; 12384 prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID); 12385 12386 custom_data->cmd = ION_IOC_PREFETCH; 12387 custom_data->arg = (unsigned long )prefetch_data; 12388 12389 rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data); 12390 if (rc) { 12391 DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno); 12392 } 12393 12394 prefetch_exit: 12395 close(ion_fd); 12396 free(sizes); 12397 free(regions); 12398 free(prefetch_data); 12399 free(custom_data); 12400 } 12401 } 12402 12403 // No code beyond this ! 12404 12405 // inline import of vendor-extensions implementation 12406 #include "omx_vdec_extensions.hpp" 12407