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