omx_vdec_msm8974.cpp revision 00c00c349f132b5bba20e26ed54d01e9be9f87e4
1/*-------------------------------------------------------------------------- 2Copyright (c) 2010 - 2014, 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 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = 2984 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 2985 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); 2986 eRet = update_portdef(portDefn); 2987 if (eRet == OMX_ErrorNone) 2988 m_port_def = *portDefn; 2989 break; 2990 } 2991 case OMX_IndexParamVideoInit: { 2992 OMX_PORT_PARAM_TYPE *portParamType = 2993 (OMX_PORT_PARAM_TYPE *) paramData; 2994 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); 2995 2996 portParamType->nVersion.nVersion = OMX_SPEC_VERSION; 2997 portParamType->nSize = sizeof(portParamType); 2998 portParamType->nPorts = 2; 2999 portParamType->nStartPortNumber = 0; 3000 break; 3001 } 3002 case OMX_IndexParamVideoPortFormat: { 3003 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3004 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3005 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); 3006 3007 portFmt->nVersion.nVersion = OMX_SPEC_VERSION; 3008 portFmt->nSize = sizeof(portFmt); 3009 3010 if (0 == portFmt->nPortIndex) { 3011 if (0 == portFmt->nIndex) { 3012 portFmt->eColorFormat = OMX_COLOR_FormatUnused; 3013 portFmt->eCompressionFormat = eCompressionFormat; 3014 } else { 3015 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3016 " NoMore compression formats"); 3017 eRet = OMX_ErrorNoMore; 3018 } 3019 } else if (1 == portFmt->nPortIndex) { 3020 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; 3021 3022 // Distinguish non-surface mode from normal playback use-case based on 3023 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2" 3024 // For non-android, use the default list 3025 // Also use default format-list if FLEXIBLE YUV is supported, 3026 // as the client negotiates the standard color-format if it needs to 3027 bool useNonSurfaceMode = false; 3028#if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) 3029 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE); 3030#endif 3031 portFmt->eColorFormat = useNonSurfaceMode ? 3032 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) : 3033 getPreferredColorFormatDefaultMode(portFmt->nIndex); 3034 3035 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) { 3036 eRet = OMX_ErrorNoMore; 3037 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ 3038 " NoMore Color formats"); 3039 } 3040 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat); 3041 } else { 3042 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d", 3043 (int)portFmt->nPortIndex); 3044 eRet = OMX_ErrorBadPortIndex; 3045 } 3046 break; 3047 } 3048 /*Component should support this port definition*/ 3049 case OMX_IndexParamAudioInit: { 3050 OMX_PORT_PARAM_TYPE *audioPortParamType = 3051 (OMX_PORT_PARAM_TYPE *) paramData; 3052 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); 3053 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3054 audioPortParamType->nSize = sizeof(audioPortParamType); 3055 audioPortParamType->nPorts = 0; 3056 audioPortParamType->nStartPortNumber = 0; 3057 break; 3058 } 3059 /*Component should support this port definition*/ 3060 case OMX_IndexParamImageInit: { 3061 OMX_PORT_PARAM_TYPE *imagePortParamType = 3062 (OMX_PORT_PARAM_TYPE *) paramData; 3063 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); 3064 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; 3065 imagePortParamType->nSize = sizeof(imagePortParamType); 3066 imagePortParamType->nPorts = 0; 3067 imagePortParamType->nStartPortNumber = 0; 3068 break; 3069 3070 } 3071 /*Component should support this port definition*/ 3072 case OMX_IndexParamOtherInit: { 3073 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x", 3074 paramIndex); 3075 eRet =OMX_ErrorUnsupportedIndex; 3076 break; 3077 } 3078 case OMX_IndexParamStandardComponentRole: { 3079 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3080 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3081 comp_role->nVersion.nVersion = OMX_SPEC_VERSION; 3082 comp_role->nSize = sizeof(*comp_role); 3083 3084 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d", 3085 paramIndex); 3086 strlcpy((char*)comp_role->cRole,(const char*)m_cRole, 3087 OMX_MAX_STRINGNAME_SIZE); 3088 break; 3089 } 3090 /* Added for parameter test */ 3091 case OMX_IndexParamPriorityMgmt: { 3092 3093 OMX_PRIORITYMGMTTYPE *priorityMgmType = 3094 (OMX_PRIORITYMGMTTYPE *) paramData; 3095 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); 3096 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; 3097 priorityMgmType->nSize = sizeof(priorityMgmType); 3098 3099 break; 3100 } 3101 /* Added for parameter test */ 3102 case OMX_IndexParamCompBufferSupplier: { 3103 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = 3104 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3105 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); 3106 3107 bufferSupplierType->nSize = sizeof(bufferSupplierType); 3108 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; 3109 if (0 == bufferSupplierType->nPortIndex) 3110 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3111 else if (1 == bufferSupplierType->nPortIndex) 3112 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; 3113 else 3114 eRet = OMX_ErrorBadPortIndex; 3115 3116 3117 break; 3118 } 3119 case OMX_IndexParamVideoAvc: { 3120 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x", 3121 paramIndex); 3122 break; 3123 } 3124 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 3125 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x", 3126 paramIndex); 3127 break; 3128 } 3129 case OMX_IndexParamVideoH263: { 3130 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x", 3131 paramIndex); 3132 break; 3133 } 3134 case OMX_IndexParamVideoMpeg4: { 3135 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x", 3136 paramIndex); 3137 break; 3138 } 3139 case OMX_IndexParamVideoMpeg2: { 3140 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x", 3141 paramIndex); 3142 break; 3143 } 3144 case OMX_IndexParamVideoProfileLevelQuerySupported: { 3145 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex); 3146 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = 3147 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; 3148 eRet = get_supported_profile_level(profileLevelType); 3149 break; 3150 } 3151#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3152 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: { 3153 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); 3154 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; 3155 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3156 3157 if (secure_mode && !secure_scaling_to_non_secure_opb) { 3158 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | 3159 GRALLOC_USAGE_PRIVATE_UNCACHED); 3160 } else { 3161 nativeBuffersUsage->nUsage = 3162 (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | 3163 GRALLOC_USAGE_PRIVATE_UNCACHED); 3164 } 3165 } else { 3166 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!"); 3167 eRet = OMX_ErrorBadParameter; 3168 } 3169 } 3170 break; 3171#endif 3172 3173#ifdef FLEXYUV_SUPPORTED 3174 case OMX_QcomIndexFlexibleYUVDescription: { 3175 DEBUG_PRINT_LOW("get_parameter: describeColorFormat"); 3176 eRet = describeColorFormat(paramData); 3177 break; 3178 } 3179#endif 3180 3181 default: { 3182 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex); 3183 eRet =OMX_ErrorUnsupportedIndex; 3184 } 3185 3186 } 3187 3188 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)", 3189 drv_ctx.video_resolution.frame_width, 3190 drv_ctx.video_resolution.frame_height, 3191 drv_ctx.video_resolution.stride, 3192 drv_ctx.video_resolution.scan_lines); 3193 3194 return eRet; 3195} 3196 3197#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3198OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) 3199{ 3200 DEBUG_PRINT_LOW("Inside use_android_native_buffer"); 3201 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3202 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; 3203 3204 if ((params == NULL) || 3205 (params->nativeBuffer == NULL) || 3206 (params->nativeBuffer->handle == NULL) || 3207 !m_enable_android_native_buffers) 3208 return OMX_ErrorBadParameter; 3209 m_use_android_native_buffers = OMX_TRUE; 3210 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 3211 private_handle_t *handle = (private_handle_t *)nBuf->handle; 3212 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port 3213 OMX_U8 *buffer = NULL; 3214 if (!secure_mode) { 3215 buffer = (OMX_U8*)mmap(0, handle->size, 3216 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 3217 if (buffer == MAP_FAILED) { 3218 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 3219 return OMX_ErrorInsufficientResources; 3220 } 3221 } 3222 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); 3223 } else { 3224 eRet = OMX_ErrorBadParameter; 3225 } 3226 return eRet; 3227} 3228#endif 3229 3230OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() { 3231 struct v4l2_control control; 3232 struct v4l2_format fmt; 3233 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER; 3234 control.value = 1; 3235 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 3236 if (rc < 0) { 3237 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); 3238 return OMX_ErrorHardware; 3239 } 3240 m_smoothstreaming_mode = true; 3241 return OMX_ErrorNone; 3242} 3243 3244/* ====================================================================== 3245 FUNCTION 3246 omx_vdec::Setparameter 3247 3248 DESCRIPTION 3249 OMX Set Parameter method implementation. 3250 3251 PARAMETERS 3252 <TBD>. 3253 3254 RETURN VALUE 3255 OMX Error None if successful. 3256 3257 ========================================================================== */ 3258OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, 3259 OMX_IN OMX_INDEXTYPE paramIndex, 3260 OMX_IN OMX_PTR paramData) 3261{ 3262 OMX_ERRORTYPE eRet = OMX_ErrorNone; 3263 int ret=0; 3264 struct v4l2_format fmt; 3265#ifdef _ANDROID_ 3266 char property_value[PROPERTY_VALUE_MAX] = {0}; 3267#endif 3268 if (m_state == OMX_StateInvalid) { 3269 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3270 return OMX_ErrorInvalidState; 3271 } 3272 if (paramData == NULL) { 3273 DEBUG_PRINT_ERROR("Get Param in Invalid paramData"); 3274 return OMX_ErrorBadParameter; 3275 } 3276 if ((m_state != OMX_StateLoaded) && 3277 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && 3278 (m_out_bEnabled == OMX_TRUE) && 3279 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && 3280 (m_inp_bEnabled == OMX_TRUE)) { 3281 DEBUG_PRINT_ERROR("Set Param in Invalid State"); 3282 return OMX_ErrorIncorrectStateOperation; 3283 } 3284 switch ((unsigned long)paramIndex) { 3285 case OMX_IndexParamPortDefinition: { 3286 OMX_PARAM_PORTDEFINITIONTYPE *portDefn; 3287 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; 3288 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has 3289 //been called. 3290 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", 3291 (int)portDefn->format.video.nFrameHeight, 3292 (int)portDefn->format.video.nFrameWidth); 3293 if (OMX_DirOutput == portDefn->eDir) { 3294 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); 3295 bool port_format_changed = false; 3296 m_display_id = portDefn->format.video.pNativeWindow; 3297 unsigned int buffer_size; 3298 /* update output port resolution with client supplied dimensions 3299 in case scaling is enabled, else it follows input resolution set 3300 */ 3301 if (is_down_scalar_enabled) { 3302 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)", 3303 (unsigned int)portDefn->format.video.nFrameWidth, 3304 (unsigned int)portDefn->format.video.nFrameHeight); 3305 if (portDefn->format.video.nFrameHeight != 0x0 && 3306 portDefn->format.video.nFrameWidth != 0x0) { 3307 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3308 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3309 fmt.fmt.pix_mp.pixelformat = capture_capability; 3310 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 3311 if (ret) { 3312 DEBUG_PRINT_ERROR("Get Resolution failed"); 3313 eRet = OMX_ErrorHardware; 3314 break; 3315 } 3316 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) || 3317 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) { 3318 port_format_changed = true; 3319 } 3320 update_resolution(portDefn->format.video.nFrameWidth, 3321 portDefn->format.video.nFrameHeight, 3322 portDefn->format.video.nFrameWidth, 3323 portDefn->format.video.nFrameHeight); 3324 3325 /* set crop info */ 3326 rectangle.nLeft = 0; 3327 rectangle.nTop = 0; 3328 rectangle.nWidth = portDefn->format.video.nFrameWidth; 3329 rectangle.nHeight = portDefn->format.video.nFrameHeight; 3330 3331 eRet = is_video_session_supported(); 3332 if (eRet) 3333 break; 3334 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3335 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3336 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3337 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3338 fmt.fmt.pix_mp.pixelformat = capture_capability; 3339 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", 3340 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width); 3341 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3342 if (ret) { 3343 DEBUG_PRINT_ERROR("Set Resolution failed"); 3344 eRet = OMX_ErrorUnsupportedSetting; 3345 } else 3346 eRet = get_buffer_req(&drv_ctx.op_buf); 3347 } 3348 3349 if (eRet) { 3350 break; 3351 } 3352 3353 if (secure_mode) { 3354 struct v4l2_control control; 3355 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD; 3356 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 3357 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id); 3358 eRet = OMX_ErrorHardware; 3359 } else { 3360 /* This is a workaround for a bug in fw which uses stride 3361 * and slice instead of width and height to check against 3362 * the threshold. 3363 */ 3364 OMX_U32 stride, slice; 3365 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 3366 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth); 3367 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight); 3368 } else { 3369 stride = portDefn->format.video.nFrameWidth; 3370 slice = portDefn->format.video.nFrameHeight; 3371 } 3372 3373 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice); 3374 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value); 3375 3376 if (stride * slice <= (OMX_U32)control.value) { 3377 secure_scaling_to_non_secure_opb = true; 3378 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ"); 3379 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2; 3380 control.value = 1; 3381 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) { 3382 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed"); 3383 eRet = OMX_ErrorUnsupportedSetting; 3384 } 3385 } 3386 } 3387 } 3388 } 3389 3390 if (eRet) { 3391 break; 3392 } 3393 3394 if (!client_buffers.get_buffer_req(buffer_size)) { 3395 DEBUG_PRINT_ERROR("Error in getting buffer requirements"); 3396 eRet = OMX_ErrorBadParameter; 3397 } else if (!port_format_changed) { 3398 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && 3399 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) { 3400 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; 3401 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize; 3402 drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount; 3403 drv_ctx.extradata_info.size = drv_ctx.extradata_info.count * 3404 drv_ctx.extradata_info.buffer_size; 3405 eRet = set_buffer_req(&drv_ctx.op_buf); 3406 if (eRet == OMX_ErrorNone) 3407 m_port_def = *portDefn; 3408 } else { 3409 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)", 3410 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size, 3411 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 3412 eRet = OMX_ErrorBadParameter; 3413 } 3414 } 3415 } else if (OMX_DirInput == portDefn->eDir) { 3416 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port"); 3417 bool port_format_changed = false; 3418 if ((portDefn->format.video.xFramerate >> 16) > 0 && 3419 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) { 3420 // Frame rate only should be set if this is a "known value" or to 3421 // activate ts prediction logic (arbitrary mode only) sending input 3422 // timestamps with max value (LLONG_MAX). 3423 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u", 3424 (unsigned int)portDefn->format.video.xFramerate >> 16); 3425 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, 3426 drv_ctx.frame_rate.fps_denominator); 3427 if (!drv_ctx.frame_rate.fps_numerator) { 3428 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 3429 drv_ctx.frame_rate.fps_numerator = 30; 3430 } 3431 if (drv_ctx.frame_rate.fps_denominator) 3432 drv_ctx.frame_rate.fps_numerator = (int) 3433 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 3434 drv_ctx.frame_rate.fps_denominator = 1; 3435 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 3436 drv_ctx.frame_rate.fps_numerator; 3437 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", 3438 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 3439 (float)drv_ctx.frame_rate.fps_denominator); 3440 3441 struct v4l2_outputparm oparm; 3442 /*XXX: we're providing timing info as seconds per frame rather than frames 3443 * per second.*/ 3444 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 3445 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 3446 3447 struct v4l2_streamparm sparm; 3448 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 3449 sparm.parm.output = oparm; 3450 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 3451 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected"); 3452 eRet = OMX_ErrorHardware; 3453 break; 3454 } 3455 //m_perf_control.request_cores(frm_int); 3456 } 3457 3458 if (drv_ctx.video_resolution.frame_height != 3459 portDefn->format.video.nFrameHeight || 3460 drv_ctx.video_resolution.frame_width != 3461 portDefn->format.video.nFrameWidth) { 3462 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)", 3463 (unsigned int)portDefn->format.video.nFrameWidth, 3464 (unsigned int)portDefn->format.video.nFrameHeight); 3465 port_format_changed = true; 3466 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth; 3467 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight; 3468 if (frameHeight != 0x0 && frameWidth != 0x0) { 3469 if (m_smoothstreaming_mode && 3470 ((frameWidth * frameHeight) < 3471 (m_smoothstreaming_width * m_smoothstreaming_height))) { 3472 frameWidth = m_smoothstreaming_width; 3473 frameHeight = m_smoothstreaming_height; 3474 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u " 3475 "for adaptive-playback/smooth-streaming", 3476 (unsigned int)frameWidth, (unsigned int)frameHeight); 3477 } 3478 update_resolution(frameWidth, frameHeight, 3479 frameWidth, frameHeight); 3480 eRet = is_video_session_supported(); 3481 if (eRet) 3482 break; 3483 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3484 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 3485 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3486 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3487 fmt.fmt.pix_mp.pixelformat = output_capability; 3488 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); 3489 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3490 if (ret) { 3491 DEBUG_PRINT_ERROR("Set Resolution failed"); 3492 eRet = OMX_ErrorUnsupportedSetting; 3493 } else { 3494 if (!is_down_scalar_enabled) 3495 eRet = get_buffer_req(&drv_ctx.op_buf); 3496 } 3497 } 3498 } 3499 if (m_custom_buffersize.input_buffersize 3500 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) { 3501 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d", 3502 m_custom_buffersize.input_buffersize, portDefn->nBufferSize); 3503 eRet = OMX_ErrorBadParameter; 3504 break; 3505 } 3506 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount 3507 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) { 3508 port_format_changed = true; 3509 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf; 3510 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; 3511 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) & 3512 (~(buffer_prop->alignment - 1)); 3513 eRet = set_buffer_req(buffer_prop); 3514 } 3515 if (false == port_format_changed) { 3516 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)", 3517 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size, 3518 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); 3519 eRet = OMX_ErrorBadParameter; 3520 } 3521 } else if (portDefn->eDir == OMX_DirMax) { 3522 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", 3523 (int)portDefn->nPortIndex); 3524 eRet = OMX_ErrorBadPortIndex; 3525 } 3526 } 3527 break; 3528 case OMX_IndexParamVideoPortFormat: { 3529 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = 3530 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; 3531 int ret=0; 3532 struct v4l2_format fmt; 3533 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u", 3534 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex); 3535 3536 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 3537 if (1 == portFmt->nPortIndex) { 3538 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3539 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 3540 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 3541 fmt.fmt.pix_mp.pixelformat = capture_capability; 3542 enum vdec_output_fromat op_format; 3543 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 3544 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m || 3545 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE) 3546 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView || 3547 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar || 3548 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) 3549 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12; 3550 else 3551 eRet = OMX_ErrorBadParameter; 3552 3553 if (eRet == OMX_ErrorNone) { 3554 drv_ctx.output_format = op_format; 3555 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 3556 if (ret) { 3557 DEBUG_PRINT_ERROR("Set output format failed"); 3558 eRet = OMX_ErrorUnsupportedSetting; 3559 /*TODO: How to handle this case */ 3560 } else { 3561 eRet = get_buffer_req(&drv_ctx.op_buf); 3562 } 3563 } 3564 if (eRet == OMX_ErrorNone) { 3565 if (!client_buffers.set_color_format(portFmt->eColorFormat)) { 3566 DEBUG_PRINT_ERROR("Set color format failed"); 3567 eRet = OMX_ErrorBadParameter; 3568 } 3569 } 3570 } 3571 } 3572 break; 3573 3574 case OMX_QcomIndexPortDefn: { 3575 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = 3576 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; 3577 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u", 3578 (unsigned int)portFmt->nFramePackingFormat); 3579 3580 /* Input port */ 3581 if (portFmt->nPortIndex == 0) { 3582 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) { 3583 if (secure_mode) { 3584 arbitrary_bytes = false; 3585 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session"); 3586 eRet = OMX_ErrorUnsupportedSetting; 3587 } else { 3588 arbitrary_bytes = true; 3589 } 3590 } else if (portFmt->nFramePackingFormat == 3591 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) { 3592 arbitrary_bytes = false; 3593#ifdef _ANDROID_ 3594 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); 3595 if (atoi(property_value)) { 3596 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command"); 3597 arbitrary_bytes = true; 3598 } 3599#endif 3600 } else { 3601 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u", 3602 (unsigned int)portFmt->nFramePackingFormat); 3603 eRet = OMX_ErrorUnsupportedSetting; 3604 } 3605 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3606 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port"); 3607 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && 3608 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && 3609 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) { 3610 m_out_mem_region_smi = OMX_TRUE; 3611 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 3612 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set"); 3613 m_use_output_pmem = OMX_TRUE; 3614 } 3615 } 3616 } 3617 } 3618 break; 3619 3620 case OMX_IndexParamStandardComponentRole: { 3621 OMX_PARAM_COMPONENTROLETYPE *comp_role; 3622 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; 3623 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", 3624 comp_role->cRole); 3625 3626 if ((m_state == OMX_StateLoaded)&& 3627 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 3628 DEBUG_PRINT_LOW("Set Parameter called in valid state"); 3629 } else { 3630 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 3631 return OMX_ErrorIncorrectStateOperation; 3632 } 3633 3634 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 3635 if (!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 3636 strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 3637 } else { 3638 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3639 eRet =OMX_ErrorUnsupportedSetting; 3640 } 3641 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 3642 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 3643 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 3644 } else { 3645 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3646 eRet =OMX_ErrorUnsupportedSetting; 3647 } 3648 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 3649 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 3650 strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); 3651 } else { 3652 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3653 eRet = OMX_ErrorUnsupportedSetting; 3654 } 3655 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) { 3656 if (!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) { 3657 strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 3658 } else { 3659 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3660 eRet =OMX_ErrorUnsupportedSetting; 3661 } 3662 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 3663 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 3664 strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); 3665 } else { 3666 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3667 eRet = OMX_ErrorUnsupportedSetting; 3668 } 3669 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || 3670 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) || 3671 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE)) 3672 ) { 3673 if (!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) { 3674 strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 3675 } else { 3676 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3677 eRet =OMX_ErrorUnsupportedSetting; 3678 } 3679 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || 3680 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) 3681 ) { 3682 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) { 3683 strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 3684 } else { 3685 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3686 eRet =OMX_ErrorUnsupportedSetting; 3687 } 3688 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) { 3689 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE) || 3690 (!strncmp((const char*)comp_role->cRole,"video_decoder.vpx",OMX_MAX_STRINGNAME_SIZE))) { 3691 strlcpy((char*)m_cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 3692 } else { 3693 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3694 eRet = OMX_ErrorUnsupportedSetting; 3695 } 3696 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 3697 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 3698 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 3699 } else { 3700 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole); 3701 eRet = OMX_ErrorUnsupportedSetting; 3702 } 3703 } else { 3704 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind); 3705 eRet = OMX_ErrorInvalidComponentName; 3706 } 3707 break; 3708 } 3709 3710 case OMX_IndexParamPriorityMgmt: { 3711 if (m_state != OMX_StateLoaded) { 3712 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); 3713 return OMX_ErrorIncorrectStateOperation; 3714 } 3715 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; 3716 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u", 3717 (unsigned int)priorityMgmtype->nGroupID); 3718 3719 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u", 3720 (unsigned int)priorityMgmtype->nGroupPriority); 3721 3722 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; 3723 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; 3724 3725 break; 3726 } 3727 3728 case OMX_IndexParamCompBufferSupplier: { 3729 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; 3730 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", 3731 bufferSupplierType->eBufferSupplier); 3732 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) 3733 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; 3734 3735 else 3736 3737 eRet = OMX_ErrorBadPortIndex; 3738 3739 break; 3740 3741 } 3742 case OMX_IndexParamVideoAvc: { 3743 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d", 3744 paramIndex); 3745 break; 3746 } 3747 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: { 3748 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d", 3749 paramIndex); 3750 break; 3751 } 3752 case OMX_IndexParamVideoH263: { 3753 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d", 3754 paramIndex); 3755 break; 3756 } 3757 case OMX_IndexParamVideoMpeg4: { 3758 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d", 3759 paramIndex); 3760 break; 3761 } 3762 case OMX_IndexParamVideoMpeg2: { 3763 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d", 3764 paramIndex); 3765 break; 3766 } 3767 case OMX_QcomIndexParamVideoDecoderPictureOrder: { 3768 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = 3769 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; 3770 struct v4l2_control control; 3771 int pic_order,rc=0; 3772 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d", 3773 pictureOrder->eOutputPictureOrder); 3774 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) { 3775 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; 3776 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) { 3777 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 3778 time_stamp_dts.set_timestamp_reorder_mode(false); 3779 } else 3780 eRet = OMX_ErrorBadParameter; 3781 if (eRet == OMX_ErrorNone) { 3782 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 3783 control.value = pic_order; 3784 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3785 if (rc) { 3786 DEBUG_PRINT_ERROR("Set picture order failed"); 3787 eRet = OMX_ErrorUnsupportedSetting; 3788 } 3789 } 3790 break; 3791 } 3792 case OMX_QcomIndexParamConcealMBMapExtraData: 3793 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false, 3794 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3795 break; 3796 case OMX_QcomIndexParamFrameInfoExtraData: 3797 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, 3798 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3799 break; 3800 case OMX_ExtraDataFrameDimension: 3801 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false, 3802 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3803 break; 3804 case OMX_QcomIndexParamInterlaceExtraData: 3805 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false, 3806 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3807 break; 3808 case OMX_QcomIndexParamH264TimeInfo: 3809 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false, 3810 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3811 break; 3812 case OMX_QcomIndexParamVideoFramePackingExtradata: 3813 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false, 3814 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3815 break; 3816 case OMX_QcomIndexParamVideoQPExtraData: 3817 eRet = enable_extradata(OMX_QP_EXTRADATA, false, 3818 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3819 break; 3820 case OMX_QcomIndexParamVideoInputBitsInfoExtraData: 3821 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false, 3822 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3823 break; 3824 case OMX_QcomIndexEnableExtnUserData: 3825 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false, 3826 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3827 break; 3828 case OMX_QcomIndexParamMpeg2SeqDispExtraData: 3829 eRet = enable_extradata(OMX_MPEG2SEQDISP_EXTRADATA, false, 3830 ((QOMX_ENABLETYPE *)paramData)->bEnable); 3831 break; 3832 case OMX_QcomIndexParamVideoDivx: { 3833 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; 3834 } 3835 break; 3836 case OMX_QcomIndexPlatformPvt: { 3837 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); 3838 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; 3839 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 3840 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); 3841 eRet = OMX_ErrorUnsupportedSetting; 3842 } else { 3843 m_out_pvt_entry_pmem = OMX_TRUE; 3844 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) { 3845 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set"); 3846 m_use_output_pmem = OMX_TRUE; 3847 } 3848 } 3849 3850 } 3851 break; 3852 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: { 3853 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); 3854 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); 3855 struct v4l2_control control; 3856 int rc; 3857 drv_ctx.idr_only_decoding = 1; 3858 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; 3859 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; 3860 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3861 if (rc) { 3862 DEBUG_PRINT_ERROR("Set picture order failed"); 3863 eRet = OMX_ErrorUnsupportedSetting; 3864 } else { 3865 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE; 3866 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE; 3867 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 3868 if (rc) { 3869 DEBUG_PRINT_ERROR("Sync frame setting failed"); 3870 eRet = OMX_ErrorUnsupportedSetting; 3871 } 3872 /*Setting sync frame decoding on driver might change buffer 3873 * requirements so update them here*/ 3874 if (get_buffer_req(&drv_ctx.ip_buf)) { 3875 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements"); 3876 eRet = OMX_ErrorUnsupportedSetting; 3877 } 3878 if (get_buffer_req(&drv_ctx.op_buf)) { 3879 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements"); 3880 eRet = OMX_ErrorUnsupportedSetting; 3881 } 3882 } 3883 } 3884 break; 3885 3886 case OMX_QcomIndexParamIndexExtraDataType: { 3887 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; 3888 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && 3889 (extradataIndexType->bEnabled == OMX_TRUE) && 3890 (extradataIndexType->nPortIndex == 1)) { 3891 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming"); 3892 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled); 3893 3894 } 3895 } 3896 break; 3897 case OMX_QcomIndexParamEnableSmoothStreaming: { 3898#ifndef SMOOTH_STREAMING_DISABLED 3899 eRet = enable_smoothstreaming(); 3900#else 3901 eRet = OMX_ErrorUnsupportedSetting; 3902#endif 3903 } 3904 break; 3905#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 3906 /* Need to allow following two set_parameters even in Idle 3907 * state. This is ANDROID architecture which is not in sync 3908 * with openmax standard. */ 3909 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: { 3910 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; 3911 if (enableNativeBuffers) { 3912 m_enable_android_native_buffers = enableNativeBuffers->enable; 3913 } 3914#if !defined(FLEXYUV_SUPPORTED) 3915 if (m_enable_android_native_buffers) { 3916 // Use the most-preferred-native-color-format as surface-mode is hinted here 3917 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) { 3918 DEBUG_PRINT_ERROR("Failed to set native color format!"); 3919 eRet = OMX_ErrorUnsupportedSetting; 3920 } 3921 } 3922#endif 3923 } 3924 break; 3925 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: { 3926 eRet = use_android_native_buffer(hComp, paramData); 3927 } 3928 break; 3929 case OMX_GoogleAndroidIndexAllocateNativeHandle: { 3930 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData; 3931 if (allocateNativeHandleParams != NULL) { 3932 allocate_native_handle = allocateNativeHandleParams->enable; 3933 } 3934 } 3935 break; 3936#endif 3937 case OMX_QcomIndexParamEnableTimeStampReorder: { 3938 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; 3939 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) { 3940 if (reorder->bEnable == OMX_TRUE) { 3941 frm_int =0; 3942 time_stamp_dts.set_timestamp_reorder_mode(true); 3943 } else 3944 time_stamp_dts.set_timestamp_reorder_mode(false); 3945 } else { 3946 time_stamp_dts.set_timestamp_reorder_mode(false); 3947 if (reorder->bEnable == OMX_TRUE) { 3948 eRet = OMX_ErrorUnsupportedSetting; 3949 } 3950 } 3951 } 3952 break; 3953 case OMX_IndexParamVideoProfileLevelCurrent: { 3954 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = 3955 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; 3956 if (pParam) { 3957 m_profile_lvl.eProfile = pParam->eProfile; 3958 m_profile_lvl.eLevel = pParam->eLevel; 3959 } 3960 break; 3961 3962 } 3963 case OMX_QcomIndexParamVideoMetaBufferMode: 3964 { 3965 StoreMetaDataInBuffersParams *metabuffer = 3966 (StoreMetaDataInBuffersParams *)paramData; 3967 if (!metabuffer) { 3968 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer); 3969 eRet = OMX_ErrorBadParameter; 3970 break; 3971 } 3972 if (m_disable_dynamic_buf_mode) { 3973 DEBUG_PRINT_HIGH("Dynamic buffer mode disabled by setprop"); 3974 eRet = OMX_ErrorUnsupportedSetting; 3975 break; 3976 } 3977 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 3978 //set property dynamic buffer mode to driver. 3979 struct v4l2_control control; 3980 struct v4l2_format fmt; 3981 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT; 3982 if (metabuffer->bStoreMetaData == true) { 3983 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC; 3984 } else { 3985 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC; 3986 } 3987 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); 3988 if (!rc) { 3989 DEBUG_PRINT_HIGH("%s buffer mode", 3990 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic"); 3991 dynamic_buf_mode = metabuffer->bStoreMetaData; 3992 } else { 3993 DEBUG_PRINT_ERROR("Failed to %s buffer mode", 3994 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic"); 3995 eRet = OMX_ErrorUnsupportedSetting; 3996 } 3997 } else { 3998 DEBUG_PRINT_ERROR( 3999 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u", 4000 (unsigned int)metabuffer->nPortIndex); 4001 eRet = OMX_ErrorUnsupportedSetting; 4002 } 4003 break; 4004 } 4005 case OMX_QcomIndexParamVideoDownScalar: 4006 { 4007 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData; 4008 struct v4l2_control control; 4009 int rc; 4010 if (pParam) { 4011 is_down_scalar_enabled = pParam->bEnable; 4012 if (is_down_scalar_enabled) { 4013 control.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE; 4014 control.value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY; 4015 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar value = %d", pParam->bEnable); 4016 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4017 if (rc < 0) { 4018 DEBUG_PRINT_ERROR("Failed to set down scalar on driver."); 4019 eRet = OMX_ErrorUnsupportedSetting; 4020 } 4021 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO; 4022 control.value = 1; 4023 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); 4024 if (rc < 0) { 4025 DEBUG_PRINT_ERROR("Failed to set keep aspect ratio on driver."); 4026 eRet = OMX_ErrorUnsupportedSetting; 4027 } 4028 } 4029 } 4030 break; 4031 } 4032#ifdef ADAPTIVE_PLAYBACK_SUPPORTED 4033 case OMX_QcomIndexParamVideoAdaptivePlaybackMode: 4034 { 4035 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback"); 4036 PrepareForAdaptivePlaybackParams* pParams = 4037 (PrepareForAdaptivePlaybackParams *) paramData; 4038 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { 4039 if (!pParams->bEnable) { 4040 return OMX_ErrorNone; 4041 } 4042 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth 4043 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) { 4044 DEBUG_PRINT_ERROR( 4045 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]", 4046 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight, 4047 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight); 4048 eRet = OMX_ErrorBadParameter; 4049 } else { 4050 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight); 4051 } 4052 } else { 4053 DEBUG_PRINT_ERROR( 4054 "Prepare for adaptive playback supported only on output port"); 4055 eRet = OMX_ErrorBadParameter; 4056 } 4057 break; 4058 } 4059 4060#endif 4061 case OMX_QcomIndexParamVideoCustomBufferSize: 4062 { 4063 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize"); 4064 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData; 4065 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 4066 struct v4l2_control control; 4067 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT; 4068 control.value = pParam->nBufferSize; 4069 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 4070 DEBUG_PRINT_ERROR("Failed to set input buffer size"); 4071 eRet = OMX_ErrorUnsupportedSetting; 4072 } else { 4073 eRet = get_buffer_req(&drv_ctx.ip_buf); 4074 if (eRet == OMX_ErrorNone) { 4075 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size; 4076 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d", 4077 m_custom_buffersize.input_buffersize); 4078 } else { 4079 DEBUG_PRINT_ERROR("Failed to get buffer requirement"); 4080 } 4081 } 4082 } else { 4083 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port"); 4084 eRet = OMX_ErrorBadParameter; 4085 } 4086 break; 4087 } 4088 default: { 4089 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex); 4090 eRet = OMX_ErrorUnsupportedIndex; 4091 } 4092 } 4093 if (eRet != OMX_ErrorNone) 4094 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex); 4095 return eRet; 4096} 4097 4098/* ====================================================================== 4099 FUNCTION 4100 omx_vdec::GetConfig 4101 4102 DESCRIPTION 4103 OMX Get Config Method implementation. 4104 4105 PARAMETERS 4106 <TBD>. 4107 4108 RETURN VALUE 4109 OMX Error None if successful. 4110 4111 ========================================================================== */ 4112OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, 4113 OMX_IN OMX_INDEXTYPE configIndex, 4114 OMX_INOUT OMX_PTR configData) 4115{ 4116 (void) hComp; 4117 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4118 4119 if (m_state == OMX_StateInvalid) { 4120 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 4121 return OMX_ErrorInvalidState; 4122 } 4123 4124 switch ((unsigned long)configIndex) { 4125 case OMX_QcomIndexConfigInterlaced: { 4126 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = 4127 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; 4128 if (configFmt->nPortIndex == 1) { 4129 if (configFmt->nIndex == 0) { 4130 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; 4131 } else if (configFmt->nIndex == 1) { 4132 configFmt->eInterlaceType = 4133 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 4134 } else if (configFmt->nIndex == 2) { 4135 configFmt->eInterlaceType = 4136 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 4137 } else { 4138 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" 4139 " NoMore Interlaced formats"); 4140 eRet = OMX_ErrorNoMore; 4141 } 4142 4143 } else { 4144 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port", 4145 (int)configFmt->nPortIndex); 4146 eRet = OMX_ErrorBadPortIndex; 4147 } 4148 break; 4149 } 4150 case OMX_QcomIndexQueryNumberOfVideoDecInstance: { 4151 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = 4152 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; 4153 decoderinstances->nNumOfInstances = 16; 4154 /*TODO: How to handle this case */ 4155 break; 4156 } 4157 case OMX_QcomIndexConfigVideoFramePackingArrangement: { 4158 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) { 4159 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = 4160 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; 4161 memcpy(configFmt, &m_frame_pack_arrangement, 4162 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 4163 } else { 4164 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); 4165 } 4166 break; 4167 } 4168 case OMX_IndexConfigCommonOutputCrop: { 4169 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData; 4170 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE)); 4171 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u", 4172 rectangle.nLeft, rectangle.nTop, 4173 rectangle.nWidth, rectangle.nHeight); 4174 break; 4175 } 4176 case OMX_QcomIndexConfigPerfLevel: { 4177 struct v4l2_control control; 4178 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 4179 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 4180 4181 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 4182 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { 4183 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno); 4184 eRet = OMX_ErrorHardware; 4185 } 4186 4187 if (eRet == OMX_ErrorNone) { 4188 switch (control.value) { 4189 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: 4190 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo; 4191 break; 4192 default: 4193 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value); 4194 /* Fall through */ 4195 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: 4196 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal; 4197 break; 4198 } 4199 } 4200 4201 break; 4202 } 4203 default: { 4204 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); 4205 eRet = OMX_ErrorBadParameter; 4206 } 4207 4208 } 4209 4210 return eRet; 4211} 4212 4213/* ====================================================================== 4214 FUNCTION 4215 omx_vdec::SetConfig 4216 4217 DESCRIPTION 4218 OMX Set Config method implementation 4219 4220 PARAMETERS 4221 <TBD>. 4222 4223 RETURN VALUE 4224 OMX Error None if successful. 4225 ========================================================================== */ 4226OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, 4227 OMX_IN OMX_INDEXTYPE configIndex, 4228 OMX_IN OMX_PTR configData) 4229{ 4230 (void) hComp; 4231 if (m_state == OMX_StateInvalid) { 4232 DEBUG_PRINT_ERROR("Get Config in Invalid State"); 4233 return OMX_ErrorInvalidState; 4234 } 4235 4236 OMX_ERRORTYPE ret = OMX_ErrorNone; 4237 OMX_VIDEO_CONFIG_NALSIZE *pNal; 4238 4239 DEBUG_PRINT_LOW("Set Config Called"); 4240 4241 if (configIndex == (OMX_INDEXTYPE)OMX_IndexVendorVideoExtraData) { 4242 OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData; 4243 DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called"); 4244 if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc") || 4245 !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc")) { 4246 DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData AVC"); 4247 OMX_U32 extra_size; 4248 // Parsing done here for the AVC atom is definitely not generic 4249 // Currently this piece of code is working, but certainly 4250 // not tested with all .mp4 files. 4251 // Incase of failure, we might need to revisit this 4252 // for a generic piece of code. 4253 4254 // Retrieve size of NAL length field 4255 // byte #4 contains the size of NAL lenght field 4256 nal_length = (config->pData[4] & 0x03) + 1; 4257 4258 extra_size = 0; 4259 if (nal_length > 2) { 4260 /* Presently we assume that only one SPS and one PPS in AvC1 Atom */ 4261 extra_size = (nal_length - 2) * 2; 4262 } 4263 4264 // SPS starts from byte #6 4265 OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]); 4266 OMX_U8 *pDestBuf; 4267 m_vendor_config.nPortIndex = config->nPortIndex; 4268 4269 // minus 6 --> SPS starts from byte #6 4270 // minus 1 --> picture param set byte to be ignored from avcatom 4271 m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size; 4272 m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize); 4273 OMX_U32 len; 4274 OMX_U8 index = 0; 4275 // case where SPS+PPS is sent as part of set_config 4276 pDestBuf = m_vendor_config.pData; 4277 4278 DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%u] len[%u] data[%p]", 4279 (unsigned int)m_vendor_config.nPortIndex, 4280 (unsigned int)m_vendor_config.nDataSize, 4281 m_vendor_config.pData); 4282 while (index < 2) { 4283 uint8 *psize; 4284 len = *pSrcBuf; 4285 len = len << 8; 4286 len |= *(pSrcBuf + 1); 4287 psize = (uint8 *) & len; 4288 memcpy(pDestBuf + nal_length, pSrcBuf + 2,len); 4289 for (unsigned int i = 0; i < nal_length; i++) { 4290 pDestBuf[i] = psize[nal_length - 1 - i]; 4291 } 4292 //memcpy(pDestBuf,pSrcBuf,(len+2)); 4293 pDestBuf += len + nal_length; 4294 pSrcBuf += len + 2; 4295 index++; 4296 pSrcBuf++; // skip picture param set 4297 len = 0; 4298 } 4299 } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") || 4300 !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) { 4301 m_vendor_config.nPortIndex = config->nPortIndex; 4302 m_vendor_config.nDataSize = config->nDataSize; 4303 m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize)); 4304 memcpy(m_vendor_config.pData, config->pData,config->nDataSize); 4305 } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) { 4306 if (m_vendor_config.pData) { 4307 free(m_vendor_config.pData); 4308 m_vendor_config.pData = NULL; 4309 m_vendor_config.nDataSize = 0; 4310 } 4311 4312 if (((*((OMX_U32 *) config->pData)) & 4313 VC1_SP_MP_START_CODE_MASK) == 4314 VC1_SP_MP_START_CODE) { 4315 DEBUG_PRINT_LOW("set_config - VC1 simple/main profile"); 4316 m_vendor_config.nPortIndex = config->nPortIndex; 4317 m_vendor_config.nDataSize = config->nDataSize; 4318 m_vendor_config.pData = 4319 (OMX_U8 *) malloc(config->nDataSize); 4320 memcpy(m_vendor_config.pData, config->pData, 4321 config->nDataSize); 4322 m_vc1_profile = VC1_SP_MP_RCV; 4323 } else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) { 4324 DEBUG_PRINT_LOW("set_config - VC1 Advance profile"); 4325 m_vendor_config.nPortIndex = config->nPortIndex; 4326 m_vendor_config.nDataSize = config->nDataSize; 4327 m_vendor_config.pData = 4328 (OMX_U8 *) malloc((config->nDataSize)); 4329 memcpy(m_vendor_config.pData, config->pData, 4330 config->nDataSize); 4331 m_vc1_profile = VC1_AP; 4332 } else if ((config->nDataSize == VC1_STRUCT_C_LEN)) { 4333 DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only"); 4334 m_vendor_config.nPortIndex = config->nPortIndex; 4335 m_vendor_config.nDataSize = config->nDataSize; 4336 m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize); 4337 memcpy(m_vendor_config.pData,config->pData,config->nDataSize); 4338 m_vc1_profile = VC1_SP_MP_RCV; 4339 } else { 4340 DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile"); 4341 } 4342 } 4343 return ret; 4344 } else if (configIndex == OMX_IndexConfigVideoNalSize) { 4345 struct v4l2_control temp; 4346 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT; 4347 4348 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); 4349 switch (pNal->nNaluBytes) { 4350 case 0: 4351 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES; 4352 break; 4353 case 2: 4354 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH; 4355 break; 4356 case 4: 4357 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH; 4358 break; 4359 default: 4360 return OMX_ErrorUnsupportedSetting; 4361 } 4362 4363 if (!arbitrary_bytes) { 4364 /* In arbitrary bytes mode, the assembler strips out nal size and replaces 4365 * with start code, so only need to notify driver in frame by frame mode */ 4366 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) { 4367 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT"); 4368 return OMX_ErrorHardware; 4369 } 4370 } 4371 4372 nal_length = pNal->nNaluBytes; 4373 m_frame_parser.init_nal_length(nal_length); 4374 4375 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length); 4376 return ret; 4377 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) { 4378 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData; 4379 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps); 4380 4381 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { 4382 if (config->bEnabled) { 4383 if ((config->nFps >> 16) > 0) { 4384 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u", 4385 (unsigned int)config->nFps >> 16); 4386 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator, 4387 drv_ctx.frame_rate.fps_denominator); 4388 4389 if (!drv_ctx.frame_rate.fps_numerator) { 4390 DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); 4391 drv_ctx.frame_rate.fps_numerator = 30; 4392 } 4393 4394 if (drv_ctx.frame_rate.fps_denominator) { 4395 drv_ctx.frame_rate.fps_numerator = (int) 4396 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; 4397 } 4398 4399 drv_ctx.frame_rate.fps_denominator = 1; 4400 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / 4401 drv_ctx.frame_rate.fps_numerator; 4402 4403 struct v4l2_outputparm oparm; 4404 /*XXX: we're providing timing info as seconds per frame rather than frames 4405 * per second.*/ 4406 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 4407 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 4408 4409 struct v4l2_streamparm sparm; 4410 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 4411 sparm.parm.output = oparm; 4412 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 4413 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 4414 performance might be affected"); 4415 ret = OMX_ErrorHardware; 4416 } 4417 client_set_fps = true; 4418 } else { 4419 DEBUG_PRINT_ERROR("Frame rate not supported."); 4420 ret = OMX_ErrorUnsupportedSetting; 4421 } 4422 } else { 4423 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate"); 4424 client_set_fps = false; 4425 } 4426 } else { 4427 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d", 4428 (int)config->nPortIndex); 4429 ret = OMX_ErrorBadPortIndex; 4430 } 4431 4432 return ret; 4433 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) { 4434 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = 4435 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; 4436 struct v4l2_control control; 4437 4438 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel); 4439 4440 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; 4441 4442 switch (perf->ePerfLevel) { 4443 case OMX_QCOM_PerfLevelNominal: 4444 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; 4445 break; 4446 case OMX_QCOM_PerfLevelTurbo: 4447 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; 4448 break; 4449 default: 4450 ret = OMX_ErrorUnsupportedSetting; 4451 break; 4452 } 4453 4454 if (ret == OMX_ErrorNone) { 4455 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? 4456 OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 4457 } 4458 4459 return ret; 4460 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) { 4461 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData; 4462 DEBUG_PRINT_LOW("Set_config: priority %d", priority->nU32); 4463 4464 struct v4l2_control control; 4465 4466 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; 4467 if (priority->nU32 == 0) 4468 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE; 4469 else 4470 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; 4471 4472 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 4473 DEBUG_PRINT_ERROR("Failed to set Priority"); 4474 ret = OMX_ErrorUnsupportedSetting; 4475 } 4476 return ret; 4477 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) { 4478 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData; 4479 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16); 4480 4481 struct v4l2_control control; 4482 4483 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE; 4484 control.value = rate->nU32; 4485 4486 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 4487 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources : 4488 OMX_ErrorUnsupportedSetting; 4489 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)", 4490 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno)); 4491 } 4492 return ret; 4493 } 4494 4495 return OMX_ErrorNotImplemented; 4496} 4497 4498#define extn_equals(param, extn) (!strncmp(param, extn, strlen(extn))) 4499 4500/* ====================================================================== 4501 FUNCTION 4502 omx_vdec::GetExtensionIndex 4503 4504 DESCRIPTION 4505 OMX GetExtensionIndex method implementaion. <TBD> 4506 4507 PARAMETERS 4508 <TBD>. 4509 4510 RETURN VALUE 4511 OMX Error None if everything successful. 4512 4513 ========================================================================== */ 4514OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, 4515 OMX_IN OMX_STRING paramName, 4516 OMX_OUT OMX_INDEXTYPE* indexType) 4517{ 4518 (void) hComp; 4519 if (m_state == OMX_StateInvalid) { 4520 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State"); 4521 return OMX_ErrorInvalidState; 4522 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) { 4523 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; 4524 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) { 4525 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; 4526 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) { 4527 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata; 4528 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) { 4529 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement; 4530 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) { 4531 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData; 4532 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) { 4533 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData; 4534 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) { 4535 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData; 4536 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_MPEG2SEQDISP_EXTRADATA)) { 4537 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamMpeg2SeqDispExtraData; 4538 } 4539#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) 4540 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) { 4541 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; 4542 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) { 4543 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; 4544 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) { 4545 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName); 4546 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; 4547 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) { 4548 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; 4549 } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) { 4550 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle; 4551 } 4552#endif 4553 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { 4554 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; 4555 } 4556#ifdef ADAPTIVE_PLAYBACK_SUPPORTED 4557 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) { 4558 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode; 4559 } 4560#endif 4561#ifdef FLEXYUV_SUPPORTED 4562 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) { 4563 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription; 4564 } 4565#endif 4566 else { 4567 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); 4568 return OMX_ErrorNotImplemented; 4569 } 4570 return OMX_ErrorNone; 4571} 4572 4573/* ====================================================================== 4574 FUNCTION 4575 omx_vdec::GetState 4576 4577 DESCRIPTION 4578 Returns the state information back to the caller.<TBD> 4579 4580 PARAMETERS 4581 <TBD>. 4582 4583 RETURN VALUE 4584 Error None if everything is successful. 4585 ========================================================================== */ 4586OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, 4587 OMX_OUT OMX_STATETYPE* state) 4588{ 4589 (void) hComp; 4590 *state = m_state; 4591 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state); 4592 return OMX_ErrorNone; 4593} 4594 4595/* ====================================================================== 4596 FUNCTION 4597 omx_vdec::ComponentTunnelRequest 4598 4599 DESCRIPTION 4600 OMX Component Tunnel Request method implementation. <TBD> 4601 4602 PARAMETERS 4603 None. 4604 4605 RETURN VALUE 4606 OMX Error None if everything successful. 4607 4608 ========================================================================== */ 4609OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, 4610 OMX_IN OMX_U32 port, 4611 OMX_IN OMX_HANDLETYPE peerComponent, 4612 OMX_IN OMX_U32 peerPort, 4613 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) 4614{ 4615 (void) hComp; 4616 (void) port; 4617 (void) peerComponent; 4618 (void) peerPort; 4619 (void) tunnelSetup; 4620 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented"); 4621 return OMX_ErrorNotImplemented; 4622} 4623 4624/* ====================================================================== 4625 FUNCTION 4626 omx_vdec::UseOutputBuffer 4627 4628 DESCRIPTION 4629 Helper function for Use buffer in the input pin 4630 4631 PARAMETERS 4632 None. 4633 4634 RETURN VALUE 4635 true/false 4636 4637 ========================================================================== */ 4638OMX_ERRORTYPE omx_vdec::allocate_extradata() 4639{ 4640#ifdef USE_ION 4641 if (drv_ctx.extradata_info.buffer_size) { 4642 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { 4643 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 4644 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4645 free_ion_memory(&drv_ctx.extradata_info.ion); 4646 } 4647 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); 4648 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( 4649 drv_ctx.extradata_info.size, 4096, 4650 &drv_ctx.extradata_info.ion.ion_alloc_data, 4651 &drv_ctx.extradata_info.ion.fd_ion_data, 0); 4652 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) { 4653 DEBUG_PRINT_ERROR("Failed to alloc extradata memory"); 4654 return OMX_ErrorInsufficientResources; 4655 } 4656 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL, 4657 drv_ctx.extradata_info.size, 4658 PROT_READ|PROT_WRITE, MAP_SHARED, 4659 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0); 4660 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) { 4661 DEBUG_PRINT_ERROR("Failed to map extradata memory"); 4662 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4663 free_ion_memory(&drv_ctx.extradata_info.ion); 4664 return OMX_ErrorInsufficientResources; 4665 } 4666 } 4667#endif 4668 if (!m_other_extradata) { 4669 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size); 4670 if (!m_other_extradata) { 4671 DEBUG_PRINT_ERROR("Failed to alloc memory\n"); 4672 return OMX_ErrorInsufficientResources; 4673 } 4674 } 4675 return OMX_ErrorNone; 4676} 4677 4678void omx_vdec::free_extradata() 4679{ 4680#ifdef USE_ION 4681 if (drv_ctx.extradata_info.uaddr) { 4682 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); 4683 close(drv_ctx.extradata_info.ion.fd_ion_data.fd); 4684 free_ion_memory(&drv_ctx.extradata_info.ion); 4685 } 4686 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); 4687#endif 4688 if (m_other_extradata) { 4689 free(m_other_extradata); 4690 m_other_extradata = NULL; 4691 } 4692} 4693 4694OMX_ERRORTYPE omx_vdec::use_output_buffer( 4695 OMX_IN OMX_HANDLETYPE hComp, 4696 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 4697 OMX_IN OMX_U32 port, 4698 OMX_IN OMX_PTR appData, 4699 OMX_IN OMX_U32 bytes, 4700 OMX_IN OMX_U8* buffer) 4701{ 4702 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4703 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 4704 unsigned i= 0; // Temporary counter 4705 struct vdec_setbuffer_cmd setbuffers; 4706 OMX_PTR privateAppData = NULL; 4707 private_handle_t *handle = NULL; 4708 OMX_U8 *buff = buffer; 4709 struct v4l2_buffer buf; 4710 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 4711 int extra_idx = 0; 4712 (void) hComp; 4713 (void) port; 4714 4715 if (!m_out_mem_ptr) { 4716 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); 4717 eRet = allocate_output_headers(); 4718 if (eRet == OMX_ErrorNone) 4719 eRet = allocate_extradata(); 4720 } 4721 4722 if (eRet == OMX_ErrorNone) { 4723 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 4724 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 4725 break; 4726 } 4727 } 4728 } 4729 4730 if (i >= drv_ctx.op_buf.actualcount) { 4731 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount); 4732 eRet = OMX_ErrorInsufficientResources; 4733 } 4734 4735 if (eRet != OMX_ErrorNone) 4736 return eRet; 4737 4738 if (dynamic_buf_mode) { 4739 *bufferHdr = (m_out_mem_ptr + i ); 4740 (*bufferHdr)->pBuffer = NULL; 4741 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 4742 enum v4l2_buf_type buf_type; 4743 int rr = 0; 4744 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4745 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 4746 DEBUG_PRINT_ERROR(" STREAMON FAILED : %d",rr); 4747 return OMX_ErrorInsufficientResources; 4748 } else { 4749 streaming[CAPTURE_PORT] = true; 4750 DEBUG_PRINT_LOW("STREAMON Successful"); 4751 } 4752 } 4753 BITMASK_SET(&m_out_bm_count,i); 4754 (*bufferHdr)->pAppPrivate = appData; 4755 (*bufferHdr)->pBuffer = buffer; 4756 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 4757 return eRet; 4758 } 4759 4760 if (eRet == OMX_ErrorNone) { 4761#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) 4762 if (m_enable_android_native_buffers) { 4763 if (m_use_android_native_buffers) { 4764 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; 4765 sp<android_native_buffer_t> nBuf = params->nativeBuffer; 4766 handle = (private_handle_t *)nBuf->handle; 4767 privateAppData = params->pAppPrivate; 4768 } else { 4769 handle = (private_handle_t *)buff; 4770 privateAppData = appData; 4771 } 4772 if (!handle) { 4773 DEBUG_PRINT_ERROR("handle is invalid"); 4774 return OMX_ErrorBadParameter; 4775 } 4776 4777 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { 4778 if (secure_mode && secure_scaling_to_non_secure_opb) { 4779 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it", 4780 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 4781 } else { 4782 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," 4783 " expected %u, got %u", 4784 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); 4785 return OMX_ErrorBadParameter; 4786 } 4787 } 4788 4789 drv_ctx.op_buf.buffer_size = handle->size; 4790 4791 if (!m_use_android_native_buffers) { 4792 if (!secure_mode) { 4793 buff = (OMX_U8*)mmap(0, handle->size, 4794 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 4795 if (buff == MAP_FAILED) { 4796 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); 4797 return OMX_ErrorInsufficientResources; 4798 } 4799 } 4800 } 4801#if defined(_ANDROID_ICS_) 4802 native_buffer[i].nativehandle = handle; 4803 native_buffer[i].privatehandle = handle; 4804#endif 4805 if (!handle) { 4806 DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); 4807 return OMX_ErrorBadParameter; 4808 } 4809 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; 4810 drv_ctx.ptr_outputbuffer[i].offset = 0; 4811 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 4812 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 4813 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size; 4814 } else 4815#endif 4816 4817 if (!ouput_egl_buffers && !m_use_output_pmem) { 4818#ifdef USE_ION 4819 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 4820 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, 4821 &drv_ctx.op_buf_ion_info[i].ion_alloc_data, 4822 &drv_ctx.op_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0); 4823 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { 4824 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd); 4825 return OMX_ErrorInsufficientResources; 4826 } 4827 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4828 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 4829#else 4830 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4831 open (MEM_DEVICE,O_RDWR); 4832 4833 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 4834 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 4835 return OMX_ErrorInsufficientResources; 4836 } 4837 4838 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */ 4839 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) { 4840 drv_ctx.ptr_outputbuffer[i].pmem_fd = \ 4841 open (MEM_DEVICE,O_RDWR); 4842 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { 4843 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd); 4844 return OMX_ErrorInsufficientResources; 4845 } 4846 } 4847 4848 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, 4849 drv_ctx.op_buf.buffer_size, 4850 drv_ctx.op_buf.alignment)) { 4851 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 4852 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 4853 return OMX_ErrorInsufficientResources; 4854 } 4855#endif 4856 if (!secure_mode) { 4857 drv_ctx.ptr_outputbuffer[i].bufferaddr = 4858 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, 4859 PROT_READ|PROT_WRITE, MAP_SHARED, 4860 drv_ctx.ptr_outputbuffer[i].pmem_fd,0); 4861 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { 4862 close(drv_ctx.ptr_outputbuffer[i].pmem_fd); 4863#ifdef USE_ION 4864 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 4865#endif 4866 DEBUG_PRINT_ERROR("Unable to mmap output buffer"); 4867 return OMX_ErrorInsufficientResources; 4868 } 4869 } 4870 drv_ctx.ptr_outputbuffer[i].offset = 0; 4871 privateAppData = appData; 4872 } else { 4873 4874 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem); 4875 if (!appData || !bytes ) { 4876 if (!secure_mode && !buffer) { 4877 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case"); 4878 return OMX_ErrorBadParameter; 4879 } 4880 } 4881 4882 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; 4883 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; 4884 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; 4885 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry || 4886 !pmem_list->nEntries || 4887 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { 4888 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer"); 4889 return OMX_ErrorBadParameter; 4890 } 4891 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 4892 pmem_list->entryList->entry; 4893 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx", 4894 pmem_info->pmem_fd); 4895 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; 4896 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; 4897 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; 4898 drv_ctx.ptr_outputbuffer[i].mmaped_size = 4899 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; 4900 privateAppData = appData; 4901 } 4902 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 4903 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; 4904 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 4905 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 4906 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 4907 4908 *bufferHdr = (m_out_mem_ptr + i ); 4909 if (secure_mode) 4910 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 4911 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 4912 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], 4913 sizeof (vdec_bufferpayload)); 4914 4915 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i, 4916 drv_ctx.ptr_outputbuffer[i].bufferaddr, 4917 drv_ctx.ptr_outputbuffer[i].pmem_fd ); 4918 4919 buf.index = i; 4920 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4921 buf.memory = V4L2_MEMORY_USERPTR; 4922 plane[0].length = drv_ctx.op_buf.buffer_size; 4923 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 4924 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 4925 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd; 4926 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 4927 plane[0].data_offset = 0; 4928 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 4929 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 4930 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 4931 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 4932#ifdef USE_ION 4933 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 4934#endif 4935 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 4936 plane[extra_idx].data_offset = 0; 4937 } else if (extra_idx >= VIDEO_MAX_PLANES) { 4938 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 4939 return OMX_ErrorBadParameter; 4940 } 4941 buf.m.planes = plane; 4942 buf.length = drv_ctx.num_planes; 4943 4944 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) { 4945 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 4946 /*TODO: How to handle this case */ 4947 return OMX_ErrorInsufficientResources; 4948 } 4949 4950 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) { 4951 enum v4l2_buf_type buf_type; 4952 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 4953 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) { 4954 return OMX_ErrorInsufficientResources; 4955 } else { 4956 streaming[CAPTURE_PORT] = true; 4957 DEBUG_PRINT_LOW("STREAMON Successful"); 4958 } 4959 } 4960 4961 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; 4962 if (m_enable_android_native_buffers) { 4963 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle); 4964 (*bufferHdr)->pBuffer = (OMX_U8 *)handle; 4965 } else { 4966 (*bufferHdr)->pBuffer = buff; 4967 } 4968 (*bufferHdr)->pAppPrivate = privateAppData; 4969 BITMASK_SET(&m_out_bm_count,i); 4970 } 4971 return eRet; 4972} 4973 4974/* ====================================================================== 4975 FUNCTION 4976 omx_vdec::use_input_heap_buffers 4977 4978 DESCRIPTION 4979 OMX Use Buffer Heap allocation method implementation. 4980 4981 PARAMETERS 4982 <TBD>. 4983 4984 RETURN VALUE 4985 OMX Error None , if everything successful. 4986 4987 ========================================================================== */ 4988OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( 4989 OMX_IN OMX_HANDLETYPE hComp, 4990 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 4991 OMX_IN OMX_U32 port, 4992 OMX_IN OMX_PTR appData, 4993 OMX_IN OMX_U32 bytes, 4994 OMX_IN OMX_U8* buffer) 4995{ 4996 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer); 4997 OMX_ERRORTYPE eRet = OMX_ErrorNone; 4998 if (!m_inp_heap_ptr) 4999 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) 5000 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 5001 drv_ctx.ip_buf.actualcount); 5002 if (!m_phdr_pmem_ptr) 5003 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) 5004 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 5005 drv_ctx.ip_buf.actualcount); 5006 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) { 5007 DEBUG_PRINT_ERROR("Insufficent memory"); 5008 eRet = OMX_ErrorInsufficientResources; 5009 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) { 5010 input_use_buffer = true; 5011 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); 5012 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; 5013 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; 5014 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; 5015 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; 5016 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; 5017 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; 5018 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); 5019 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); 5020 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt], 5021 (unsigned)NULL, (unsigned)NULL)) { 5022 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 5023 return OMX_ErrorInsufficientResources; 5024 } 5025 m_in_alloc_cnt++; 5026 } else { 5027 DEBUG_PRINT_ERROR("All i/p buffers have been set!"); 5028 eRet = OMX_ErrorInsufficientResources; 5029 } 5030 return eRet; 5031} 5032 5033/* ====================================================================== 5034 FUNCTION 5035 omx_vdec::UseBuffer 5036 5037 DESCRIPTION 5038 OMX Use Buffer method implementation. 5039 5040 PARAMETERS 5041 <TBD>. 5042 5043 RETURN VALUE 5044 OMX Error None , if everything successful. 5045 5046 ========================================================================== */ 5047OMX_ERRORTYPE omx_vdec::use_buffer( 5048 OMX_IN OMX_HANDLETYPE hComp, 5049 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5050 OMX_IN OMX_U32 port, 5051 OMX_IN OMX_PTR appData, 5052 OMX_IN OMX_U32 bytes, 5053 OMX_IN OMX_U8* buffer) 5054{ 5055 OMX_ERRORTYPE error = OMX_ErrorNone; 5056 struct vdec_setbuffer_cmd setbuffers; 5057 5058 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) { 5059 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer); 5060 return OMX_ErrorBadParameter; 5061 } 5062 if (m_state == OMX_StateInvalid) { 5063 DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); 5064 return OMX_ErrorInvalidState; 5065 } 5066 if (port == OMX_CORE_INPUT_PORT_INDEX) 5067 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); 5068 else if (port == OMX_CORE_OUTPUT_PORT_INDEX) 5069 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested 5070 else { 5071 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 5072 error = OMX_ErrorBadPortIndex; 5073 } 5074 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error); 5075 if (error == OMX_ErrorNone) { 5076 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 5077 // Send the callback now 5078 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 5079 post_event(OMX_CommandStateSet,OMX_StateIdle, 5080 OMX_COMPONENT_GENERATE_EVENT); 5081 } 5082 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && 5083 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 5084 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 5085 post_event(OMX_CommandPortEnable, 5086 OMX_CORE_INPUT_PORT_INDEX, 5087 OMX_COMPONENT_GENERATE_EVENT); 5088 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && 5089 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 5090 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 5091 post_event(OMX_CommandPortEnable, 5092 OMX_CORE_OUTPUT_PORT_INDEX, 5093 OMX_COMPONENT_GENERATE_EVENT); 5094 } 5095 } 5096 return error; 5097} 5098 5099OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, 5100 OMX_BUFFERHEADERTYPE *pmem_bufferHdr) 5101{ 5102 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) { 5103 if (m_inp_heap_ptr[bufferindex].pBuffer) 5104 free(m_inp_heap_ptr[bufferindex].pBuffer); 5105 m_inp_heap_ptr[bufferindex].pBuffer = NULL; 5106 } 5107 if (pmem_bufferHdr) 5108 free_input_buffer(pmem_bufferHdr); 5109 return OMX_ErrorNone; 5110} 5111 5112OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 5113{ 5114 unsigned int index = 0; 5115 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) { 5116 return OMX_ErrorBadParameter; 5117 } 5118 5119 index = bufferHdr - m_inp_mem_ptr; 5120 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 5121 5122 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) { 5123 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); 5124 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) { 5125 struct vdec_setbuffer_cmd setbuffers; 5126 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; 5127 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], 5128 sizeof (vdec_bufferpayload)); 5129 if (!secure_mode) { 5130 DEBUG_PRINT_LOW("unmap the input buffer fd=%d", 5131 drv_ctx.ptr_inputbuffer[index].pmem_fd); 5132 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p", 5133 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size, 5134 drv_ctx.ptr_inputbuffer[index].bufferaddr); 5135 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, 5136 drv_ctx.ptr_inputbuffer[index].mmaped_size); 5137 close (drv_ctx.ptr_inputbuffer[index].pmem_fd); 5138 } else if (allocate_native_handle){ 5139 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer; 5140 native_handle_close(nh); 5141 native_handle_delete(nh); 5142 } 5143 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; 5144 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) { 5145 free(m_desc_buffer_ptr[index].buf_addr); 5146 m_desc_buffer_ptr[index].buf_addr = NULL; 5147 m_desc_buffer_ptr[index].desc_data_size = 0; 5148 } 5149#ifdef USE_ION 5150 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); 5151#endif 5152 } 5153 } 5154 5155 return OMX_ErrorNone; 5156} 5157 5158OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) 5159{ 5160 unsigned int index = 0; 5161 5162 if (bufferHdr == NULL || m_out_mem_ptr == NULL) { 5163 return OMX_ErrorBadParameter; 5164 } 5165 5166 index = bufferHdr - m_out_mem_ptr; 5167 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index); 5168 5169 if (index < drv_ctx.op_buf.actualcount 5170 && drv_ctx.ptr_outputbuffer) { 5171 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index, 5172 drv_ctx.ptr_outputbuffer[index].bufferaddr); 5173 5174 struct vdec_setbuffer_cmd setbuffers; 5175 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 5176 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], 5177 sizeof (vdec_bufferpayload)); 5178 5179 if (!dynamic_buf_mode) { 5180#ifdef _ANDROID_ 5181 if (m_enable_android_native_buffers) { 5182 if (!secure_mode) { 5183 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { 5184 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, 5185 drv_ctx.ptr_outputbuffer[index].mmaped_size); 5186 } 5187 } 5188 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; 5189 } else { 5190#endif 5191 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { 5192 if (!secure_mode) { 5193 DEBUG_PRINT_LOW("unmap the output buffer fd = %d", 5194 drv_ctx.ptr_outputbuffer[0].pmem_fd); 5195 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p", 5196 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, 5197 drv_ctx.ptr_outputbuffer[0].bufferaddr); 5198 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, 5199 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); 5200 } 5201 close (drv_ctx.ptr_outputbuffer[0].pmem_fd); 5202 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; 5203#ifdef USE_ION 5204 free_ion_memory(&drv_ctx.op_buf_ion_info[0]); 5205#endif 5206 } 5207#ifdef _ANDROID_ 5208 } 5209#endif 5210 } //!dynamic_buf_mode 5211 if (release_output_done()) { 5212 free_extradata(); 5213 } 5214 } 5215 5216 return OMX_ErrorNone; 5217 5218} 5219 5220OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, 5221 OMX_BUFFERHEADERTYPE **bufferHdr, 5222 OMX_U32 port, 5223 OMX_PTR appData, 5224 OMX_U32 bytes) 5225{ 5226 OMX_BUFFERHEADERTYPE *input = NULL; 5227 unsigned char *buf_addr = NULL; 5228 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5229 unsigned i = 0; 5230 5231 /* Sanity Check*/ 5232 if (bufferHdr == NULL) { 5233 return OMX_ErrorBadParameter; 5234 } 5235 5236 if (m_inp_heap_ptr == NULL) { 5237 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ 5238 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), 5239 drv_ctx.ip_buf.actualcount); 5240 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ 5241 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), 5242 drv_ctx.ip_buf.actualcount); 5243 5244 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) { 5245 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed "); 5246 return OMX_ErrorInsufficientResources; 5247 } 5248 } 5249 5250 /*Find a Free index*/ 5251 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 5252 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) { 5253 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 5254 break; 5255 } 5256 } 5257 5258 if (i < drv_ctx.ip_buf.actualcount) { 5259 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); 5260 5261 if (buf_addr == NULL) { 5262 return OMX_ErrorInsufficientResources; 5263 } 5264 5265 *bufferHdr = (m_inp_heap_ptr + i); 5266 input = *bufferHdr; 5267 BITMASK_SET(&m_heap_inp_bm_count,i); 5268 5269 input->pBuffer = (OMX_U8 *)buf_addr; 5270 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5271 input->nVersion.nVersion = OMX_SPEC_VERSION; 5272 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 5273 input->pAppPrivate = appData; 5274 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 5275 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr ); 5276 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); 5277 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]); 5278 /*Add the Buffers to freeq*/ 5279 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i], 5280 (unsigned)NULL, (unsigned)NULL)) { 5281 DEBUG_PRINT_ERROR("ERROR:Free_q is full"); 5282 return OMX_ErrorInsufficientResources; 5283 } 5284 } else { 5285 return OMX_ErrorBadParameter; 5286 } 5287 5288 return eRet; 5289 5290} 5291 5292 5293/* ====================================================================== 5294 FUNCTION 5295 omx_vdec::AllocateInputBuffer 5296 5297 DESCRIPTION 5298 Helper function for allocate buffer in the input pin 5299 5300 PARAMETERS 5301 None. 5302 5303 RETURN VALUE 5304 true/false 5305 5306 ========================================================================== */ 5307OMX_ERRORTYPE omx_vdec::allocate_input_buffer( 5308 OMX_IN OMX_HANDLETYPE hComp, 5309 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5310 OMX_IN OMX_U32 port, 5311 OMX_IN OMX_PTR appData, 5312 OMX_IN OMX_U32 bytes) 5313{ 5314 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5315 struct vdec_setbuffer_cmd setbuffers; 5316 OMX_BUFFERHEADERTYPE *input = NULL; 5317 unsigned i = 0; 5318 unsigned char *buf_addr = NULL; 5319 int pmem_fd = -1; 5320 5321 (void) hComp; 5322 (void) port; 5323 5324 5325 if (bytes != drv_ctx.ip_buf.buffer_size) { 5326 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u", 5327 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size); 5328 return OMX_ErrorBadParameter; 5329 } 5330 5331 if (!m_inp_mem_ptr) { 5332 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)", 5333 drv_ctx.ip_buf.actualcount, 5334 (unsigned int)drv_ctx.ip_buf.buffer_size); 5335 5336 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ 5337 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); 5338 5339 if (m_inp_mem_ptr == NULL) { 5340 return OMX_ErrorInsufficientResources; 5341 } 5342 5343 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ 5344 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); 5345 5346 if (drv_ctx.ptr_inputbuffer == NULL) { 5347 return OMX_ErrorInsufficientResources; 5348 } 5349#ifdef USE_ION 5350 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ 5351 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); 5352 5353 if (drv_ctx.ip_buf_ion_info == NULL) { 5354 return OMX_ErrorInsufficientResources; 5355 } 5356#endif 5357 5358 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) { 5359 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; 5360#ifdef USE_ION 5361 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; 5362#endif 5363 } 5364 } 5365 5366 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) { 5367 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 5368 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); 5369 break; 5370 } 5371 } 5372 5373 if (i < drv_ctx.ip_buf.actualcount) { 5374 struct v4l2_buffer buf; 5375 struct v4l2_plane plane; 5376 int rc; 5377 DEBUG_PRINT_LOW("Allocate input Buffer"); 5378#ifdef USE_ION 5379 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( 5380 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, 5381 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, 5382 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE 5383#ifndef DISABLE_INPUT_BUFFER_CACHE 5384 : ION_FLAG_CACHED 5385#else 5386 : 0 5387#endif 5388 ); 5389 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { 5390 return OMX_ErrorInsufficientResources; 5391 } 5392 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; 5393#else 5394 pmem_fd = open (MEM_DEVICE,O_RDWR); 5395 5396 if (pmem_fd < 0) { 5397 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 5398 return OMX_ErrorInsufficientResources; 5399 } 5400 5401 if (pmem_fd == 0) { 5402 pmem_fd = open (MEM_DEVICE,O_RDWR); 5403 5404 if (pmem_fd < 0) { 5405 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer"); 5406 return OMX_ErrorInsufficientResources; 5407 } 5408 } 5409 5410 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, 5411 drv_ctx.ip_buf.alignment)) { 5412 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 5413 close(pmem_fd); 5414 return OMX_ErrorInsufficientResources; 5415 } 5416#endif 5417 if (!secure_mode) { 5418 buf_addr = (unsigned char *)mmap(NULL, 5419 drv_ctx.ip_buf.buffer_size, 5420 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); 5421 5422 if (buf_addr == MAP_FAILED) { 5423 close(pmem_fd); 5424#ifdef USE_ION 5425 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); 5426#endif 5427 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer"); 5428 return OMX_ErrorInsufficientResources; 5429 } 5430 } 5431 *bufferHdr = (m_inp_mem_ptr + i); 5432 if (secure_mode) 5433 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; 5434 else 5435 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; 5436 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; 5437 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; 5438 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; 5439 drv_ctx.ptr_inputbuffer [i].offset = 0; 5440 5441 5442 buf.index = i; 5443 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 5444 buf.memory = V4L2_MEMORY_USERPTR; 5445 plane.bytesused = 0; 5446 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size; 5447 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr; 5448 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd; 5449 plane.reserved[1] = 0; 5450 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset; 5451 buf.m.planes = &plane; 5452 buf.length = 1; 5453 5454 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i, 5455 drv_ctx.ptr_inputbuffer[i].bufferaddr); 5456 5457 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 5458 5459 if (rc) { 5460 DEBUG_PRINT_ERROR("Failed to prepare bufs"); 5461 /*TODO: How to handle this case */ 5462 return OMX_ErrorInsufficientResources; 5463 } 5464 5465 input = *bufferHdr; 5466 BITMASK_SET(&m_inp_bm_count,i); 5467 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr); 5468 if (allocate_native_handle) { 5469 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/); 5470 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd; 5471 input->pBuffer = (OMX_U8 *)nh; 5472 } else if (secure_mode) { 5473 /*Legacy method, pass ion fd stashed directly in pBuffer*/ 5474 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer [i].pmem_fd; 5475 } else { 5476 input->pBuffer = (OMX_U8 *)buf_addr; 5477 } 5478 input->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5479 input->nVersion.nVersion = OMX_SPEC_VERSION; 5480 input->nAllocLen = drv_ctx.ip_buf.buffer_size; 5481 input->pAppPrivate = appData; 5482 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; 5483 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; 5484 5485 if (drv_ctx.disable_dmx) { 5486 eRet = allocate_desc_buffer(i); 5487 } 5488 } else { 5489 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found"); 5490 eRet = OMX_ErrorInsufficientResources; 5491 } 5492 return eRet; 5493} 5494 5495 5496/* ====================================================================== 5497 FUNCTION 5498 omx_vdec::AllocateOutputBuffer 5499 5500 DESCRIPTION 5501 Helper fn for AllocateBuffer in the output pin 5502 5503 PARAMETERS 5504 <TBD>. 5505 5506 RETURN VALUE 5507 OMX Error None if everything went well. 5508 5509 ========================================================================== */ 5510OMX_ERRORTYPE omx_vdec::allocate_output_buffer( 5511 OMX_IN OMX_HANDLETYPE hComp, 5512 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5513 OMX_IN OMX_U32 port, 5514 OMX_IN OMX_PTR appData, 5515 OMX_IN OMX_U32 bytes) 5516{ 5517 (void)hComp; 5518 (void)port; 5519 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5520 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header 5521 unsigned i= 0; // Temporary counter 5522 struct vdec_setbuffer_cmd setbuffers; 5523 int extra_idx = 0; 5524#ifdef USE_ION 5525 int ion_device_fd =-1; 5526 struct ion_allocation_data ion_alloc_data; 5527 struct ion_fd_data fd_ion_data; 5528#endif 5529 if (!m_out_mem_ptr) { 5530 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)", 5531 drv_ctx.op_buf.actualcount, 5532 (unsigned int)drv_ctx.op_buf.buffer_size); 5533 int nBufHdrSize = 0; 5534 int nPlatformEntrySize = 0; 5535 int nPlatformListSize = 0; 5536 int nPMEMInfoSize = 0; 5537 int pmem_fd = -1; 5538 unsigned char *pmem_baseaddress = NULL; 5539 5540 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 5541 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 5542 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 5543 5544 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)", 5545 drv_ctx.op_buf.actualcount); 5546 nBufHdrSize = drv_ctx.op_buf.actualcount * 5547 sizeof(OMX_BUFFERHEADERTYPE); 5548 5549 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 5550 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 5551 nPlatformListSize = drv_ctx.op_buf.actualcount * 5552 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 5553 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 5554 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 5555 5556 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 5557 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 5558 nPMEMInfoSize, 5559 nPlatformListSize); 5560 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, 5561 drv_ctx.op_buf.actualcount); 5562#ifdef USE_ION 5563 // Allocate output buffers as cached to improve performance of software-reading 5564 // of the YUVs. Output buffers are cache-invalidated in driver. 5565 // If color-conversion is involved, Only the C2D output buffers are cached, no 5566 // need to cache the decoder's output buffers 5567 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED; 5568 ion_device_fd = alloc_map_ion_memory( 5569 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount, 5570 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment, 5571 &ion_alloc_data, &fd_ion_data, 5572 (secure_mode && !secure_scaling_to_non_secure_opb) ? ION_SECURE : cache_flag); 5573 if (ion_device_fd < 0) { 5574 return OMX_ErrorInsufficientResources; 5575 } 5576 pmem_fd = fd_ion_data.fd; 5577#else 5578 pmem_fd = open (MEM_DEVICE,O_RDWR); 5579 5580 if (pmem_fd < 0) { 5581 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 5582 drv_ctx.op_buf.buffer_size); 5583 return OMX_ErrorInsufficientResources; 5584 } 5585 5586 if (pmem_fd == 0) { 5587 pmem_fd = open (MEM_DEVICE,O_RDWR); 5588 5589 if (pmem_fd < 0) { 5590 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d", 5591 drv_ctx.op_buf.buffer_size); 5592 return OMX_ErrorInsufficientResources; 5593 } 5594 } 5595 5596 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size * 5597 drv_ctx.op_buf.actualcount, 5598 drv_ctx.op_buf.alignment)) { 5599 DEBUG_PRINT_ERROR("align_pmem_buffers() failed"); 5600 close(pmem_fd); 5601 return OMX_ErrorInsufficientResources; 5602 } 5603#endif 5604 if (!secure_mode) { 5605 pmem_baseaddress = (unsigned char *)mmap(NULL, 5606 (drv_ctx.op_buf.buffer_size * 5607 drv_ctx.op_buf.actualcount), 5608 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); 5609 if (pmem_baseaddress == MAP_FAILED) { 5610 DEBUG_PRINT_ERROR("MMAP failed for Size %u", 5611 (unsigned int)drv_ctx.op_buf.buffer_size); 5612 close(pmem_fd); 5613#ifdef USE_ION 5614 free_ion_memory(&drv_ctx.op_buf_ion_info[i]); 5615#endif 5616 return OMX_ErrorInsufficientResources; 5617 } 5618 } 5619 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 5620 // Alloc mem for platform specific info 5621 char *pPtr=NULL; 5622 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 5623 nPMEMInfoSize,1); 5624 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ 5625 calloc (sizeof(struct vdec_bufferpayload), 5626 drv_ctx.op_buf.actualcount); 5627 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 5628 calloc (sizeof (struct vdec_output_frameinfo), 5629 drv_ctx.op_buf.actualcount); 5630 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 5631 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer "); 5632 return OMX_ErrorInsufficientResources; 5633 } 5634 5635#ifdef USE_ION 5636 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ 5637 calloc (sizeof(struct vdec_ion), 5638 drv_ctx.op_buf.actualcount); 5639 if (!drv_ctx.op_buf_ion_info) { 5640 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 5641 return OMX_ErrorInsufficientResources; 5642 } 5643#endif 5644 5645 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 5646 && drv_ctx.ptr_respbuffer) { 5647 drv_ctx.ptr_outputbuffer[0].mmaped_size = 5648 (drv_ctx.op_buf.buffer_size * 5649 drv_ctx.op_buf.actualcount); 5650 bufHdr = m_out_mem_ptr; 5651 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 5652 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 5653 (((char *) m_platform_list) + nPlatformListSize); 5654 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 5655 (((char *) m_platform_entry) + nPlatformEntrySize); 5656 pPlatformList = m_platform_list; 5657 pPlatformEntry = m_platform_entry; 5658 pPMEMInfo = m_pmem_info; 5659 5660 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 5661 5662 // Settting the entire storage nicely 5663 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry); 5664 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 5665 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 5666 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 5667 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 5668 // Set the values when we determine the right HxW param 5669 bufHdr->nAllocLen = bytes; 5670 bufHdr->nFilledLen = 0; 5671 bufHdr->pAppPrivate = appData; 5672 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 5673 // Platform specific PMEM Information 5674 // Initialize the Platform Entry 5675 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i); 5676 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 5677 pPlatformEntry->entry = pPMEMInfo; 5678 // Initialize the Platform List 5679 pPlatformList->nEntries = 1; 5680 pPlatformList->entryList = pPlatformEntry; 5681 // Keep pBuffer NULL till vdec is opened 5682 bufHdr->pBuffer = NULL; 5683 bufHdr->nOffset = 0; 5684 5685 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i; 5686 pPMEMInfo->pmem_fd = 0; 5687 bufHdr->pPlatformPrivate = pPlatformList; 5688 5689 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd; 5690 m_pmem_info[i].pmem_fd = pmem_fd; 5691#ifdef USE_ION 5692 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd; 5693 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data; 5694 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data; 5695#endif 5696 5697 /*Create a mapping between buffers*/ 5698 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 5699 drv_ctx.ptr_respbuffer[i].client_data = (void *)\ 5700 &drv_ctx.ptr_outputbuffer[i]; 5701 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i; 5702 drv_ctx.ptr_outputbuffer[i].bufferaddr = 5703 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i); 5704 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len; 5705 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; 5706 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; 5707 5708 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p", 5709 pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset, 5710 drv_ctx.ptr_outputbuffer[i].bufferaddr); 5711 // Move the buffer and buffer header pointers 5712 bufHdr++; 5713 pPMEMInfo++; 5714 pPlatformEntry++; 5715 pPlatformList++; 5716 } 5717 } else { 5718 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 5719 m_out_mem_ptr, pPtr); 5720 if (m_out_mem_ptr) { 5721 free(m_out_mem_ptr); 5722 m_out_mem_ptr = NULL; 5723 } 5724 if (pPtr) { 5725 free(pPtr); 5726 pPtr = NULL; 5727 } 5728 if (drv_ctx.ptr_outputbuffer) { 5729 free(drv_ctx.ptr_outputbuffer); 5730 drv_ctx.ptr_outputbuffer = NULL; 5731 } 5732 if (drv_ctx.ptr_respbuffer) { 5733 free(drv_ctx.ptr_respbuffer); 5734 drv_ctx.ptr_respbuffer = NULL; 5735 } 5736#ifdef USE_ION 5737 if (drv_ctx.op_buf_ion_info) { 5738 DEBUG_PRINT_LOW("Free o/p ion context"); 5739 free(drv_ctx.op_buf_ion_info); 5740 drv_ctx.op_buf_ion_info = NULL; 5741 } 5742#endif 5743 eRet = OMX_ErrorInsufficientResources; 5744 } 5745 if (eRet == OMX_ErrorNone) 5746 eRet = allocate_extradata(); 5747 } 5748 5749 for (i=0; i< drv_ctx.op_buf.actualcount; i++) { 5750 if (BITMASK_ABSENT(&m_out_bm_count,i)) { 5751 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i); 5752 break; 5753 } 5754 } 5755 5756 if (eRet == OMX_ErrorNone) { 5757 if (i < drv_ctx.op_buf.actualcount) { 5758 struct v4l2_buffer buf; 5759 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 5760 int rc; 5761 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; 5762 5763 drv_ctx.ptr_outputbuffer[i].buffer_len = 5764 drv_ctx.op_buf.buffer_size; 5765 5766 *bufferHdr = (m_out_mem_ptr + i ); 5767 if (secure_mode) { 5768#ifdef USE_ION 5769 drv_ctx.ptr_outputbuffer[i].bufferaddr = 5770 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 5771#else 5772 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; 5773#endif 5774 } 5775 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; 5776 5777 buf.index = i; 5778 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5779 buf.memory = V4L2_MEMORY_USERPTR; 5780 plane[0].length = drv_ctx.op_buf.buffer_size; 5781 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr - 5782 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset; 5783#ifdef USE_ION 5784 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; 5785#endif 5786 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; 5787 plane[0].data_offset = 0; 5788 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 5789 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 5790 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 5791 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size); 5792#ifdef USE_ION 5793 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 5794#endif 5795 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size; 5796 plane[extra_idx].data_offset = 0; 5797 } else if (extra_idx >= VIDEO_MAX_PLANES) { 5798 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx); 5799 return OMX_ErrorBadParameter; 5800 } 5801 buf.m.planes = plane; 5802 buf.length = drv_ctx.num_planes; 5803 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr); 5804 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); 5805 if (rc) { 5806 /*TODO: How to handle this case */ 5807 return OMX_ErrorInsufficientResources; 5808 } 5809 5810 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { 5811 enum v4l2_buf_type buf_type; 5812 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 5813 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 5814 if (rc) { 5815 return OMX_ErrorInsufficientResources; 5816 } else { 5817 streaming[CAPTURE_PORT] = true; 5818 DEBUG_PRINT_LOW("STREAMON Successful"); 5819 } 5820 } 5821 5822 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; 5823 (*bufferHdr)->pAppPrivate = appData; 5824 BITMASK_SET(&m_out_bm_count,i); 5825 } else { 5826 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient"); 5827 eRet = OMX_ErrorInsufficientResources; 5828 } 5829 } 5830 5831 return eRet; 5832} 5833 5834 5835// AllocateBuffer -- API Call 5836/* ====================================================================== 5837 FUNCTION 5838 omx_vdec::AllocateBuffer 5839 5840 DESCRIPTION 5841 Returns zero if all the buffers released.. 5842 5843 PARAMETERS 5844 None. 5845 5846 RETURN VALUE 5847 true/false 5848 5849 ========================================================================== */ 5850OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, 5851 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 5852 OMX_IN OMX_U32 port, 5853 OMX_IN OMX_PTR appData, 5854 OMX_IN OMX_U32 bytes) 5855{ 5856 unsigned i = 0; 5857 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type 5858 5859 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port); 5860 if (m_state == OMX_StateInvalid) { 5861 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State"); 5862 return OMX_ErrorInvalidState; 5863 } 5864 5865 if (port == OMX_CORE_INPUT_PORT_INDEX) { 5866 if (arbitrary_bytes) { 5867 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); 5868 } else { 5869 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); 5870 } 5871 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 5872 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port, 5873 appData,bytes); 5874 } else { 5875 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); 5876 eRet = OMX_ErrorBadPortIndex; 5877 } 5878 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); 5879 if (eRet == OMX_ErrorNone) { 5880 if (allocate_done()) { 5881 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) { 5882 // Send the callback now 5883 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); 5884 post_event(OMX_CommandStateSet,OMX_StateIdle, 5885 OMX_COMPONENT_GENERATE_EVENT); 5886 } 5887 } 5888 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) { 5889 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) { 5890 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); 5891 post_event(OMX_CommandPortEnable, 5892 OMX_CORE_INPUT_PORT_INDEX, 5893 OMX_COMPONENT_GENERATE_EVENT); 5894 } 5895 } 5896 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) { 5897 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) { 5898 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); 5899 post_event(OMX_CommandPortEnable, 5900 OMX_CORE_OUTPUT_PORT_INDEX, 5901 OMX_COMPONENT_GENERATE_EVENT); 5902 } 5903 } 5904 } 5905 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet); 5906 return eRet; 5907} 5908 5909// Free Buffer - API call 5910/* ====================================================================== 5911 FUNCTION 5912 omx_vdec::FreeBuffer 5913 5914 DESCRIPTION 5915 5916 PARAMETERS 5917 None. 5918 5919 RETURN VALUE 5920 true/false 5921 5922 ========================================================================== */ 5923OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, 5924 OMX_IN OMX_U32 port, 5925 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 5926{ 5927 OMX_ERRORTYPE eRet = OMX_ErrorNone; 5928 unsigned int nPortIndex; 5929 (void) hComp; 5930 DEBUG_PRINT_LOW("In for decoder free_buffer"); 5931 5932 if (m_state == OMX_StateIdle && 5933 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 5934 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); 5935 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| 5936 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) { 5937 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port); 5938 } else if ((port == OMX_CORE_INPUT_PORT_INDEX && 5939 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) || 5940 (port == OMX_CORE_OUTPUT_PORT_INDEX && 5941 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) { 5942 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port); 5943 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) { 5944 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled"); 5945 post_event(OMX_EventError, 5946 OMX_ErrorPortUnpopulated, 5947 OMX_COMPONENT_GENERATE_EVENT); 5948 5949 return OMX_ErrorIncorrectStateOperation; 5950 } else if (m_state != OMX_StateInvalid) { 5951 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers"); 5952 post_event(OMX_EventError, 5953 OMX_ErrorPortUnpopulated, 5954 OMX_COMPONENT_GENERATE_EVENT); 5955 } 5956 5957 if (port == OMX_CORE_INPUT_PORT_INDEX) { 5958 /*Check if arbitrary bytes*/ 5959 if (!arbitrary_bytes && !input_use_buffer) 5960 nPortIndex = buffer - m_inp_mem_ptr; 5961 else 5962 nPortIndex = buffer - m_inp_heap_ptr; 5963 5964 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); 5965 if (nPortIndex < drv_ctx.ip_buf.actualcount) { 5966 // Clear the bit associated with it. 5967 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); 5968 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); 5969 if (input_use_buffer == true) { 5970 5971 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex); 5972 if (m_phdr_pmem_ptr) 5973 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); 5974 } else { 5975 if (arbitrary_bytes) { 5976 if (m_phdr_pmem_ptr) 5977 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); 5978 else 5979 free_input_buffer(nPortIndex,NULL); 5980 } else 5981 free_input_buffer(buffer); 5982 } 5983 m_inp_bPopulated = OMX_FALSE; 5984 if(release_input_done()) 5985 release_buffers(this, VDEC_BUFFER_TYPE_INPUT); 5986 /*Free the Buffer Header*/ 5987 if (release_input_done()) { 5988 DEBUG_PRINT_HIGH("ALL input buffers are freed/released"); 5989 free_input_buffer_header(); 5990 } 5991 } else { 5992 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid"); 5993 eRet = OMX_ErrorBadPortIndex; 5994 } 5995 5996 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) 5997 && release_input_done()) { 5998 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 5999 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); 6000 post_event(OMX_CommandPortDisable, 6001 OMX_CORE_INPUT_PORT_INDEX, 6002 OMX_COMPONENT_GENERATE_EVENT); 6003 } 6004 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 6005 // check if the buffer is valid 6006 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 6007 if (nPortIndex < drv_ctx.op_buf.actualcount) { 6008 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); 6009 // Clear the bit associated with it. 6010 BITMASK_CLEAR(&m_out_bm_count,nPortIndex); 6011 m_out_bPopulated = OMX_FALSE; 6012 client_buffers.free_output_buffer (buffer); 6013 6014 if(release_output_done()) { 6015 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT); 6016 } 6017 if (release_output_done()) { 6018 free_output_buffer_header(); 6019 } 6020 } else { 6021 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid"); 6022 eRet = OMX_ErrorBadPortIndex; 6023 } 6024 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) 6025 && release_output_done()) { 6026 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it"); 6027 6028 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); 6029 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); 6030#ifdef _ANDROID_ICS_ 6031 if (m_enable_android_native_buffers) { 6032 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); 6033 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 6034 } 6035#endif 6036 6037 post_event(OMX_CommandPortDisable, 6038 OMX_CORE_OUTPUT_PORT_INDEX, 6039 OMX_COMPONENT_GENERATE_EVENT); 6040 } 6041 } else { 6042 eRet = OMX_ErrorBadPortIndex; 6043 } 6044 if ((eRet == OMX_ErrorNone) && 6045 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { 6046 if (release_done()) { 6047 // Send the callback now 6048 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); 6049 post_event(OMX_CommandStateSet, OMX_StateLoaded, 6050 OMX_COMPONENT_GENERATE_EVENT); 6051 } 6052 } 6053 return eRet; 6054} 6055 6056 6057/* ====================================================================== 6058 FUNCTION 6059 omx_vdec::EmptyThisBuffer 6060 6061 DESCRIPTION 6062 This routine is used to push the encoded video frames to 6063 the video decoder. 6064 6065 PARAMETERS 6066 None. 6067 6068 RETURN VALUE 6069 OMX Error None if everything went successful. 6070 6071 ========================================================================== */ 6072OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 6073 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6074{ 6075 OMX_ERRORTYPE ret1 = OMX_ErrorNone; 6076 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; 6077 6078 if (m_state == OMX_StateInvalid) { 6079 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State"); 6080 return OMX_ErrorInvalidState; 6081 } 6082 6083 if (buffer == NULL) { 6084 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL"); 6085 return OMX_ErrorBadParameter; 6086 } 6087 6088 if (!m_inp_bEnabled) { 6089 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled."); 6090 return OMX_ErrorIncorrectStateOperation; 6091 } 6092 6093 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) { 6094 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex); 6095 return OMX_ErrorBadPortIndex; 6096 } 6097 6098#ifdef _ANDROID_ 6099 if (iDivXDrmDecrypt) { 6100 OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer); 6101 if (drmErr != OMX_ErrorNone) { 6102 // this error can be ignored 6103 DEBUG_PRINT_LOW("ERROR:iDivXDrmDecrypt->Decrypt %d", drmErr); 6104 } 6105 } 6106#endif //_ANDROID_ 6107 if (perf_flag) { 6108 if (!latency) { 6109 dec_time.stop(); 6110 latency = dec_time.processing_time_us(); 6111 dec_time.start(); 6112 } 6113 } 6114 6115 if (arbitrary_bytes) { 6116 nBufferIndex = buffer - m_inp_heap_ptr; 6117 } else { 6118 if (input_use_buffer == true) { 6119 nBufferIndex = buffer - m_inp_heap_ptr; 6120 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; 6121 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; 6122 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; 6123 buffer = &m_inp_mem_ptr[nBufferIndex]; 6124 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u", 6125 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen); 6126 } else { 6127 nBufferIndex = buffer - m_inp_mem_ptr; 6128 } 6129 } 6130 6131 if (nBufferIndex > drv_ctx.ip_buf.actualcount ) { 6132 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); 6133 return OMX_ErrorBadParameter; 6134 } 6135 6136 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 6137 codec_config_flag = true; 6138 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); 6139 } 6140 6141 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)", 6142 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen); 6143 if (arbitrary_bytes) { 6144 post_event ((unsigned long)hComp,(unsigned long)buffer, 6145 OMX_COMPONENT_GENERATE_ETB_ARBITRARY); 6146 } else { 6147 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB); 6148 } 6149 time_stamp_dts.insert_timestamp(buffer); 6150 return OMX_ErrorNone; 6151} 6152 6153/* ====================================================================== 6154 FUNCTION 6155 omx_vdec::empty_this_buffer_proxy 6156 6157 DESCRIPTION 6158 This routine is used to push the encoded video frames to 6159 the video decoder. 6160 6161 PARAMETERS 6162 None. 6163 6164 RETURN VALUE 6165 OMX Error None if everything went successful. 6166 6167 ========================================================================== */ 6168OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, 6169 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6170{ 6171 (void) hComp; 6172 int push_cnt = 0,i=0; 6173 unsigned nPortIndex = 0; 6174 OMX_ERRORTYPE ret = OMX_ErrorNone; 6175 struct vdec_input_frameinfo frameinfo; 6176 struct vdec_bufferpayload *temp_buffer; 6177 struct vdec_seqheader seq_header; 6178 bool port_setting_changed = true; 6179 6180 /*Should we generate a Aync error event*/ 6181 if (buffer == NULL || buffer->pInputPortPrivate == NULL) { 6182 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid"); 6183 return OMX_ErrorBadParameter; 6184 } 6185 6186 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 6187 6188 if (nPortIndex > drv_ctx.ip_buf.actualcount) { 6189 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", 6190 nPortIndex); 6191 return OMX_ErrorBadParameter; 6192 } 6193 6194 pending_input_buffers++; 6195 6196 /* return zero length and not an EOS buffer */ 6197 if (!arbitrary_bytes && (buffer->nFilledLen == 0) && 6198 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) { 6199 DEBUG_PRINT_HIGH("return zero legth buffer"); 6200 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 6201 OMX_COMPONENT_GENERATE_EBD); 6202 return OMX_ErrorNone; 6203 } 6204 6205 if (input_flush_progress == true) { 6206 DEBUG_PRINT_LOW("Flush in progress return buffer "); 6207 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 6208 OMX_COMPONENT_GENERATE_EBD); 6209 return OMX_ErrorNone; 6210 } 6211 6212 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; 6213 6214 if ((temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) { 6215 return OMX_ErrorBadParameter; 6216 } 6217 /* If its first frame, H264 codec and reject is true, then parse the nal 6218 and get the profile. Based on this, reject the clip playback */ 6219 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 && 6220 m_reject_avc_1080p_mp) { 6221 first_frame = 1; 6222 DEBUG_PRINT_ERROR("Parse nal to get the profile"); 6223 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen, 6224 NALU_TYPE_SPS); 6225 m_profile = h264_parser->get_profile(); 6226 ret = is_video_session_supported(); 6227 if (ret) { 6228 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD); 6229 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT); 6230 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */ 6231 m_state = OMX_StateInvalid; 6232 return OMX_ErrorNone; 6233 } 6234 } 6235 6236 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 6237 /*for use buffer we need to memcpy the data*/ 6238 temp_buffer->buffer_len = buffer->nFilledLen; 6239 6240 if (input_use_buffer) { 6241 if (buffer->nFilledLen <= temp_buffer->buffer_len) { 6242 if (arbitrary_bytes) { 6243 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); 6244 } else { 6245 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), 6246 buffer->nFilledLen); 6247 } 6248 } else { 6249 return OMX_ErrorBadParameter; 6250 } 6251 6252 } 6253 6254 frameinfo.bufferaddr = temp_buffer->bufferaddr; 6255 frameinfo.client_data = (void *) buffer; 6256 frameinfo.datalen = temp_buffer->buffer_len; 6257 frameinfo.flags = 0; 6258 frameinfo.offset = buffer->nOffset; 6259 frameinfo.pmem_fd = temp_buffer->pmem_fd; 6260 frameinfo.pmem_offset = temp_buffer->offset; 6261 frameinfo.timestamp = buffer->nTimeStamp; 6262 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) { 6263 DEBUG_PRINT_LOW("ETB: dmx enabled"); 6264 if (m_demux_entries == 0) { 6265 extract_demux_addr_offsets(buffer); 6266 } 6267 6268 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries); 6269 handle_demux_data(buffer); 6270 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; 6271 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; 6272 } else { 6273 frameinfo.desc_addr = NULL; 6274 frameinfo.desc_size = 0; 6275 } 6276 if (!arbitrary_bytes) { 6277 frameinfo.flags |= buffer->nFlags; 6278 } 6279 6280#ifdef _ANDROID_ 6281 if (m_debug_timestamp) { 6282 if (arbitrary_bytes) { 6283 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 6284 m_timestamp_list.insert_ts(buffer->nTimeStamp); 6285 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 6286 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); 6287 m_timestamp_list.insert_ts(buffer->nTimeStamp); 6288 } 6289 } 6290#endif 6291 6292 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); 6293 6294 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 6295 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 6296 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 6297 } 6298 6299 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 6300 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached"); 6301 frameinfo.flags |= VDEC_BUFFERFLAG_EOS; 6302 h264_scratch.nFilledLen = 0; 6303 nal_count = 0; 6304 look_ahead_nal = false; 6305 frame_count = 0; 6306 if (m_frame_parser.mutils) 6307 m_frame_parser.mutils->initialize_frame_checking_environment(); 6308 m_frame_parser.flush(); 6309 h264_last_au_ts = LLONG_MAX; 6310 h264_last_au_flags = 0; 6311 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 6312 m_demux_entries = 0; 6313 } 6314 struct v4l2_buffer buf; 6315 struct v4l2_plane plane; 6316 memset( (void *)&buf, 0, sizeof(buf)); 6317 memset( (void *)&plane, 0, sizeof(plane)); 6318 int rc; 6319 unsigned long print_count; 6320 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 6321 buf.flags = V4L2_QCOM_BUF_FLAG_EOS; 6322 DEBUG_PRINT_HIGH("INPUT EOS reached") ; 6323 } 6324 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6325 buf.index = nPortIndex; 6326 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6327 buf.memory = V4L2_MEMORY_USERPTR; 6328 plane.bytesused = temp_buffer->buffer_len; 6329 plane.length = drv_ctx.ip_buf.buffer_size; 6330 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr - 6331 (unsigned long)temp_buffer->offset; 6332 plane.reserved[0] = temp_buffer->pmem_fd; 6333 plane.reserved[1] = temp_buffer->offset; 6334 plane.data_offset = 0; 6335 buf.m.planes = &plane; 6336 buf.length = 1; 6337 if (frameinfo.timestamp >= LLONG_MAX) { 6338 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID; 6339 } 6340 //assumption is that timestamp is in milliseconds 6341 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000; 6342 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000); 6343 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0; 6344 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0; 6345 6346 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 6347 DEBUG_PRINT_LOW("Increment codec_config buffer counter"); 6348 android_atomic_inc(&m_queued_codec_config_count); 6349 } 6350 6351 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 6352 if (rc) { 6353 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver"); 6354 return OMX_ErrorHardware; 6355 } 6356 6357 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 6358 codec_config_flag = false; 6359 } 6360 if (!streaming[OUTPUT_PORT]) { 6361 enum v4l2_buf_type buf_type; 6362 int ret,r; 6363 6364 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 6365 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing"); 6366 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); 6367 if (!ret) { 6368 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful"); 6369 streaming[OUTPUT_PORT] = true; 6370 } else if (errno == EBUSY) { 6371 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD"); 6372 post_event ((unsigned long)buffer, VDEC_S_SUCCESS, 6373 OMX_COMPONENT_GENERATE_EBD); 6374 return OMX_ErrorInsufficientResources; 6375 } else { 6376 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT"); 6377 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued"); 6378 post_event ((unsigned long)buffer,VDEC_S_SUCCESS, 6379 OMX_COMPONENT_GENERATE_EBD); 6380 return OMX_ErrorBadParameter; 6381 } 6382 } 6383 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)", 6384 frameinfo.bufferaddr, (long long)frameinfo.timestamp, 6385 (unsigned int)frameinfo.datalen); 6386 6387 return ret; 6388} 6389 6390/* ====================================================================== 6391 FUNCTION 6392 omx_vdec::FillThisBuffer 6393 6394 DESCRIPTION 6395 IL client uses this method to release the frame buffer 6396 after displaying them. 6397 6398 PARAMETERS 6399 None. 6400 6401 RETURN VALUE 6402 true/false 6403 6404 ========================================================================== */ 6405OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, 6406 OMX_IN OMX_BUFFERHEADERTYPE* buffer) 6407{ 6408 unsigned nPortIndex = 0; 6409 if (dynamic_buf_mode) { 6410 private_handle_t *handle = NULL; 6411 struct VideoDecoderOutputMetaData *meta; 6412 unsigned int nPortIndex = 0; 6413 6414 if (!buffer || !buffer->pBuffer) { 6415 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer); 6416 return OMX_ErrorBadParameter; 6417 } 6418 6419 //get the buffer type and fd info 6420 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer; 6421 handle = (private_handle_t *)meta->pHandle; 6422 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle); 6423 6424 if (!handle) { 6425 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle); 6426 return OMX_ErrorBadParameter; 6427 } 6428 6429 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF 6430 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 6431 if (nPortIndex < drv_ctx.op_buf.actualcount && 6432 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 6433 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd; 6434 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer; 6435 6436 //Store private handle from GraphicBuffer 6437 native_buffer[nPortIndex].privatehandle = handle; 6438 native_buffer[nPortIndex].nativehandle = handle; 6439 } else { 6440 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex); 6441 return OMX_ErrorBadParameter; 6442 } 6443 6444 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite 6445 //this with a more sane size so that we don't compensate in rest of code 6446 //We'll restore this size later on, so that it's transparent to client 6447 buffer->nFilledLen = 0; 6448 buffer->nAllocLen = handle->size; 6449 } 6450 6451 6452 if (m_state == OMX_StateInvalid) { 6453 DEBUG_PRINT_ERROR("FTB in Invalid State"); 6454 return OMX_ErrorInvalidState; 6455 } 6456 6457 if (!m_out_bEnabled) { 6458 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); 6459 return OMX_ErrorIncorrectStateOperation; 6460 } 6461 6462 nPortIndex = buffer - client_buffers.get_il_buf_hdr(); 6463 if (buffer == NULL || 6464 (nPortIndex >= drv_ctx.op_buf.actualcount)) { 6465 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 6466 nPortIndex, drv_ctx.op_buf.actualcount); 6467 return OMX_ErrorBadParameter; 6468 } 6469 6470 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { 6471 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex); 6472 return OMX_ErrorBadPortIndex; 6473 } 6474 6475 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 6476 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg); 6477 return OMX_ErrorNone; 6478} 6479/* ====================================================================== 6480 FUNCTION 6481 omx_vdec::fill_this_buffer_proxy 6482 6483 DESCRIPTION 6484 IL client uses this method to release the frame buffer 6485 after displaying them. 6486 6487 PARAMETERS 6488 None. 6489 6490 RETURN VALUE 6491 true/false 6492 6493 ========================================================================== */ 6494OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( 6495 OMX_IN OMX_HANDLETYPE hComp, 6496 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) 6497{ 6498 OMX_ERRORTYPE nRet = OMX_ErrorNone; 6499 OMX_BUFFERHEADERTYPE *buffer = bufferAdd; 6500 unsigned nPortIndex = 0; 6501 struct vdec_fillbuffer_cmd fillbuffer; 6502 struct vdec_bufferpayload *ptr_outputbuffer = NULL; 6503 struct vdec_output_frameinfo *ptr_respbuffer = NULL; 6504 6505 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 6506 6507 if (!bufferAdd || !bufferAdd->pBuffer || nPortIndex > drv_ctx.op_buf.actualcount) { 6508 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", 6509 nPortIndex, drv_ctx.op_buf.actualcount); 6510 return OMX_ErrorBadParameter; 6511 } 6512 6513 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", 6514 bufferAdd, bufferAdd->pBuffer); 6515 /*Return back the output buffer to client*/ 6516 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) { 6517 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition"); 6518 buffer->nFilledLen = 0; 6519 m_cb.FillBufferDone (hComp,m_app_data,buffer); 6520 return OMX_ErrorNone; 6521 } 6522 6523 if (dynamic_buf_mode) { 6524 6525 if (drv_ctx.ptr_outputbuffer) { 6526 private_handle_t *handle = NULL; 6527 struct VideoDecoderOutputMetaData *meta; 6528 6529 //get the buffer type and fd info 6530 meta = (struct VideoDecoderOutputMetaData *)bufferAdd->pBuffer; 6531 handle = (private_handle_t *)meta->pHandle; 6532 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle); 6533 6534 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF 6535 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd; 6536 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) bufferAdd; 6537 6538 //map the buffer handle based on the size set on output port definition. 6539 if (!secure_mode) { 6540 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = 6541 (OMX_U8*)mmap(0, drv_ctx.op_buf.buffer_size, 6542 PROT_READ|PROT_WRITE, MAP_SHARED, 6543 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0); 6544 } 6545 6546 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0; 6547 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = drv_ctx.op_buf.buffer_size; 6548 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = drv_ctx.op_buf.buffer_size; 6549 buf_ref_add(drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 6550 drv_ctx.ptr_outputbuffer[nPortIndex].offset); 6551 } else { 6552 DEBUG_PRINT_ERROR("Output Buffers are already free'd !"); 6553 return OMX_ErrorBadParameter; 6554 } 6555 } 6556 6557 pending_output_buffers++; 6558 buffer = client_buffers.get_dr_buf_hdr(bufferAdd); 6559 if (!buffer) { 6560 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid"); 6561 return OMX_ErrorBadParameter; 6562 } 6563 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; 6564 if (ptr_respbuffer) { 6565 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; 6566 } 6567 6568 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) { 6569 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); 6570 buffer->nFilledLen = 0; 6571 m_cb.FillBufferDone (hComp,m_app_data,buffer); 6572 pending_output_buffers--; 6573 return OMX_ErrorBadParameter; 6574 } 6575 6576 int rc = 0; 6577 struct v4l2_buffer buf; 6578 struct v4l2_plane plane[VIDEO_MAX_PLANES]; 6579 memset( (void *)&buf, 0, sizeof(buf)); 6580 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); 6581 unsigned int extra_idx = 0; 6582 6583 buf.index = nPortIndex; 6584 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 6585 buf.memory = V4L2_MEMORY_USERPTR; 6586 plane[0].bytesused = buffer->nFilledLen; 6587 plane[0].length = drv_ctx.op_buf.buffer_size; 6588 plane[0].m.userptr = 6589 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr - 6590 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset; 6591 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; 6592 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset; 6593 plane[0].data_offset = 0; 6594 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 6595 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 6596 plane[extra_idx].bytesused = 0; 6597 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size; 6598 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size); 6599#ifdef USE_ION 6600 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd; 6601#endif 6602 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; 6603 plane[extra_idx].data_offset = 0; 6604 } else if (extra_idx >= VIDEO_MAX_PLANES) { 6605 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx); 6606 return OMX_ErrorBadParameter; 6607 } 6608 buf.m.planes = plane; 6609 buf.length = drv_ctx.num_planes; 6610 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d", 6611 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1]); 6612 6613 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); 6614 if (rc) { 6615 /*TODO: How to handle this case */ 6616 DEBUG_PRINT_ERROR("Failed to qbuf to driver"); 6617 } 6618 return OMX_ErrorNone; 6619} 6620 6621/* ====================================================================== 6622 FUNCTION 6623 omx_vdec::SetCallbacks 6624 6625 DESCRIPTION 6626 Set the callbacks. 6627 6628 PARAMETERS 6629 None. 6630 6631 RETURN VALUE 6632 OMX Error None if everything successful. 6633 6634 ========================================================================== */ 6635OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, 6636 OMX_IN OMX_CALLBACKTYPE* callbacks, 6637 OMX_IN OMX_PTR appData) 6638{ 6639 (void) hComp; 6640 m_cb = *callbacks; 6641 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ 6642 m_cb.EventHandler,m_cb.FillBufferDone); 6643 m_app_data = appData; 6644 return OMX_ErrorNotImplemented; 6645} 6646 6647/* ====================================================================== 6648 FUNCTION 6649 omx_vdec::ComponentDeInit 6650 6651 DESCRIPTION 6652 Destroys the component and release memory allocated to the heap. 6653 6654 PARAMETERS 6655 <TBD>. 6656 6657 RETURN VALUE 6658 OMX Error None if everything successful. 6659 6660 ========================================================================== */ 6661OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) 6662{ 6663 (void) hComp; 6664#ifdef _ANDROID_ 6665 if (iDivXDrmDecrypt) { 6666 delete iDivXDrmDecrypt; 6667 iDivXDrmDecrypt=NULL; 6668 } 6669#endif //_ANDROID_ 6670 6671 unsigned i = 0; 6672 if (OMX_StateLoaded != m_state) { 6673 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\ 6674 m_state); 6675 DEBUG_PRINT_ERROR("Playback Ended - FAILED"); 6676 } else { 6677 DEBUG_PRINT_HIGH("Playback Ended - PASSED"); 6678 } 6679 6680 /*Check if the output buffers have to be cleaned up*/ 6681 if (m_out_mem_ptr) { 6682 DEBUG_PRINT_LOW("Freeing the Output Memory"); 6683 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) { 6684 free_output_buffer (&m_out_mem_ptr[i]); 6685 } 6686#ifdef _ANDROID_ICS_ 6687 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); 6688#endif 6689 } 6690 6691 /*Check if the input buffers have to be cleaned up*/ 6692 if (m_inp_mem_ptr || m_inp_heap_ptr) { 6693 DEBUG_PRINT_LOW("Freeing the Input Memory"); 6694 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) { 6695 if (m_inp_mem_ptr) 6696 free_input_buffer (i,&m_inp_mem_ptr[i]); 6697 else 6698 free_input_buffer (i,NULL); 6699 } 6700 } 6701 free_input_buffer_header(); 6702 free_output_buffer_header(); 6703 if (h264_scratch.pBuffer) { 6704 free(h264_scratch.pBuffer); 6705 h264_scratch.pBuffer = NULL; 6706 } 6707 6708 if (h264_parser) { 6709 delete h264_parser; 6710 h264_parser = NULL; 6711 } 6712 6713 if (m_frame_parser.mutils) { 6714 DEBUG_PRINT_LOW("Free utils parser"); 6715 delete (m_frame_parser.mutils); 6716 m_frame_parser.mutils = NULL; 6717 } 6718 6719 if (m_platform_list) { 6720 free(m_platform_list); 6721 m_platform_list = NULL; 6722 } 6723 if (m_vendor_config.pData) { 6724 free(m_vendor_config.pData); 6725 m_vendor_config.pData = NULL; 6726 } 6727 6728 // Reset counters in mesg queues 6729 m_ftb_q.m_size=0; 6730 m_cmd_q.m_size=0; 6731 m_etb_q.m_size=0; 6732 m_ftb_q.m_read = m_ftb_q.m_write =0; 6733 m_cmd_q.m_read = m_cmd_q.m_write =0; 6734 m_etb_q.m_read = m_etb_q.m_write =0; 6735#ifdef _ANDROID_ 6736 if (m_debug_timestamp) { 6737 m_timestamp_list.reset_ts_list(); 6738 } 6739#endif 6740 6741 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG"); 6742 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, 6743 // NULL); 6744 DEBUG_PRINT_HIGH("Close the driver instance"); 6745 6746 if (m_debug.infile) { 6747 fclose(m_debug.infile); 6748 m_debug.infile = NULL; 6749 } 6750 if (m_debug.outfile) { 6751 fclose(m_debug.outfile); 6752 m_debug.outfile = NULL; 6753 } 6754#ifdef OUTPUT_EXTRADATA_LOG 6755 if (outputExtradataFile) 6756 fclose (outputExtradataFile); 6757#endif 6758 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete"); 6759 return OMX_ErrorNone; 6760} 6761 6762/* ====================================================================== 6763 FUNCTION 6764 omx_vdec::UseEGLImage 6765 6766 DESCRIPTION 6767 OMX Use EGL Image method implementation <TBD>. 6768 6769 PARAMETERS 6770 <TBD>. 6771 6772 RETURN VALUE 6773 Not Implemented error. 6774 6775 ========================================================================== */ 6776OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, 6777 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, 6778 OMX_IN OMX_U32 port, 6779 OMX_IN OMX_PTR appData, 6780 OMX_IN void* eglImage) 6781{ 6782 (void) appData; 6783 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; 6784 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; 6785 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; 6786 6787#ifdef USE_EGL_IMAGE_GPU 6788 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; 6789 EGLint fd = -1, offset = 0,pmemPtr = 0; 6790#else 6791 int fd = -1, offset = 0; 6792#endif 6793 DEBUG_PRINT_HIGH("use EGL image support for decoder"); 6794 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { 6795 DEBUG_PRINT_ERROR("Invalid EGL image"); 6796 } 6797#ifdef USE_EGL_IMAGE_GPU 6798 if (m_display_id == NULL) { 6799 DEBUG_PRINT_ERROR("Display ID is not set by IL client"); 6800 return OMX_ErrorInsufficientResources; 6801 } 6802 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) 6803 eglGetProcAddress("eglQueryImageKHR"); 6804 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd); 6805 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset); 6806 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr); 6807#else //with OMX test app 6808 struct temp_egl { 6809 int pmem_fd; 6810 int offset; 6811 }; 6812 struct temp_egl *temp_egl_id = NULL; 6813 void * pmemPtr = (void *) eglImage; 6814 temp_egl_id = (struct temp_egl *)eglImage; 6815 if (temp_egl_id != NULL) { 6816 fd = temp_egl_id->pmem_fd; 6817 offset = temp_egl_id->offset; 6818 } 6819#endif 6820 if (fd < 0) { 6821 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd); 6822 return OMX_ErrorInsufficientResources; 6823 } 6824 pmem_info.pmem_fd = (OMX_U32) fd; 6825 pmem_info.offset = (OMX_U32) offset; 6826 pmem_entry.entry = (void *) &pmem_info; 6827 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 6828 pmem_list.entryList = &pmem_entry; 6829 pmem_list.nEntries = 1; 6830 ouput_egl_buffers = true; 6831 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, 6832 (void *)&pmem_list, drv_ctx.op_buf.buffer_size, 6833 (OMX_U8 *)pmemPtr)) { 6834 DEBUG_PRINT_ERROR("use buffer call failed for egl image"); 6835 return OMX_ErrorInsufficientResources; 6836 } 6837 return OMX_ErrorNone; 6838} 6839 6840/* ====================================================================== 6841 FUNCTION 6842 omx_vdec::ComponentRoleEnum 6843 6844 DESCRIPTION 6845 OMX Component Role Enum method implementation. 6846 6847 PARAMETERS 6848 <TBD>. 6849 6850 RETURN VALUE 6851 OMX Error None if everything is successful. 6852 ========================================================================== */ 6853OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, 6854 OMX_OUT OMX_U8* role, 6855 OMX_IN OMX_U32 index) 6856{ 6857 (void) hComp; 6858 OMX_ERRORTYPE eRet = OMX_ErrorNone; 6859 6860 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) { 6861 if ((0 == index) && role) { 6862 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); 6863 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6864 } else { 6865 eRet = OMX_ErrorNoMore; 6866 } 6867 } 6868 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { 6869 if ((0 == index) && role) { 6870 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); 6871 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6872 } else { 6873 eRet = OMX_ErrorNoMore; 6874 } 6875 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) { 6876 if ((0 == index) && role) { 6877 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); 6878 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6879 } else { 6880 DEBUG_PRINT_LOW("No more roles"); 6881 eRet = OMX_ErrorNoMore; 6882 } 6883 } 6884 6885 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || 6886 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) { 6887 if ((0 == index) && role) { 6888 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); 6889 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6890 } else { 6891 DEBUG_PRINT_LOW("No more roles"); 6892 eRet = OMX_ErrorNoMore; 6893 } 6894 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { 6895 if ((0 == index) && role) { 6896 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); 6897 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6898 } else { 6899 DEBUG_PRINT_LOW("No more roles"); 6900 eRet = OMX_ErrorNoMore; 6901 } 6902 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { 6903 if ((0 == index) && role) { 6904 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE); 6905 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6906 } else { 6907 DEBUG_PRINT_LOW("No more roles"); 6908 eRet = OMX_ErrorNoMore; 6909 } 6910 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { 6911 if ((0 == index) && role) { 6912 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE); 6913 DEBUG_PRINT_LOW("component_role_enum: role %s", role); 6914 } else { 6915 DEBUG_PRINT_LOW("No more roles"); 6916 eRet = OMX_ErrorNoMore; 6917 } 6918 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || 6919 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) 6920 ) { 6921 if ((0 == index) && role) { 6922 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); 6923 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6924 } else { 6925 DEBUG_PRINT_LOW("No more roles"); 6926 eRet = OMX_ErrorNoMore; 6927 } 6928 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) { 6929 if ((0 == index) && role) { 6930 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); 6931 DEBUG_PRINT_LOW("component_role_enum: role %s",role); 6932 } else { 6933 DEBUG_PRINT_LOW("No more roles"); 6934 eRet = OMX_ErrorNoMore; 6935 } 6936 } else { 6937 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component"); 6938 eRet = OMX_ErrorInvalidComponentName; 6939 } 6940 return eRet; 6941} 6942 6943 6944 6945 6946/* ====================================================================== 6947 FUNCTION 6948 omx_vdec::AllocateDone 6949 6950 DESCRIPTION 6951 Checks if entire buffer pool is allocated by IL Client or not. 6952 Need this to move to IDLE state. 6953 6954 PARAMETERS 6955 None. 6956 6957 RETURN VALUE 6958 true/false. 6959 6960 ========================================================================== */ 6961bool omx_vdec::allocate_done(void) 6962{ 6963 bool bRet = false; 6964 bool bRet_In = false; 6965 bool bRet_Out = false; 6966 6967 bRet_In = allocate_input_done(); 6968 bRet_Out = allocate_output_done(); 6969 6970 if (bRet_In && bRet_Out) { 6971 bRet = true; 6972 } 6973 6974 return bRet; 6975} 6976/* ====================================================================== 6977 FUNCTION 6978 omx_vdec::AllocateInputDone 6979 6980 DESCRIPTION 6981 Checks if I/P buffer pool is allocated by IL Client or not. 6982 6983 PARAMETERS 6984 None. 6985 6986 RETURN VALUE 6987 true/false. 6988 6989 ========================================================================== */ 6990bool omx_vdec::allocate_input_done(void) 6991{ 6992 bool bRet = false; 6993 unsigned i=0; 6994 6995 if (m_inp_mem_ptr == NULL) { 6996 return bRet; 6997 } 6998 if (m_inp_mem_ptr ) { 6999 for (; i<drv_ctx.ip_buf.actualcount; i++) { 7000 if (BITMASK_ABSENT(&m_inp_bm_count,i)) { 7001 break; 7002 } 7003 } 7004 } 7005 if (i == drv_ctx.ip_buf.actualcount) { 7006 bRet = true; 7007 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers"); 7008 } 7009 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) { 7010 m_inp_bPopulated = OMX_TRUE; 7011 } 7012 return bRet; 7013} 7014/* ====================================================================== 7015 FUNCTION 7016 omx_vdec::AllocateOutputDone 7017 7018 DESCRIPTION 7019 Checks if entire O/P buffer pool is allocated by IL Client or not. 7020 7021 PARAMETERS 7022 None. 7023 7024 RETURN VALUE 7025 true/false. 7026 7027 ========================================================================== */ 7028bool omx_vdec::allocate_output_done(void) 7029{ 7030 bool bRet = false; 7031 unsigned j=0; 7032 7033 if (m_out_mem_ptr == NULL) { 7034 return bRet; 7035 } 7036 7037 if (m_out_mem_ptr) { 7038 for (; j < drv_ctx.op_buf.actualcount; j++) { 7039 if (BITMASK_ABSENT(&m_out_bm_count,j)) { 7040 break; 7041 } 7042 } 7043 } 7044 7045 if (j == drv_ctx.op_buf.actualcount) { 7046 bRet = true; 7047 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers"); 7048 if (m_out_bEnabled) 7049 m_out_bPopulated = OMX_TRUE; 7050 } 7051 7052 return bRet; 7053} 7054 7055/* ====================================================================== 7056 FUNCTION 7057 omx_vdec::ReleaseDone 7058 7059 DESCRIPTION 7060 Checks if IL client has released all the buffers. 7061 7062 PARAMETERS 7063 None. 7064 7065 RETURN VALUE 7066 true/false 7067 7068 ========================================================================== */ 7069bool omx_vdec::release_done(void) 7070{ 7071 bool bRet = false; 7072 7073 if (release_input_done()) { 7074 if (release_output_done()) { 7075 bRet = true; 7076 } 7077 } 7078 return bRet; 7079} 7080 7081 7082/* ====================================================================== 7083 FUNCTION 7084 omx_vdec::ReleaseOutputDone 7085 7086 DESCRIPTION 7087 Checks if IL client has released all the buffers. 7088 7089 PARAMETERS 7090 None. 7091 7092 RETURN VALUE 7093 true/false 7094 7095 ========================================================================== */ 7096bool omx_vdec::release_output_done(void) 7097{ 7098 bool bRet = false; 7099 unsigned i=0,j=0; 7100 7101 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_inp_mem_ptr); 7102 if (m_out_mem_ptr) { 7103 for (; j < drv_ctx.op_buf.actualcount ; j++) { 7104 if (BITMASK_PRESENT(&m_out_bm_count,j)) { 7105 break; 7106 } 7107 } 7108 if (j == drv_ctx.op_buf.actualcount) { 7109 m_out_bm_count = 0; 7110 bRet = true; 7111 } 7112 } else { 7113 m_out_bm_count = 0; 7114 bRet = true; 7115 } 7116 return bRet; 7117} 7118/* ====================================================================== 7119 FUNCTION 7120 omx_vdec::ReleaseInputDone 7121 7122 DESCRIPTION 7123 Checks if IL client has released all the buffers. 7124 7125 PARAMETERS 7126 None. 7127 7128 RETURN VALUE 7129 true/false 7130 7131 ========================================================================== */ 7132bool omx_vdec::release_input_done(void) 7133{ 7134 bool bRet = false; 7135 unsigned i=0,j=0; 7136 7137 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr); 7138 if (m_inp_mem_ptr) { 7139 for (; j<drv_ctx.ip_buf.actualcount; j++) { 7140 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) { 7141 break; 7142 } 7143 } 7144 if (j==drv_ctx.ip_buf.actualcount) { 7145 bRet = true; 7146 } 7147 } else { 7148 bRet = true; 7149 } 7150 return bRet; 7151} 7152 7153OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, 7154 OMX_BUFFERHEADERTYPE * buffer) 7155{ 7156 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; 7157 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) { 7158 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer); 7159 return OMX_ErrorBadParameter; 7160 } else if (output_flush_progress) { 7161 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); 7162 buffer->nFilledLen = 0; 7163 buffer->nTimeStamp = 0; 7164 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; 7165 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7166 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 7167 } 7168 7169 if (m_debug_extradata) { 7170 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { 7171 DEBUG_PRINT_HIGH("***************************************************"); 7172 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received"); 7173 DEBUG_PRINT_HIGH("***************************************************"); 7174 } 7175 7176 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) { 7177 DEBUG_PRINT_HIGH("***************************************************"); 7178 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 7179 DEBUG_PRINT_HIGH("***************************************************"); 7180 } 7181 } 7182 7183 7184 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", 7185 buffer, buffer->pBuffer); 7186 pending_output_buffers --; 7187 7188 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 7189 DEBUG_PRINT_HIGH("Output EOS has been reached"); 7190 if (!output_flush_progress) 7191 post_event((unsigned)NULL, (unsigned)NULL, 7192 OMX_COMPONENT_GENERATE_EOS_DONE); 7193 7194 if (psource_frame) { 7195 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); 7196 psource_frame = NULL; 7197 } 7198 if (pdest_frame) { 7199 pdest_frame->nFilledLen = 0; 7200 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL, 7201 (unsigned)NULL); 7202 pdest_frame = NULL; 7203 } 7204 } 7205 7206 if (!output_flush_progress && (buffer->nFilledLen > 0)) { 7207 DEBUG_PRINT_LOW("Processing extradata"); 7208 handle_extradata(buffer); 7209 } 7210 7211#ifdef OUTPUT_EXTRADATA_LOG 7212 if (outputExtradataFile) { 7213 int buf_index = buffer - m_out_mem_ptr; 7214 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr); 7215 7216 OMX_OTHER_EXTRADATATYPE *p_extra = NULL; 7217 p_extra = (OMX_OTHER_EXTRADATATYPE *) 7218 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3)); 7219 7220 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) { 7221 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x", 7222 p_extra->nSize, p_extra->eType); 7223 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); 7224 7225 if (p_extra->eType == OMX_ExtraDataNone) { 7226 break; 7227 } 7228 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 7229 } 7230 } 7231#endif 7232 7233 /* For use buffer we need to copy the data */ 7234 if (!output_flush_progress) { 7235 /* This is the error check for non-recoverable errros */ 7236 bool is_duplicate_ts_valid = true; 7237 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive); 7238 7239 if (output_capability == V4L2_PIX_FMT_MPEG4 || 7240 output_capability == V4L2_PIX_FMT_MPEG2 || 7241 output_capability == V4L2_PIX_FMT_DIVX || 7242 output_capability == V4L2_PIX_FMT_DIVX_311) 7243 is_duplicate_ts_valid = false; 7244 7245 if ((output_capability == V4L2_PIX_FMT_H264 || 7246 output_capability == V4L2_PIX_FMT_H264_MVC) && 7247 is_interlaced) { 7248 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) { 7249 is_interlaced = false; 7250 } 7251 } 7252 7253 if (buffer->nFilledLen > 0) { 7254 time_stamp_dts.get_next_timestamp(buffer, 7255 is_interlaced && is_duplicate_ts_valid); 7256 if (m_debug_timestamp) { 7257 { 7258 OMX_TICKS expected_ts = 0; 7259 m_timestamp_list.pop_min_ts(expected_ts); 7260 if (is_interlaced && is_duplicate_ts_valid) { 7261 m_timestamp_list.pop_min_ts(expected_ts); 7262 } 7263 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", 7264 buffer->nTimeStamp, expected_ts); 7265 7266 if (buffer->nTimeStamp != expected_ts) { 7267 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check"); 7268 } 7269 } 7270 } 7271 } 7272 } 7273 7274 /* Since we're passing around handles, adjust nFilledLen and nAllocLen 7275 * to size of the handle. Do it _after_ handle_extradata() which 7276 * requires the respective sizes to be accurate. */ 7277 if (dynamic_buf_mode) { 7278 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); 7279 buffer->nFilledLen = buffer->nFilledLen ? 7280 sizeof(struct VideoDecoderOutputMetaData) : 0; 7281 } 7282 if (m_cb.FillBufferDone) { 7283 if (buffer->nFilledLen > 0) { 7284 if (arbitrary_bytes) 7285 adjust_timestamp(buffer->nTimeStamp); 7286 else 7287 set_frame_rate(buffer->nTimeStamp); 7288 7289 if (perf_flag) { 7290 if (!proc_frms) { 7291 dec_time.stop(); 7292 latency = dec_time.processing_time_us() - latency; 7293 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); 7294 dec_time.start(); 7295 fps_metrics.start(); 7296 } 7297 proc_frms++; 7298 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 7299 OMX_U64 proc_time = 0; 7300 fps_metrics.stop(); 7301 proc_time = fps_metrics.processing_time_us(); 7302 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)", 7303 (unsigned int)proc_frms, (float)proc_time / 1e6, 7304 (float)(1e6 * proc_frms) / proc_time); 7305 proc_frms = 0; 7306 } 7307 } 7308 } 7309 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { 7310 prev_ts = LLONG_MAX; 7311 rst_prev_ts = true; 7312 } 7313 7314 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 7315 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) 7316 buffer->pPlatformPrivate)->entryList->entry; 7317 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd); 7318 OMX_BUFFERHEADERTYPE *il_buffer; 7319 il_buffer = client_buffers.get_il_buf_hdr(buffer); 7320 7321 if (il_buffer && m_last_rendered_TS >= 0) { 7322 int current_framerate = (int)(drv_ctx.frame_rate.fps_numerator /drv_ctx.frame_rate.fps_denominator); 7323 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS); 7324 7325 // Current frame can be send for rendering if 7326 // (a) current FPS is <= 60 7327 // (b) is the next frame after the frame with TS 0 7328 // (c) is the first frame after seek 7329 // (d) the delta TS b\w two consecutive frames is > 16 ms 7330 // (e) its TS is equal to previous frame TS 7331 // (f) if marked EOS 7332 7333 if(current_framerate <= 60 || m_last_rendered_TS == 0 || 7334 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 || 7335 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) { 7336 m_last_rendered_TS = il_buffer->nTimeStamp; 7337 } else { 7338 //mark for droping 7339 buffer->nFilledLen = 0; 7340 } 7341 7342 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)", 7343 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS, 7344 il_buffer->nTimeStamp,ts_delta); 7345 } 7346 7347 if (il_buffer) { 7348 log_output_buffers(il_buffer); 7349 if (dynamic_buf_mode) { 7350 unsigned int nPortIndex = 0; 7351 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); 7352 7353 if (!secure_mode) { 7354 munmap(drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr, 7355 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size); 7356 } 7357 7358 //Clear graphic buffer handles in dynamic mode 7359 if (nPortIndex < drv_ctx.op_buf.actualcount && 7360 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) { 7361 native_buffer[nPortIndex].privatehandle = NULL; 7362 native_buffer[nPortIndex].nativehandle = NULL; 7363 } else { 7364 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex); 7365 return OMX_ErrorBadParameter; 7366 } 7367 } 7368 m_cb.FillBufferDone (hComp,m_app_data,il_buffer); 7369 } else { 7370 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr"); 7371 return OMX_ErrorBadParameter; 7372 } 7373 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd); 7374 } else { 7375 return OMX_ErrorBadParameter; 7376 } 7377 7378#ifdef ADAPTIVE_PLAYBACK_SUPPORTED 7379 if (m_smoothstreaming_mode && m_out_mem_ptr) { 7380 OMX_U32 buf_index = buffer - m_out_mem_ptr; 7381 BufferDim_t dim; 7382 private_handle_t *private_handle = NULL; 7383 dim.sliceWidth = framesize.nWidth; 7384 dim.sliceHeight = framesize.nHeight; 7385 if (buf_index < drv_ctx.op_buf.actualcount && 7386 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && 7387 native_buffer[buf_index].privatehandle) 7388 private_handle = native_buffer[buf_index].privatehandle; 7389 if (private_handle) { 7390 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d", 7391 dim.sliceWidth, dim.sliceHeight); 7392 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim); 7393 } 7394 } 7395#endif 7396 7397 return OMX_ErrorNone; 7398} 7399 7400OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, 7401 OMX_BUFFERHEADERTYPE* buffer) 7402{ 7403 7404 if (buffer == NULL || ((buffer - m_inp_mem_ptr) > (int)drv_ctx.ip_buf.actualcount)) { 7405 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); 7406 return OMX_ErrorBadParameter; 7407 } 7408 7409 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = %x", 7410 buffer, buffer->pBuffer, buffer->nFlags); 7411 pending_input_buffers--; 7412 7413 if (arbitrary_bytes) { 7414 if (pdest_frame == NULL && input_flush_progress == false) { 7415 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer); 7416 pdest_frame = buffer; 7417 buffer->nFilledLen = 0; 7418 buffer->nTimeStamp = LLONG_MAX; 7419 push_input_buffer (hComp); 7420 } else { 7421 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer); 7422 buffer->nFilledLen = 0; 7423 if (!m_input_free_q.insert_entry((unsigned long)buffer, 7424 (unsigned)NULL, (unsigned)NULL)) { 7425 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error"); 7426 } 7427 } 7428 } else if (m_cb.EmptyBufferDone) { 7429 buffer->nFilledLen = 0; 7430 if (input_use_buffer == true) { 7431 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; 7432 } 7433 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); 7434 } 7435 return OMX_ErrorNone; 7436} 7437 7438int omx_vdec::async_message_process (void *context, void* message) 7439{ 7440 omx_vdec* omx = NULL; 7441 struct vdec_msginfo *vdec_msg = NULL; 7442 OMX_BUFFERHEADERTYPE* omxhdr = NULL; 7443 struct v4l2_buffer *v4l2_buf_ptr = NULL; 7444 struct vdec_output_frameinfo *output_respbuf = NULL; 7445 int rc=1; 7446 if (context == NULL || message == NULL) { 7447 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check"); 7448 return -1; 7449 } 7450 vdec_msg = (struct vdec_msginfo *)message; 7451 7452 omx = reinterpret_cast<omx_vdec*>(context); 7453 7454 switch (vdec_msg->msgcode) { 7455 7456 case VDEC_MSG_EVT_HW_ERROR: 7457 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7458 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 7459 break; 7460 7461 case VDEC_MSG_EVT_HW_OVERLOAD: 7462 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7463 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD); 7464 break; 7465 7466 case VDEC_MSG_EVT_HW_UNSUPPORTED: 7467 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7468 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); 7469 break; 7470 7471 case VDEC_MSG_RESP_START_DONE: 7472 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7473 OMX_COMPONENT_GENERATE_START_DONE); 7474 break; 7475 7476 case VDEC_MSG_RESP_STOP_DONE: 7477 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7478 OMX_COMPONENT_GENERATE_STOP_DONE); 7479 break; 7480 7481 case VDEC_MSG_RESP_RESUME_DONE: 7482 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7483 OMX_COMPONENT_GENERATE_RESUME_DONE); 7484 break; 7485 7486 case VDEC_MSG_RESP_PAUSE_DONE: 7487 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7488 OMX_COMPONENT_GENERATE_PAUSE_DONE); 7489 break; 7490 7491 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 7492 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7493 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); 7494 break; 7495 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 7496 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ 7497 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); 7498 break; 7499 case VDEC_MSG_RESP_INPUT_FLUSHED: 7500 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 7501 7502 /* omxhdr = (OMX_BUFFERHEADERTYPE* ) 7503 vdec_msg->msgdata.input_frame_clientdata; */ 7504 7505 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata; 7506 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index; 7507 if (omxhdr == NULL || 7508 ((omxhdr - omx->m_inp_mem_ptr) > (int)omx->drv_ctx.ip_buf.actualcount) ) { 7509 omxhdr = NULL; 7510 vdec_msg->status_code = VDEC_S_EFATAL; 7511 break; 7512 } 7513 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) { 7514 DEBUG_PRINT_HIGH("Unsupported input"); 7515 omx->omx_report_error (); 7516 } 7517 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 7518 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 7519 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR; 7520 } 7521 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 7522 7523 DEBUG_PRINT_LOW("Decrement codec_config buffer counter"); 7524 android_atomic_dec(&omx->m_queued_codec_config_count); 7525 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) && 7526 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) { 7527 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer"); 7528 sem_post(&omx->m_safe_flush); 7529 } 7530 } 7531 7532 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code, 7533 OMX_COMPONENT_GENERATE_EBD); 7534 break; 7535 case VDEC_MSG_EVT_INFO_FIELD_DROPPED: 7536 int64_t *timestamp; 7537 timestamp = (int64_t *) malloc(sizeof(int64_t)); 7538 if (timestamp) { 7539 *timestamp = vdec_msg->msgdata.output_frame.time_stamp; 7540 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code, 7541 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); 7542 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", 7543 (long long)vdec_msg->msgdata.output_frame.time_stamp); 7544 } 7545 break; 7546 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 7547 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 7548 7549 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; 7550 omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index; 7551 7552 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)", 7553 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp, 7554 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags, 7555 (unsigned int)vdec_msg->msgdata.output_frame.len, 7556 vdec_msg->msgdata.output_frame.framesize.left, 7557 vdec_msg->msgdata.output_frame.framesize.top, 7558 vdec_msg->msgdata.output_frame.framesize.right, 7559 vdec_msg->msgdata.output_frame.framesize.bottom); 7560 7561 if (omxhdr && omxhdr->pOutputPortPrivate && 7562 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) && 7563 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate 7564 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) { 7565 7566 if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) { 7567 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; 7568 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; 7569 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp; 7570 omxhdr->nFlags = 0; 7571 7572 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) { 7573 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS; 7574 //rc = -1; 7575 } 7576 if (omxhdr->nFilledLen) { 7577 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 7578 } 7579 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) { 7580 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 7581 } else { 7582 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME; 7583 } 7584 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) { 7585 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 7586 } 7587 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) { 7588 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY; 7589 } 7590 7591 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) { 7592 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF; 7593 } 7594 7595 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) { 7596 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY; 7597 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d", 7598 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd); 7599 } 7600 7601 if (omx->dynamic_buf_mode && !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY)) { 7602 omx->buf_ref_remove(omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd, 7603 omxhdr->nOffset); 7604 } 7605 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) && 7606 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) && 7607 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) { 7608 omx->time_stamp_dts.remove_time_stamp( 7609 omxhdr->nTimeStamp, 7610 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) 7611 ?true:false); 7612 omx->post_event ((unsigned long)NULL,(unsigned long)omxhdr, 7613 OMX_COMPONENT_GENERATE_FTB); 7614 break; 7615 } 7616 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { 7617 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 7618 } 7619 vdec_msg->msgdata.output_frame.bufferaddr = 7620 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; 7621 7622 /* Post event if resolution OR crop changed */ 7623 /* filled length will be changed if resolution changed */ 7624 /* Crop parameters can be changed even without resolution change */ 7625 if (omxhdr->nFilledLen 7626 && ((omx->prev_n_filled_len != omxhdr->nFilledLen) 7627 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left) 7628 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top) 7629 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right) 7630 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom) 7631 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width) 7632 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) { 7633 7634 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", 7635 omx->prev_n_filled_len, 7636 omx->drv_ctx.video_resolution.frame_width, 7637 omx->drv_ctx.video_resolution.frame_height, 7638 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top, 7639 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom, 7640 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width, 7641 vdec_msg->msgdata.output_frame.picsize.frame_height, 7642 vdec_msg->msgdata.output_frame.framesize.left, 7643 vdec_msg->msgdata.output_frame.framesize.top, 7644 vdec_msg->msgdata.output_frame.framesize.right, 7645 vdec_msg->msgdata.output_frame.framesize.bottom); 7646 7647 omx->drv_ctx.video_resolution.frame_width = 7648 vdec_msg->msgdata.output_frame.picsize.frame_width; 7649 omx->drv_ctx.video_resolution.frame_height = 7650 vdec_msg->msgdata.output_frame.picsize.frame_height; 7651 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { 7652 omx->drv_ctx.video_resolution.stride = 7653 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width); 7654 omx->drv_ctx.video_resolution.scan_lines = 7655 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height); 7656 } 7657 memcpy(&omx->drv_ctx.frame_size, 7658 &vdec_msg->msgdata.output_frame.framesize, 7659 sizeof(struct vdec_framesize)); 7660 7661 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX, 7662 OMX_IndexConfigCommonOutputCrop, 7663 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 7664 } 7665 7666 if (omxhdr->nFilledLen) 7667 omx->prev_n_filled_len = omxhdr->nFilledLen; 7668 7669 output_respbuf = (struct vdec_output_frameinfo *)\ 7670 omxhdr->pOutputPortPrivate; 7671 output_respbuf->len = vdec_msg->msgdata.output_frame.len; 7672 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; 7673 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) { 7674 output_respbuf->pic_type = PICTURE_TYPE_I; 7675 } 7676 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) { 7677 output_respbuf->pic_type = PICTURE_TYPE_P; 7678 } 7679 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) { 7680 output_respbuf->pic_type = PICTURE_TYPE_B; 7681 } 7682 7683 if (omx->output_use_buffer) 7684 memcpy ( omxhdr->pBuffer, (void *) 7685 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr + 7686 (unsigned long)vdec_msg->msgdata.output_frame.offset), 7687 vdec_msg->msgdata.output_frame.len); 7688 } else { 7689 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u", 7690 (unsigned int)vdec_msg->msgdata.output_frame.len, 7691 omxhdr->nAllocLen, omx->prev_n_filled_len); 7692 omxhdr->nFilledLen = 0; 7693 } 7694 7695 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code, 7696 OMX_COMPONENT_GENERATE_FBD); 7697 7698 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) { 7699 omx->post_event ((unsigned long)NULL, vdec_msg->status_code, 7700 OMX_COMPONENT_GENERATE_EOS_DONE); 7701 } else { 7702 omx->post_event ((unsigned int)NULL, vdec_msg->status_code, 7703 OMX_COMPONENT_GENERATE_HARDWARE_ERROR); 7704 } 7705 break; 7706 case VDEC_MSG_EVT_CONFIG_CHANGED: 7707 DEBUG_PRINT_HIGH("Port settings changed"); 7708 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition, 7709 OMX_COMPONENT_GENERATE_PORT_RECONFIG); 7710 break; 7711 default: 7712 break; 7713 } 7714 return rc; 7715} 7716 7717OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( 7718 OMX_HANDLETYPE hComp, 7719 OMX_BUFFERHEADERTYPE *buffer 7720 ) 7721{ 7722 unsigned address,p2,id; 7723 DEBUG_PRINT_LOW("Empty this arbitrary"); 7724 7725 if (buffer == NULL) { 7726 return OMX_ErrorBadParameter; 7727 } 7728 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); 7729 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld", 7730 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp); 7731 7732 /* return zero length and not an EOS buffer */ 7733 /* return buffer if input flush in progress */ 7734 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && 7735 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) { 7736 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress"); 7737 m_cb.EmptyBufferDone (hComp,m_app_data,buffer); 7738 return OMX_ErrorNone; 7739 } 7740 7741 if (psource_frame == NULL) { 7742 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp); 7743 psource_frame = buffer; 7744 DEBUG_PRINT_LOW("Try to Push One Input Buffer "); 7745 push_input_buffer (hComp); 7746 } else { 7747 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer); 7748 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL, 7749 (unsigned)NULL)) { 7750 return OMX_ErrorBadParameter; 7751 } 7752 } 7753 7754 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 7755 codec_config_flag = false; 7756 } 7757 return OMX_ErrorNone; 7758} 7759 7760OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) 7761{ 7762 unsigned long address,p2,id; 7763 OMX_ERRORTYPE ret = OMX_ErrorNone; 7764 7765 if (pdest_frame == NULL || psource_frame == NULL) { 7766 /*Check if we have a destination buffer*/ 7767 if (pdest_frame == NULL) { 7768 DEBUG_PRINT_LOW("Get a Destination buffer from the queue"); 7769 if (m_input_free_q.m_size) { 7770 m_input_free_q.pop_entry(&address,&p2,&id); 7771 pdest_frame = (OMX_BUFFERHEADERTYPE *)address; 7772 pdest_frame->nFilledLen = 0; 7773 pdest_frame->nTimeStamp = LLONG_MAX; 7774 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame); 7775 } 7776 } 7777 7778 /*Check if we have a destination buffer*/ 7779 if (psource_frame == NULL) { 7780 DEBUG_PRINT_LOW("Get a source buffer from the queue"); 7781 if (m_input_pending_q.m_size) { 7782 m_input_pending_q.pop_entry(&address,&p2,&id); 7783 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 7784 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 7785 psource_frame->nTimeStamp); 7786 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 7787 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 7788 7789 } 7790 } 7791 7792 } 7793 7794 while ((pdest_frame != NULL) && (psource_frame != NULL)) { 7795 switch (codec_type_parse) { 7796 case CODEC_TYPE_MPEG4: 7797 case CODEC_TYPE_H263: 7798 case CODEC_TYPE_MPEG2: 7799 ret = push_input_sc_codec(hComp); 7800 break; 7801 case CODEC_TYPE_H264: 7802 ret = push_input_h264(hComp); 7803 break; 7804 case CODEC_TYPE_HEVC: 7805 ret = push_input_hevc(hComp); 7806 break; 7807 case CODEC_TYPE_VC1: 7808 ret = push_input_vc1(hComp); 7809 break; 7810 default: 7811 break; 7812 } 7813 if (ret != OMX_ErrorNone) { 7814 DEBUG_PRINT_ERROR("Pushing input Buffer Failed"); 7815 omx_report_error (); 7816 break; 7817 } 7818 } 7819 7820 return ret; 7821} 7822 7823OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp) 7824{ 7825 OMX_U32 partial_frame = 1; 7826 OMX_BOOL generate_ebd = OMX_TRUE; 7827 unsigned long address = 0, p2 = 0, id = 0; 7828 7829 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld", 7830 psource_frame,psource_frame->nTimeStamp); 7831 if (m_frame_parser.parse_sc_frame(psource_frame, 7832 pdest_frame,&partial_frame) == -1) { 7833 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 7834 return OMX_ErrorBadParameter; 7835 } 7836 7837 if (partial_frame == 0) { 7838 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d", 7839 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count); 7840 7841 7842 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp); 7843 /*First Parsed buffer will have only header Hence skip*/ 7844 if (frame_count == 0) { 7845 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame "); 7846 7847 if (codec_type_parse == CODEC_TYPE_MPEG4 || 7848 codec_type_parse == CODEC_TYPE_DIVX) { 7849 mp4StreamType psBits; 7850 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset; 7851 psBits.numBytes = pdest_frame->nFilledLen; 7852 mp4_headerparser.parseHeader(&psBits); 7853 } 7854 7855 frame_count++; 7856 } else { 7857 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 7858 if (pdest_frame->nFilledLen) { 7859 /*Push the frame to the Decoder*/ 7860 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 7861 return OMX_ErrorBadParameter; 7862 } 7863 frame_count++; 7864 pdest_frame = NULL; 7865 7866 if (m_input_free_q.m_size) { 7867 m_input_free_q.pop_entry(&address,&p2,&id); 7868 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 7869 pdest_frame->nFilledLen = 0; 7870 } 7871 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) { 7872 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL"); 7873 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL, 7874 (unsigned)NULL); 7875 pdest_frame = NULL; 7876 } 7877 } 7878 } else { 7879 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen); 7880 /*Check if Destination Buffer is full*/ 7881 if (pdest_frame->nAllocLen == 7882 pdest_frame->nFilledLen + pdest_frame->nOffset) { 7883 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled"); 7884 return OMX_ErrorStreamCorrupt; 7885 } 7886 } 7887 7888 if (psource_frame->nFilledLen == 0) { 7889 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 7890 if (pdest_frame) { 7891 pdest_frame->nFlags |= psource_frame->nFlags; 7892 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld", 7893 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 7894 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 7895 (unsigned int)pdest_frame->nFilledLen,frame_count++); 7896 /*Push the frame to the Decoder*/ 7897 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 7898 return OMX_ErrorBadParameter; 7899 } 7900 frame_count++; 7901 pdest_frame = NULL; 7902 } else { 7903 DEBUG_PRINT_LOW("Last frame in else dest addr") ; 7904 generate_ebd = OMX_FALSE; 7905 } 7906 } 7907 if (generate_ebd) { 7908 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame); 7909 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 7910 psource_frame = NULL; 7911 7912 if (m_input_pending_q.m_size) { 7913 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 7914 m_input_pending_q.pop_entry(&address,&p2,&id); 7915 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 7916 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame, 7917 psource_frame->nTimeStamp); 7918 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u", 7919 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 7920 } 7921 } 7922 } 7923 return OMX_ErrorNone; 7924} 7925 7926OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) 7927{ 7928 OMX_U32 partial_frame = 1; 7929 unsigned long address = 0, p2 = 0, id = 0; 7930 OMX_BOOL isNewFrame = OMX_FALSE; 7931 OMX_BOOL generate_ebd = OMX_TRUE; 7932 7933 if (h264_scratch.pBuffer == NULL) { 7934 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated"); 7935 return OMX_ErrorBadParameter; 7936 } 7937 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u " 7938 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal); 7939 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen); 7940 if (h264_scratch.nFilledLen && look_ahead_nal) { 7941 look_ahead_nal = false; 7942 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 7943 h264_scratch.nFilledLen) { 7944 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 7945 h264_scratch.pBuffer,h264_scratch.nFilledLen); 7946 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 7947 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame"); 7948 h264_scratch.nFilledLen = 0; 7949 } else { 7950 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264"); 7951 return OMX_ErrorBadParameter; 7952 } 7953 } 7954 7955 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result 7956 in EOS flag getting associated with the destination 7957 */ 7958 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) && 7959 pdest_frame->nFilledLen) { 7960 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'"); 7961 generate_ebd = OMX_FALSE; 7962 } 7963 7964 if (nal_length == 0) { 7965 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code"); 7966 if (m_frame_parser.parse_sc_frame(psource_frame, 7967 &h264_scratch,&partial_frame) == -1) { 7968 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 7969 return OMX_ErrorBadParameter; 7970 } 7971 } else { 7972 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length); 7973 if (m_frame_parser.parse_h264_nallength(psource_frame, 7974 &h264_scratch,&partial_frame) == -1) { 7975 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 7976 return OMX_ErrorBadParameter; 7977 } 7978 } 7979 7980 if (partial_frame == 0) { 7981 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 7982 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 7983 nal_count++; 7984 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 7985 h264_scratch.nFlags = psource_frame->nFlags; 7986 } else { 7987 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen); 7988 if (h264_scratch.nFilledLen) { 7989 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen, 7990 NALU_TYPE_SPS); 7991#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 7992 if (client_extradata & OMX_TIMEINFO_EXTRADATA) 7993 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 7994 h264_scratch.nFilledLen, NALU_TYPE_SEI); 7995 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 7996 // If timeinfo is present frame info from SEI is already processed 7997 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, 7998 h264_scratch.nFilledLen, NALU_TYPE_SEI); 7999#endif 8000 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 8001 nal_count++; 8002 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) { 8003 pdest_frame->nTimeStamp = h264_last_au_ts; 8004 pdest_frame->nFlags = h264_last_au_flags; 8005#ifdef PANSCAN_HDLR 8006 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) 8007 h264_parser->update_panscan_data(h264_last_au_ts); 8008#endif 8009 } 8010 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR || 8011 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) { 8012 h264_last_au_ts = h264_scratch.nTimeStamp; 8013 h264_last_au_flags = h264_scratch.nFlags; 8014#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 8015 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 8016 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts); 8017 if (!VALID_TS(h264_last_au_ts)) 8018 h264_last_au_ts = ts_in_sei; 8019 } 8020#endif 8021 } else 8022 h264_last_au_ts = LLONG_MAX; 8023 } 8024 8025 if (!isNewFrame) { 8026 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 8027 h264_scratch.nFilledLen) { 8028 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u", 8029 (unsigned int)h264_scratch.nFilledLen); 8030 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 8031 h264_scratch.pBuffer,h264_scratch.nFilledLen); 8032 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 8033 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ) 8034 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; 8035 h264_scratch.nFilledLen = 0; 8036 } else { 8037 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264"); 8038 return OMX_ErrorBadParameter; 8039 } 8040 } else if(h264_scratch.nFilledLen) { 8041 look_ahead_nal = true; 8042 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu", 8043 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 8044 DEBUG_PRINT_LOW("Found a frame size = %u number = %d", 8045 (unsigned int)pdest_frame->nFilledLen,frame_count++); 8046 8047 if (pdest_frame->nFilledLen == 0) { 8048 DEBUG_PRINT_LOW("Copy the Current Frame since and push it"); 8049 look_ahead_nal = false; 8050 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 8051 h264_scratch.nFilledLen) { 8052 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 8053 h264_scratch.pBuffer,h264_scratch.nFilledLen); 8054 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 8055 h264_scratch.nFilledLen = 0; 8056 } else { 8057 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264"); 8058 return OMX_ErrorBadParameter; 8059 } 8060 } else { 8061 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 8062 DEBUG_PRINT_LOW("Reset the EOS Flag"); 8063 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 8064 } 8065 /*Push the frame to the Decoder*/ 8066 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 8067 return OMX_ErrorBadParameter; 8068 } 8069 //frame_count++; 8070 pdest_frame = NULL; 8071 if (m_input_free_q.m_size) { 8072 m_input_free_q.pop_entry(&address,&p2,&id); 8073 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 8074 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame); 8075 pdest_frame->nFilledLen = 0; 8076 pdest_frame->nFlags = 0; 8077 pdest_frame->nTimeStamp = LLONG_MAX; 8078 } 8079 } 8080 } 8081 } 8082 } else { 8083 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen); 8084 /*Check if Destination Buffer is full*/ 8085 if (h264_scratch.nAllocLen == 8086 h264_scratch.nFilledLen + h264_scratch.nOffset) { 8087 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 8088 return OMX_ErrorStreamCorrupt; 8089 } 8090 } 8091 8092 if (!psource_frame->nFilledLen) { 8093 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame); 8094 8095 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 8096 if (pdest_frame) { 8097 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 8098 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= 8099 h264_scratch.nFilledLen) { 8100 if(pdest_frame->nFilledLen == 0) { 8101 /* No residual frame from before, send whatever 8102 * we have left */ 8103 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen), 8104 h264_scratch.pBuffer, h264_scratch.nFilledLen); 8105 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 8106 h264_scratch.nFilledLen = 0; 8107 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 8108 } else { 8109 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); 8110 if(!isNewFrame) { 8111 /* Have a residual frame, but we know that the 8112 * AU in this frame is belonging to whatever 8113 * frame we had left over. So append it */ 8114 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), 8115 h264_scratch.pBuffer,h264_scratch.nFilledLen); 8116 pdest_frame->nFilledLen += h264_scratch.nFilledLen; 8117 h264_scratch.nFilledLen = 0; 8118 if (h264_last_au_ts != LLONG_MAX) 8119 pdest_frame->nTimeStamp = h264_last_au_ts; 8120 } else { 8121 /* Completely new frame, let's just push what 8122 * we have now. The resulting EBD would trigger 8123 * another push */ 8124 generate_ebd = OMX_FALSE; 8125 pdest_frame->nTimeStamp = h264_last_au_ts; 8126 h264_last_au_ts = h264_scratch.nTimeStamp; 8127 } 8128 } 8129 } else { 8130 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264"); 8131 return OMX_ErrorBadParameter; 8132 } 8133 8134 /* Iff we coalesced two buffers, inherit the flags of both bufs */ 8135 if(generate_ebd == OMX_TRUE) { 8136 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 8137 } 8138 8139 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu", 8140 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp); 8141 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++); 8142#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT 8143 if (client_extradata & OMX_TIMEINFO_EXTRADATA) { 8144 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp); 8145 if (!VALID_TS(pdest_frame->nTimeStamp)) 8146 pdest_frame->nTimeStamp = ts_in_sei; 8147 } 8148#endif 8149 /*Push the frame to the Decoder*/ 8150 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) { 8151 return OMX_ErrorBadParameter; 8152 } 8153 frame_count++; 8154 pdest_frame = NULL; 8155 } else { 8156 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 8157 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 8158 generate_ebd = OMX_FALSE; 8159 } 8160 } 8161 } 8162 if (generate_ebd && !psource_frame->nFilledLen) { 8163 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); 8164 psource_frame = NULL; 8165 if (m_input_pending_q.m_size) { 8166 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); 8167 m_input_pending_q.pop_entry(&address,&p2,&id); 8168 psource_frame = (OMX_BUFFERHEADERTYPE *) address; 8169 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u", 8170 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen); 8171 } 8172 } 8173 return OMX_ErrorNone; 8174} 8175 8176OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc) 8177{ 8178 OMX_ERRORTYPE rc = OMX_ErrorNone; 8179 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) { 8180 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen); 8181 if (pDst->nTimeStamp == LLONG_MAX) { 8182 pDst->nTimeStamp = pSrc->nTimeStamp; 8183 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp); 8184 } 8185 pDst->nFilledLen += pSrc->nFilledLen; 8186 pSrc->nFilledLen = 0; 8187 } else { 8188 DEBUG_PRINT_ERROR("Error: Destination buffer overflow"); 8189 rc = OMX_ErrorBadParameter; 8190 } 8191 return rc; 8192} 8193 8194OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp) 8195{ 8196 OMX_U32 partial_frame = 1; 8197 unsigned long address,p2,id; 8198 OMX_BOOL isNewFrame = OMX_FALSE; 8199 OMX_BOOL generate_ebd = OMX_TRUE; 8200 OMX_ERRORTYPE rc = OMX_ErrorNone; 8201 if (h264_scratch.pBuffer == NULL) { 8202 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated"); 8203 return OMX_ErrorBadParameter; 8204 } 8205 8206 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \ 8207 pdest_frame nFilledLen %u nTimeStamp %lld", 8208 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 8209 8210 if (h264_scratch.nFilledLen && look_ahead_nal) { 8211 look_ahead_nal = false; 8212 rc = copy_buffer(pdest_frame, &h264_scratch); 8213 if (rc != OMX_ErrorNone) { 8214 return rc; 8215 } 8216 } 8217 8218 if (nal_length == 0) { 8219 if (m_frame_parser.parse_sc_frame(psource_frame, 8220 &h264_scratch,&partial_frame) == -1) { 8221 DEBUG_PRINT_ERROR("Error In Parsing Return Error"); 8222 return OMX_ErrorBadParameter; 8223 } 8224 } else { 8225 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length); 8226 if (m_frame_parser.parse_h264_nallength(psource_frame, 8227 &h264_scratch,&partial_frame) == -1) { 8228 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error"); 8229 return OMX_ErrorBadParameter; 8230 } 8231 } 8232 8233 if (partial_frame == 0) { 8234 if (nal_count == 0 && h264_scratch.nFilledLen == 0) { 8235 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); 8236 nal_count++; 8237 h264_scratch.nTimeStamp = psource_frame->nTimeStamp; 8238 h264_scratch.nFlags = psource_frame->nFlags; 8239 } else { 8240 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen); 8241 if (h264_scratch.nFilledLen) { 8242 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame); 8243 nal_count++; 8244 } 8245 8246 if (!isNewFrame) { 8247 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \ 8248 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld", 8249 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp, 8250 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 8251 rc = copy_buffer(pdest_frame, &h264_scratch); 8252 if (rc != OMX_ErrorNone) { 8253 return rc; 8254 } 8255 } else { 8256 look_ahead_nal = true; 8257 if (pdest_frame->nFilledLen == 0) { 8258 look_ahead_nal = false; 8259 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer"); 8260 rc = copy_buffer(pdest_frame, &h264_scratch); 8261 if (rc != OMX_ErrorNone) { 8262 return OMX_ErrorBadParameter; 8263 } 8264 } else { 8265 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) { 8266 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; 8267 } 8268 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \ 8269 nTimeStamp %lld, look_ahead_nal in h264_scratch \ 8270 nFilledLen %u nTimeStamp %lld", 8271 frame_count++, (unsigned int)pdest_frame->nFilledLen, 8272 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen, 8273 h264_scratch.nTimeStamp); 8274 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 8275 return OMX_ErrorBadParameter; 8276 } 8277 pdest_frame = NULL; 8278 if (m_input_free_q.m_size) { 8279 m_input_free_q.pop_entry(&address, &p2, &id); 8280 pdest_frame = (OMX_BUFFERHEADERTYPE *) address; 8281 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame); 8282 pdest_frame->nFilledLen = 0; 8283 pdest_frame->nFlags = 0; 8284 pdest_frame->nTimeStamp = LLONG_MAX; 8285 } 8286 } 8287 } 8288 } 8289 } else { 8290 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \ 8291 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \ 8292 nFilledLen %u nTimeStamp %lld", 8293 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp, 8294 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp, 8295 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp); 8296 8297 if (h264_scratch.nAllocLen == 8298 h264_scratch.nFilledLen + h264_scratch.nOffset) { 8299 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled"); 8300 return OMX_ErrorStreamCorrupt; 8301 } 8302 } 8303 8304 if (!psource_frame->nFilledLen) { 8305 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame); 8306 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { 8307 if (pdest_frame) { 8308 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); 8309 rc = copy_buffer(pdest_frame, &h264_scratch); 8310 if ( rc != OMX_ErrorNone ) { 8311 return rc; 8312 } 8313 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; 8314 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; 8315 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld", 8316 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp); 8317 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) { 8318 return OMX_ErrorBadParameter; 8319 } 8320 frame_count++; 8321 pdest_frame = NULL; 8322 } else { 8323 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u", 8324 pdest_frame, (unsigned int)h264_scratch.nFilledLen); 8325 generate_ebd = OMX_FALSE; 8326 } 8327 } 8328 } 8329 8330 if (generate_ebd && !psource_frame->nFilledLen) { 8331 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame); 8332 psource_frame = NULL; 8333 if (m_input_pending_q.m_size) { 8334 m_input_pending_q.pop_entry(&address, &p2, &id); 8335 psource_frame = (OMX_BUFFERHEADERTYPE *)address; 8336 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld", 8337 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp); 8338 } 8339 } 8340 return OMX_ErrorNone; 8341} 8342 8343OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp) 8344{ 8345 OMX_U8 *buf, *pdest; 8346 OMX_U32 partial_frame = 1; 8347 OMX_U32 buf_len, dest_len; 8348 8349 if (first_frame == 0) { 8350 first_frame = 1; 8351 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes"); 8352 if (!m_vendor_config.pData) { 8353 DEBUG_PRINT_LOW("Check profile type in 1st source buffer"); 8354 buf = psource_frame->pBuffer; 8355 buf_len = psource_frame->nFilledLen; 8356 8357 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) == 8358 VC1_SP_MP_START_CODE) { 8359 m_vc1_profile = VC1_SP_MP_RCV; 8360 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) { 8361 m_vc1_profile = VC1_AP; 8362 } else { 8363 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer"); 8364 return OMX_ErrorStreamCorrupt; 8365 } 8366 } else { 8367 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen + 8368 pdest_frame->nOffset; 8369 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen + 8370 pdest_frame->nOffset); 8371 8372 if (dest_len < m_vendor_config.nDataSize) { 8373 DEBUG_PRINT_ERROR("Destination buffer full"); 8374 return OMX_ErrorBadParameter; 8375 } else { 8376 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize); 8377 pdest_frame->nFilledLen += m_vendor_config.nDataSize; 8378 } 8379 } 8380 } 8381 8382 switch (m_vc1_profile) { 8383 case VC1_AP: 8384 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code"); 8385 if (push_input_sc_codec(hComp) != OMX_ErrorNone) { 8386 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code"); 8387 return OMX_ErrorBadParameter; 8388 } 8389 break; 8390 8391 case VC1_SP_MP_RCV: 8392 default: 8393 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode"); 8394 return OMX_ErrorBadParameter; 8395 } 8396 return OMX_ErrorNone; 8397} 8398 8399#ifndef USE_ION 8400bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, 8401 OMX_U32 alignment) 8402{ 8403 struct pmem_allocation allocation; 8404 allocation.size = buffer_size; 8405 allocation.align = clip2(alignment); 8406 if (allocation.align < 4096) { 8407 allocation.align = 4096; 8408 } 8409 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) { 8410 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)", 8411 allocation.align, allocation.size); 8412 return false; 8413 } 8414 return true; 8415} 8416#endif 8417#ifdef USE_ION 8418int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, 8419 OMX_U32 alignment, struct ion_allocation_data *alloc_data, 8420 struct ion_fd_data *fd_data, int flag) 8421{ 8422 int fd = -EINVAL; 8423 int rc = -EINVAL; 8424 int ion_dev_flag; 8425 struct vdec_ion ion_buf_info; 8426 if (!alloc_data || buffer_size <= 0 || !fd_data) { 8427 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory"); 8428 return -EINVAL; 8429 } 8430 ion_dev_flag = O_RDONLY; 8431 fd = open (MEM_DEVICE, ion_dev_flag); 8432 if (fd < 0) { 8433 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd); 8434 return fd; 8435 } 8436 alloc_data->flags = 0; 8437 if (!secure_mode && (flag & ION_FLAG_CACHED)) { 8438 alloc_data->flags |= ION_FLAG_CACHED; 8439 } 8440 alloc_data->len = buffer_size; 8441 alloc_data->align = clip2(alignment); 8442 if (alloc_data->align < 4096) { 8443 alloc_data->align = 4096; 8444 } 8445 if ((secure_mode) && (flag & ION_SECURE)) 8446 alloc_data->flags |= ION_SECURE; 8447 8448 alloc_data->ION_HEAP_MASK = ION_HEAP(ION_IOMMU_HEAP_ID); 8449 if (secure_mode && (alloc_data->flags & ION_SECURE)) 8450 alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID); 8451 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); 8452 if (rc || !alloc_data->handle) { 8453 DEBUG_PRINT_ERROR("ION ALLOC memory failed"); 8454 alloc_data->handle = 0; 8455 close(fd); 8456 fd = -ENOMEM; 8457 return fd; 8458 } 8459 fd_data->handle = alloc_data->handle; 8460 rc = ioctl(fd,ION_IOC_MAP,fd_data); 8461 if (rc) { 8462 DEBUG_PRINT_ERROR("ION MAP failed "); 8463 ion_buf_info.ion_alloc_data = *alloc_data; 8464 ion_buf_info.ion_device_fd = fd; 8465 ion_buf_info.fd_ion_data = *fd_data; 8466 free_ion_memory(&ion_buf_info); 8467 fd_data->fd =-1; 8468 fd = -ENOMEM; 8469 } 8470 8471 return fd; 8472} 8473 8474void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) 8475{ 8476 8477 if (!buf_ion_info) { 8478 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata"); 8479 return; 8480 } 8481 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, 8482 &buf_ion_info->ion_alloc_data.handle)) { 8483 DEBUG_PRINT_ERROR("ION: free failed" ); 8484 } 8485 close(buf_ion_info->ion_device_fd); 8486 buf_ion_info->ion_device_fd = -1; 8487 buf_ion_info->ion_alloc_data.handle = 0; 8488 buf_ion_info->fd_ion_data.fd = -1; 8489} 8490#endif 8491void omx_vdec::free_output_buffer_header() 8492{ 8493 DEBUG_PRINT_HIGH("ALL output buffers are freed/released"); 8494 output_use_buffer = false; 8495 ouput_egl_buffers = false; 8496 8497 if (m_out_mem_ptr) { 8498 free (m_out_mem_ptr); 8499 m_out_mem_ptr = NULL; 8500 } 8501 8502 if (m_platform_list) { 8503 free(m_platform_list); 8504 m_platform_list = NULL; 8505 } 8506 8507 if (drv_ctx.ptr_respbuffer) { 8508 free (drv_ctx.ptr_respbuffer); 8509 drv_ctx.ptr_respbuffer = NULL; 8510 } 8511 if (drv_ctx.ptr_outputbuffer) { 8512 free (drv_ctx.ptr_outputbuffer); 8513 drv_ctx.ptr_outputbuffer = NULL; 8514 } 8515#ifdef USE_ION 8516 if (drv_ctx.op_buf_ion_info) { 8517 DEBUG_PRINT_LOW("Free o/p ion context"); 8518 free(drv_ctx.op_buf_ion_info); 8519 drv_ctx.op_buf_ion_info = NULL; 8520 } 8521#endif 8522 if (out_dynamic_list) { 8523 free(out_dynamic_list); 8524 out_dynamic_list = NULL; 8525 } 8526} 8527 8528void omx_vdec::free_input_buffer_header() 8529{ 8530 input_use_buffer = false; 8531 if (arbitrary_bytes) { 8532 if (m_inp_heap_ptr) { 8533 DEBUG_PRINT_LOW("Free input Heap Pointer"); 8534 free (m_inp_heap_ptr); 8535 m_inp_heap_ptr = NULL; 8536 } 8537 8538 if (m_phdr_pmem_ptr) { 8539 DEBUG_PRINT_LOW("Free input pmem header Pointer"); 8540 free (m_phdr_pmem_ptr); 8541 m_phdr_pmem_ptr = NULL; 8542 } 8543 } 8544 if (m_inp_mem_ptr) { 8545 DEBUG_PRINT_LOW("Free input pmem Pointer area"); 8546 free (m_inp_mem_ptr); 8547 m_inp_mem_ptr = NULL; 8548 } 8549 /* We just freed all the buffer headers, every thing in m_input_free_q, 8550 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */ 8551 while (m_input_free_q.m_size) { 8552 unsigned long address, p2, id; 8553 m_input_free_q.pop_entry(&address, &p2, &id); 8554 } 8555 while (m_input_pending_q.m_size) { 8556 unsigned long address, p2, id; 8557 m_input_pending_q.pop_entry(&address, &p2, &id); 8558 } 8559 pdest_frame = NULL; 8560 psource_frame = NULL; 8561 if (drv_ctx.ptr_inputbuffer) { 8562 DEBUG_PRINT_LOW("Free Driver Context pointer"); 8563 free (drv_ctx.ptr_inputbuffer); 8564 drv_ctx.ptr_inputbuffer = NULL; 8565 } 8566#ifdef USE_ION 8567 if (drv_ctx.ip_buf_ion_info) { 8568 DEBUG_PRINT_LOW("Free ion context"); 8569 free(drv_ctx.ip_buf_ion_info); 8570 drv_ctx.ip_buf_ion_info = NULL; 8571 } 8572#endif 8573} 8574 8575int omx_vdec::stream_off(OMX_U32 port) 8576{ 8577 enum v4l2_buf_type btype; 8578 int rc = 0; 8579 enum v4l2_ports v4l2_port = OUTPUT_PORT; 8580 8581 if (port == OMX_CORE_INPUT_PORT_INDEX) { 8582 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8583 v4l2_port = OUTPUT_PORT; 8584 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { 8585 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8586 v4l2_port = CAPTURE_PORT; 8587 } else if (port == OMX_ALL) { 8588 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX); 8589 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX); 8590 8591 if (!rc_input) 8592 return rc_input; 8593 else 8594 return rc_output; 8595 } 8596 8597 if (!streaming[v4l2_port]) { 8598 // already streamed off, warn and move on 8599 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port," 8600 " which is already streamed off", v4l2_port); 8601 return 0; 8602 } 8603 8604 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port); 8605 8606 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); 8607 if (rc) { 8608 /*TODO: How to handle this case */ 8609 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port); 8610 } else { 8611 streaming[v4l2_port] = false; 8612 } 8613 8614 return rc; 8615} 8616 8617OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) 8618{ 8619 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8620 struct v4l2_requestbuffers bufreq; 8621 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0; 8622 unsigned int final_extra_data_size = 0; 8623 struct v4l2_format fmt; 8624 int ret = 0; 8625 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 8626 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 8627 bufreq.memory = V4L2_MEMORY_USERPTR; 8628 bufreq.count = 1; 8629 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 8630 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8631 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8632 fmt.fmt.pix_mp.pixelformat = output_capability; 8633 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8634 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8635 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8636 fmt.fmt.pix_mp.pixelformat = capture_capability; 8637 } else { 8638 eRet = OMX_ErrorBadParameter; 8639 } 8640 if (eRet==OMX_ErrorNone) { 8641 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 8642 } 8643 if (ret) { 8644 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 8645 /*TODO: How to handle this case */ 8646 eRet = OMX_ErrorInsufficientResources; 8647 return eRet; 8648 } else { 8649 buffer_prop->actualcount = bufreq.count; 8650 buffer_prop->mincount = bufreq.count; 8651 DEBUG_PRINT_HIGH("Count = %d",bufreq.count); 8652 } 8653 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", 8654 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 8655 8656 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 8657 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 8658 8659 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 8660 8661 update_resolution(fmt.fmt.pix_mp.width, 8662 fmt.fmt.pix_mp.height, 8663 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, 8664 fmt.fmt.pix_mp.plane_fmt[0].reserved[0]); 8665 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 8666 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes; 8667 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage); 8668 8669 if (ret) { 8670 /*TODO: How to handle this case */ 8671 DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); 8672 eRet = OMX_ErrorInsufficientResources; 8673 } else { 8674 int extra_idx = 0; 8675 8676 eRet = is_video_session_supported(); 8677 if (eRet) 8678 return eRet; 8679 8680 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; 8681 buf_size = buffer_prop->buffer_size; 8682 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes); 8683 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { 8684 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage; 8685 } else if (extra_idx >= VIDEO_MAX_PLANES) { 8686 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); 8687 return OMX_ErrorBadParameter; 8688 } 8689 8690 default_extra_data_size = VENUS_EXTRADATA_SIZE( 8691 drv_ctx.video_resolution.frame_height, 8692 drv_ctx.video_resolution.frame_width); 8693 final_extra_data_size = extra_data_size > default_extra_data_size ? 8694 extra_data_size : default_extra_data_size; 8695 8696 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) & 8697 (~(buffer_prop->alignment - 1)); 8698 8699 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size; 8700 drv_ctx.extradata_info.count = buffer_prop->actualcount; 8701 drv_ctx.extradata_info.buffer_size = final_extra_data_size; 8702 if (!secure_mode) 8703 buf_size += final_extra_data_size; 8704 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 8705 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)", 8706 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size); 8707 if (extra_data_size) 8708 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)", 8709 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size); 8710 8711 if (in_reconfig) // BufReq will be set to driver when port is disabled 8712 buffer_prop->buffer_size = buf_size; 8713 else if (buf_size != buffer_prop->buffer_size) { 8714 buffer_prop->buffer_size = buf_size; 8715 eRet = set_buffer_req(buffer_prop); 8716 } 8717 } 8718 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)", 8719 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 8720 return eRet; 8721} 8722 8723OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) 8724{ 8725 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8726 unsigned buf_size = 0; 8727 struct v4l2_format fmt; 8728 struct v4l2_requestbuffers bufreq; 8729 int ret; 8730 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)", 8731 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); 8732 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); 8733 if (buf_size != buffer_prop->buffer_size) { 8734 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)", 8735 (unsigned int)buffer_prop->buffer_size, buf_size); 8736 eRet = OMX_ErrorBadParameter; 8737 } else { 8738 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 8739 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 8740 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 8741 8742 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 8743 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8744 fmt.fmt.pix_mp.pixelformat = output_capability; 8745 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size; 8746 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8747 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8748 fmt.fmt.pix_mp.pixelformat = capture_capability; 8749 } else { 8750 eRet = OMX_ErrorBadParameter; 8751 } 8752 8753 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 8754 if (ret) { 8755 /*TODO: How to handle this case */ 8756 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret); 8757 eRet = OMX_ErrorInsufficientResources; 8758 } 8759 8760 bufreq.memory = V4L2_MEMORY_USERPTR; 8761 bufreq.count = buffer_prop->actualcount; 8762 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { 8763 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8764 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) { 8765 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8766 } else { 8767 eRet = OMX_ErrorBadParameter; 8768 } 8769 8770 if (eRet==OMX_ErrorNone) { 8771 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); 8772 } 8773 8774 if (ret) { 8775 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret); 8776 /*TODO: How to handle this case */ 8777 eRet = OMX_ErrorInsufficientResources; 8778 } else if (bufreq.count < buffer_prop->actualcount) { 8779 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers" 8780 " on v4l2 port %d to %d (prefers %d)", bufreq.type, 8781 buffer_prop->actualcount, bufreq.count); 8782 eRet = OMX_ErrorInsufficientResources; 8783 } else { 8784 if (!client_buffers.update_buffer_req()) { 8785 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); 8786 eRet = OMX_ErrorInsufficientResources; 8787 } 8788 } 8789 } 8790 return eRet; 8791} 8792 8793OMX_ERRORTYPE omx_vdec::update_picture_resolution() 8794{ 8795 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8796 return eRet; 8797} 8798 8799OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) 8800{ 8801 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8802 struct v4l2_format fmt; 8803 if (!portDefn) { 8804 return OMX_ErrorBadParameter; 8805 } 8806 DEBUG_PRINT_LOW("omx_vdec::update_portdef"); 8807 portDefn->nVersion.nVersion = OMX_SPEC_VERSION; 8808 portDefn->nSize = sizeof(portDefn); 8809 portDefn->eDomain = OMX_PortDomainVideo; 8810 if (drv_ctx.frame_rate.fps_denominator > 0) 8811 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator / 8812 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format 8813 else { 8814 DEBUG_PRINT_ERROR("Error: Divide by zero"); 8815 return OMX_ErrorBadParameter; 8816 } 8817 memset(&fmt, 0x0, sizeof(struct v4l2_format)); 8818 if (0 == portDefn->nPortIndex) { 8819 portDefn->eDir = OMX_DirInput; 8820 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; 8821 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; 8822 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size; 8823 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; 8824 portDefn->format.video.eCompressionFormat = eCompressionFormat; 8825 portDefn->bEnabled = m_inp_bEnabled; 8826 portDefn->bPopulated = m_inp_bPopulated; 8827 8828 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 8829 fmt.fmt.pix_mp.pixelformat = output_capability; 8830 } else if (1 == portDefn->nPortIndex) { 8831 unsigned int buf_size = 0; 8832 if (!client_buffers.update_buffer_req()) { 8833 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed"); 8834 return OMX_ErrorHardware; 8835 } 8836 if (!client_buffers.get_buffer_req(buf_size)) { 8837 DEBUG_PRINT_ERROR("update buffer requirements"); 8838 return OMX_ErrorHardware; 8839 } 8840 portDefn->nBufferSize = buf_size; 8841 portDefn->eDir = OMX_DirOutput; 8842 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; 8843 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; 8844 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 8845 portDefn->bEnabled = m_out_bEnabled; 8846 portDefn->bPopulated = m_out_bPopulated; 8847 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) { 8848 DEBUG_PRINT_ERROR("Error in getting color format"); 8849 return OMX_ErrorHardware; 8850 } 8851 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 8852 fmt.fmt.pix_mp.pixelformat = capture_capability; 8853 } else { 8854 portDefn->eDir = OMX_DirMax; 8855 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", 8856 (int)portDefn->nPortIndex); 8857 eRet = OMX_ErrorBadPortIndex; 8858 } 8859 if (is_down_scalar_enabled) { 8860 int ret = 0; 8861 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); 8862 if (ret) { 8863 DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution"); 8864 return OMX_ErrorHardware; 8865 } else { 8866 portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width; 8867 portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height; 8868 portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; 8869 portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0]; 8870 } 8871 } else { 8872 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; 8873 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; 8874 portDefn->format.video.nStride = drv_ctx.video_resolution.stride; 8875 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; 8876 } 8877 8878 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) || 8879 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) { 8880 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16); 8881 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height; 8882 } 8883 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d " 8884 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u", 8885 (unsigned int)portDefn->nPortIndex, 8886 (unsigned int)portDefn->format.video.nFrameWidth, 8887 (unsigned int)portDefn->format.video.nFrameHeight, 8888 (int)portDefn->format.video.nStride, 8889 (unsigned int)portDefn->format.video.nSliceHeight, 8890 (unsigned int)portDefn->format.video.eColorFormat, 8891 (unsigned int)portDefn->nBufferSize, 8892 (unsigned int)portDefn->nBufferCountActual); 8893 8894 return eRet; 8895} 8896 8897OMX_ERRORTYPE omx_vdec::allocate_output_headers() 8898{ 8899 OMX_ERRORTYPE eRet = OMX_ErrorNone; 8900 OMX_BUFFERHEADERTYPE *bufHdr = NULL; 8901 unsigned i= 0; 8902 8903 if (!m_out_mem_ptr) { 8904 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation"); 8905 int nBufHdrSize = 0; 8906 int nPlatformEntrySize = 0; 8907 int nPlatformListSize = 0; 8908 int nPMEMInfoSize = 0; 8909 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; 8910 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; 8911 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; 8912 8913 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)", 8914 drv_ctx.op_buf.actualcount); 8915 nBufHdrSize = drv_ctx.op_buf.actualcount * 8916 sizeof(OMX_BUFFERHEADERTYPE); 8917 8918 nPMEMInfoSize = drv_ctx.op_buf.actualcount * 8919 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); 8920 nPlatformListSize = drv_ctx.op_buf.actualcount * 8921 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); 8922 nPlatformEntrySize = drv_ctx.op_buf.actualcount * 8923 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); 8924 8925 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, 8926 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), 8927 nPMEMInfoSize, 8928 nPlatformListSize); 8929 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize, 8930 m_out_bm_count); 8931 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); 8932 // Alloc mem for platform specific info 8933 char *pPtr=NULL; 8934 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + 8935 nPMEMInfoSize,1); 8936 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ 8937 calloc (sizeof(struct vdec_bufferpayload), 8938 drv_ctx.op_buf.actualcount); 8939 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ 8940 calloc (sizeof (struct vdec_output_frameinfo), 8941 drv_ctx.op_buf.actualcount); 8942 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { 8943 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer"); 8944 return OMX_ErrorInsufficientResources; 8945 } 8946 8947#ifdef USE_ION 8948 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ 8949 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); 8950 if (!drv_ctx.op_buf_ion_info) { 8951 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); 8952 return OMX_ErrorInsufficientResources; 8953 } 8954#endif 8955 if (dynamic_buf_mode) { 8956 out_dynamic_list = (struct dynamic_buf_list *) \ 8957 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount); 8958 } 8959 8960 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer 8961 && drv_ctx.ptr_respbuffer) { 8962 bufHdr = m_out_mem_ptr; 8963 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); 8964 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) 8965 (((char *) m_platform_list) + nPlatformListSize); 8966 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 8967 (((char *) m_platform_entry) + nPlatformEntrySize); 8968 pPlatformList = m_platform_list; 8969 pPlatformEntry = m_platform_entry; 8970 pPMEMInfo = m_pmem_info; 8971 8972 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); 8973 8974 // Settting the entire storage nicely 8975 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, 8976 m_out_mem_ptr,pPlatformEntry); 8977 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo); 8978 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) { 8979 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 8980 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; 8981 // Set the values when we determine the right HxW param 8982 bufHdr->nAllocLen = 0; 8983 bufHdr->nFilledLen = 0; 8984 bufHdr->pAppPrivate = NULL; 8985 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 8986 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 8987 pPlatformEntry->entry = pPMEMInfo; 8988 // Initialize the Platform List 8989 pPlatformList->nEntries = 1; 8990 pPlatformList->entryList = pPlatformEntry; 8991 // Keep pBuffer NULL till vdec is opened 8992 bufHdr->pBuffer = NULL; 8993 pPMEMInfo->offset = 0; 8994 pPMEMInfo->pmem_fd = 0; 8995 bufHdr->pPlatformPrivate = pPlatformList; 8996 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; 8997#ifdef USE_ION 8998 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; 8999#endif 9000 /*Create a mapping between buffers*/ 9001 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; 9002 drv_ctx.ptr_respbuffer[i].client_data = (void *) \ 9003 &drv_ctx.ptr_outputbuffer[i]; 9004 // Move the buffer and buffer header pointers 9005 bufHdr++; 9006 pPMEMInfo++; 9007 pPlatformEntry++; 9008 pPlatformList++; 9009 } 9010 } else { 9011 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\ 9012 m_out_mem_ptr, pPtr); 9013 if (m_out_mem_ptr) { 9014 free(m_out_mem_ptr); 9015 m_out_mem_ptr = NULL; 9016 } 9017 if (pPtr) { 9018 free(pPtr); 9019 pPtr = NULL; 9020 } 9021 if (drv_ctx.ptr_outputbuffer) { 9022 free(drv_ctx.ptr_outputbuffer); 9023 drv_ctx.ptr_outputbuffer = NULL; 9024 } 9025 if (drv_ctx.ptr_respbuffer) { 9026 free(drv_ctx.ptr_respbuffer); 9027 drv_ctx.ptr_respbuffer = NULL; 9028 } 9029#ifdef USE_ION 9030 if (drv_ctx.op_buf_ion_info) { 9031 DEBUG_PRINT_LOW("Free o/p ion context"); 9032 free(drv_ctx.op_buf_ion_info); 9033 drv_ctx.op_buf_ion_info = NULL; 9034 } 9035#endif 9036 eRet = OMX_ErrorInsufficientResources; 9037 } 9038 } else { 9039 eRet = OMX_ErrorInsufficientResources; 9040 } 9041 return eRet; 9042} 9043 9044void omx_vdec::complete_pending_buffer_done_cbs() 9045{ 9046 unsigned long p1, p2, ident; 9047 omx_cmd_queue tmp_q, pending_bd_q; 9048 pthread_mutex_lock(&m_lock); 9049 // pop all pending GENERATE FDB from ftb queue 9050 while (m_ftb_q.m_size) { 9051 m_ftb_q.pop_entry(&p1,&p2,&ident); 9052 if (ident == OMX_COMPONENT_GENERATE_FBD) { 9053 pending_bd_q.insert_entry(p1,p2,ident); 9054 } else { 9055 tmp_q.insert_entry(p1,p2,ident); 9056 } 9057 } 9058 //return all non GENERATE FDB to ftb queue 9059 while (tmp_q.m_size) { 9060 tmp_q.pop_entry(&p1,&p2,&ident); 9061 m_ftb_q.insert_entry(p1,p2,ident); 9062 } 9063 // pop all pending GENERATE EDB from etb queue 9064 while (m_etb_q.m_size) { 9065 m_etb_q.pop_entry(&p1,&p2,&ident); 9066 if (ident == OMX_COMPONENT_GENERATE_EBD) { 9067 pending_bd_q.insert_entry(p1,p2,ident); 9068 } else { 9069 tmp_q.insert_entry(p1,p2,ident); 9070 } 9071 } 9072 //return all non GENERATE FDB to etb queue 9073 while (tmp_q.m_size) { 9074 tmp_q.pop_entry(&p1,&p2,&ident); 9075 m_etb_q.insert_entry(p1,p2,ident); 9076 } 9077 pthread_mutex_unlock(&m_lock); 9078 // process all pending buffer dones 9079 while (pending_bd_q.m_size) { 9080 pending_bd_q.pop_entry(&p1,&p2,&ident); 9081 switch (ident) { 9082 case OMX_COMPONENT_GENERATE_EBD: 9083 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) { 9084 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!"); 9085 omx_report_error (); 9086 } 9087 break; 9088 9089 case OMX_COMPONENT_GENERATE_FBD: 9090 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) { 9091 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!"); 9092 omx_report_error (); 9093 } 9094 break; 9095 } 9096 } 9097} 9098 9099void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) 9100{ 9101 OMX_U32 new_frame_interval = 0; 9102 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts 9103 && llabs(act_timestamp - prev_ts) > 2000) { 9104 new_frame_interval = client_set_fps ? frm_int : 9105 llabs(act_timestamp - prev_ts); 9106 if (new_frame_interval != frm_int || frm_int == 0) { 9107 frm_int = new_frame_interval; 9108 if (frm_int) { 9109 drv_ctx.frame_rate.fps_numerator = 1e6; 9110 drv_ctx.frame_rate.fps_denominator = frm_int; 9111 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", 9112 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / 9113 (float)drv_ctx.frame_rate.fps_denominator); 9114 //m_perf_control.request_cores(frm_int); 9115 /* We need to report the difference between this FBD and the previous FBD 9116 * back to the driver for clock scaling purposes. */ 9117 struct v4l2_outputparm oparm; 9118 /*XXX: we're providing timing info as seconds per frame rather than frames 9119 * per second.*/ 9120 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator; 9121 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator; 9122 9123 struct v4l2_streamparm sparm; 9124 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 9125 sparm.parm.output = oparm; 9126 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) { 9127 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \ 9128 performance might be affected"); 9129 } 9130 9131 } 9132 } 9133 } 9134 prev_ts = act_timestamp; 9135} 9136 9137void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) 9138{ 9139 if (rst_prev_ts && VALID_TS(act_timestamp)) { 9140 prev_ts = act_timestamp; 9141 rst_prev_ts = false; 9142 } else if (VALID_TS(prev_ts)) { 9143 bool codec_cond = (drv_ctx.timestamp_adjust)? 9144 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts || llabs(act_timestamp - prev_ts) <= 2000) : 9145 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts); 9146 if (frm_int > 0 && codec_cond) { 9147 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); 9148 act_timestamp = prev_ts + frm_int; 9149 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); 9150 prev_ts = act_timestamp; 9151 } else { 9152 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) { 9153 // ensure that timestamps can never step backwards when in display order 9154 act_timestamp = prev_ts; 9155 } 9156 set_frame_rate(act_timestamp); 9157 } 9158 } else if (frm_int > 0) // In this case the frame rate was set along 9159 { // with the port definition, start ts with 0 9160 act_timestamp = prev_ts = 0; // and correct if a valid ts is received. 9161 rst_prev_ts = true; 9162 } 9163} 9164 9165void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) 9166{ 9167 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; 9168 OMX_U32 num_conceal_MB = 0; 9169 OMX_TICKS time_stamp = 0; 9170 OMX_U32 frame_rate = 0; 9171 unsigned long consumed_len = 0; 9172 OMX_U32 num_MB_in_frame; 9173 OMX_U32 recovery_sei_flags = 1; 9174 int enable = 0; 9175 9176 int buf_index = p_buf_hdr - m_out_mem_ptr; 9177 if (buf_index >= drv_ctx.extradata_info.count) { 9178 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", 9179 buf_index, drv_ctx.extradata_info.count); 9180 return; 9181 } 9182 struct msm_vidc_panscan_window_payload *panscan_payload = NULL; 9183 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) + 9184 p_buf_hdr->nOffset; 9185 9186 if (!drv_ctx.extradata_info.uaddr) { 9187 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr"); 9188 return; 9189 } 9190 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) { 9191 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data"); 9192 p_extra = NULL; 9193 return; 9194 } 9195 if (!secure_mode) 9196 p_extra = (OMX_OTHER_EXTRADATATYPE *) 9197 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3)); 9198 else 9199 p_extra = m_other_extradata; 9200 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size; 9201 9202 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { 9203 p_extra = NULL; 9204 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); 9205 return; 9206 } 9207 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; 9208 if (data && p_extra) { 9209 while ((consumed_len < drv_ctx.extradata_info.buffer_size) 9210 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) { 9211 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) { 9212 DEBUG_PRINT_LOW("Invalid extra data size"); 9213 break; 9214 } 9215 DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType); 9216 switch ((unsigned long)data->eType) { 9217 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO: 9218 struct msm_vidc_interlace_payload *payload; 9219 payload = (struct msm_vidc_interlace_payload *)(void *)data->data; 9220 if (payload) { 9221 enable = 1; 9222 switch (payload->format) { 9223 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE: 9224 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 9225 enable = 0; 9226 break; 9227 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST: 9228 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 9229 break; 9230 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST: 9231 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst; 9232 break; 9233 default: 9234 DEBUG_PRINT_LOW("default case - set interlace to topfield"); 9235 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 9236 } 9237 } 9238 9239 if (m_enable_android_native_buffers) { 9240 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d mbaff:%d", 9241 payload->format, enable, 9242 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false); 9243 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 9244 PP_PARAM_INTERLACED, (void*)&enable); 9245 } 9246 if (client_extradata & OMX_INTERLACE_EXTRADATA) { 9247 append_interlace_extradata(p_extra, payload->format, 9248 p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF); 9249 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9250 } 9251 break; 9252 case MSM_VIDC_EXTRADATA_FRAME_RATE: 9253 struct msm_vidc_framerate_payload *frame_rate_payload; 9254 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data; 9255 frame_rate = frame_rate_payload->frame_rate; 9256 break; 9257 case MSM_VIDC_EXTRADATA_TIMESTAMP: 9258 struct msm_vidc_ts_payload *time_stamp_payload; 9259 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data; 9260 time_stamp = time_stamp_payload->timestamp_lo; 9261 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32); 9262 p_buf_hdr->nTimeStamp = time_stamp; 9263 break; 9264 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB: 9265 struct msm_vidc_concealmb_payload *conceal_mb_payload; 9266 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data; 9267 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 9268 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 9269 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0); 9270 break; 9271 case MSM_VIDC_EXTRADATA_INDEX: 9272 int *etype; 9273 etype = (int *)(void *)data->data; 9274 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) { 9275 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload; 9276 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype); 9277 if (aspect_ratio_payload) { 9278 ((struct vdec_output_frameinfo *) 9279 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width; 9280 ((struct vdec_output_frameinfo *) 9281 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height; 9282 } 9283 } 9284 break; 9285 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI: 9286 struct msm_vidc_recoverysei_payload *recovery_sei_payload; 9287 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data; 9288 recovery_sei_flags = recovery_sei_payload->flags; 9289 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) { 9290 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 9291 DEBUG_PRINT_HIGH("***************************************************"); 9292 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received"); 9293 DEBUG_PRINT_HIGH("***************************************************"); 9294 } 9295 break; 9296 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW: 9297 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data; 9298 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) { 9299 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n"); 9300 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n", 9301 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows); 9302 return; 9303 } 9304 break; 9305 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP: 9306 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload; 9307 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)(void *)data->data; 9308 if (seqdisp_payload) { 9309 m_disp_hor_size = seqdisp_payload->disp_width; 9310 m_disp_vert_size = seqdisp_payload->disp_height; 9311 if (client_extradata & OMX_MPEG2SEQDISP_EXTRADATA) { 9312 append_mpeg2_seqdisplay_extradata(p_extra, seqdisp_payload); 9313 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9314 } 9315 } 9316 break; 9317 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING: 9318 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload; 9319 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data; 9320 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) { 9321 append_framepack_extradata(p_extra, s3d_frame_packing_payload); 9322 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9323 } 9324 break; 9325 case MSM_VIDC_EXTRADATA_FRAME_QP: 9326 struct msm_vidc_frame_qp_payload *qp_payload; 9327 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data; 9328 if (client_extradata & OMX_QP_EXTRADATA) { 9329 append_qp_extradata(p_extra, qp_payload); 9330 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9331 } 9332 break; 9333 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO: 9334 struct msm_vidc_frame_bits_info_payload *bits_info_payload; 9335 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data; 9336 if (client_extradata & OMX_BITSINFO_EXTRADATA) { 9337 append_bitsinfo_extradata(p_extra, bits_info_payload); 9338 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9339 } 9340 break; 9341 case MSM_VIDC_EXTRADATA_STREAM_USERDATA: 9342 if (client_extradata & OMX_EXTNUSER_EXTRADATA) { 9343 append_user_extradata(p_extra, data); 9344 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9345 } 9346 break; 9347 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO: 9348 struct msm_vidc_vui_display_info_payload *display_info_payload; 9349 display_info_payload = (struct msm_vidc_vui_display_info_payload*)(void *)data->data; 9350 9351 if (client_extradata & OMX_VUI_DISPLAY_INFO_EXTRADATA) { 9352 /* This extradata usually isn't needed by clients. Leave it unimplemented for now */ 9353 DEBUG_PRINT_ERROR("VUI display info not propagated to client"); 9354 } 9355 9356 if (m_enable_android_native_buffers 9357 && display_info_payload->video_signal_present_flag 9358 && display_info_payload->color_description_present_flag) { 9359 ColorSpace_t color_space = ITU_R_601; 9360 9361 switch (display_info_payload->color_primaries) { 9362 case 1: 9363 color_space = ITU_R_709; 9364 break; 9365 case 5: 9366 color_space = display_info_payload->video_full_range_flag ? 9367 ITU_R_601_FR : ITU_R_601; 9368 break; 9369 } 9370 9371 DEBUG_PRINT_LOW("colorspace from VUI = %d", color_space); 9372 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle, 9373 UPDATE_COLOR_SPACE, (void*)&color_space); 9374 } 9375 break; 9376 default: 9377 DEBUG_PRINT_LOW("Unrecognized extradata"); 9378 goto unrecognized_extradata; 9379 } 9380 consumed_len += data->nSize; 9381 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); 9382 } 9383 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) { 9384 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 9385 append_frame_info_extradata(p_extra, 9386 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate, 9387 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *) 9388 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info); 9389 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9390 } 9391 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) { 9392 append_frame_dimension_extradata(p_extra); 9393 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); 9394 } 9395 } 9396unrecognized_extradata: 9397 if (client_extradata && p_extra) { 9398 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 9399 append_terminator_extradata(p_extra); 9400 } 9401 if (secure_mode && p_extradata && m_other_extradata) { 9402 struct vdec_output_frameinfo *ptr_extradatabuff = NULL; 9403 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size); 9404 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate; 9405 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata; 9406 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size; 9407 } 9408 return; 9409} 9410 9411OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, 9412 bool is_internal, bool enable) 9413{ 9414 OMX_ERRORTYPE ret = OMX_ErrorNone; 9415 struct v4l2_control control; 9416 if (m_state != OMX_StateLoaded) { 9417 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); 9418 return OMX_ErrorIncorrectStateOperation; 9419 } 9420 9421 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d", 9422 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal); 9423 9424 if (!is_internal) { 9425 if (enable) 9426 client_extradata |= requested_extradata; 9427 else 9428 client_extradata = client_extradata & ~requested_extradata; 9429 } 9430 9431 if (enable) { 9432 if (requested_extradata & OMX_INTERLACE_EXTRADATA) { 9433 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9434 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO; 9435 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9436 DEBUG_PRINT_HIGH("Failed to set interlaced extradata." 9437 " Quality of interlaced clips might be impacted."); 9438 } 9439 } 9440 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) { 9441 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9442 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE; 9443 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9444 DEBUG_PRINT_HIGH("Failed to set framerate extradata"); 9445 } 9446 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9447 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB; 9448 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9449 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata"); 9450 } 9451 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9452 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI; 9453 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9454 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata"); 9455 } 9456 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9457 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW; 9458 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9459 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 9460 } 9461 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9462 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO; 9463 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9464 DEBUG_PRINT_HIGH("Failed to set panscan extradata"); 9465 } 9466 } 9467 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) { 9468 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9469 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP; 9470 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9471 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata"); 9472 } 9473 } 9474 if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) { 9475 if (output_capability == V4L2_PIX_FMT_H264) { 9476 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA"); 9477 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9478 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING; 9479 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9480 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata"); 9481 } 9482 } else { 9483 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only"); 9484 } 9485 } 9486 if (requested_extradata & OMX_QP_EXTRADATA) { 9487 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9488 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP; 9489 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9490 DEBUG_PRINT_HIGH("Failed to set QP extradata"); 9491 } 9492 } 9493 if (requested_extradata & OMX_BITSINFO_EXTRADATA) { 9494 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9495 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO; 9496 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9497 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata"); 9498 } 9499 } 9500 if (requested_extradata & OMX_EXTNUSER_EXTRADATA) { 9501 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9502 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA; 9503 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9504 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata"); 9505 } 9506 } 9507 if (requested_extradata & OMX_MPEG2SEQDISP_EXTRADATA) { 9508 if (output_capability == V4L2_PIX_FMT_MPEG2) { 9509 DEBUG_PRINT_HIGH("Enable seq display extradata"); 9510 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9511 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; 9512 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9513 DEBUG_PRINT_HIGH("Failed to set seqdisp extradata"); 9514 } 9515 } else { 9516 DEBUG_PRINT_HIGH("Seq display extradata is supported for MPEG2 only"); 9517 } 9518 } 9519 if (requested_extradata & OMX_VUI_DISPLAY_INFO_EXTRADATA) { 9520 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; 9521 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY; 9522 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { 9523 DEBUG_PRINT_HIGH("Failed to set display VUI extradata"); 9524 } 9525 } 9526 } 9527 ret = get_buffer_req(&drv_ctx.op_buf); 9528 return ret; 9529} 9530 9531OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9532{ 9533 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; 9534 OMX_U8 *data_ptr = extra->data, data = 0; 9535 while (byte_count < extra->nDataSize) { 9536 data = *data_ptr; 9537 while (data) { 9538 num_MB += (data&0x01); 9539 data >>= 1; 9540 } 9541 data_ptr++; 9542 byte_count++; 9543 } 9544 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * 9545 (drv_ctx.video_resolution.frame_height + 15)) >> 8; 9546 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); 9547} 9548 9549void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9550{ 9551 if (!m_debug_extradata || !extra) 9552 return; 9553 9554 9555 DEBUG_PRINT_HIGH( 9556 "============== Extra Data ==============\n" 9557 " Size: %u\n" 9558 " Version: %u\n" 9559 " PortIndex: %u\n" 9560 " Type: %x\n" 9561 " DataSize: %u", 9562 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion, 9563 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize); 9564 9565 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) { 9566 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 9567 DEBUG_PRINT_HIGH( 9568 "------ Interlace Format ------\n" 9569 " Size: %u\n" 9570 " Version: %u\n" 9571 " PortIndex: %u\n" 9572 " Is Interlace Format: %d\n" 9573 " Interlace Formats: %u\n" 9574 "=========== End of Interlace ===========", 9575 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex, 9576 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats); 9577 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) { 9578 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 9579 9580 DEBUG_PRINT_HIGH( 9581 "-------- Frame Format --------\n" 9582 " Picture Type: %d\n" 9583 " Interlace Type: %d\n" 9584 " Pan Scan Total Frame Num: %u\n" 9585 " Concealed Macro Blocks: %u\n" 9586 " frame rate: %u\n" 9587 " Time Stamp: %llu\n" 9588 " Aspect Ratio X: %u\n" 9589 " Aspect Ratio Y: %u", 9590 fminfo->ePicType, 9591 fminfo->interlaceType, 9592 (unsigned int)fminfo->panScan.numWindows, 9593 (unsigned int)fminfo->nConcealedMacroblocks, 9594 (unsigned int)fminfo->nFrameRate, 9595 fminfo->nTimeStamp, 9596 (unsigned int)fminfo->aspectRatio.aspectRatioX, 9597 (unsigned int)fminfo->aspectRatio.aspectRatioY); 9598 9599 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) { 9600 DEBUG_PRINT_HIGH( 9601 "------------------------------" 9602 " Pan Scan Frame Num: %u\n" 9603 " Rectangle x: %d\n" 9604 " Rectangle y: %d\n" 9605 " Rectangle dx: %d\n" 9606 " Rectangle dy: %d", 9607 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y, 9608 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy); 9609 } 9610 9611 DEBUG_PRINT_HIGH("========= End of Frame Format =========="); 9612 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) { 9613 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 9614 DEBUG_PRINT_HIGH( 9615 "------------------ Framepack Format ----------\n" 9616 " id: %u \n" 9617 " cancel_flag: %u \n" 9618 " type: %u \n" 9619 " quincunx_sampling_flagFormat: %u \n" 9620 " content_interpretation_type: %u \n" 9621 " spatial_flipping_flag: %u \n" 9622 " frame0_flipped_flag: %u \n" 9623 " field_views_flag: %u \n" 9624 " current_frame_is_frame0_flag: %u \n" 9625 " frame0_self_contained_flag: %u \n" 9626 " frame1_self_contained_flag: %u \n" 9627 " frame0_grid_position_x: %u \n" 9628 " frame0_grid_position_y: %u \n" 9629 " frame1_grid_position_x: %u \n" 9630 " frame1_grid_position_y: %u \n" 9631 " reserved_byte: %u \n" 9632 " repetition_period: %u \n" 9633 " extension_flag: %u \n" 9634 "================== End of Framepack ===========", 9635 (unsigned int)framepack->id, 9636 (unsigned int)framepack->cancel_flag, 9637 (unsigned int)framepack->type, 9638 (unsigned int)framepack->quincunx_sampling_flag, 9639 (unsigned int)framepack->content_interpretation_type, 9640 (unsigned int)framepack->spatial_flipping_flag, 9641 (unsigned int)framepack->frame0_flipped_flag, 9642 (unsigned int)framepack->field_views_flag, 9643 (unsigned int)framepack->current_frame_is_frame0_flag, 9644 (unsigned int)framepack->frame0_self_contained_flag, 9645 (unsigned int)framepack->frame1_self_contained_flag, 9646 (unsigned int)framepack->frame0_grid_position_x, 9647 (unsigned int)framepack->frame0_grid_position_y, 9648 (unsigned int)framepack->frame1_grid_position_x, 9649 (unsigned int)framepack->frame1_grid_position_y, 9650 (unsigned int)framepack->reserved_byte, 9651 (unsigned int)framepack->repetition_period, 9652 (unsigned int)framepack->extension_flag); 9653 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) { 9654 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 9655 DEBUG_PRINT_HIGH( 9656 "---- QP (Frame quantization parameter) ----\n" 9657 " Frame QP: %u \n" 9658 "================ End of QP ================\n", 9659 (unsigned int)qp->nQP); 9660 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) { 9661 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data; 9662 DEBUG_PRINT_HIGH( 9663 "--------- Input bits information --------\n" 9664 " Header bits: %u \n" 9665 " Frame bits: %u \n" 9666 "===== End of Input bits information =====\n", 9667 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits); 9668 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) { 9669 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data; 9670 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data; 9671 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type); 9672 OMX_U32 i = 0; 9673 DEBUG_PRINT_HIGH( 9674 "-------------- Userdata -------------\n" 9675 " Stream userdata type: %u\n" 9676 " userdata size: %u\n" 9677 " STREAM_USERDATA:", 9678 (unsigned int)userdata->type, (unsigned int)userdata_size); 9679 for (i = 0; i < userdata_size; i+=4) { 9680 DEBUG_PRINT_HIGH(" %x %x %x %x", 9681 data_ptr[i], data_ptr[i+1], 9682 data_ptr[i+2], data_ptr[i+3]); 9683 } 9684 DEBUG_PRINT_HIGH( 9685 "=========== End of Userdata ==========="); 9686 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay) { 9687 OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY*)(void*)extra->data; 9688 DEBUG_PRINT_HIGH( 9689 "------Mpeg2SeqDisplay ------\n" 9690 " Frame Width: %d\n" 9691 " Frame Height: %d\n" 9692 "=========== End of Mpeg2SeqDisplay ===========", 9693 seq_display->disp_width, seq_display->disp_height); 9694 } else if (extra->eType == OMX_ExtraDataNone) { 9695 DEBUG_PRINT_HIGH("========== End of Terminator ==========="); 9696 } else { 9697 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); 9698 } 9699} 9700 9701void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9702 OMX_U32 interlaced_format_type, bool is_mbaff) 9703{ 9704 OMX_STREAMINTERLACEFORMAT *interlace_format; 9705 9706 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) { 9707 return; 9708 } 9709 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; 9710 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9711 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9712 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; 9713 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); 9714 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data; 9715 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); 9716 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; 9717 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9718 9719 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) { 9720 interlace_format->bInterlaceFormat = OMX_FALSE; 9721 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; 9722 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 9723 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) { 9724 interlace_format->bInterlaceFormat = OMX_TRUE; 9725 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 9726 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 9727 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) { 9728 interlace_format->bInterlaceFormat = OMX_TRUE; 9729 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst; 9730 drv_ctx.interlace = VDEC_InterlaceFrameProgressive; 9731 } else { 9732 interlace_format->bInterlaceFormat = OMX_TRUE; 9733 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; 9734 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; 9735 } 9736 print_debug_extradata(extra); 9737} 9738 9739void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9740{ 9741 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension; 9742 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) { 9743 return; 9744 } 9745 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE; 9746 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9747 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9748 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension; 9749 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION); 9750 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data; 9751 frame_dimension->nDecWidth = rectangle.nLeft; 9752 frame_dimension->nDecHeight = rectangle.nTop; 9753 frame_dimension->nActualWidth = rectangle.nWidth; 9754 frame_dimension->nActualHeight = rectangle.nHeight; 9755} 9756 9757void omx_vdec::fill_aspect_ratio_info( 9758 struct vdec_aspectratioinfo *aspect_ratio_info, 9759 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info) 9760{ 9761 m_extradata = frame_info; 9762 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width; 9763 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height; 9764 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX, 9765 (unsigned int)m_extradata->aspectRatio.aspectRatioY); 9766} 9767 9768void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9769 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate, 9770 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload, 9771 struct vdec_aspectratioinfo *aspect_ratio_info) 9772{ 9773 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; 9774 struct msm_vidc_panscan_window *panscan_window; 9775 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) { 9776 return; 9777 } 9778 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; 9779 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9780 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9781 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; 9782 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); 9783 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data; 9784 switch (picture_type) { 9785 case PICTURE_TYPE_I: 9786 frame_info->ePicType = OMX_VIDEO_PictureTypeI; 9787 break; 9788 case PICTURE_TYPE_P: 9789 frame_info->ePicType = OMX_VIDEO_PictureTypeP; 9790 break; 9791 case PICTURE_TYPE_B: 9792 frame_info->ePicType = OMX_VIDEO_PictureTypeB; 9793 break; 9794 default: 9795 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; 9796 } 9797 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) 9798 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 9799 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) 9800 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 9801 else 9802 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; 9803 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); 9804 frame_info->nConcealedMacroblocks = num_conceal_mb; 9805 frame_info->nFrameRate = frame_rate; 9806 frame_info->nTimeStamp = time_stamp; 9807 frame_info->panScan.numWindows = 0; 9808 if (output_capability == V4L2_PIX_FMT_MPEG2) { 9809 if (m_disp_hor_size && m_disp_vert_size) { 9810 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size; 9811 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size; 9812 } else { 9813 frame_info->displayAspectRatio.displayHorizontalSize = 0; 9814 frame_info->displayAspectRatio.displayVerticalSize = 0; 9815 } 9816 } 9817 9818 if (panscan_payload) { 9819 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows; 9820 panscan_window = &panscan_payload->wnd[0]; 9821 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) { 9822 frame_info->panScan.window[i].x = panscan_window->panscan_window_width; 9823 frame_info->panScan.window[i].y = panscan_window->panscan_window_height; 9824 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset; 9825 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset; 9826 panscan_window++; 9827 } 9828 } 9829 fill_aspect_ratio_info(aspect_ratio_info, frame_info); 9830 print_debug_extradata(extra); 9831} 9832 9833void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9834{ 9835 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; 9836 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; 9837 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9838 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9839 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; 9840 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 9841 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data; 9842 *portDefn = m_port_def; 9843 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u " 9844 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight, 9845 (unsigned int)portDefn->format.video.nFrameWidth, 9846 (unsigned int)portDefn->format.video.nStride, 9847 (unsigned int)portDefn->format.video.nSliceHeight); 9848} 9849 9850void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9851 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload) 9852{ 9853 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack; 9854 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) { 9855 DEBUG_PRINT_ERROR("frame packing size mismatch"); 9856 return; 9857 } 9858 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE; 9859 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9860 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9861 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement; 9862 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 9863 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data; 9864 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT); 9865 framepack->nVersion.nVersion = OMX_SPEC_VERSION; 9866 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9867 memcpy(&framepack->id, s3d_frame_packing_payload, 9868 sizeof(struct msm_vidc_s3d_frame_packing_payload)); 9869 memcpy(&m_frame_pack_arrangement, framepack, 9870 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT)); 9871 print_debug_extradata(extra); 9872} 9873 9874void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9875 struct msm_vidc_frame_qp_payload *qp_payload) 9876{ 9877 OMX_QCOM_EXTRADATA_QP * qp = NULL; 9878 if (!qp_payload) { 9879 DEBUG_PRINT_ERROR("QP payload is NULL"); 9880 return; 9881 } 9882 extra->nSize = OMX_QP_EXTRADATA_SIZE; 9883 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9884 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9885 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP; 9886 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP); 9887 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data; 9888 qp->nQP = qp_payload->frame_qp; 9889 print_debug_extradata(extra); 9890} 9891 9892void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9893 struct msm_vidc_frame_bits_info_payload *bits_payload) 9894{ 9895 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL; 9896 if (!bits_payload) { 9897 DEBUG_PRINT_ERROR("bits info payload is NULL"); 9898 return; 9899 } 9900 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE; 9901 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9902 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9903 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo; 9904 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO); 9905 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data; 9906 bits->frame_bits = bits_payload->frame_bits; 9907 bits->header_bits = bits_payload->header_bits; 9908 print_debug_extradata(extra); 9909} 9910 9911void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9912 OMX_OTHER_EXTRADATATYPE *p_user) 9913{ 9914 int userdata_size = 0; 9915 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL; 9916 userdata_payload = 9917 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data; 9918 userdata_size = p_user->nDataSize; 9919 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size; 9920 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9921 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9922 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData; 9923 extra->nDataSize = userdata_size; 9924 if (extra->data && p_user->data && extra->nDataSize) 9925 memcpy(extra->data, p_user->data, extra->nDataSize); 9926 print_debug_extradata(extra); 9927} 9928 9929void omx_vdec::append_mpeg2_seqdisplay_extradata(OMX_OTHER_EXTRADATATYPE *extra, 9930 struct msm_vidc_mpeg2_seqdisp_payload *seq_display_payload) 9931{ 9932 OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = NULL; 9933 extra->nSize = OMX_MPEG2SEQDISP_EXTRADATA_SIZE; 9934 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9935 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 9936 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay; 9937 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY); 9938 seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *)(void *)extra->data; 9939 seq_display->disp_width = seq_display_payload->disp_width; 9940 seq_display->disp_height = seq_display_payload->disp_height; 9941 print_debug_extradata(extra); 9942} 9943void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) 9944{ 9945 if (!client_extradata) { 9946 return; 9947 } 9948 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); 9949 extra->nVersion.nVersion = OMX_SPEC_VERSION; 9950 extra->eType = OMX_ExtraDataNone; 9951 extra->nDataSize = 0; 9952 extra->data[0] = 0; 9953 9954 print_debug_extradata(extra); 9955} 9956 9957OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) 9958{ 9959 OMX_ERRORTYPE eRet = OMX_ErrorNone; 9960 if (index >= drv_ctx.ip_buf.actualcount) { 9961 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found"); 9962 return OMX_ErrorInsufficientResources; 9963 } 9964 if (m_desc_buffer_ptr == NULL) { 9965 m_desc_buffer_ptr = (desc_buffer_hdr*) \ 9966 calloc( (sizeof(desc_buffer_hdr)), 9967 drv_ctx.ip_buf.actualcount); 9968 if (m_desc_buffer_ptr == NULL) { 9969 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed "); 9970 return OMX_ErrorInsufficientResources; 9971 } 9972 } 9973 9974 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); 9975 if (m_desc_buffer_ptr[index].buf_addr == NULL) { 9976 DEBUG_PRINT_ERROR("desc buffer Allocation failed "); 9977 return OMX_ErrorInsufficientResources; 9978 } 9979 9980 return eRet; 9981} 9982 9983void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) 9984{ 9985 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries); 9986 if (m_demux_entries < 8192) { 9987 m_demux_offsets[m_demux_entries++] = address_offset; 9988 } 9989 return; 9990} 9991 9992void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) 9993{ 9994 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; 9995 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; 9996 OMX_U32 index = 0; 9997 9998 m_demux_entries = 0; 9999 10000 while (index < bytes_to_parse) { 10001 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 10002 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || 10003 ((buf[index] == 0x00) && (buf[index+1] == 0x00) && 10004 (buf[index+2] == 0x01)) ) { 10005 //Found start code, insert address offset 10006 insert_demux_addr_offset(index); 10007 if (buf[index+2] == 0x01) // 3 byte start code 10008 index += 3; 10009 else //4 byte start code 10010 index += 4; 10011 } else 10012 index++; 10013 } 10014 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries); 10015 return; 10016} 10017 10018OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) 10019{ 10020 //fix this, handle 3 byte start code, vc1 terminator entry 10021 OMX_U8 *p_demux_data = NULL; 10022 OMX_U32 desc_data = 0; 10023 OMX_U32 start_addr = 0; 10024 OMX_U32 nal_size = 0; 10025 OMX_U32 suffix_byte = 0; 10026 OMX_U32 demux_index = 0; 10027 OMX_U32 buffer_index = 0; 10028 10029 if (m_desc_buffer_ptr == NULL) { 10030 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); 10031 return OMX_ErrorBadParameter; 10032 } 10033 10034 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); 10035 if (buffer_index > drv_ctx.ip_buf.actualcount) { 10036 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index); 10037 return OMX_ErrorBadParameter; 10038 } 10039 10040 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; 10041 10042 if ( ((OMX_U8*)p_demux_data == NULL) || 10043 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) { 10044 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); 10045 return OMX_ErrorBadParameter; 10046 } else { 10047 for (; demux_index < m_demux_entries; demux_index++) { 10048 desc_data = 0; 10049 start_addr = m_demux_offsets[demux_index]; 10050 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) { 10051 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; 10052 } else { 10053 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; 10054 } 10055 if (demux_index < (m_demux_entries - 1)) { 10056 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; 10057 } else { 10058 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; 10059 } 10060 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)", 10061 (unsigned int)start_addr, 10062 (unsigned int)suffix_byte, 10063 (unsigned int)nal_size, 10064 (unsigned int)demux_index); 10065 desc_data = (start_addr >> 3) << 1; 10066 desc_data |= (start_addr & 7) << 21; 10067 desc_data |= suffix_byte << 24; 10068 10069 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 10070 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); 10071 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 10072 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 10073 10074 p_demux_data += 16; 10075 } 10076 if (codec_type_parse == CODEC_TYPE_VC1) { 10077 DEBUG_PRINT_LOW("VC1 terminator entry"); 10078 desc_data = 0; 10079 desc_data = 0x82 << 24; 10080 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); 10081 memset(p_demux_data + 4, 0, sizeof(OMX_U32)); 10082 memset(p_demux_data + 8, 0, sizeof(OMX_U32)); 10083 memset(p_demux_data + 12, 0, sizeof(OMX_U32)); 10084 p_demux_data += 16; 10085 m_demux_entries++; 10086 } 10087 //Add zero word to indicate end of descriptors 10088 memset(p_demux_data, 0, sizeof(OMX_U32)); 10089 10090 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); 10091 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size); 10092 } 10093 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); 10094 m_demux_entries = 0; 10095 DEBUG_PRINT_LOW("Demux table complete!"); 10096 return OMX_ErrorNone; 10097} 10098 10099OMX_ERRORTYPE omx_vdec::createDivxDrmContext() 10100{ 10101 OMX_ERRORTYPE err = OMX_ErrorNone; 10102 iDivXDrmDecrypt = DivXDrmDecrypt::Create(); 10103 if (iDivXDrmDecrypt) { 10104 OMX_ERRORTYPE err = iDivXDrmDecrypt->Init(); 10105 if (err!=OMX_ErrorNone) { 10106 DEBUG_PRINT_ERROR("ERROR :iDivXDrmDecrypt->Init %d", err); 10107 delete iDivXDrmDecrypt; 10108 iDivXDrmDecrypt = NULL; 10109 } 10110 } else { 10111 DEBUG_PRINT_ERROR("Unable to Create DIVX DRM"); 10112 err = OMX_ErrorUndefined; 10113 } 10114 return err; 10115} 10116 10117omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf() 10118{ 10119 enabled = false; 10120 omx = NULL; 10121 init_members(); 10122 ColorFormat = OMX_COLOR_FormatMax; 10123 dest_format = YCbCr420P; 10124} 10125 10126void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client) 10127{ 10128 omx = reinterpret_cast<omx_vdec*>(client); 10129} 10130 10131void omx_vdec::allocate_color_convert_buf::init_members() 10132{ 10133 allocated_count = 0; 10134 buffer_size_req = 0; 10135 buffer_alignment_req = 0; 10136 memset(m_platform_list_client,0,sizeof(m_platform_list_client)); 10137 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client)); 10138 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client)); 10139 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client)); 10140#ifdef USE_ION 10141 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client)); 10142#endif 10143 for (int i = 0; i < MAX_COUNT; i++) 10144 pmem_fd[i] = -1; 10145} 10146 10147omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf() 10148{ 10149 c2d.destroy(); 10150} 10151 10152bool omx_vdec::allocate_color_convert_buf::update_buffer_req() 10153{ 10154 bool status = true; 10155 unsigned int src_size = 0, destination_size = 0; 10156 OMX_COLOR_FORMATTYPE drv_color_format; 10157 if (!omx) { 10158 DEBUG_PRINT_ERROR("Invalid client in color convert"); 10159 return false; 10160 } 10161 if (!enabled) { 10162 DEBUG_PRINT_HIGH("No color conversion required"); 10163 return status; 10164 } 10165 pthread_mutex_lock(&omx->c_lock); 10166 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 && 10167 ColorFormat != OMX_COLOR_FormatYUV420Planar) { 10168 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion"); 10169 status = false; 10170 goto fail_update_buf_req; 10171 } 10172 c2d.close(); 10173 status = c2d.open(omx->drv_ctx.video_resolution.frame_height, 10174 omx->drv_ctx.video_resolution.frame_width, 10175 NV12_128m,dest_format); 10176 if (status) { 10177 status = c2d.get_buffer_size(C2D_INPUT,src_size); 10178 if (status) 10179 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size); 10180 } 10181 if (status) { 10182 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size || 10183 !destination_size) { 10184 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d" 10185 "driver size %u destination size %d", 10186 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size, 10187 destination_size); 10188 status = false; 10189 c2d.close(); 10190 buffer_size_req = 0; 10191 } else { 10192 buffer_size_req = destination_size; 10193 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size) 10194 buffer_size_req = omx->drv_ctx.op_buf.buffer_size; 10195 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 10196 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 10197 } 10198 } 10199fail_update_buf_req: 10200 pthread_mutex_unlock(&omx->c_lock); 10201 return status; 10202} 10203 10204bool omx_vdec::allocate_color_convert_buf::set_color_format( 10205 OMX_COLOR_FORMATTYPE dest_color_format) 10206{ 10207 bool status = true; 10208 OMX_COLOR_FORMATTYPE drv_color_format; 10209 if (!omx) { 10210 DEBUG_PRINT_ERROR("Invalid client in color convert"); 10211 return false; 10212 } 10213 pthread_mutex_lock(&omx->c_lock); 10214 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 10215 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 10216 drv_color_format = (OMX_COLOR_FORMATTYPE) 10217 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 10218 else 10219 drv_color_format = (OMX_COLOR_FORMATTYPE) 10220 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 10221 else { 10222 DEBUG_PRINT_ERROR("Incorrect color format"); 10223 status = false; 10224 } 10225 if (status && !omx->is_component_secure() && 10226 drv_color_format != dest_color_format && 10227 drv_color_format != (OMX_COLOR_FORMATTYPE) 10228 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) { 10229 DEBUG_PRINT_LOW("Enabling C2D"); 10230 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) && 10231 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) { 10232 DEBUG_PRINT_ERROR("Unsupported color format for c2d"); 10233 status = false; 10234 } else { 10235 ColorFormat = dest_color_format; 10236 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ? 10237 YCbCr420P : YCbCr420SP; 10238 if (enabled) 10239 c2d.destroy(); 10240 enabled = false; 10241 if (!c2d.init()) { 10242 DEBUG_PRINT_ERROR("open failed for c2d"); 10243 status = false; 10244 } else 10245 enabled = true; 10246 } 10247 } else { 10248 if (enabled) 10249 c2d.destroy(); 10250 enabled = false; 10251 } 10252 pthread_mutex_unlock(&omx->c_lock); 10253 return status; 10254} 10255 10256OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() 10257{ 10258 if (!omx) { 10259 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 10260 return NULL; 10261 } 10262 if (!enabled) 10263 return omx->m_out_mem_ptr; 10264 return m_out_mem_ptr_client; 10265} 10266 10267 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr 10268(OMX_BUFFERHEADERTYPE *bufadd) 10269{ 10270 if (!omx) { 10271 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 10272 return NULL; 10273 } 10274 if (!enabled) 10275 return bufadd; 10276 10277 unsigned index = 0; 10278 index = bufadd - omx->m_out_mem_ptr; 10279 if (index < omx->drv_ctx.op_buf.actualcount) { 10280 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS); 10281 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp; 10282 bool status; 10283 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) { 10284 pthread_mutex_lock(&omx->c_lock); 10285 cache_clean_buffer(index); 10286 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd, 10287 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index], 10288 pmem_baseaddress[index], pmem_baseaddress[index]); 10289 if (!status) { 10290 DEBUG_PRINT_ERROR("Failed color conversion %d", status); 10291 m_out_mem_ptr_client[index].nFilledLen = 0; 10292 pthread_mutex_unlock(&omx->c_lock); 10293 return &m_out_mem_ptr_client[index]; 10294 } else { 10295 unsigned int filledLen = 0; 10296 c2d.get_output_filled_length(filledLen); 10297 m_out_mem_ptr_client[index].nFilledLen = filledLen; 10298 cache_clean_invalidate_buffer(index); 10299 } 10300 pthread_mutex_unlock(&omx->c_lock); 10301 } else 10302 m_out_mem_ptr_client[index].nFilledLen = 0; 10303 return &m_out_mem_ptr_client[index]; 10304 } 10305 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr"); 10306 return NULL; 10307} 10308 10309 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr 10310(OMX_BUFFERHEADERTYPE *bufadd) 10311{ 10312 if (!omx) { 10313 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr"); 10314 return NULL; 10315 } 10316 if (!enabled) 10317 return bufadd; 10318 unsigned index = 0; 10319 index = bufadd - m_out_mem_ptr_client; 10320 if (index < omx->drv_ctx.op_buf.actualcount) { 10321 return &omx->m_out_mem_ptr[index]; 10322 } 10323 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr"); 10324 return NULL; 10325} 10326 bool omx_vdec::allocate_color_convert_buf::get_buffer_req 10327(unsigned int &buffer_size) 10328{ 10329 bool status = true; 10330 pthread_mutex_lock(&omx->c_lock); 10331 if (!enabled) 10332 buffer_size = omx->drv_ctx.op_buf.buffer_size; 10333 else { 10334 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) { 10335 DEBUG_PRINT_ERROR("Get buffer size failed"); 10336 status = false; 10337 goto fail_get_buffer_size; 10338 } 10339 } 10340 if (buffer_size < omx->drv_ctx.op_buf.buffer_size) 10341 buffer_size = omx->drv_ctx.op_buf.buffer_size; 10342 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment) 10343 buffer_alignment_req = omx->drv_ctx.op_buf.alignment; 10344fail_get_buffer_size: 10345 pthread_mutex_unlock(&omx->c_lock); 10346 return status; 10347} 10348OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer( 10349 OMX_BUFFERHEADERTYPE *bufhdr) 10350{ 10351 unsigned int index = 0; 10352 10353 if (!enabled) 10354 return omx->free_output_buffer(bufhdr); 10355 if (enabled && omx->is_component_secure()) 10356 return OMX_ErrorNone; 10357 if (!allocated_count || !bufhdr) { 10358 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr); 10359 return OMX_ErrorBadParameter; 10360 } 10361 index = bufhdr - m_out_mem_ptr_client; 10362 if (index >= omx->drv_ctx.op_buf.actualcount) { 10363 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer"); 10364 return OMX_ErrorBadParameter; 10365 } 10366 if (pmem_fd[index] > 0) { 10367 munmap(pmem_baseaddress[index], buffer_size_req); 10368 close(pmem_fd[index]); 10369 } 10370 pmem_fd[index] = -1; 10371#ifdef USE_ION 10372 omx->free_ion_memory(&op_buf_ion_info[index]); 10373#endif 10374 m_heap_ptr[index].video_heap_ptr = NULL; 10375 if (allocated_count > 0) 10376 allocated_count--; 10377 else 10378 allocated_count = 0; 10379 if (!allocated_count) { 10380 pthread_mutex_lock(&omx->c_lock); 10381 c2d.close(); 10382 init_members(); 10383 pthread_mutex_unlock(&omx->c_lock); 10384 } 10385 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]); 10386} 10387 10388OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp, 10389 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes) 10390{ 10391 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10392 if (!enabled) { 10393 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); 10394 return eRet; 10395 } 10396 if (enabled && omx->is_component_secure()) { 10397 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d", 10398 omx->is_component_secure()); 10399 return OMX_ErrorUnsupportedSetting; 10400 } 10401 if (!bufferHdr || bytes > buffer_size_req) { 10402 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr); 10403 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u", 10404 (unsigned int)buffer_size_req, (unsigned int)bytes); 10405 return OMX_ErrorBadParameter; 10406 } 10407 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) { 10408 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert"); 10409 return OMX_ErrorInsufficientResources; 10410 } 10411 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL; 10412 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr, 10413 port,appData,omx->drv_ctx.op_buf.buffer_size); 10414 if (eRet != OMX_ErrorNone || !temp_bufferHdr) { 10415 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert"); 10416 return eRet; 10417 } 10418 if ((temp_bufferHdr - omx->m_out_mem_ptr) >= 10419 (int)omx->drv_ctx.op_buf.actualcount) { 10420 DEBUG_PRINT_ERROR("Invalid header index %ld", 10421 (long int)(temp_bufferHdr - omx->m_out_mem_ptr)); 10422 return OMX_ErrorUndefined; 10423 } 10424 unsigned int i = allocated_count; 10425#ifdef USE_ION 10426 // Allocate color-conversion buffers as cached to improve software-reading 10427 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit 10428 // cache invalidation. 10429 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory( 10430 buffer_size_req,buffer_alignment_req, 10431 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data, 10432 ION_FLAG_CACHED); 10433 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd; 10434 if (op_buf_ion_info[i].ion_device_fd < 0) { 10435 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert"); 10436 return OMX_ErrorInsufficientResources; 10437 } 10438 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req, 10439 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0); 10440 10441 if (pmem_baseaddress[i] == MAP_FAILED) { 10442 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req); 10443 close(pmem_fd[i]); 10444 omx->free_ion_memory(&op_buf_ion_info[i]); 10445 return OMX_ErrorInsufficientResources; 10446 } 10447 m_heap_ptr[i].video_heap_ptr = new VideoHeap ( 10448 op_buf_ion_info[i].ion_device_fd,buffer_size_req, 10449 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]); 10450#endif 10451 m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get(); 10452 m_pmem_info_client[i].offset = 0; 10453 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i]; 10454 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; 10455 m_platform_list_client[i].nEntries = 1; 10456 m_platform_list_client[i].entryList = &m_platform_entry_client[i]; 10457 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL; 10458 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req; 10459 m_out_mem_ptr_client[i].nFilledLen = 0; 10460 m_out_mem_ptr_client[i].nFlags = 0; 10461 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; 10462 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE); 10463 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION; 10464 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i]; 10465 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i]; 10466 m_out_mem_ptr_client[i].pAppPrivate = appData; 10467 *bufferHdr = &m_out_mem_ptr_client[i]; 10468 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr); 10469 allocated_count++; 10470 return eRet; 10471} 10472 10473bool omx_vdec::is_component_secure() 10474{ 10475 return secure_mode; 10476} 10477 10478bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format) 10479{ 10480 bool status = true; 10481 if (!enabled) { 10482 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) 10483 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) 10484 dest_color_format = (OMX_COLOR_FORMATTYPE) 10485 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView; 10486 else 10487 dest_color_format = (OMX_COLOR_FORMATTYPE) 10488 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; 10489 else 10490 status = false; 10491 } else { 10492 if (ColorFormat == OMX_COLOR_FormatYUV420Planar || 10493 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 10494 dest_color_format = ColorFormat; 10495 } else 10496 status = false; 10497 } 10498 return status; 10499} 10500 10501OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops( 10502 unsigned int index, unsigned int cmd) 10503{ 10504 if (!enabled) { 10505 return OMX_ErrorNone; 10506 } 10507 10508 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) { 10509 DEBUG_PRINT_ERROR("%s: Invalid param", __func__); 10510 return OMX_ErrorBadParameter; 10511 } 10512 10513 struct ion_flush_data flush_data; 10514 struct ion_custom_data custom_data; 10515 10516 memset(&flush_data, 0x0, sizeof(flush_data)); 10517 memset(&custom_data, 0x0, sizeof(custom_data)); 10518 10519 flush_data.vaddr = pmem_baseaddress[index]; 10520 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd; 10521 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle; 10522 flush_data.length = buffer_size_req; 10523 custom_data.cmd = cmd; 10524 custom_data.arg = (unsigned long)&flush_data; 10525 10526 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d", 10527 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 10528 flush_data.fd, flush_data.handle, flush_data.vaddr, 10529 flush_data.length); 10530 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data); 10531 if (ret < 0) { 10532 DEBUG_PRINT_ERROR("Cache %s failed: %s\n", 10533 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", 10534 strerror(errno)); 10535 return OMX_ErrorUndefined; 10536 } 10537 return OMX_ErrorNone; 10538} 10539 10540void omx_vdec::buf_ref_add(OMX_U32 fd, OMX_U32 offset) 10541{ 10542 unsigned long i = 0; 10543 bool buf_present = false; 10544 10545 if (!dynamic_buf_mode) { 10546 return; 10547 } 10548 10549 if (!out_dynamic_list) { 10550 DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL"); 10551 return; 10552 } 10553 10554 pthread_mutex_lock(&m_lock); 10555 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 10556 //check the buffer fd, offset, uv addr with list contents 10557 //If present increment reference. 10558 if ((out_dynamic_list[i].fd == fd) && 10559 (out_dynamic_list[i].offset == offset)) { 10560 out_dynamic_list[i].ref_count++; 10561 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u", 10562 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 10563 buf_present = true; 10564 break; 10565 } 10566 } 10567 if (!buf_present) { 10568 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 10569 //search for a entry to insert details of the new buffer 10570 if (out_dynamic_list[i].dup_fd == 0) { 10571 out_dynamic_list[i].fd = fd; 10572 out_dynamic_list[i].offset = offset; 10573 out_dynamic_list[i].dup_fd = dup(fd); 10574 out_dynamic_list[i].ref_count++; 10575 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u", 10576 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 10577 break; 10578 } 10579 } 10580 } 10581 pthread_mutex_unlock(&m_lock); 10582} 10583 10584void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset) 10585{ 10586 unsigned long i = 0; 10587 10588 if (!dynamic_buf_mode) { 10589 return; 10590 } 10591 10592 if (!out_dynamic_list) { 10593 DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL"); 10594 return; 10595 } 10596 10597 pthread_mutex_lock(&m_lock); 10598 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { 10599 //check the buffer fd, offset, uv addr with list contents 10600 //If present decrement reference. 10601 if ((out_dynamic_list[i].fd == fd) && 10602 (out_dynamic_list[i].offset == offset)) { 10603 out_dynamic_list[i].ref_count--; 10604 if (out_dynamic_list[i].ref_count == 0) { 10605 close(out_dynamic_list[i].dup_fd); 10606 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u", 10607 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count); 10608 out_dynamic_list[i].dup_fd = 0; 10609 out_dynamic_list[i].fd = 0; 10610 out_dynamic_list[i].offset = 0; 10611 } 10612 break; 10613 } 10614 } 10615 if (i >= drv_ctx.op_buf.actualcount) { 10616 DEBUG_PRINT_ERROR("Error - could not remove ref, no match with any entry in list"); 10617 } 10618 pthread_mutex_unlock(&m_lock); 10619} 10620 10621#ifdef _MSM8974_ 10622void omx_vdec::send_codec_config() { 10623 if (codec_config_flag) { 10624 unsigned long p1 = 0; // Parameter - 1 10625 unsigned long p2 = 0; // Parameter - 2 10626 unsigned long ident = 0; 10627 pthread_mutex_lock(&m_lock); 10628 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n"); 10629 while (m_etb_q.m_size) { 10630 m_etb_q.pop_entry(&p1,&p2,&ident); 10631 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { 10632 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 10633 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ 10634 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 10635 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); 10636 omx_report_error(); 10637 } 10638 } else { 10639 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); 10640 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); 10641 } 10642 } else if (ident == OMX_COMPONENT_GENERATE_ETB) { 10643 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 10644 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ 10645 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { 10646 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); 10647 omx_report_error (); 10648 } 10649 } else { 10650 pending_input_buffers++; 10651 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", 10652 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); 10653 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); 10654 } 10655 } else if (ident == OMX_COMPONENT_GENERATE_EBD) { 10656 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", 10657 (OMX_BUFFERHEADERTYPE *)p1); 10658 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); 10659 } 10660 } 10661 pthread_mutex_unlock(&m_lock); 10662 } 10663} 10664#endif 10665 10666omx_vdec::perf_control::perf_control () 10667{ 10668 m_perf_lib = NULL; 10669 m_perf_handle = -1; 10670 m_perf_lock_acquire = NULL; 10671 m_perf_lock_release = NULL; 10672} 10673 10674omx_vdec::perf_control::~perf_control() 10675{ 10676 if (m_perf_handle >= 0 && m_perf_lock_release) { 10677 DEBUG_PRINT_LOW("NOTE2: release perf lock"); 10678 m_perf_lock_release(m_perf_handle); 10679 } 10680 if (m_perf_lib) { 10681 dlclose(m_perf_lib); 10682 } 10683} 10684 10685void omx_vdec::perf_control::request_cores(int frame_duration_us) 10686{ 10687 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) { 10688 return; 10689 } 10690 load_lib(); 10691 if (m_perf_lock_acquire && m_perf_handle < 0) { 10692 int arg = 0x700 /*base value*/ + 2 /*cores*/; 10693 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int)); 10694 if (m_perf_handle) { 10695 DEBUG_PRINT_HIGH("perf lock acquired"); 10696 } 10697 } 10698} 10699 10700void omx_vdec::perf_control::load_lib() 10701{ 10702 char perf_lib_path[PROPERTY_VALUE_MAX] = {0}; 10703 if (m_perf_lib) 10704 return; 10705 10706 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) { 10707 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library"); 10708 return; 10709 } 10710 10711 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) { 10712 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror()); 10713 } else { 10714 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq"); 10715 if (m_perf_lock_acquire == NULL) { 10716 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq"); 10717 } 10718 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel"); 10719 if (m_perf_lock_release == NULL) { 10720 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel"); 10721 } 10722 } 10723} 10724 10725OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth, 10726 unsigned long nMaxFrameHeight) 10727{ 10728 10729 OMX_ERRORTYPE eRet = OMX_ErrorNone; 10730 int ret = 0; 10731 unsigned long min_res_buf_count = 0; 10732 10733 eRet = enable_smoothstreaming(); 10734 if (eRet != OMX_ErrorNone) { 10735 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver"); 10736 return eRet; 10737 } 10738 10739 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu", 10740 nMaxFrameWidth, 10741 nMaxFrameHeight); 10742 m_smoothstreaming_mode = true; 10743 m_smoothstreaming_width = nMaxFrameWidth; 10744 m_smoothstreaming_height = nMaxFrameHeight; 10745 10746 //Get upper limit buffer count for min supported resolution 10747 struct v4l2_format fmt; 10748 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10749 fmt.fmt.pix_mp.height = m_decoder_capability.min_height; 10750 fmt.fmt.pix_mp.width = m_decoder_capability.min_width; 10751 fmt.fmt.pix_mp.pixelformat = output_capability; 10752 10753 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 10754 if (ret) { 10755 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u", 10756 m_decoder_capability.min_height, 10757 m_decoder_capability.min_width); 10758 return OMX_ErrorUnsupportedSetting; 10759 } 10760 10761 eRet = get_buffer_req(&drv_ctx.op_buf); 10762 if (eRet != OMX_ErrorNone) { 10763 DEBUG_PRINT_ERROR("failed to get_buffer_req"); 10764 return eRet; 10765 } 10766 10767 min_res_buf_count = drv_ctx.op_buf.mincount; 10768 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u", 10769 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width); 10770 10771 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, 10772 m_smoothstreaming_width, m_smoothstreaming_height); 10773 eRet = is_video_session_supported(); 10774 if (eRet != OMX_ErrorNone) { 10775 DEBUG_PRINT_ERROR("video session is not supported"); 10776 return eRet; 10777 } 10778 10779 //Get upper limit buffer size for max smooth streaming resolution set 10780 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 10781 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; 10782 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; 10783 fmt.fmt.pix_mp.pixelformat = output_capability; 10784 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); 10785 if (ret) { 10786 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback"); 10787 return OMX_ErrorUnsupportedSetting; 10788 } 10789 10790 eRet = get_buffer_req(&drv_ctx.op_buf); 10791 if (eRet != OMX_ErrorNone) { 10792 DEBUG_PRINT_ERROR("failed to get_buffer_req!!"); 10793 return eRet; 10794 } 10795 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u", 10796 (unsigned int)drv_ctx.op_buf.buffer_size); 10797 10798 drv_ctx.op_buf.mincount = min_res_buf_count; 10799 drv_ctx.op_buf.actualcount = min_res_buf_count; 10800 eRet = set_buffer_req(&drv_ctx.op_buf); 10801 if (eRet != OMX_ErrorNone) { 10802 DEBUG_PRINT_ERROR("failed to set_buffer_req"); 10803 return eRet; 10804 } 10805 10806 eRet = get_buffer_req(&drv_ctx.op_buf); 10807 if (eRet != OMX_ErrorNone) { 10808 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!"); 10809 return eRet; 10810 } 10811 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u", 10812 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size); 10813 return eRet; 10814} 10815 10816//static 10817OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { 10818 10819#ifndef FLEXYUV_SUPPORTED 10820 (void) pParam; 10821 return OMX_ErrorUndefined; 10822#else 10823 10824 if (pParam == NULL) { 10825 DEBUG_PRINT_ERROR("describeColorFormat: invalid params"); 10826 return OMX_ErrorBadParameter; 10827 } 10828 10829 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam; 10830 10831 MediaImage *img = &(params->sMediaImage); 10832 switch(params->eColorFormat) { 10833 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m: 10834 { 10835 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 10836 img->mNumPlanes = 3; 10837 // mWidth and mHeight represent the W x H of the largest plane 10838 // In our case, this happens to be the Stride x Scanlines of Y plane 10839 img->mWidth = params->nFrameWidth; 10840 img->mHeight = params->nFrameHeight; 10841 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 10842 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight); 10843 img->mBitDepth = 8; 10844 //Plane 0 (Y) 10845 img->mPlane[MediaImage::Y].mOffset = 0; 10846 img->mPlane[MediaImage::Y].mColInc = 1; 10847 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride 10848 img->mPlane[MediaImage::Y].mHorizSubsampling = 1; 10849 img->mPlane[MediaImage::Y].mVertSubsampling = 1; 10850 //Plane 1 (U) 10851 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight; 10852 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV 10853 img->mPlane[MediaImage::U].mRowInc = 10854 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 10855 img->mPlane[MediaImage::U].mHorizSubsampling = 2; 10856 img->mPlane[MediaImage::U].mVertSubsampling = 2; 10857 //Plane 2 (V) 10858 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1; 10859 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV 10860 img->mPlane[MediaImage::V].mRowInc = 10861 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth); 10862 img->mPlane[MediaImage::V].mHorizSubsampling = 2; 10863 img->mPlane[MediaImage::V].mVertSubsampling = 2; 10864 break; 10865 } 10866 10867 case OMX_COLOR_FormatYUV420Planar: 10868 case OMX_COLOR_FormatYUV420SemiPlanar: 10869 // We need not describe the standard OMX linear formats as these are 10870 // understood by client. Fail this deliberately to let client fill-in 10871 return OMX_ErrorUnsupportedSetting; 10872 10873 default: 10874 // Rest all formats which are non-linear cannot be described 10875 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat); 10876 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 10877 return OMX_ErrorNone; 10878 }; 10879 10880 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat); 10881 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight); 10882 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight); 10883 for (size_t i = 0; i < img->mNumPlanes; ++i) { 10884 DEBUG_PRINT_LOW(" Plane[%d] : offset=%d / xStep=%d / yStep = %d", 10885 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc); 10886 } 10887 return OMX_ErrorNone; 10888#endif //FLEXYUV_SUPPORTED 10889} 10890