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