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