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