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