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