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