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