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