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