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