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