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