1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2018, 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 <fcntl.h>
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <media/hardware/HardwareAPI.h>
55 #include <sys/eventfd.h>
56 #include <nativebase/nativebase.h>
57
58 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
59 #include <sys/ioctl.h>
60 #include <sys/mman.h>
61 #endif
62
63 #ifdef _ANDROID_
64 #include <cutils/properties.h>
65 #undef USE_EGL_IMAGE_GPU
66
67 #ifdef _QUERY_DISP_RES_
68 #include "display_config.h"
69 #endif
70 #endif
71
72 #ifdef _USE_GLIB_
73 #include <glib.h>
74 #define strlcpy g_strlcpy
75 #endif
76
77 #include <qdMetaData.h>
78 #include <gralloc_priv.h>
79
80 #ifdef ANDROID_JELLYBEAN_MR2
81 #include "QComOMXMetadata.h"
82 #endif
83
84 #ifdef USE_EGL_IMAGE_GPU
85 #include <EGL/egl.h>
86 #include <EGL/eglQCOM.h>
87 #define EGL_BUFFER_HANDLE 0x4F00
88 #define EGL_BUFFER_OFFSET 0x4F01
89 #endif
90
91 #define BUFFER_LOG_LOC "/data/vendor/media"
92
93 #ifdef OUTPUT_EXTRADATA_LOG
94 FILE *outputExtradataFile;
95 char output_extradata_filename [] = "/data/vendor/media/extradata";
96 #endif
97
98 #define DEFAULT_FPS 30
99 #define MAX_SUPPORTED_FPS 240
100 #define DEFAULT_WIDTH_ALIGNMENT 128
101 #define DEFAULT_HEIGHT_ALIGNMENT 32
102
103 #define VC1_SP_MP_START_CODE 0xC5000000
104 #define VC1_SP_MP_START_CODE_MASK 0xFF000000
105 #define VC1_AP_SEQ_START_CODE 0x0F010000
106 #define VC1_STRUCT_C_PROFILE_MASK 0xF0
107 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
108 #define VC1_SIMPLE_PROFILE 0
109 #define VC1_MAIN_PROFILE 1
110 #define VC1_ADVANCE_PROFILE 3
111 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
112 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2
113 #define VC1_STRUCT_C_LEN 4
114 #define VC1_STRUCT_C_POS 8
115 #define VC1_STRUCT_A_POS 12
116 #define VC1_STRUCT_B_POS 24
117 #define VC1_SEQ_LAYER_SIZE 36
118 #define POLL_TIMEOUT 0x7fffffff
119
120 #define MEM_DEVICE "/dev/ion"
121
122 #ifdef _ANDROID_
123 extern "C" {
124 #include<utils/Log.h>
125 }
126 #endif//_ANDROID_
127
128 #define SZ_4K 0x1000
129 #define SZ_1M 0x100000
130
131 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
132 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
133 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
134 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
135
136 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
137 | OMX_DISPLAY_INFO_EXTRADATA | OMX_HDR_COLOR_INFO_EXTRADATA)
138 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
139
140 #ifndef ION_FLAG_CP_BITSTREAM
141 #define ION_FLAG_CP_BITSTREAM 0
142 #endif
143
144 #ifndef ION_FLAG_CP_PIXEL
145 #define ION_FLAG_CP_PIXEL 0
146 #endif
147
148 #ifdef MASTER_SIDE_CP
149 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
150 #define SECURE_ALIGN SZ_4K
151 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
152 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
153 #else //SLAVE_SIDE_CP
154 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
155 #define SECURE_ALIGN SZ_1M
156 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
157 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
158 #endif
159
160 #define LUMINANCE_DIV_FACTOR 10000.0
161
162 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
163 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
164
165 static OMX_U32 maxSmoothStreamingWidth = 1920;
166 static OMX_U32 maxSmoothStreamingHeight = 1088;
167
async_message_thread(void * input)168 void* async_message_thread (void *input)
169 {
170 OMX_BUFFERHEADERTYPE *buffer;
171 struct v4l2_plane plane[VIDEO_MAX_PLANES];
172 struct pollfd pfds[2];
173 struct v4l2_buffer v4l2_buf;
174 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
175 struct v4l2_event dqevent;
176 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
177 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
178 pfds[1].events = POLLIN | POLLERR;
179 pfds[0].fd = omx->drv_ctx.video_driver_fd;
180 pfds[1].fd = omx->m_poll_efd;
181 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
182 DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
183 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
184 while (!omx->async_thread_force_stop) {
185 rc = poll(pfds, 2, POLL_TIMEOUT);
186 if (!rc) {
187 DEBUG_PRINT_ERROR("Poll timedout");
188 break;
189 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
190 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
191 break;
192 }
193 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
194 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
195 break;
196 }
197 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
198 struct vdec_msginfo vdec_msg;
199 memset(&vdec_msg, 0, sizeof(vdec_msg));
200 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
201 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
202 v4l2_buf.length = omx->drv_ctx.num_planes;
203 v4l2_buf.m.planes = plane;
204 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
205 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
206 vdec_msg.status_code=VDEC_S_SUCCESS;
207 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
208 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
209 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
210 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
211 (uint64_t)v4l2_buf.timestamp.tv_usec;
212
213 if (omx->async_message_process(input,&vdec_msg) < 0) {
214 DEBUG_PRINT_HIGH("async_message_thread Exited");
215 break;
216 }
217 }
218 }
219 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
220 struct vdec_msginfo vdec_msg;
221 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
222 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
223 v4l2_buf.length = 1;
224 v4l2_buf.m.planes = plane;
225 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
226 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
227 vdec_msg.status_code=VDEC_S_SUCCESS;
228 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
229 if (omx->async_message_process(input,&vdec_msg) < 0) {
230 DEBUG_PRINT_HIGH("async_message_thread Exited");
231 break;
232 }
233 }
234 }
235 if (pfds[0].revents & POLLPRI) {
236 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
237 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
238 struct vdec_msginfo vdec_msg;
239 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
240
241 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
242 vdec_msg.status_code=VDEC_S_SUCCESS;
243 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
244 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
245 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
246 if(ptr[2] & V4L2_EVENT_BITDEPTH_FLAG) {
247 omx->dpb_bit_depth = ptr[3];
248 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", ptr[3]);
249 }
250 if(ptr[2] & V4L2_EVENT_PICSTRUCT_FLAG) {
251 omx->m_progressive = ptr[4];
252 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct change - %d", ptr[4]);
253 }
254 if(ptr[2] & V4L2_EVENT_COLOUR_SPACE_FLAG) {
255 if (ptr[5] == MSM_VIDC_BT2020) {
256 omx->m_color_space = omx_vdec::BT2020;
257 } else {
258 omx->m_color_space = omx_vdec::EXCEPT_BT2020;
259 }
260 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace change - %d", omx->m_color_space);
261 }
262 if (omx->async_message_process(input,&vdec_msg) < 0) {
263 DEBUG_PRINT_HIGH("async_message_thread Exited");
264 break;
265 }
266 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
267 struct vdec_msginfo vdec_msg;
268 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
269 // Old driver doesn't send flushType information.
270 // To make this backward compatible fallback to old approach
271 // if the flush_type is not present.
272 vdec_msg.status_code=VDEC_S_SUCCESS;
273 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
274 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
275 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
276 if (omx->async_message_process(input,&vdec_msg) < 0) {
277 DEBUG_PRINT_HIGH("async_message_thread Exited");
278 break;
279 }
280 }
281
282 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
283 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
284 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
285 if (omx->async_message_process(input,&vdec_msg) < 0) {
286 DEBUG_PRINT_HIGH("async_message_thread Exited");
287 break;
288 }
289 }
290 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
291 struct vdec_msginfo vdec_msg;
292 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
293 vdec_msg.status_code=VDEC_S_SUCCESS;
294 DEBUG_PRINT_ERROR("HW Overload received");
295 if (omx->async_message_process(input,&vdec_msg) < 0) {
296 DEBUG_PRINT_HIGH("async_message_thread Exited");
297 break;
298 }
299 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
300 struct vdec_msginfo vdec_msg;
301 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
302 vdec_msg.status_code=VDEC_S_SUCCESS;
303 DEBUG_PRINT_ERROR("HW Unsupported received");
304 if (omx->async_message_process(input,&vdec_msg) < 0) {
305 DEBUG_PRINT_HIGH("async_message_thread Exited");
306 break;
307 }
308 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
309 struct vdec_msginfo vdec_msg;
310 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
311 vdec_msg.status_code = VDEC_S_SUCCESS;
312 DEBUG_PRINT_HIGH("SYS Error Recieved");
313 if (omx->async_message_process(input,&vdec_msg) < 0) {
314 DEBUG_PRINT_HIGH("async_message_thread Exited");
315 break;
316 }
317 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
318 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
319
320 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
321 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
322 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
323 struct vdec_msginfo vdec_msg;
324
325 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
326
327 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
328 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
329 v4l2_buf.length = omx->drv_ctx.num_planes;
330 v4l2_buf.m.planes = plane;
331 v4l2_buf.index = ptr[5];
332 v4l2_buf.flags = 0;
333
334 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
335 vdec_msg.status_code = VDEC_S_SUCCESS;
336 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
337 vdec_msg.msgdata.output_frame.len = 0;
338 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
339 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
340 (uint64_t)ptr[4];
341 if (omx->async_message_process(input,&vdec_msg) < 0) {
342 DEBUG_PRINT_HIGH("async_message_thread Exitedn");
343 break;
344 }
345 } else {
346 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
347 continue;
348 }
349 }
350 }
351 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
352 return NULL;
353 }
354
message_thread_dec(void * input)355 void* message_thread_dec(void *input)
356 {
357 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
358 unsigned char id;
359 int n;
360
361 fd_set readFds;
362 int res = 0;
363 struct timeval tv;
364
365 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
366 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
367 while (!omx->message_thread_stop) {
368
369 tv.tv_sec = 2;
370 tv.tv_usec = 0;
371
372 FD_ZERO(&readFds);
373 FD_SET(omx->m_pipe_in, &readFds);
374
375 res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
376 if (res < 0) {
377 DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
378 continue;
379 } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
380 continue;
381 }
382
383 n = read(omx->m_pipe_in, &id, 1);
384
385 if (0 == n) {
386 break;
387 }
388
389 if (1 == n) {
390 omx->process_event_cb(omx, id);
391 }
392
393 if ((n < 0) && (errno != EINTR)) {
394 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
395 break;
396 }
397 }
398 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
399 return 0;
400 }
401
post_message(omx_vdec * omx,unsigned char id)402 void post_message(omx_vdec *omx, unsigned char id)
403 {
404 int ret_value;
405 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
406 ret_value = write(omx->m_pipe_out, &id, 1);
407 if (ret_value <= 0) {
408 DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
409 } else {
410 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
411 }
412 }
413
414 // omx_cmd_queue destructor
~omx_cmd_queue()415 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
416 {
417 // Nothing to do
418 }
419
420 // omx cmd queue constructor
omx_cmd_queue()421 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
422 {
423 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
424 }
425
426 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)427 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
428 {
429 bool ret = true;
430 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
431 m_q[m_write].id = id;
432 m_q[m_write].param1 = p1;
433 m_q[m_write].param2 = p2;
434 m_write++;
435 m_size ++;
436 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
437 m_write = 0;
438 }
439 } else {
440 ret = false;
441 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
442 }
443 return ret;
444 }
445
446 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)447 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
448 {
449 bool ret = true;
450 if (m_size > 0) {
451 *id = m_q[m_read].id;
452 *p1 = m_q[m_read].param1;
453 *p2 = m_q[m_read].param2;
454 // Move the read pointer ahead
455 ++m_read;
456 --m_size;
457 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
458 m_read = 0;
459 }
460 } else {
461 ret = false;
462 }
463 return ret;
464 }
465
466 // Retrieve the first mesg type in the queue
get_q_msg_type()467 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
468 {
469 return m_q[m_read].id;
470 }
471
472 #ifdef _ANDROID_
ts_arr_list()473 omx_vdec::ts_arr_list::ts_arr_list()
474 {
475 //initialize timestamps array
476 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
477 }
~ts_arr_list()478 omx_vdec::ts_arr_list::~ts_arr_list()
479 {
480 //free m_ts_arr_list?
481 }
482
insert_ts(OMX_TICKS ts)483 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
484 {
485 bool ret = true;
486 bool duplicate_ts = false;
487 int idx = 0;
488
489 //insert at the first available empty location
490 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
491 if (!m_ts_arr_list[idx].valid) {
492 //found invalid or empty entry, save timestamp
493 m_ts_arr_list[idx].valid = true;
494 m_ts_arr_list[idx].timestamp = ts;
495 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
496 ts, idx);
497 break;
498 }
499 }
500
501 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
502 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
503 ret = false;
504 }
505 return ret;
506 }
507
pop_min_ts(OMX_TICKS & ts)508 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
509 {
510 bool ret = true;
511 int min_idx = -1;
512 OMX_TICKS min_ts = 0;
513 int idx = 0;
514
515 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
516
517 if (m_ts_arr_list[idx].valid) {
518 //found valid entry, save index
519 if (min_idx < 0) {
520 //first valid entry
521 min_ts = m_ts_arr_list[idx].timestamp;
522 min_idx = idx;
523 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
524 min_ts = m_ts_arr_list[idx].timestamp;
525 min_idx = idx;
526 }
527 }
528
529 }
530
531 if (min_idx < 0) {
532 //no valid entries found
533 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
534 ts = 0;
535 ret = false;
536 } else {
537 ts = m_ts_arr_list[min_idx].timestamp;
538 m_ts_arr_list[min_idx].valid = false;
539 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
540 ts, min_idx);
541 }
542
543 return ret;
544
545 }
546
547
reset_ts_list()548 bool omx_vdec::ts_arr_list::reset_ts_list()
549 {
550 bool ret = true;
551 int idx = 0;
552
553 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
554 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
555 m_ts_arr_list[idx].valid = false;
556 }
557 return ret;
558 }
559 #endif
560
561 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)562 void *get_omx_component_factory_fn(void)
563 {
564 return (new omx_vdec);
565 }
566
is_platform_tp10capture_supported()567 bool is_platform_tp10capture_supported()
568 {
569 char platform_name[PROPERTY_VALUE_MAX] = {0};
570 property_get("ro.board.platform", platform_name, "0");
571 if (!strncmp(platform_name, "msm8998", 7)) {
572 DEBUG_PRINT_HIGH("TP10 on capture port is supported");
573 return true;
574 }
575 DEBUG_PRINT_HIGH("TP10 on capture port is not supported");
576 return false;
577 }
578
579 /* ======================================================================
580 FUNCTION
581 omx_vdec::omx_vdec
582
583 DESCRIPTION
584 Constructor
585
586 PARAMETERS
587 None
588
589 RETURN VALUE
590 None.
591 ========================================================================== */
omx_vdec()592 omx_vdec::omx_vdec(): m_error_propogated(false),
593 m_state(OMX_StateInvalid),
594 m_app_data(NULL),
595 m_inp_mem_ptr(NULL),
596 m_out_mem_ptr(NULL),
597 m_client_output_extradata_mem_ptr(NULL),
598 input_flush_progress (false),
599 output_flush_progress (false),
600 input_use_buffer (false),
601 output_use_buffer (false),
602 ouput_egl_buffers(false),
603 m_use_output_pmem(OMX_FALSE),
604 m_out_mem_region_smi(OMX_FALSE),
605 m_out_pvt_entry_pmem(OMX_FALSE),
606 pending_input_buffers(0),
607 pending_output_buffers(0),
608 m_out_bm_count(0),
609 m_inp_bm_count(0),
610 m_out_extradata_bm_count(0),
611 m_inp_bPopulated(OMX_FALSE),
612 m_out_bPopulated(OMX_FALSE),
613 m_flags(0),
614 m_inp_bEnabled(OMX_TRUE),
615 m_out_bEnabled(OMX_TRUE),
616 m_in_alloc_cnt(0),
617 m_platform_list(NULL),
618 m_platform_entry(NULL),
619 m_pmem_info(NULL),
620 h264_parser(NULL),
621 arbitrary_bytes (true),
622 psource_frame (NULL),
623 pdest_frame (NULL),
624 m_inp_heap_ptr (NULL),
625 m_phdr_pmem_ptr(NULL),
626 m_heap_inp_bm_count (0),
627 codec_type_parse ((codec_type)0),
628 first_frame_meta (true),
629 frame_count (0),
630 nal_count (0),
631 nal_length(0),
632 look_ahead_nal (false),
633 first_frame(0),
634 first_buffer(NULL),
635 first_frame_size (0),
636 m_device_file_ptr(NULL),
637 m_vc1_profile((vc1_profile_type)0),
638 h264_last_au_ts(LLONG_MAX),
639 h264_last_au_flags(0),
640 m_disp_hor_size(0),
641 m_disp_vert_size(0),
642 prev_ts(LLONG_MAX),
643 prev_ts_actual(LLONG_MAX),
644 rst_prev_ts(true),
645 frm_int(0),
646 m_fps_received(0),
647 m_fps_prev(0),
648 m_drc_enable(0),
649 in_reconfig(false),
650 m_display_id(NULL),
651 client_extradata(0),
652 m_reject_avc_1080p_mp (0),
653 #ifdef _ANDROID_
654 m_enable_android_native_buffers(OMX_FALSE),
655 m_use_android_native_buffers(OMX_FALSE),
656 #endif
657 m_desc_buffer_ptr(NULL),
658 secure_mode(false),
659 allocate_native_handle(false),
660 m_other_extradata(NULL),
661 m_profile(0),
662 m_need_turbo(0),
663 client_set_fps(false),
664 stereo_output_mode(HAL_NO_3D),
665 m_last_rendered_TS(-1),
666 m_queued_codec_config_count(0),
667 current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
668 secure_scaling_to_non_secure_opb(false),
669 m_force_compressed_for_dpb(true),
670 m_is_display_session(false),
671 m_buffer_error(false)
672 {
673 m_pipe_in = -1;
674 m_pipe_out = -1;
675 m_poll_efd = -1;
676 drv_ctx.video_driver_fd = -1;
677 drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
678 /* Assumption is that , to begin with , we have all the frames with decoder */
679 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
680 memset(&m_debug,0,sizeof(m_debug));
681 #ifdef _ANDROID_
682 char property_value[PROPERTY_VALUE_MAX] = {0};
683 property_get("vendor.vidc.debug.level", property_value, "1");
684 debug_level = strtoul(property_value, NULL, 16);
685 property_value[0] = '\0';
686
687 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
688
689 property_get("vendor.vidc.dec.debug.perf", property_value, "0");
690 perf_flag = atoi(property_value);
691 if (perf_flag) {
692 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
693 dec_time.start();
694 }
695 proc_frms = latency = 0;
696 prev_n_filled_len = 0;
697 property_value[0] = '\0';
698 property_get("vendor.vidc.dec.debug.ts", property_value, "0");
699 m_debug_timestamp = atoi(property_value);
700 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
701 if (m_debug_timestamp) {
702 time_stamp_dts.set_timestamp_reorder_mode(true);
703 time_stamp_dts.enable_debug_print(true);
704 }
705
706 property_value[0] = '\0';
707 property_get("vendor.vidc.dec.debug.concealedmb", property_value, "0");
708 m_debug_concealedmb = atoi(property_value);
709 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
710
711 property_value[0] = '\0';
712 property_get("vendor.vidc.dec.profile.check", property_value, "0");
713 m_reject_avc_1080p_mp = atoi(property_value);
714 DEBUG_PRINT_HIGH("vendor.vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
715
716 property_value[0] = '\0';
717 property_get("vendor.vidc.dec.log.in", property_value, "0");
718 m_debug.in_buffer_log = atoi(property_value);
719
720 property_value[0] = '\0';
721 property_get("vendor.vidc.dec.log.out", property_value, "0");
722 m_debug.out_buffer_log = atoi(property_value);
723 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
724
725 property_value[0] = '\0';
726 property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
727 m_debug.out_meta_buffer_log = atoi(property_value);
728 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
729
730 property_value[0] = '\0';
731 property_get("vendor.vidc.log.loc", property_value, "");
732 if (*property_value)
733 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
734
735 property_value[0] = '\0';
736 property_get("vendor.vidc.dec.120fps.enabled", property_value, "0");
737
738 //if this feature is not enabled then reset this value -ve
739 if(atoi(property_value)) {
740 DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
741 m_last_rendered_TS = 0;
742 }
743
744 property_value[0] = '\0';
745 property_get("vendor.vidc.dec.debug.dyn.disabled", property_value, "0");
746 m_disable_dynamic_buf_mode = atoi(property_value);
747 DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
748
749 property_value[0] = '\0';
750 property_get("vendor.vidc.dec.drc.enable", property_value, "0");
751 if (atoi(property_value)) {
752 m_drc_enable = true;
753 DEBUG_PRINT_HIGH("DRC enabled");
754 }
755
756 #ifdef _UBWC_
757 property_value[0] = '\0';
758 property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
759 m_disable_ubwc_mode = atoi(property_value);
760 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
761 #else
762 m_disable_ubwc_mode = true;
763 #endif
764 #endif
765 memset(&m_cmp,0,sizeof(m_cmp));
766 memset(&m_cb,0,sizeof(m_cb));
767 memset (&drv_ctx,0,sizeof(drv_ctx));
768 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
769 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
770 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
771 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
772 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
773 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
774 memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
775 memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
776 memset(&m_color_mdata, 0, sizeof(ColorMetaData));
777 m_demux_entries = 0;
778 msg_thread_id = 0;
779 async_thread_id = 0;
780 msg_thread_created = false;
781 async_thread_created = false;
782 async_thread_force_stop = false;
783 message_thread_stop = false;
784 #ifdef _ANDROID_ICS_
785 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
786 #endif
787 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
788
789 /* invalidate m_frame_pack_arrangement */
790 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
791 m_frame_pack_arrangement.cancel_flag = 1;
792
793 drv_ctx.timestamp_adjust = false;
794 m_vendor_config.pData = NULL;
795 pthread_mutex_init(&m_lock, NULL);
796 pthread_mutex_init(&c_lock, NULL);
797 pthread_mutex_init(&buf_lock, NULL);
798 sem_init(&m_cmd_lock,0,0);
799 sem_init(&m_safe_flush, 0, 0);
800 streaming[CAPTURE_PORT] =
801 streaming[OUTPUT_PORT] = false;
802 #ifdef _ANDROID_
803 char extradata_value[PROPERTY_VALUE_MAX] = {0};
804 property_get("vendor.vidc.dec.debug.extradata", extradata_value, "0");
805 m_debug_extradata = atoi(extradata_value);
806 DEBUG_PRINT_HIGH("vendor.vidc.dec.debug.extradata value is %d",m_debug_extradata);
807 #endif
808 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
809 client_buffers.set_vdec_client(this);
810 dynamic_buf_mode = false;
811 out_dynamic_list = NULL;
812 is_down_scalar_enabled = false;
813 m_enable_downscalar = 0;
814 m_downscalar_width = 0;
815 m_downscalar_height = 0;
816 m_force_down_scalar = 0;
817 m_reconfig_height = 0;
818 m_reconfig_width = 0;
819 m_smoothstreaming_mode = false;
820 m_smoothstreaming_width = 0;
821 m_smoothstreaming_height = 0;
822 m_decode_order_mode = false;
823 is_q6_platform = false;
824 m_perf_control.send_hint_to_mpctl(true);
825 m_input_pass_buffer_fd = false;
826 memset(&m_extradata_info, 0, sizeof(m_extradata_info));
827 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
828 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
829 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
830 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
831 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
832
833 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
834 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
835 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
836 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
837 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
838 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
839
840 m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
841 m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
842 m_change_client_hdr_info = false;
843 pthread_mutex_init(&m_hdr_info_client_lock, NULL);
844
845 char dither_value[PROPERTY_VALUE_MAX] = {0};
846 property_get("vendor.vidc.dec.dither", dither_value, "0");
847 if ((atoi(dither_value) > DITHER_ALL_COLORSPACE) ||
848 (atoi(dither_value) < DITHER_DISABLE)) {
849 m_dither_config = DITHER_ALL_COLORSPACE;
850 } else {
851 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)atoi(dither_value) : DITHER_ALL_COLORSPACE;
852 }
853
854 DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
855 m_color_space = EXCEPT_BT2020;
856 }
857
858 static const int event_type[] = {
859 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
860 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
861 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
862 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
863 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
864 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
865 V4L2_EVENT_MSM_VIDC_SYS_ERROR,
866 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
867 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
868 };
869
subscribe_to_events(int fd)870 static OMX_ERRORTYPE subscribe_to_events(int fd)
871 {
872 OMX_ERRORTYPE eRet = OMX_ErrorNone;
873 struct v4l2_event_subscription sub;
874 int array_sz = sizeof(event_type)/sizeof(int);
875 int i,rc;
876 if (fd < 0) {
877 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
878 return OMX_ErrorBadParameter;
879 }
880
881 for (i = 0; i < array_sz; ++i) {
882 memset(&sub, 0, sizeof(sub));
883 sub.type = event_type[i];
884 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
885 if (rc) {
886 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
887 break;
888 }
889 }
890 if (i < array_sz) {
891 for (--i; i >=0 ; i--) {
892 memset(&sub, 0, sizeof(sub));
893 sub.type = event_type[i];
894 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
895 if (rc)
896 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
897 }
898 eRet = OMX_ErrorNotImplemented;
899 }
900 return eRet;
901 }
902
903
unsubscribe_to_events(int fd)904 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
905 {
906 OMX_ERRORTYPE eRet = OMX_ErrorNone;
907 struct v4l2_event_subscription sub;
908 int array_sz = sizeof(event_type)/sizeof(int);
909 int i,rc;
910 if (fd < 0) {
911 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
912 return OMX_ErrorBadParameter;
913 }
914
915 for (i = 0; i < array_sz; ++i) {
916 memset(&sub, 0, sizeof(sub));
917 sub.type = event_type[i];
918 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
919 if (rc) {
920 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
921 break;
922 }
923 }
924 return eRet;
925 }
926
927 /* ======================================================================
928 FUNCTION
929 omx_vdec::~omx_vdec
930
931 DESCRIPTION
932 Destructor
933
934 PARAMETERS
935 None
936
937 RETURN VALUE
938 None.
939 ========================================================================== */
~omx_vdec()940 omx_vdec::~omx_vdec()
941 {
942 m_pmem_info = NULL;
943 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
944 if (msg_thread_created) {
945 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
946 message_thread_stop = true;
947 post_message(this, OMX_COMPONENT_CLOSE_MSG);
948 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
949 pthread_join(msg_thread_id,NULL);
950 }
951 close(m_pipe_in);
952 close(m_pipe_out);
953 m_pipe_in = -1;
954 m_pipe_out = -1;
955 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
956 if(eventfd_write(m_poll_efd, 1)) {
957 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
958 async_thread_force_stop = true;
959 }
960
961 if (async_thread_created)
962 pthread_join(async_thread_id,NULL);
963 unsubscribe_to_events(drv_ctx.video_driver_fd);
964 close(m_poll_efd);
965 close(drv_ctx.video_driver_fd);
966 pthread_mutex_destroy(&m_lock);
967 pthread_mutex_destroy(&c_lock);
968 pthread_mutex_destroy(&buf_lock);
969 sem_destroy(&m_cmd_lock);
970 pthread_mutex_destroy(&m_hdr_info_client_lock);
971 if (perf_flag) {
972 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
973 dec_time.end();
974 }
975 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
976 m_perf_control.send_hint_to_mpctl(false);
977 }
978
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)979 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
980 {
981 struct v4l2_requestbuffers bufreq;
982 int rc = 0;
983 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
984 bufreq.memory = V4L2_MEMORY_USERPTR;
985 bufreq.count = 0;
986 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
987 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
988 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
989 bufreq.memory = V4L2_MEMORY_USERPTR;
990 bufreq.count = 0;
991 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
992 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
993 }
994 return rc;
995 }
996
set_dpb(bool is_split_mode,int dpb_color_format)997 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
998 {
999 int rc = 0;
1000 struct v4l2_ext_control ctrl[2];
1001 struct v4l2_ext_controls controls;
1002
1003 DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
1004 is_split_mode ? "split" : "combined",
1005 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
1006 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
1007 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
1008 "unknown",
1009 capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
1010 capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
1011 capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC ? "nv12_10bit_ubwc":
1012 "unknown");
1013
1014 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1015 if (is_split_mode) {
1016 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1017 } else {
1018 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1019 }
1020
1021 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
1022 ctrl[1].value = dpb_color_format;
1023
1024 controls.count = 2;
1025 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1026 controls.controls = ctrl;
1027
1028 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1029 if (rc) {
1030 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1031 return OMX_ErrorUnsupportedSetting;
1032 }
1033 return OMX_ErrorNone;
1034 }
1035
1036
decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt)1037 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool split_opb_dpb_with_same_color_fmt)
1038 {
1039 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1040 struct v4l2_format fmt;
1041 int rc = 0;
1042 bool cpu_access = (capture_capability != V4L2_PIX_FMT_NV12_UBWC) &&
1043 capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC;
1044 bool tp10_enable = !drv_ctx.idr_only_decoding &&
1045 !client_buffers.is_color_conversion_enabled() &&
1046 dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10;
1047 bool dither_enable = true;
1048
1049 switch (m_dither_config) {
1050 case DITHER_DISABLE:
1051 dither_enable = false;
1052 break;
1053 case DITHER_COLORSPACE_EXCEPTBT2020:
1054 dither_enable = (m_color_space == EXCEPT_BT2020);
1055 break;
1056 case DITHER_ALL_COLORSPACE:
1057 dither_enable = true;
1058 break;
1059 default:
1060 DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1061 }
1062
1063 if (tp10_enable && !dither_enable) {
1064 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1065 capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1066 cpu_access = false;
1067
1068 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1069 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1070 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1071 if (rc) {
1072 DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1073 return OMX_ErrorUnsupportedSetting;
1074 }
1075 fmt.fmt.pix_mp.pixelformat = capture_capability;
1076 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1077 if (rc) {
1078 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1079 return OMX_ErrorUnsupportedSetting;
1080 }
1081 }
1082
1083
1084 if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1085 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1086 DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1087 return eRet;
1088 }
1089
1090
1091 if (cpu_access) {
1092 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1093 /* Disabled split mode for VP9. In split mode the DPB buffers are part of the internal
1094 * scratch buffers and the driver does not does the reference buffer management for
1095 * scratch buffers. In case of VP9 with spatial scalability, when a sequence changed
1096 * event is received with the new resolution, and when a flush is sent by the driver, it
1097 * releases all the references of internal scratch buffers. However as per the VP9
1098 * spatial scalability, even after the flush, the buffers which have not yet received
1099 * release reference event should not be unmapped and freed. Currently in driver,
1100 * reference buffer management of the internal scratch buffer is not implemented
1101 * and hence the DPB buffers get unmapped. For other codecs it does not matter
1102 * as with the new SPS/PPS, the DPB is flushed.
1103 */
1104 bool is_not_vp9 = eCompressionFormat != OMX_VIDEO_CodingVP9;
1105 bool eligible_for_split_dpb_ubwc =
1106 m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE && //@ Due to Venus limitation for Interlaced, Split mode enabled only for Progressive.
1107 is_not_vp9 && //@ Split mode disabled for VP9.
1108 !drv_ctx.idr_only_decoding && //@ Split mode disabled for Thumbnail usecase.
1109 !m_disable_split_mode; //@ Set prop to disable split mode
1110
1111 //Since opb is linear, dpb should also be linear.
1112 if (split_opb_dpb_with_same_color_fmt) {
1113 eligible_for_split_dpb_ubwc = false;
1114 }
1115
1116 if (eligible_for_split_dpb_ubwc) {
1117 //split DPB-OPB
1118 //DPB -> UBWC , OPB -> Linear
1119 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1120 } else if (split_opb_dpb_with_same_color_fmt) {
1121 //DPB -> Linear, OPB -> Linear
1122 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1123 } else {
1124 //DPB-OPB combined linear
1125 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1126 }
1127 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1128 //split DPB-OPB
1129 //DPB -> UBWC, OPB -> Linear
1130 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1131 }
1132 } else { //no cpu access
1133 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1134 if (split_opb_dpb_with_same_color_fmt) {
1135 //split DPB-OPB
1136 //DPB -> UBWC, OPB -> UBWC
1137 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1138 } else {
1139 //DPB-OPB combined UBWC
1140 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1141 }
1142 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1143 if (dither_enable) {
1144 //split DPB-OPB
1145 //DPB -> TP10UBWC, OPB -> UBWC
1146 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1147 } else {
1148 //combined DPB-OPB
1149 //DPB -> TP10UBWC, OPB -> TP10UBWC
1150 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1151 }
1152 }
1153 }
1154 if (eRet) {
1155 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1156 }
1157
1158
1159
1160 return eRet;
1161 }
1162
enable_downscalar()1163 int omx_vdec::enable_downscalar()
1164 {
1165 int rc = 0;
1166 struct v4l2_control control;
1167 struct v4l2_format fmt;
1168
1169 if (is_down_scalar_enabled) {
1170 DEBUG_PRINT_LOW("%s: already enabled", __func__);
1171 return 0;
1172 }
1173
1174 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1175 rc = decide_dpb_buffer_mode(true);
1176 if (rc) {
1177 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1178 return rc;
1179 }
1180 is_down_scalar_enabled = true;
1181
1182 memset(&control, 0x0, sizeof(struct v4l2_control));
1183 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1184 control.value = 1;
1185 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1186 if (rc) {
1187 DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1188 return rc;
1189 }
1190
1191 return 0;
1192 }
1193
disable_downscalar()1194 int omx_vdec::disable_downscalar()
1195 {
1196 int rc = 0;
1197 struct v4l2_control control;
1198
1199 if (!is_down_scalar_enabled) {
1200 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1201 return 0;
1202 }
1203
1204 rc = decide_dpb_buffer_mode(false);
1205 if (rc < 0) {
1206 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1207 return rc;
1208 }
1209 is_down_scalar_enabled = false;
1210
1211 return rc;
1212 }
1213
decide_downscalar()1214 int omx_vdec::decide_downscalar()
1215 {
1216 int rc = 0;
1217 struct v4l2_format fmt;
1218 enum color_fmts color_format;
1219 OMX_U32 width, height;
1220 OMX_BOOL isPortraitVideo = OMX_FALSE;
1221
1222 if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1223 rc = disable_downscalar();
1224 if (rc) {
1225 DEBUG_PRINT_ERROR("Disable downscalar failed!");
1226 return rc;
1227 }
1228 return 0;
1229 }
1230
1231 if (!m_enable_downscalar) {
1232 DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1233 return 0;
1234 }
1235
1236 #ifdef _QUERY_DISP_RES_
1237 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1238 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1239 fmt.fmt.pix_mp.pixelformat = capture_capability;
1240 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1241 if (rc < 0) {
1242 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1243 return rc;
1244 }
1245 isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
1246 if (!m_downscalar_width || !m_downscalar_height) {
1247 qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
1248 int prim_config, ext_config, virt_config;
1249
1250 prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
1251 dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
1252 DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d dpa.yres=%d dpa.xdpi = %f dpa.ydpi = %f ",
1253 __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
1254
1255 ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
1256 dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
1257 DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d dsa.yres = %d dsa.xdpi = %f dsa.ydpi = %f ",
1258 __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
1259
1260 virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
1261 dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
1262 DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d dva.yres = %d dva.xdpi = %f dva.ydpi = %f ",
1263 __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
1264
1265 /* Below logic takes care of following conditions:
1266 * 1. Choose display resolution as maximum resolution of all the connected
1267 * displays (secondary, primary, virtual), so that we do not downscale
1268 * unnecessarily which might be supported on one of the display losing quality.
1269 * 2. Displays connected might be in landscape or portrait mode, so the xres might
1270 * be smaller or greater than the yres. So we first take the max of the two
1271 * in width and min of two in height and then rotate it if below point is true.
1272 * 3. Video might also be in portrait mode, so invert the downscalar width and
1273 * height for such cases.
1274 */
1275 if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
1276 m_downscalar_width = MAX(dsa.xres, dsa.yres);
1277 m_downscalar_height = MIN(dsa.xres, dsa.yres);
1278 } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
1279 m_downscalar_width = MAX(dva.xres, dva.yres);
1280 m_downscalar_height = MIN(dva.xres, dva.yres);
1281
1282 } else {
1283 m_downscalar_width = MAX(dpa.xres, dpa.yres);
1284 m_downscalar_height = MIN(dpa.xres, dpa.yres);
1285 }
1286 if (isPortraitVideo) {
1287 // Swap width and height
1288 m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1289 m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
1290 m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1291 }
1292 }
1293 m_downscalar_width = ALIGN(m_downscalar_width, 128);
1294 m_downscalar_height = ALIGN(m_downscalar_height, 32);
1295 #endif
1296
1297 if (!m_downscalar_width || !m_downscalar_height) {
1298 DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
1299 return 0;
1300 }
1301
1302 if (m_force_down_scalar) {
1303 DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1304 return 0;
1305 }
1306
1307 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1308 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1309 fmt.fmt.pix_mp.pixelformat = capture_capability;
1310 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1311 if (rc < 0) {
1312 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1313 return rc;
1314 }
1315
1316 height = fmt.fmt.pix_mp.height;
1317 width = fmt.fmt.pix_mp.width;
1318
1319 DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
1320 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
1321
1322 if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
1323 m_is_display_session) {
1324 rc = enable_downscalar();
1325 if (rc < 0) {
1326 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1327 return rc;
1328 }
1329
1330 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1331 fmt.fmt.pix_mp.width : m_downscalar_width;
1332 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1333 fmt.fmt.pix_mp.height : m_downscalar_height;
1334 switch (capture_capability) {
1335 case V4L2_PIX_FMT_NV12:
1336 color_format = COLOR_FMT_NV12;
1337 break;
1338 case V4L2_PIX_FMT_NV12_UBWC:
1339 color_format = COLOR_FMT_NV12_UBWC;
1340 break;
1341 case V4L2_PIX_FMT_NV12_TP10_UBWC:
1342 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1343 break;
1344 default:
1345 DEBUG_PRINT_ERROR("Color format not recognized\n");
1346 rc = OMX_ErrorUndefined;
1347 return rc;
1348 }
1349 } else {
1350
1351 rc = disable_downscalar();
1352 if (rc < 0) {
1353 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1354 return rc;
1355 }
1356 }
1357
1358 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1359 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1360 fmt.fmt.pix_mp.height = height;
1361 fmt.fmt.pix_mp.width = width;
1362 fmt.fmt.pix_mp.pixelformat = capture_capability;
1363 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1364 if (rc) {
1365 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1366 return rc;
1367 }
1368
1369 rc = get_buffer_req(&drv_ctx.op_buf);
1370 if (rc) {
1371 DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1372 return rc;
1373 }
1374
1375 return rc;
1376 }
1377
1378 /* ======================================================================
1379 FUNCTION
1380 omx_vdec::OMXCntrlProcessMsgCb
1381
1382 DESCRIPTION
1383 IL Client callbacks are generated through this routine. The decoder
1384 provides the thread context for this routine.
1385
1386 PARAMETERS
1387 ctxt -- Context information related to the self.
1388 id -- Event identifier. This could be any of the following:
1389 1. Command completion event
1390 2. Buffer done callback event
1391 3. Frame done callback event
1392
1393 RETURN VALUE
1394 None.
1395
1396 ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1397 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1398 {
1399 unsigned long p1; // Parameter - 1
1400 unsigned long p2; // Parameter - 2
1401 unsigned long ident;
1402 unsigned qsize=0; // qsize
1403 omx_vdec *pThis = (omx_vdec *) ctxt;
1404
1405 if (!pThis) {
1406 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1407 __func__);
1408 return;
1409 }
1410
1411 // Protect the shared queue data structure
1412 do {
1413 /*Read the message id's from the queue*/
1414 pthread_mutex_lock(&pThis->m_lock);
1415 qsize = pThis->m_cmd_q.m_size;
1416 if (qsize) {
1417 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1418 }
1419
1420 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1421 qsize = pThis->m_ftb_q.m_size;
1422 if (qsize) {
1423 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1424 }
1425 }
1426
1427 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1428 qsize = pThis->m_etb_q.m_size;
1429 if (qsize) {
1430 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1431 }
1432 }
1433 pthread_mutex_unlock(&pThis->m_lock);
1434
1435 /*process message if we have one*/
1436 if (qsize > 0) {
1437 id = ident;
1438 switch (id) {
1439 case OMX_COMPONENT_GENERATE_EVENT:
1440 if (pThis->m_cb.EventHandler) {
1441 switch (p1) {
1442 case OMX_CommandStateSet:
1443 pThis->m_state = (OMX_STATETYPE) p2;
1444 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1445 pThis->m_state);
1446 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1447 OMX_EventCmdComplete, p1, p2, NULL);
1448 break;
1449
1450 case OMX_EventError:
1451 if (p2 == OMX_StateInvalid) {
1452 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1453 pThis->m_state = (OMX_STATETYPE) p2;
1454 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1455 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1456 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1457 pThis->omx_report_error();
1458 } else {
1459 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1460 OMX_EventError, p2, (OMX_U32)NULL, NULL );
1461 }
1462 break;
1463
1464 case OMX_CommandPortDisable:
1465 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1466 if (BITMASK_PRESENT(&pThis->m_flags,
1467 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1468 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1469 break;
1470 }
1471 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1472 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1473 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1474 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1475 DEBUG_PRINT_HIGH("Failed to release output buffers");
1476 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1477 if (eRet != OMX_ErrorNone) {
1478 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1479 pThis->omx_report_error();
1480 break;
1481 }
1482 }
1483 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1484 OMX_EventCmdComplete, p1, p2, NULL );
1485 break;
1486 case OMX_CommandPortEnable:
1487 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1488 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1489 OMX_EventCmdComplete, p1, p2, NULL );
1490 pThis->in_reconfig = false;
1491 break;
1492
1493 default:
1494 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1495 OMX_EventCmdComplete, p1, p2, NULL );
1496 break;
1497
1498 }
1499 } else {
1500 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1501 }
1502 break;
1503 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1504 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1505 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1506 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1507 pThis->omx_report_error ();
1508 }
1509 break;
1510 case OMX_COMPONENT_GENERATE_ETB: {
1511 OMX_ERRORTYPE iret;
1512 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1513 if (iret == OMX_ErrorInsufficientResources) {
1514 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1515 pThis->omx_report_hw_overload ();
1516 } else if (iret != OMX_ErrorNone) {
1517 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1518 pThis->omx_report_error ();
1519 }
1520 }
1521 break;
1522
1523 case OMX_COMPONENT_GENERATE_FTB:
1524 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1525 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1526 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1527 pThis->omx_report_error ();
1528 }
1529 break;
1530
1531 case OMX_COMPONENT_GENERATE_COMMAND:
1532 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1533 (OMX_U32)p2,(OMX_PTR)NULL);
1534 break;
1535
1536 case OMX_COMPONENT_GENERATE_EBD:
1537
1538 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1539 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1540 pThis->omx_report_error ();
1541 } else {
1542 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1543 pThis->time_stamp_dts.remove_time_stamp(
1544 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1545 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1546 ?true:false);
1547 }
1548
1549 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1550 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1551 DEBUG_PRINT_ERROR("empty_buffer_done failure");
1552 pThis->omx_report_error ();
1553 }
1554 }
1555 break;
1556 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1557 int64_t *timestamp = (int64_t *)(intptr_t)p1;
1558 if (p1) {
1559 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1560 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1561 ?true:false);
1562 free(timestamp);
1563 }
1564 }
1565 break;
1566 case OMX_COMPONENT_GENERATE_FBD:
1567 if (p2 != VDEC_S_SUCCESS) {
1568 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1569 pThis->omx_report_error ();
1570 } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1571 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1572 DEBUG_PRINT_ERROR("fill_buffer_done failure");
1573 pThis->omx_report_error ();
1574 }
1575 break;
1576
1577 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1578 DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1579 if (!pThis->input_flush_progress) {
1580 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1581 } else {
1582 pThis->execute_input_flush();
1583 if (pThis->m_cb.EventHandler) {
1584 if (p2 != VDEC_S_SUCCESS) {
1585 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1586 pThis->omx_report_error ();
1587 } else {
1588 /*Check if we need generate event for Flush done*/
1589 pThis->notify_flush_done(ctxt);
1590
1591 if (BITMASK_PRESENT(&pThis->m_flags,
1592 OMX_COMPONENT_IDLE_PENDING)) {
1593 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1594 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1595 pThis->omx_report_error ();
1596 } else {
1597 pThis->streaming[OUTPUT_PORT] = false;
1598 }
1599 if (!pThis->output_flush_progress) {
1600 DEBUG_PRINT_LOW("Input flush done hence issue stop");
1601 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1602 OMX_COMPONENT_GENERATE_STOP_DONE);
1603 }
1604 }
1605 }
1606 } else {
1607 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1608 }
1609 }
1610 break;
1611
1612 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1613 DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1614 if (!pThis->output_flush_progress) {
1615 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1616 } else {
1617 pThis->execute_output_flush();
1618 if (pThis->m_cb.EventHandler) {
1619 if (p2 != VDEC_S_SUCCESS) {
1620 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1621 pThis->omx_report_error ();
1622 } else {
1623 /*Check if we need generate event for Flush done*/
1624 pThis->notify_flush_done(ctxt);
1625
1626 if (BITMASK_PRESENT(&pThis->m_flags,
1627 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1628 DEBUG_PRINT_LOW("Internal flush complete");
1629 BITMASK_CLEAR (&pThis->m_flags,
1630 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1631 if (BITMASK_PRESENT(&pThis->m_flags,
1632 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1633 pThis->post_event(OMX_CommandPortDisable,
1634 OMX_CORE_OUTPUT_PORT_INDEX,
1635 OMX_COMPONENT_GENERATE_EVENT);
1636 BITMASK_CLEAR (&pThis->m_flags,
1637 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1638 BITMASK_CLEAR (&pThis->m_flags,
1639 OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1640
1641 }
1642 }
1643
1644 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1645 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1646 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1647 pThis->omx_report_error ();
1648 break;
1649 }
1650 pThis->streaming[CAPTURE_PORT] = false;
1651 if (!pThis->input_flush_progress) {
1652 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1653 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1654 OMX_COMPONENT_GENERATE_STOP_DONE);
1655 }
1656 }
1657 }
1658 } else {
1659 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1660 }
1661 }
1662 break;
1663
1664 case OMX_COMPONENT_GENERATE_START_DONE:
1665 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1666
1667 if (pThis->m_cb.EventHandler) {
1668 if (p2 != VDEC_S_SUCCESS) {
1669 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1670 pThis->omx_report_error ();
1671 } else {
1672 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1673 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1674 DEBUG_PRINT_LOW("Move to executing");
1675 // Send the callback now
1676 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1677 pThis->m_state = OMX_StateExecuting;
1678 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1679 OMX_EventCmdComplete,OMX_CommandStateSet,
1680 OMX_StateExecuting, NULL);
1681 } else if (BITMASK_PRESENT(&pThis->m_flags,
1682 OMX_COMPONENT_PAUSE_PENDING)) {
1683 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1684 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1685 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1686 pThis->omx_report_error ();
1687 }
1688 }
1689 }
1690 } else {
1691 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1692 }
1693 break;
1694
1695 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1696 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1697 if (pThis->m_cb.EventHandler) {
1698 if (p2 != VDEC_S_SUCCESS) {
1699 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1700 pThis->omx_report_error ();
1701 } else {
1702 pThis->complete_pending_buffer_done_cbs();
1703 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1704 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1705 //Send the callback now
1706 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1707 pThis->m_state = OMX_StatePause;
1708 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1709 OMX_EventCmdComplete,OMX_CommandStateSet,
1710 OMX_StatePause, NULL);
1711 }
1712 }
1713 } else {
1714 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1715 }
1716
1717 break;
1718
1719 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1720 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1721 if (pThis->m_cb.EventHandler) {
1722 if (p2 != VDEC_S_SUCCESS) {
1723 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1724 pThis->omx_report_error ();
1725 } else {
1726 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1727 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1728 // Send the callback now
1729 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1730 pThis->m_state = OMX_StateExecuting;
1731 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1732 OMX_EventCmdComplete,OMX_CommandStateSet,
1733 OMX_StateExecuting,NULL);
1734 }
1735 }
1736 } else {
1737 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1738 }
1739
1740 break;
1741
1742 case OMX_COMPONENT_GENERATE_STOP_DONE:
1743 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1744 if (pThis->m_cb.EventHandler) {
1745 if (p2 != VDEC_S_SUCCESS) {
1746 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1747 pThis->omx_report_error ();
1748 } else {
1749 pThis->complete_pending_buffer_done_cbs();
1750 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1751 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1752 // Send the callback now
1753 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1754 pThis->m_state = OMX_StateIdle;
1755 DEBUG_PRINT_LOW("Move to Idle State");
1756 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1757 OMX_EventCmdComplete,OMX_CommandStateSet,
1758 OMX_StateIdle,NULL);
1759 }
1760 }
1761 } else {
1762 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1763 }
1764
1765 break;
1766
1767 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1768 if (p2 == OMX_IndexParamPortDefinition) {
1769 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1770 pThis->in_reconfig = true;
1771 pThis->m_need_turbo &= ~TURBO_MODE_HIGH_FPS;
1772 } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1773 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1774
1775 /* Check if resolution is changed in smooth streaming mode */
1776 if (pThis->m_smoothstreaming_mode &&
1777 (pThis->framesize.nWidth !=
1778 pThis->drv_ctx.video_resolution.frame_width) ||
1779 (pThis->framesize.nHeight !=
1780 pThis->drv_ctx.video_resolution.frame_height)) {
1781
1782 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1783 pThis->framesize.nWidth,
1784 pThis->framesize.nHeight,
1785 pThis->drv_ctx.video_resolution.frame_width,
1786 pThis->drv_ctx.video_resolution.frame_height);
1787
1788 /* Update new resolution */
1789 pThis->framesize.nWidth =
1790 pThis->drv_ctx.video_resolution.frame_width;
1791 pThis->framesize.nHeight =
1792 pThis->drv_ctx.video_resolution.frame_height;
1793
1794 /* Update C2D with new resolution */
1795 if (!pThis->client_buffers.update_buffer_req()) {
1796 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1797 }
1798 }
1799
1800 /* Update new crop information */
1801 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1802 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1803 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1804 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1805
1806 /* Validate the new crop information */
1807 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1808 pThis->drv_ctx.video_resolution.frame_width) {
1809
1810 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1811 pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1812 pThis->drv_ctx.video_resolution.frame_width);
1813 pThis->rectangle.nLeft = 0;
1814
1815 if (pThis->rectangle.nWidth >
1816 pThis->drv_ctx.video_resolution.frame_width) {
1817
1818 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1819 pThis->rectangle.nWidth,
1820 pThis->drv_ctx.video_resolution.frame_width);
1821 pThis->rectangle.nWidth =
1822 pThis->drv_ctx.video_resolution.frame_width;
1823 }
1824 }
1825 if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1826 pThis->drv_ctx.video_resolution.frame_height) {
1827
1828 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1829 pThis->rectangle.nTop, pThis->rectangle.nHeight,
1830 pThis->drv_ctx.video_resolution.frame_height);
1831 pThis->rectangle.nTop = 0;
1832
1833 if (pThis->rectangle.nHeight >
1834 pThis->drv_ctx.video_resolution.frame_height) {
1835
1836 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1837 pThis->rectangle.nHeight,
1838 pThis->drv_ctx.video_resolution.frame_height);
1839 pThis->rectangle.nHeight =
1840 pThis->drv_ctx.video_resolution.frame_height;
1841 }
1842 }
1843 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1844 pThis->rectangle.nLeft, pThis->rectangle.nTop,
1845 pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1846 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1847 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1848 } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1849 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1850 } else {
1851 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1852 break;
1853 }
1854 if (pThis->m_debug.outfile) {
1855 fclose(pThis->m_debug.outfile);
1856 pThis->m_debug.outfile = NULL;
1857 }
1858 if (pThis->m_debug.out_ymeta_file) {
1859 fclose(pThis->m_debug.out_ymeta_file);
1860 pThis->m_debug.out_ymeta_file = NULL;
1861 }
1862 if (pThis->m_debug.out_uvmeta_file) {
1863 fclose(pThis->m_debug.out_uvmeta_file);
1864 pThis->m_debug.out_uvmeta_file = NULL;
1865 }
1866
1867 if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1868 pThis->prefetchNewBuffers();
1869 }
1870
1871 if (pThis->m_cb.EventHandler) {
1872 uint32_t frame_data[7];
1873 frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1874 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1875 frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1876 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1877
1878 frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ?
1879 frame_data[0] : pThis->drv_ctx.video_resolution.frame_height;
1880
1881 frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ?
1882 frame_data[1] : pThis->drv_ctx.video_resolution.frame_width;
1883 frame_data[4] = pThis->dpb_bit_depth;
1884 frame_data[5] = pThis->m_color_space;
1885 frame_data[6] = pThis->m_dither_config;
1886
1887 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1888 OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1889 } else {
1890 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1891 }
1892 break;
1893
1894 case OMX_COMPONENT_GENERATE_EOS_DONE:
1895 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1896 if (pThis->m_cb.EventHandler) {
1897 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1898 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1899 } else {
1900 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1901 }
1902 pThis->prev_ts = LLONG_MAX;
1903 pThis->rst_prev_ts = true;
1904 break;
1905
1906 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1907 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1908 pThis->omx_report_error();
1909 break;
1910
1911 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1912 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1913 pThis->omx_report_unsupported_setting();
1914 break;
1915
1916 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1917 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1918 pThis->omx_report_hw_overload();
1919 break;
1920
1921 default:
1922 break;
1923 }
1924 }
1925 pthread_mutex_lock(&pThis->m_lock);
1926 qsize = pThis->m_cmd_q.m_size;
1927 if (pThis->m_state != OMX_StatePause)
1928 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1929 pthread_mutex_unlock(&pThis->m_lock);
1930 } while (qsize>0);
1931
1932 }
1933
update_resolution(int width,int height,int stride,int scan_lines)1934 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1935 {
1936 int format_changed = 0;
1937 if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1938 (width != (int)drv_ctx.video_resolution.frame_width)) {
1939 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1940 width, drv_ctx.video_resolution.frame_width,
1941 height,drv_ctx.video_resolution.frame_height);
1942 format_changed = 1;
1943 }
1944 drv_ctx.video_resolution.frame_height = height;
1945 drv_ctx.video_resolution.frame_width = width;
1946 drv_ctx.video_resolution.scan_lines = scan_lines;
1947 drv_ctx.video_resolution.stride = stride;
1948
1949 if (!is_down_scalar_enabled) {
1950 rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
1951 rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
1952 rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
1953 rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
1954 }
1955 return format_changed;
1956 }
1957
is_video_session_supported()1958 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1959 {
1960 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1961 OMX_MAX_STRINGNAME_SIZE) &&
1962 (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1963 m_decoder_capability.max_width = 1280;
1964 m_decoder_capability.max_height = 720;
1965 DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1966 }
1967
1968 if ((drv_ctx.video_resolution.frame_width *
1969 drv_ctx.video_resolution.frame_height >
1970 m_decoder_capability.max_width *
1971 m_decoder_capability.max_height) ||
1972 (drv_ctx.video_resolution.frame_width*
1973 drv_ctx.video_resolution.frame_height <
1974 m_decoder_capability.min_width *
1975 m_decoder_capability.min_height)) {
1976 DEBUG_PRINT_ERROR(
1977 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1978 drv_ctx.video_resolution.frame_width,
1979 drv_ctx.video_resolution.frame_height,
1980 m_decoder_capability.min_width,
1981 m_decoder_capability.min_height,
1982 m_decoder_capability.max_width,
1983 m_decoder_capability.max_height);
1984 return OMX_ErrorUnsupportedSetting;
1985 }
1986 DEBUG_PRINT_HIGH("video session supported");
1987 return OMX_ErrorNone;
1988 }
1989
log_input_buffers(const char * buffer_addr,int buffer_len)1990 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1991 {
1992 if (m_debug.in_buffer_log && !m_debug.infile) {
1993 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1994 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1995 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1996 } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1997 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1998 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1999 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
2000 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
2001 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2002 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
2003 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2004 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
2005 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2006 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2007 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
2008 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2009 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
2010 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2011 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2012 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
2013 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
2014 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2015 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
2016 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2017 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2018 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2019 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2020 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2021 } else {
2022 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
2023 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2024 }
2025 m_debug.infile = fopen (m_debug.infile_name, "ab");
2026 if (!m_debug.infile) {
2027 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
2028 m_debug.infile_name[0] = '\0';
2029 return -1;
2030 }
2031 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2032 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2033 struct ivf_file_header {
2034 OMX_U8 signature[4]; //='DKIF';
2035 OMX_U8 version ; //= 0;
2036 OMX_U8 headersize ; //= 32;
2037 OMX_U32 FourCC;
2038 OMX_U8 width;
2039 OMX_U8 height;
2040 OMX_U32 rate;
2041 OMX_U32 scale;
2042 OMX_U32 length;
2043 OMX_U8 unused[4];
2044 } file_header;
2045
2046 memset((void *)&file_header,0,sizeof(file_header));
2047 file_header.signature[0] = 'D';
2048 file_header.signature[1] = 'K';
2049 file_header.signature[2] = 'I';
2050 file_header.signature[3] = 'F';
2051 file_header.version = 0;
2052 file_header.headersize = 32;
2053 switch (drv_ctx.decoder_format) {
2054 case VDEC_CODECTYPE_VP8:
2055 file_header.FourCC = 0x30385056;
2056 break;
2057 case VDEC_CODECTYPE_VP9:
2058 file_header.FourCC = 0x30395056;
2059 break;
2060 default:
2061 DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
2062 break;
2063 }
2064 fwrite((const char *)&file_header,
2065 sizeof(file_header),1,m_debug.infile);
2066 }
2067 }
2068 if (m_debug.infile && buffer_addr && buffer_len) {
2069 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2070 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2071 struct vpx_ivf_frame_header {
2072 OMX_U32 framesize;
2073 OMX_U32 timestamp_lo;
2074 OMX_U32 timestamp_hi;
2075 } vpx_frame_header;
2076 vpx_frame_header.framesize = buffer_len;
2077 /* Currently FW doesn't use timestamp values */
2078 vpx_frame_header.timestamp_lo = 0;
2079 vpx_frame_header.timestamp_hi = 0;
2080 fwrite((const char *)&vpx_frame_header,
2081 sizeof(vpx_frame_header),1,m_debug.infile);
2082 }
2083 fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
2084 }
2085 return 0;
2086 }
2087
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2088 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2089 int buf_index = 0;
2090 char *temp = NULL;
2091
2092 if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2093 return 0;
2094
2095 if (m_debug.out_buffer_log && !m_debug.outfile) {
2096 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
2097 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2098 m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2099 if (!m_debug.outfile) {
2100 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2101 m_debug.outfile_name[0] = '\0';
2102 return -1;
2103 }
2104 }
2105
2106 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2107 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2108 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2109 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2110 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2111 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2112 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2113 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2114 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2115 m_debug.out_ymetafile_name[0] = '\0';
2116 m_debug.out_uvmetafile_name[0] = '\0';
2117 return -1;
2118 }
2119 }
2120
2121 buf_index = buffer - m_out_mem_ptr;
2122 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2123
2124 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2125 drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2126 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2127 drv_ctx.video_resolution.frame_width,
2128 drv_ctx.video_resolution.frame_height);
2129
2130 if (m_debug.outfile)
2131 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2132
2133 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2134 unsigned int width = 0, height = 0;
2135 unsigned int y_plane, y_meta_plane;
2136 int y_stride = 0, y_sclines = 0;
2137 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2138 int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2139 int i;
2140 int bytes_written = 0;
2141
2142 width = drv_ctx.video_resolution.frame_width;
2143 height = drv_ctx.video_resolution.frame_height;
2144 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2145 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2146 y_stride = VENUS_Y_STRIDE(color_fmt, width);
2147 y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2148 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2149 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2150
2151 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2152 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2153
2154 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2155 for (i = 0; i < y_meta_scanlines; i++) {
2156 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2157 temp += y_meta_stride;
2158 }
2159
2160 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
2161 for(i = 0; i < uv_meta_scanlines; i++) {
2162 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2163 temp += uv_meta_stride;
2164 }
2165 }
2166 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2167 int stride = drv_ctx.video_resolution.stride;
2168 int scanlines = drv_ctx.video_resolution.scan_lines;
2169 if (m_smoothstreaming_mode) {
2170 stride = drv_ctx.video_resolution.frame_width;
2171 scanlines = drv_ctx.video_resolution.frame_height;
2172 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2173 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2174 }
2175 unsigned i;
2176 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2177 drv_ctx.video_resolution.frame_width,
2178 drv_ctx.video_resolution.frame_height, stride, scanlines);
2179 int bytes_written = 0;
2180 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2181 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2182 temp += stride;
2183 }
2184 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
2185 int stride_c = stride;
2186 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2187 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2188 temp += stride_c;
2189 }
2190 }
2191 return 0;
2192 }
2193
2194 /* ======================================================================
2195 FUNCTION
2196 omx_vdec::ComponentInit
2197
2198 DESCRIPTION
2199 Initialize the component.
2200
2201 PARAMETERS
2202 ctxt -- Context information related to the self.
2203 id -- Event identifier. This could be any of the following:
2204 1. Command completion event
2205 2. Buffer done callback event
2206 3. Frame done callback event
2207
2208 RETURN VALUE
2209 None.
2210
2211 ========================================================================== */
component_init(OMX_STRING role)2212 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2213 {
2214
2215 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2216 struct v4l2_fmtdesc fdesc;
2217 struct v4l2_format fmt;
2218 struct v4l2_requestbuffers bufreq;
2219 struct v4l2_control control;
2220 struct v4l2_frmsizeenum frmsize;
2221 unsigned int alignment = 0,buffer_size = 0;
2222 int fds[2];
2223 int r,ret=0;
2224 bool codec_ambiguous = false;
2225 OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2226 char property_value[PROPERTY_VALUE_MAX] = {0};
2227 FILE *soc_file = NULL;
2228 char buffer[10];
2229
2230 #ifdef _ANDROID_
2231 char platform_name[PROPERTY_VALUE_MAX];
2232 property_get("ro.board.platform", platform_name, "0");
2233 if (!strncmp(platform_name, "msm8610", 7)) {
2234 device_name = (OMX_STRING)"/dev/video/q6_dec";
2235 is_q6_platform = true;
2236 maxSmoothStreamingWidth = 1280;
2237 maxSmoothStreamingHeight = 720;
2238 }
2239 #endif
2240
2241 is_thulium_v1 = false;
2242 soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2243 if (soc_file) {
2244 fread(buffer, 1, 4, soc_file);
2245 fclose(soc_file);
2246 if (atoi(buffer) == 246) {
2247 soc_file = fopen("/sys/devices/soc0/revision", "r");
2248 if (soc_file) {
2249 fread(buffer, 1, 4, soc_file);
2250 fclose(soc_file);
2251 if (atoi(buffer) == 1) {
2252 is_thulium_v1 = true;
2253 DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2254 }
2255 }
2256 }
2257 }
2258
2259 #ifdef _ANDROID_
2260 /*
2261 * turn off frame parsing for Android by default.
2262 * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2263 */
2264 arbitrary_bytes = false;
2265 property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2266 if (atoi(property_value)) {
2267 DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2268 arbitrary_bytes = true;
2269 }
2270 #endif
2271
2272 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2273 OMX_MAX_STRINGNAME_SIZE)) {
2274 secure_mode = true;
2275 arbitrary_bytes = false;
2276 role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2277 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2278 OMX_MAX_STRINGNAME_SIZE)) {
2279 secure_mode = true;
2280 arbitrary_bytes = false;
2281 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2282 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2283 OMX_MAX_STRINGNAME_SIZE)) {
2284 secure_mode = true;
2285 arbitrary_bytes = false;
2286 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2287 } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2288 OMX_MAX_STRINGNAME_SIZE)) {
2289 secure_mode = true;
2290 arbitrary_bytes = false;
2291 role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2292 } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2293 OMX_MAX_STRINGNAME_SIZE)) {
2294 secure_mode = true;
2295 arbitrary_bytes = false;
2296 role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2297 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2298 OMX_MAX_STRINGNAME_SIZE)) {
2299 secure_mode = true;
2300 arbitrary_bytes = false;
2301 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2302 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2303 OMX_MAX_STRINGNAME_SIZE)) {
2304 secure_mode = true;
2305 arbitrary_bytes = false;
2306 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2307 }
2308 else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure",
2309 OMX_MAX_STRINGNAME_SIZE)) {
2310 secure_mode = true;
2311 arbitrary_bytes = false;
2312 role = (OMX_STRING)"OMX.qcom.video.decoder.vp8";
2313 }
2314
2315 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2316
2317 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2318
2319 if (drv_ctx.video_driver_fd < 0) {
2320 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2321 return OMX_ErrorInsufficientResources;
2322 }
2323 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2324 drv_ctx.frame_rate.fps_denominator = 1;
2325 operating_frame_rate = DEFAULT_FPS;
2326 m_poll_efd = eventfd(0, 0);
2327 if (m_poll_efd < 0) {
2328 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2329 return OMX_ErrorInsufficientResources;
2330 }
2331 ret = subscribe_to_events(drv_ctx.video_driver_fd);
2332 if (!ret) {
2333 async_thread_created = true;
2334 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2335 }
2336 if (ret) {
2337 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2338 async_thread_created = false;
2339 return OMX_ErrorInsufficientResources;
2340 }
2341
2342 #ifdef OUTPUT_EXTRADATA_LOG
2343 outputExtradataFile = fopen (output_extradata_filename, "ab");
2344 #endif
2345
2346 // Copy the role information which provides the decoder kind
2347 strlcpy(drv_ctx.kind,role,128);
2348
2349 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2350 OMX_MAX_STRINGNAME_SIZE)) {
2351 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2352 OMX_MAX_STRINGNAME_SIZE);
2353 drv_ctx.timestamp_adjust = true;
2354 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2355 eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2356 output_capability=V4L2_PIX_FMT_MPEG4;
2357 /*Initialize Start Code for MPEG4*/
2358 codec_type_parse = CODEC_TYPE_MPEG4;
2359 m_frame_parser.init_start_codes(codec_type_parse);
2360 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2361 OMX_MAX_STRINGNAME_SIZE)) {
2362 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2363 OMX_MAX_STRINGNAME_SIZE);
2364 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2365 output_capability = V4L2_PIX_FMT_MPEG2;
2366 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2367 /*Initialize Start Code for MPEG2*/
2368 codec_type_parse = CODEC_TYPE_MPEG2;
2369 m_frame_parser.init_start_codes(codec_type_parse);
2370 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2371 OMX_MAX_STRINGNAME_SIZE)) {
2372 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2373 DEBUG_PRINT_LOW("H263 Decoder selected");
2374 drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2375 eCompressionFormat = OMX_VIDEO_CodingH263;
2376 output_capability = V4L2_PIX_FMT_H263;
2377 codec_type_parse = CODEC_TYPE_H263;
2378 m_frame_parser.init_start_codes(codec_type_parse);
2379 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2380 OMX_MAX_STRINGNAME_SIZE)) {
2381 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2382 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2383 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2384 output_capability = V4L2_PIX_FMT_DIVX_311;
2385 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2386 codec_type_parse = CODEC_TYPE_DIVX;
2387 m_frame_parser.init_start_codes(codec_type_parse);
2388
2389 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2390 OMX_MAX_STRINGNAME_SIZE)) {
2391 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2392 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2393 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2394 output_capability = V4L2_PIX_FMT_DIVX;
2395 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2396 codec_type_parse = CODEC_TYPE_DIVX;
2397 codec_ambiguous = true;
2398 m_frame_parser.init_start_codes(codec_type_parse);
2399
2400 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2401 OMX_MAX_STRINGNAME_SIZE)) {
2402 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2403 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2404 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2405 output_capability = V4L2_PIX_FMT_DIVX;
2406 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2407 codec_type_parse = CODEC_TYPE_DIVX;
2408 codec_ambiguous = true;
2409 m_frame_parser.init_start_codes(codec_type_parse);
2410
2411 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2412 OMX_MAX_STRINGNAME_SIZE)) {
2413 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2414 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2415 output_capability=V4L2_PIX_FMT_H264;
2416 eCompressionFormat = OMX_VIDEO_CodingAVC;
2417 codec_type_parse = CODEC_TYPE_H264;
2418 m_frame_parser.init_start_codes(codec_type_parse);
2419 m_frame_parser.init_nal_length(nal_length);
2420 if (is_thulium_v1) {
2421 arbitrary_bytes = true;
2422 DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2423 }
2424 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2425 OMX_MAX_STRINGNAME_SIZE)) {
2426 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2427 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2428 output_capability = V4L2_PIX_FMT_H264_MVC;
2429 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2430 codec_type_parse = CODEC_TYPE_H264;
2431 m_frame_parser.init_start_codes(codec_type_parse);
2432 m_frame_parser.init_nal_length(nal_length);
2433 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2434 OMX_MAX_STRINGNAME_SIZE)) {
2435 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2436 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2437 output_capability = V4L2_PIX_FMT_HEVC;
2438 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2439 codec_type_parse = CODEC_TYPE_HEVC;
2440 m_frame_parser.init_start_codes(codec_type_parse);
2441 m_frame_parser.init_nal_length(nal_length);
2442 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2443 OMX_MAX_STRINGNAME_SIZE)) {
2444 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2445 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2446 eCompressionFormat = OMX_VIDEO_CodingWMV;
2447 codec_type_parse = CODEC_TYPE_VC1;
2448 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2449 m_frame_parser.init_start_codes(codec_type_parse);
2450 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2451 OMX_MAX_STRINGNAME_SIZE)) {
2452 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2453 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2454 eCompressionFormat = OMX_VIDEO_CodingWMV;
2455 codec_type_parse = CODEC_TYPE_VC1;
2456 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2457 m_frame_parser.init_start_codes(codec_type_parse);
2458 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
2459 OMX_MAX_STRINGNAME_SIZE)) {
2460 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2461 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2462 output_capability = V4L2_PIX_FMT_VP8;
2463 eCompressionFormat = OMX_VIDEO_CodingVP8;
2464 codec_type_parse = CODEC_TYPE_VP8;
2465 arbitrary_bytes = false;
2466 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \
2467 OMX_MAX_STRINGNAME_SIZE)) {
2468 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2469 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2470 output_capability = V4L2_PIX_FMT_VP9;
2471 eCompressionFormat = OMX_VIDEO_CodingVP9;
2472 codec_type_parse = CODEC_TYPE_VP9;
2473 arbitrary_bytes = false;
2474 } else {
2475 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2476 eRet = OMX_ErrorInvalidComponentName;
2477 }
2478
2479 if (eRet == OMX_ErrorNone) {
2480 OMX_COLOR_FORMATTYPE dest_color_format;
2481 if (m_disable_ubwc_mode) {
2482 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2483 } else {
2484 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2485 }
2486 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2487 dest_color_format = (OMX_COLOR_FORMATTYPE)
2488 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2489 else
2490 dest_color_format = (OMX_COLOR_FORMATTYPE)
2491 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2492 if (!client_buffers.set_color_format(dest_color_format)) {
2493 DEBUG_PRINT_ERROR("Setting color format failed");
2494 eRet = OMX_ErrorInsufficientResources;
2495 }
2496
2497 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2498 m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2499
2500 if (m_disable_ubwc_mode) {
2501 capture_capability = V4L2_PIX_FMT_NV12;
2502 } else {
2503 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2504 }
2505
2506 struct v4l2_capability cap;
2507 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2508 if (ret) {
2509 DEBUG_PRINT_ERROR("Failed to query capabilities");
2510 /*TODO: How to handle this case */
2511 } else {
2512 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2513 " version = %d, capabilities = %x", cap.driver, cap.card,
2514 cap.bus_info, cap.version, cap.capabilities);
2515 }
2516 ret=0;
2517 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2518 fdesc.index=0;
2519 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2520 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2521 fdesc.pixelformat, fdesc.flags);
2522 fdesc.index++;
2523 }
2524 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2525 fdesc.index=0;
2526 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2527
2528 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2529 fdesc.pixelformat, fdesc.flags);
2530 fdesc.index++;
2531 }
2532 m_extradata_info.output_crop_rect.nLeft = 0;
2533 m_extradata_info.output_crop_rect.nTop = 0;
2534 m_extradata_info.output_crop_rect.nWidth = 320;
2535 m_extradata_info.output_crop_rect.nHeight = 240;
2536 update_resolution(320, 240, 320, 240);
2537
2538 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2539 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2540 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2541 fmt.fmt.pix_mp.pixelformat = output_capability;
2542 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2543 if (ret) {
2544 /*TODO: How to handle this case */
2545 DEBUG_PRINT_ERROR("Failed to set format on output port");
2546 return OMX_ErrorInsufficientResources;
2547 }
2548 DEBUG_PRINT_HIGH("Set Format was successful");
2549 if (codec_ambiguous) {
2550 if (output_capability == V4L2_PIX_FMT_DIVX) {
2551 struct v4l2_control divx_ctrl;
2552
2553 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2554 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2555 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2556 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2557 } else {
2558 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2559 }
2560
2561 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2562 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2563 if (ret) {
2564 DEBUG_PRINT_ERROR("Failed to set divx version");
2565 }
2566 } else {
2567 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2568 }
2569 }
2570
2571 property_get("persist.vendor.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2572 m_conceal_color= atoi(property_value);
2573 DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2574 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2575 control.value = m_conceal_color;
2576 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2577 if (ret) {
2578 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2579 }
2580
2581 //Get the hardware capabilities
2582 memset((void *)&frmsize,0,sizeof(frmsize));
2583 frmsize.index = 0;
2584 frmsize.pixel_format = output_capability;
2585 ret = ioctl(drv_ctx.video_driver_fd,
2586 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2587 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2588 DEBUG_PRINT_ERROR("Failed to get framesizes");
2589 return OMX_ErrorHardware;
2590 }
2591
2592 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2593 m_decoder_capability.min_width = frmsize.stepwise.min_width;
2594 m_decoder_capability.max_width = frmsize.stepwise.max_width;
2595 m_decoder_capability.min_height = frmsize.stepwise.min_height;
2596 m_decoder_capability.max_height = frmsize.stepwise.max_height;
2597 }
2598
2599 memset(&fmt, 0x0, sizeof(struct v4l2_format));
2600 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2601 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2602 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2603 fmt.fmt.pix_mp.pixelformat = capture_capability;
2604 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2605 if (ret) {
2606 /*TODO: How to handle this case */
2607 DEBUG_PRINT_ERROR("Failed to set format on capture port");
2608 }
2609 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2610 framesize.nWidth = drv_ctx.video_resolution.frame_width;
2611 framesize.nHeight = drv_ctx.video_resolution.frame_height;
2612
2613 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2614 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2615 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2616
2617 DEBUG_PRINT_HIGH("Set Format was successful");
2618 if (secure_mode) {
2619 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2620 control.value = 1;
2621 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2622 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2623 if (ret) {
2624 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2625 return OMX_ErrorInsufficientResources;
2626 }
2627 }
2628 if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2629 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2630 control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2631 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2632 if (ret) {
2633 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2634 return OMX_ErrorInsufficientResources;
2635 }
2636 }
2637
2638 if (is_thulium_v1) {
2639 eRet = enable_smoothstreaming();
2640 if (eRet != OMX_ErrorNone) {
2641 DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2642 return eRet;
2643 }
2644 }
2645
2646 /*Get the Buffer requirements for input and output ports*/
2647 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2648 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2649
2650 if (secure_mode) {
2651 drv_ctx.op_buf.alignment = SECURE_ALIGN;
2652 drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2653 } else {
2654 drv_ctx.op_buf.alignment = SZ_4K;
2655 drv_ctx.ip_buf.alignment = SZ_4K;
2656 }
2657
2658 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2659 drv_ctx.extradata = 0;
2660 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2661 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2662 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2663 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2664 drv_ctx.idr_only_decoding = 0;
2665
2666 #ifdef _ANDROID_
2667 property_get("vendor.vidc.dec.enable.downscalar",property_value,"0");
2668 if (atoi(property_value)) {
2669 m_enable_downscalar = atoi(property_value);
2670 property_get("vendor.vidc.dec.downscalar_width",property_value,"0");
2671 if (atoi(property_value)) {
2672 m_downscalar_width = atoi(property_value);
2673 }
2674 property_get("vendor.vidc.dec.downscalar_height",property_value,"0");
2675 if (atoi(property_value)) {
2676 m_downscalar_height = atoi(property_value);
2677 }
2678
2679 if (m_downscalar_width < m_decoder_capability.min_width ||
2680 m_downscalar_height < m_decoder_capability.min_height) {
2681 m_downscalar_width = 0;
2682 m_downscalar_height = 0;
2683 }
2684
2685 DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2686 m_downscalar_width, m_downscalar_height);
2687 }
2688 property_get("vendor.vidc.disable.split.mode",property_value,"0");
2689 m_disable_split_mode = atoi(property_value);
2690 DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");
2691 #endif
2692 m_state = OMX_StateLoaded;
2693 #ifdef DEFAULT_EXTRADATA
2694 enable_extradata(DEFAULT_EXTRADATA, true, true);
2695 #endif
2696 eRet = get_buffer_req(&drv_ctx.ip_buf);
2697 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2698 get_buffer_req(&drv_ctx.op_buf);
2699 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2700 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2701 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2702 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2703 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2704 h264_scratch.nFilledLen = 0;
2705 h264_scratch.nOffset = 0;
2706
2707 if (h264_scratch.pBuffer == NULL) {
2708 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2709 return OMX_ErrorInsufficientResources;
2710 }
2711 }
2712 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2713 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2714 if (m_frame_parser.mutils == NULL) {
2715 m_frame_parser.mutils = new H264_Utils();
2716 if (m_frame_parser.mutils == NULL) {
2717 DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2718 eRet = OMX_ErrorInsufficientResources;
2719 } else {
2720 m_frame_parser.mutils->initialize_frame_checking_environment();
2721 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2722 }
2723 }
2724
2725 h264_parser = new h264_stream_parser();
2726 if (!h264_parser) {
2727 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2728 eRet = OMX_ErrorInsufficientResources;
2729 }
2730 }
2731
2732 if (pipe(fds)) {
2733 DEBUG_PRINT_ERROR("pipe creation failed");
2734 eRet = OMX_ErrorInsufficientResources;
2735 } else {
2736 m_pipe_in = fds[0];
2737 m_pipe_out = fds[1];
2738 msg_thread_created = true;
2739 r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2740
2741 if (r < 0) {
2742 DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2743 msg_thread_created = false;
2744 eRet = OMX_ErrorInsufficientResources;
2745 }
2746 }
2747 }
2748
2749 {
2750 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2751 init_vendor_extensions(*extStore);
2752 mVendorExtensionStore.dumpExtensions((const char *)role);
2753 }
2754
2755 if (eRet != OMX_ErrorNone) {
2756 DEBUG_PRINT_ERROR("Component Init Failed");
2757 } else {
2758 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2759 drv_ctx.video_driver_fd);
2760 }
2761 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2762 return eRet;
2763 }
2764
2765 /* ======================================================================
2766 FUNCTION
2767 omx_vdec::GetComponentVersion
2768
2769 DESCRIPTION
2770 Returns the component version.
2771
2772 PARAMETERS
2773 TBD.
2774
2775 RETURN VALUE
2776 OMX_ErrorNone.
2777
2778 ========================================================================== */
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)2779 OMX_ERRORTYPE omx_vdec::get_component_version
2780 (
2781 OMX_IN OMX_HANDLETYPE hComp,
2782 OMX_OUT OMX_STRING componentName,
2783 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2784 OMX_OUT OMX_VERSIONTYPE* specVersion,
2785 OMX_OUT OMX_UUIDTYPE* componentUUID
2786 )
2787 {
2788 (void) hComp;
2789 (void) componentName;
2790 (void) componentVersion;
2791 (void) componentUUID;
2792 if (m_state == OMX_StateInvalid) {
2793 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2794 return OMX_ErrorInvalidState;
2795 }
2796 /* TBD -- Return the proper version */
2797 if (specVersion) {
2798 specVersion->nVersion = OMX_SPEC_VERSION;
2799 }
2800 return OMX_ErrorNone;
2801 }
2802 /* ======================================================================
2803 FUNCTION
2804 omx_vdec::SendCommand
2805
2806 DESCRIPTION
2807 Returns zero if all the buffers released..
2808
2809 PARAMETERS
2810 None.
2811
2812 RETURN VALUE
2813 true/false
2814
2815 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2816 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2817 OMX_IN OMX_COMMANDTYPE cmd,
2818 OMX_IN OMX_U32 param1,
2819 OMX_IN OMX_PTR cmdData
2820 )
2821 {
2822 (void) hComp;
2823 (void) cmdData;
2824 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2825 if (m_state == OMX_StateInvalid) {
2826 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2827 return OMX_ErrorInvalidState;
2828 }
2829 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2830 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2831 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2832 "to invalid port: %u", (unsigned int)param1);
2833 return OMX_ErrorBadPortIndex;
2834 }
2835
2836 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2837 sem_wait(&m_cmd_lock);
2838 DEBUG_PRINT_LOW("send_command: Command Processed");
2839 return OMX_ErrorNone;
2840 }
2841
2842 /* ======================================================================
2843 FUNCTION
2844 omx_vdec::SendCommand
2845
2846 DESCRIPTION
2847 Returns zero if all the buffers released..
2848
2849 PARAMETERS
2850 None.
2851
2852 RETURN VALUE
2853 true/false
2854
2855 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2856 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2857 OMX_IN OMX_COMMANDTYPE cmd,
2858 OMX_IN OMX_U32 param1,
2859 OMX_IN OMX_PTR cmdData
2860 )
2861 {
2862 (void) hComp;
2863 (void) cmdData;
2864 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2865 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2866 int bFlag = 1,sem_posted = 0,ret=0;
2867
2868 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2869 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2870 m_state, eState);
2871
2872 if (cmd == OMX_CommandStateSet) {
2873 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2874 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2875 /***************************/
2876 /* Current State is Loaded */
2877 /***************************/
2878 if (m_state == OMX_StateLoaded) {
2879 if (eState == OMX_StateIdle) {
2880 //if all buffers are allocated or all ports disabled
2881 if (allocate_done() ||
2882 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2883 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2884 } else {
2885 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2886 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2887 // Skip the event notification
2888 bFlag = 0;
2889 }
2890 }
2891 /* Requesting transition from Loaded to Loaded */
2892 else if (eState == OMX_StateLoaded) {
2893 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2894 post_event(OMX_EventError,OMX_ErrorSameState,\
2895 OMX_COMPONENT_GENERATE_EVENT);
2896 eRet = OMX_ErrorSameState;
2897 }
2898 /* Requesting transition from Loaded to WaitForResources */
2899 else if (eState == OMX_StateWaitForResources) {
2900 /* Since error is None , we will post an event
2901 at the end of this function definition */
2902 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2903 }
2904 /* Requesting transition from Loaded to Executing */
2905 else if (eState == OMX_StateExecuting) {
2906 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2907 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2908 OMX_COMPONENT_GENERATE_EVENT);
2909 eRet = OMX_ErrorIncorrectStateTransition;
2910 }
2911 /* Requesting transition from Loaded to Pause */
2912 else if (eState == OMX_StatePause) {
2913 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2914 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2915 OMX_COMPONENT_GENERATE_EVENT);
2916 eRet = OMX_ErrorIncorrectStateTransition;
2917 }
2918 /* Requesting transition from Loaded to Invalid */
2919 else if (eState == OMX_StateInvalid) {
2920 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2921 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2922 eRet = OMX_ErrorInvalidState;
2923 } else {
2924 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2925 eState);
2926 eRet = OMX_ErrorBadParameter;
2927 }
2928 }
2929
2930 /***************************/
2931 /* Current State is IDLE */
2932 /***************************/
2933 else if (m_state == OMX_StateIdle) {
2934 if (eState == OMX_StateLoaded) {
2935 if (release_done()) {
2936 /*
2937 * Since error is None , we will post an event at the end
2938 * of this function definition
2939 * Reset buffer requirements here to ensure setting buffer requirement
2940 * when component move to executing state from loaded state via Idle.
2941 */
2942 drv_ctx.op_buf.buffer_size = 0;
2943 drv_ctx.op_buf.actualcount = 0;
2944 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2945 } else {
2946 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2947 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2948 // Skip the event notification
2949 bFlag = 0;
2950 }
2951 }
2952 /* Requesting transition from Idle to Executing */
2953 else if (eState == OMX_StateExecuting) {
2954 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2955 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2956 bFlag = 1;
2957 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2958 m_state=OMX_StateExecuting;
2959 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2960 }
2961 /* Requesting transition from Idle to Idle */
2962 else if (eState == OMX_StateIdle) {
2963 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2964 post_event(OMX_EventError,OMX_ErrorSameState,\
2965 OMX_COMPONENT_GENERATE_EVENT);
2966 eRet = OMX_ErrorSameState;
2967 }
2968 /* Requesting transition from Idle to WaitForResources */
2969 else if (eState == OMX_StateWaitForResources) {
2970 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2971 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2972 OMX_COMPONENT_GENERATE_EVENT);
2973 eRet = OMX_ErrorIncorrectStateTransition;
2974 }
2975 /* Requesting transition from Idle to Pause */
2976 else if (eState == OMX_StatePause) {
2977 /*To pause the Video core we need to start the driver*/
2978 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2979 NULL) < */0) {
2980 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2981 omx_report_error ();
2982 eRet = OMX_ErrorHardware;
2983 } else {
2984 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2985 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2986 bFlag = 0;
2987 }
2988 }
2989 /* Requesting transition from Idle to Invalid */
2990 else if (eState == OMX_StateInvalid) {
2991 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2992 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2993 eRet = OMX_ErrorInvalidState;
2994 } else {
2995 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2996 eRet = OMX_ErrorBadParameter;
2997 }
2998 }
2999
3000 /******************************/
3001 /* Current State is Executing */
3002 /******************************/
3003 else if (m_state == OMX_StateExecuting) {
3004 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
3005 /* Requesting transition from Executing to Idle */
3006 if (eState == OMX_StateIdle) {
3007 /* Since error is None , we will post an event
3008 at the end of this function definition
3009 */
3010 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
3011 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3012 if (!sem_posted) {
3013 sem_posted = 1;
3014 sem_post (&m_cmd_lock);
3015 execute_omx_flush(OMX_ALL);
3016 }
3017 bFlag = 0;
3018 }
3019 /* Requesting transition from Executing to Paused */
3020 else if (eState == OMX_StatePause) {
3021 DEBUG_PRINT_LOW("PAUSE Command Issued");
3022 m_state = OMX_StatePause;
3023 bFlag = 1;
3024 }
3025 /* Requesting transition from Executing to Loaded */
3026 else if (eState == OMX_StateLoaded) {
3027 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
3028 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3029 OMX_COMPONENT_GENERATE_EVENT);
3030 eRet = OMX_ErrorIncorrectStateTransition;
3031 }
3032 /* Requesting transition from Executing to WaitForResources */
3033 else if (eState == OMX_StateWaitForResources) {
3034 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
3035 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3036 OMX_COMPONENT_GENERATE_EVENT);
3037 eRet = OMX_ErrorIncorrectStateTransition;
3038 }
3039 /* Requesting transition from Executing to Executing */
3040 else if (eState == OMX_StateExecuting) {
3041 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
3042 post_event(OMX_EventError,OMX_ErrorSameState,\
3043 OMX_COMPONENT_GENERATE_EVENT);
3044 eRet = OMX_ErrorSameState;
3045 }
3046 /* Requesting transition from Executing to Invalid */
3047 else if (eState == OMX_StateInvalid) {
3048 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
3049 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3050 eRet = OMX_ErrorInvalidState;
3051 } else {
3052 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
3053 eRet = OMX_ErrorBadParameter;
3054 }
3055 }
3056 /***************************/
3057 /* Current State is Pause */
3058 /***************************/
3059 else if (m_state == OMX_StatePause) {
3060 /* Requesting transition from Pause to Executing */
3061 if (eState == OMX_StateExecuting) {
3062 DEBUG_PRINT_LOW("Pause --> Executing");
3063 m_state = OMX_StateExecuting;
3064 bFlag = 1;
3065 }
3066 /* Requesting transition from Pause to Idle */
3067 else if (eState == OMX_StateIdle) {
3068 /* Since error is None , we will post an event
3069 at the end of this function definition */
3070 DEBUG_PRINT_LOW("Pause --> Idle");
3071 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3072 if (!sem_posted) {
3073 sem_posted = 1;
3074 sem_post (&m_cmd_lock);
3075 execute_omx_flush(OMX_ALL);
3076 }
3077 bFlag = 0;
3078 }
3079 /* Requesting transition from Pause to loaded */
3080 else if (eState == OMX_StateLoaded) {
3081 DEBUG_PRINT_ERROR("Pause --> loaded");
3082 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3083 OMX_COMPONENT_GENERATE_EVENT);
3084 eRet = OMX_ErrorIncorrectStateTransition;
3085 }
3086 /* Requesting transition from Pause to WaitForResources */
3087 else if (eState == OMX_StateWaitForResources) {
3088 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
3089 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3090 OMX_COMPONENT_GENERATE_EVENT);
3091 eRet = OMX_ErrorIncorrectStateTransition;
3092 }
3093 /* Requesting transition from Pause to Pause */
3094 else if (eState == OMX_StatePause) {
3095 DEBUG_PRINT_ERROR("Pause --> Pause");
3096 post_event(OMX_EventError,OMX_ErrorSameState,\
3097 OMX_COMPONENT_GENERATE_EVENT);
3098 eRet = OMX_ErrorSameState;
3099 }
3100 /* Requesting transition from Pause to Invalid */
3101 else if (eState == OMX_StateInvalid) {
3102 DEBUG_PRINT_ERROR("Pause --> Invalid");
3103 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3104 eRet = OMX_ErrorInvalidState;
3105 } else {
3106 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
3107 eRet = OMX_ErrorBadParameter;
3108 }
3109 }
3110 /***************************/
3111 /* Current State is WaitForResources */
3112 /***************************/
3113 else if (m_state == OMX_StateWaitForResources) {
3114 /* Requesting transition from WaitForResources to Loaded */
3115 if (eState == OMX_StateLoaded) {
3116 /* Since error is None , we will post an event
3117 at the end of this function definition */
3118 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
3119 }
3120 /* Requesting transition from WaitForResources to WaitForResources */
3121 else if (eState == OMX_StateWaitForResources) {
3122 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
3123 post_event(OMX_EventError,OMX_ErrorSameState,
3124 OMX_COMPONENT_GENERATE_EVENT);
3125 eRet = OMX_ErrorSameState;
3126 }
3127 /* Requesting transition from WaitForResources to Executing */
3128 else if (eState == OMX_StateExecuting) {
3129 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
3130 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3131 OMX_COMPONENT_GENERATE_EVENT);
3132 eRet = OMX_ErrorIncorrectStateTransition;
3133 }
3134 /* Requesting transition from WaitForResources to Pause */
3135 else if (eState == OMX_StatePause) {
3136 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
3137 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3138 OMX_COMPONENT_GENERATE_EVENT);
3139 eRet = OMX_ErrorIncorrectStateTransition;
3140 }
3141 /* Requesting transition from WaitForResources to Invalid */
3142 else if (eState == OMX_StateInvalid) {
3143 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
3144 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3145 eRet = OMX_ErrorInvalidState;
3146 }
3147 /* Requesting transition from WaitForResources to Loaded -
3148 is NOT tested by Khronos TS */
3149
3150 } else {
3151 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
3152 eRet = OMX_ErrorBadParameter;
3153 }
3154 }
3155 /********************************/
3156 /* Current State is Invalid */
3157 /*******************************/
3158 else if (m_state == OMX_StateInvalid) {
3159 /* State Transition from Invalid to any state */
3160 if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
3161 eState == OMX_StateIdle || eState == OMX_StateExecuting ||
3162 eState == OMX_StatePause || eState == OMX_StateInvalid) {
3163 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
3164 post_event(OMX_EventError,OMX_ErrorInvalidState,\
3165 OMX_COMPONENT_GENERATE_EVENT);
3166 eRet = OMX_ErrorInvalidState;
3167 }
3168 } else if (cmd == OMX_CommandFlush) {
3169 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
3170 "with param1: %u", (unsigned int)param1);
3171 #ifdef _MSM8974_
3172 send_codec_config();
3173 #endif
3174 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3175 param1 == OMX_ALL)) {
3176 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3177 struct timespec ts;
3178
3179 clock_gettime(CLOCK_REALTIME, &ts);
3180 ts.tv_sec += 2;
3181 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3182 m_queued_codec_config_count);
3183 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3184 if (sem_timedwait(&m_safe_flush, &ts)) {
3185 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3186 }
3187 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3188 }
3189 }
3190
3191 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3192 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3193 }
3194 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3195 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3196 }
3197 if (!sem_posted) {
3198 sem_posted = 1;
3199 DEBUG_PRINT_LOW("Set the Semaphore");
3200 sem_post (&m_cmd_lock);
3201 execute_omx_flush(param1);
3202 }
3203 bFlag = 0;
3204 } else if ( cmd == OMX_CommandPortEnable) {
3205 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3206 "with param1: %u", (unsigned int)param1);
3207 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3208 m_inp_bEnabled = OMX_TRUE;
3209
3210 if ( (m_state == OMX_StateLoaded &&
3211 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3212 || allocate_input_done()) {
3213 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3214 OMX_COMPONENT_GENERATE_EVENT);
3215 } else {
3216 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3217 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3218 // Skip the event notification
3219 bFlag = 0;
3220 }
3221 }
3222 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3223 DEBUG_PRINT_LOW("Enable output Port command recieved");
3224 m_out_bEnabled = OMX_TRUE;
3225
3226 if ( (m_state == OMX_StateLoaded &&
3227 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3228 || (allocate_output_done())) {
3229 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3230 OMX_COMPONENT_GENERATE_EVENT);
3231
3232 } else {
3233 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3234 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3235 // Skip the event notification
3236 bFlag = 0;
3237 /* enable/disable downscaling if required */
3238 ret = decide_downscalar();
3239 if (ret) {
3240 DEBUG_PRINT_LOW("decide_downscalar failed\n");
3241 }
3242 }
3243 }
3244 } else if (cmd == OMX_CommandPortDisable) {
3245 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3246 "with param1: %u", (unsigned int)param1);
3247 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3248 codec_config_flag = false;
3249 m_inp_bEnabled = OMX_FALSE;
3250 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3251 && release_input_done()) {
3252 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3253 OMX_COMPONENT_GENERATE_EVENT);
3254 } else {
3255 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3256 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3257 if (!sem_posted) {
3258 sem_posted = 1;
3259 sem_post (&m_cmd_lock);
3260 }
3261 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3262 }
3263
3264 // Skip the event notification
3265 bFlag = 0;
3266 }
3267 }
3268 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3269 m_out_bEnabled = OMX_FALSE;
3270 DEBUG_PRINT_LOW("Disable output Port command recieved");
3271 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3272 && release_output_done()) {
3273 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3274 OMX_COMPONENT_GENERATE_EVENT);
3275 } else {
3276 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3277 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3278 if (!sem_posted) {
3279 sem_posted = 1;
3280 sem_post (&m_cmd_lock);
3281 }
3282 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3283 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3284 }
3285 // Skip the event notification
3286 bFlag = 0;
3287
3288 }
3289 }
3290 } else {
3291 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3292 eRet = OMX_ErrorNotImplemented;
3293 }
3294 if (eRet == OMX_ErrorNone && bFlag) {
3295 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3296 }
3297 if (!sem_posted) {
3298 sem_post(&m_cmd_lock);
3299 }
3300
3301 return eRet;
3302 }
3303
3304 /* ======================================================================
3305 FUNCTION
3306 omx_vdec::ExecuteOmxFlush
3307
3308 DESCRIPTION
3309 Executes the OMX flush.
3310
3311 PARAMETERS
3312 flushtype - input flush(1)/output flush(0)/ both.
3313
3314 RETURN VALUE
3315 true/false
3316
3317 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3318 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3319 {
3320 bool bRet = false;
3321 struct v4l2_plane plane;
3322 struct v4l2_buffer v4l2_buf;
3323 struct v4l2_decoder_cmd dec;
3324 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3325 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3326 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3327
3328 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3329
3330 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3331 output_flush_progress = true;
3332 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3333 } else {
3334 /* XXX: The driver/hardware does not support flushing of individual ports
3335 * in all states. So we pretty much need to flush both ports internally,
3336 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3337 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3338 * we automatically omit sending the FLUSH done for the "opposite" port. */
3339 input_flush_progress = true;
3340 output_flush_progress = true;
3341 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3342 request_perf_level(VIDC_TURBO);
3343 }
3344
3345 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3346 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3347 bRet = false;
3348 }
3349
3350 return bRet;
3351 }
3352 /*=========================================================================
3353 FUNCTION : execute_output_flush
3354
3355 DESCRIPTION
3356 Executes the OMX flush at OUTPUT PORT.
3357
3358 PARAMETERS
3359 None.
3360
3361 RETURN VALUE
3362 true/false
3363 ==========================================================================*/
execute_output_flush()3364 bool omx_vdec::execute_output_flush()
3365 {
3366 unsigned long p1 = 0; // Parameter - 1
3367 unsigned long p2 = 0; // Parameter - 2
3368 unsigned long ident = 0;
3369 bool bRet = true;
3370
3371 /*Generate FBD for all Buffers in the FTBq*/
3372 pthread_mutex_lock(&m_lock);
3373 DEBUG_PRINT_LOW("Initiate Output Flush");
3374
3375 //reset last render TS
3376 if(m_last_rendered_TS > 0) {
3377 m_last_rendered_TS = 0;
3378 }
3379
3380 while (m_ftb_q.m_size) {
3381 DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3382 m_ftb_q.m_size,pending_output_buffers);
3383 m_ftb_q.pop_entry(&p1,&p2,&ident);
3384 DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3385 if (ident == m_fill_output_msg ) {
3386 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3387 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3388 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3389 }
3390 }
3391 pthread_mutex_unlock(&m_lock);
3392 output_flush_progress = false;
3393
3394 if (arbitrary_bytes) {
3395 prev_ts = LLONG_MAX;
3396 rst_prev_ts = true;
3397 }
3398 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3399 return bRet;
3400 }
3401 /*=========================================================================
3402 FUNCTION : execute_input_flush
3403
3404 DESCRIPTION
3405 Executes the OMX flush at INPUT PORT.
3406
3407 PARAMETERS
3408 None.
3409
3410 RETURN VALUE
3411 true/false
3412 ==========================================================================*/
execute_input_flush()3413 bool omx_vdec::execute_input_flush()
3414 {
3415 unsigned i =0;
3416 unsigned long p1 = 0; // Parameter - 1
3417 unsigned long p2 = 0; // Parameter - 2
3418 unsigned long ident = 0;
3419 bool bRet = true;
3420
3421 /*Generate EBD for all Buffers in the ETBq*/
3422 DEBUG_PRINT_LOW("Initiate Input Flush");
3423
3424 pthread_mutex_lock(&m_lock);
3425 DEBUG_PRINT_LOW("Check if the Queue is empty");
3426 while (m_etb_q.m_size) {
3427 m_etb_q.pop_entry(&p1,&p2,&ident);
3428
3429 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3430 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3431 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3432 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3433 pending_input_buffers++;
3434 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3435 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3436 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3437 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3438 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3439 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3440 (OMX_BUFFERHEADERTYPE *)p1);
3441 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3442 }
3443 }
3444 time_stamp_dts.flush_timestamp();
3445 /*Check if Heap Buffers are to be flushed*/
3446 if (arbitrary_bytes && !(codec_config_flag)) {
3447 DEBUG_PRINT_LOW("Reset all the variables before flusing");
3448 h264_scratch.nFilledLen = 0;
3449 nal_count = 0;
3450 look_ahead_nal = false;
3451 frame_count = 0;
3452 h264_last_au_ts = LLONG_MAX;
3453 h264_last_au_flags = 0;
3454 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3455 m_demux_entries = 0;
3456 DEBUG_PRINT_LOW("Initialize parser");
3457 if (m_frame_parser.mutils) {
3458 m_frame_parser.mutils->initialize_frame_checking_environment();
3459 }
3460
3461 while (m_input_pending_q.m_size) {
3462 m_input_pending_q.pop_entry(&p1,&p2,&ident);
3463 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3464 }
3465
3466 if (psource_frame) {
3467 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3468 psource_frame = NULL;
3469 }
3470
3471 if (pdest_frame) {
3472 pdest_frame->nFilledLen = 0;
3473 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3474 (unsigned int)NULL);
3475 pdest_frame = NULL;
3476 }
3477 m_frame_parser.flush();
3478 } else if (codec_config_flag) {
3479 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3480 "is not sent to the driver yet");
3481 }
3482 pthread_mutex_unlock(&m_lock);
3483 input_flush_progress = false;
3484 if (!arbitrary_bytes) {
3485 prev_ts = LLONG_MAX;
3486 rst_prev_ts = true;
3487 }
3488 #ifdef _ANDROID_
3489 if (m_debug_timestamp) {
3490 m_timestamp_list.reset_ts_list();
3491 }
3492 #endif
3493 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3494 return bRet;
3495 }
3496
3497 /*=========================================================================
3498 FUNCTION : notify_flush_done
3499
3500 DESCRIPTION
3501 Notifies flush done to the OMX Client.
3502
3503 PARAMETERS
3504 ctxt -- Context information related to the self..
3505
3506 RETURN VALUE
3507 NONE
3508 ==========================================================================*/
notify_flush_done(void * ctxt)3509 void omx_vdec::notify_flush_done(void *ctxt) {
3510
3511 omx_vdec *pThis = (omx_vdec *) ctxt;
3512
3513 if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3514 if (BITMASK_PRESENT(&pThis->m_flags,
3515 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3516 DEBUG_PRINT_LOW("Notify Output Flush done");
3517 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3518 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3519 OMX_EventCmdComplete,OMX_CommandFlush,
3520 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3521 }
3522
3523 if (BITMASK_PRESENT(&pThis->m_flags,
3524 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3525 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3526 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3527 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3528 OMX_EventCmdComplete,OMX_CommandFlush,
3529 OMX_CORE_INPUT_PORT_INDEX,NULL );
3530 }
3531 }
3532 }
3533
3534 /* ======================================================================
3535 FUNCTION
3536 omx_vdec::SendCommandEvent
3537
3538 DESCRIPTION
3539 Send the event to decoder pipe. This is needed to generate the callbacks
3540 in decoder thread context.
3541
3542 PARAMETERS
3543 None.
3544
3545 RETURN VALUE
3546 true/false
3547
3548 ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3549 bool omx_vdec::post_event(unsigned long p1,
3550 unsigned long p2,
3551 unsigned long id)
3552 {
3553 bool bRet = false;
3554
3555 /* Just drop messages typically generated by hardware (w/o client request),
3556 * if we've reported an error to client. */
3557 if (m_error_propogated) {
3558 switch (id) {
3559 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3560 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3561 DEBUG_PRINT_ERROR("Dropping message %lx "
3562 "since client expected to be in error state", id);
3563 return false;
3564 default:
3565 /* whatever */
3566 break;
3567 }
3568 }
3569
3570 pthread_mutex_lock(&m_lock);
3571
3572 if (id == m_fill_output_msg ||
3573 id == OMX_COMPONENT_GENERATE_FBD ||
3574 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3575 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3576 m_ftb_q.insert_entry(p1,p2,id);
3577 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3578 id == OMX_COMPONENT_GENERATE_EBD ||
3579 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3580 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3581 m_etb_q.insert_entry(p1,p2,id);
3582 } else {
3583 m_cmd_q.insert_entry(p1,p2,id);
3584 }
3585
3586 bRet = true;
3587 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3588 post_message(this, id);
3589
3590 pthread_mutex_unlock(&m_lock);
3591
3592 return bRet;
3593 }
3594
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3595 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3596 {
3597 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3598 if (!profileLevelType)
3599 return OMX_ErrorBadParameter;
3600
3601 if (profileLevelType->nPortIndex == 0) {
3602 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3603 profileLevelType->eLevel = OMX_VIDEO_AVCLevel52;
3604 if (profileLevelType->nProfileIndex == 0) {
3605 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3606 } else if (profileLevelType->nProfileIndex == 1) {
3607 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3608 } else if (profileLevelType->nProfileIndex == 2) {
3609 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3610 } else if (profileLevelType->nProfileIndex == 3) {
3611 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
3612 } else if (profileLevelType->nProfileIndex == 4) {
3613 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
3614 } else if (profileLevelType->nProfileIndex == 5) {
3615 profileLevelType->eProfile = OMX_VIDEO_AVCProfileConstrainedHigh;
3616 } else if (profileLevelType->nProfileIndex == 6) {
3617 profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
3618 } else {
3619 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3620 (unsigned int)profileLevelType->nProfileIndex);
3621 eRet = OMX_ErrorNoMore;
3622 }
3623 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3624 if (profileLevelType->nProfileIndex == 0) {
3625 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3626 profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51;
3627 } else {
3628 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3629 (unsigned int)profileLevelType->nProfileIndex);
3630 eRet = OMX_ErrorNoMore;
3631 }
3632 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3633 if (profileLevelType->nProfileIndex == 0) {
3634 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3635 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
3636 } else if (profileLevelType->nProfileIndex == 1) {
3637 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3638 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
3639 } else if (profileLevelType->nProfileIndex == 2) {
3640 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
3641 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
3642 } else {
3643 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3644 (unsigned int)profileLevelType->nProfileIndex);
3645 eRet = OMX_ErrorNoMore;
3646 }
3647 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3648 if (profileLevelType->nProfileIndex == 0) {
3649 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3650 profileLevelType->eLevel = OMX_VIDEO_H263Level70;
3651 } else {
3652 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3653 (unsigned int)profileLevelType->nProfileIndex);
3654 eRet = OMX_ErrorNoMore;
3655 }
3656 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3657 if (profileLevelType->nProfileIndex == 0) {
3658 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3659 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
3660 } else if (profileLevelType->nProfileIndex == 1) {
3661 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3662 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
3663 } else {
3664 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3665 (unsigned int)profileLevelType->nProfileIndex);
3666 eRet = OMX_ErrorNoMore;
3667 }
3668 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3669 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3670 eRet = OMX_ErrorNoMore;
3671 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3672 if (profileLevelType->nProfileIndex == 0) {
3673 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3674 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
3675 } else if (profileLevelType->nProfileIndex == 1) {
3676 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3677 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
3678 } else {
3679 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3680 (unsigned int)profileLevelType->nProfileIndex);
3681 eRet = OMX_ErrorNoMore;
3682 }
3683 } else {
3684 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3685 eRet = OMX_ErrorNoMore;
3686 }
3687 } else {
3688 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3689 (unsigned int)profileLevelType->nPortIndex);
3690 eRet = OMX_ErrorBadPortIndex;
3691 }
3692 return eRet;
3693 }
3694
3695 /* ======================================================================
3696 FUNCTION
3697 omx_vdec::GetParameter
3698
3699 DESCRIPTION
3700 OMX Get Parameter method implementation
3701
3702 PARAMETERS
3703 <TBD>.
3704
3705 RETURN VALUE
3706 Error None if successful.
3707
3708 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3709 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
3710 OMX_IN OMX_INDEXTYPE paramIndex,
3711 OMX_INOUT OMX_PTR paramData)
3712 {
3713 (void) hComp;
3714 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3715
3716 DEBUG_PRINT_LOW("get_parameter:");
3717 if (m_state == OMX_StateInvalid) {
3718 DEBUG_PRINT_ERROR("Get Param in Invalid State");
3719 return OMX_ErrorInvalidState;
3720 }
3721 if (paramData == NULL) {
3722 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3723 return OMX_ErrorBadParameter;
3724 }
3725 switch ((unsigned long)paramIndex) {
3726 case OMX_IndexParamPortDefinition: {
3727 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3728 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3729 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3730 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3731 decide_dpb_buffer_mode(is_down_scalar_enabled);
3732 eRet = update_portdef(portDefn);
3733 if (eRet == OMX_ErrorNone)
3734 m_port_def = *portDefn;
3735 break;
3736 }
3737 case OMX_IndexParamVideoInit: {
3738 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3739 OMX_PORT_PARAM_TYPE *portParamType =
3740 (OMX_PORT_PARAM_TYPE *) paramData;
3741 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3742
3743 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3744 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3745 portParamType->nPorts = 2;
3746 portParamType->nStartPortNumber = 0;
3747 break;
3748 }
3749 case OMX_IndexParamVideoPortFormat: {
3750 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3751 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3752 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3753 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3754
3755 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3756 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3757
3758 if (0 == portFmt->nPortIndex) {
3759 if (0 == portFmt->nIndex) {
3760 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
3761 portFmt->eCompressionFormat = eCompressionFormat;
3762 } else {
3763 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3764 " NoMore compression formats");
3765 eRet = OMX_ErrorNoMore;
3766 }
3767 } else if (1 == portFmt->nPortIndex) {
3768 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
3769
3770 // Distinguish non-surface mode from normal playback use-case based on
3771 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3772 // For non-android, use the default list
3773 // Also use default format-list if FLEXIBLE YUV is supported,
3774 // as the client negotiates the standard color-format if it needs to
3775 bool useNonSurfaceMode = false;
3776 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3777 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3778 #endif
3779 if (is_thulium_v1) {
3780 portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3781 } else {
3782 portFmt->eColorFormat = useNonSurfaceMode ?
3783 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3784 getPreferredColorFormatDefaultMode(portFmt->nIndex);
3785 }
3786
3787 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3788 eRet = OMX_ErrorNoMore;
3789 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3790 " NoMore Color formats");
3791 }
3792 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3793 } else {
3794 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3795 (int)portFmt->nPortIndex);
3796 eRet = OMX_ErrorBadPortIndex;
3797 }
3798 break;
3799 }
3800 /*Component should support this port definition*/
3801 case OMX_IndexParamAudioInit: {
3802 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3803 OMX_PORT_PARAM_TYPE *audioPortParamType =
3804 (OMX_PORT_PARAM_TYPE *) paramData;
3805 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3806 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3807 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3808 audioPortParamType->nPorts = 0;
3809 audioPortParamType->nStartPortNumber = 0;
3810 break;
3811 }
3812 /*Component should support this port definition*/
3813 case OMX_IndexParamImageInit: {
3814 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3815 OMX_PORT_PARAM_TYPE *imagePortParamType =
3816 (OMX_PORT_PARAM_TYPE *) paramData;
3817 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3818 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3819 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3820 imagePortParamType->nPorts = 0;
3821 imagePortParamType->nStartPortNumber = 0;
3822 break;
3823
3824 }
3825 /*Component should support this port definition*/
3826 case OMX_IndexParamOtherInit: {
3827 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3828 paramIndex);
3829 eRet =OMX_ErrorUnsupportedIndex;
3830 break;
3831 }
3832 case OMX_IndexParamStandardComponentRole: {
3833 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3834 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3835 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3836 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3837 comp_role->nSize = sizeof(*comp_role);
3838
3839 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3840 paramIndex);
3841 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3842 OMX_MAX_STRINGNAME_SIZE);
3843 break;
3844 }
3845 /* Added for parameter test */
3846 case OMX_IndexParamPriorityMgmt: {
3847 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3848 OMX_PRIORITYMGMTTYPE *priorityMgmType =
3849 (OMX_PRIORITYMGMTTYPE *) paramData;
3850 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3851 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3852 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3853
3854 break;
3855 }
3856 /* Added for parameter test */
3857 case OMX_IndexParamCompBufferSupplier: {
3858 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3859 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3860 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3861 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3862
3863 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3864 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3865 if (0 == bufferSupplierType->nPortIndex)
3866 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3867 else if (1 == bufferSupplierType->nPortIndex)
3868 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3869 else
3870 eRet = OMX_ErrorBadPortIndex;
3871
3872
3873 break;
3874 }
3875 case OMX_IndexParamVideoAvc: {
3876 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3877 paramIndex);
3878 break;
3879 }
3880 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3881 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3882 paramIndex);
3883 break;
3884 }
3885 case OMX_IndexParamVideoH263: {
3886 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3887 paramIndex);
3888 break;
3889 }
3890 case OMX_IndexParamVideoMpeg4: {
3891 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3892 paramIndex);
3893 break;
3894 }
3895 case OMX_IndexParamVideoMpeg2: {
3896 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3897 paramIndex);
3898 break;
3899 }
3900 case OMX_IndexParamVideoProfileLevelQuerySupported: {
3901 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3902 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3903 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3904 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3905 eRet = get_supported_profile_level(profileLevelType);
3906 break;
3907 }
3908 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3909 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3910 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3911 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3912 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3913 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3914
3915 if (secure_mode && !secure_scaling_to_non_secure_opb) {
3916 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3917 GRALLOC_USAGE_PRIVATE_UNCACHED);
3918 } else {
3919 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3920 }
3921 } else {
3922 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3923 eRet = OMX_ErrorBadParameter;
3924 }
3925 }
3926 break;
3927 #endif
3928
3929 #ifdef FLEXYUV_SUPPORTED
3930 case OMX_QcomIndexFlexibleYUVDescription: {
3931 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3932 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3933 eRet = describeColorFormat(paramData);
3934 break;
3935 }
3936 #endif
3937 case OMX_IndexParamVideoProfileLevelCurrent: {
3938 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3939 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3940 struct v4l2_control profile_control, level_control;
3941
3942 switch (drv_ctx.decoder_format) {
3943 case VDEC_CODECTYPE_H264:
3944 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3945 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3946 break;
3947 default:
3948 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3949 eRet = OMX_ErrorNotImplemented;
3950 break;
3951 }
3952
3953 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3954 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3955 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3956 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3957 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3958 break;
3959 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3960 pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3961 break;
3962 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3963 pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3964 break;
3965 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3966 pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3967 break;
3968 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3969 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3970 break;
3971 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3972 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3973 break;
3974 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3975 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3976 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3977 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3978 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3979 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3980 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3981 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3982 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3983 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3984 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3985 eRet = OMX_ErrorUnsupportedIndex;
3986 break;
3987 }
3988 } else {
3989 eRet = OMX_ErrorUnsupportedIndex;
3990 }
3991
3992
3993 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3994 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3995 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3996 pParam->eLevel = OMX_VIDEO_AVCLevel1;
3997 break;
3998 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3999 pParam->eLevel = OMX_VIDEO_AVCLevel1b;
4000 break;
4001 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
4002 pParam->eLevel = OMX_VIDEO_AVCLevel11;
4003 break;
4004 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
4005 pParam->eLevel = OMX_VIDEO_AVCLevel12;
4006 break;
4007 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
4008 pParam->eLevel = OMX_VIDEO_AVCLevel13;
4009 break;
4010 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
4011 pParam->eLevel = OMX_VIDEO_AVCLevel2;
4012 break;
4013 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
4014 pParam->eLevel = OMX_VIDEO_AVCLevel21;
4015 break;
4016 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
4017 pParam->eLevel = OMX_VIDEO_AVCLevel22;
4018 break;
4019 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4020 pParam->eLevel = OMX_VIDEO_AVCLevel3;
4021 break;
4022 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4023 pParam->eLevel = OMX_VIDEO_AVCLevel31;
4024 break;
4025 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4026 pParam->eLevel = OMX_VIDEO_AVCLevel32;
4027 break;
4028 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4029 pParam->eLevel = OMX_VIDEO_AVCLevel4;
4030 break;
4031 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4032 pParam->eLevel = OMX_VIDEO_AVCLevel41;
4033 break;
4034 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4035 pParam->eLevel = OMX_VIDEO_AVCLevel42;
4036 break;
4037 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4038 pParam->eLevel = OMX_VIDEO_AVCLevel5;
4039 break;
4040 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4041 pParam->eLevel = OMX_VIDEO_AVCLevel51;
4042 break;
4043 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4044 pParam->eLevel = OMX_VIDEO_AVCLevel52;
4045 break;
4046 }
4047 } else {
4048 eRet = OMX_ErrorUnsupportedIndex;
4049 }
4050
4051 break;
4052
4053 }
4054 case OMX_QTIIndexParamVideoClientExtradata:
4055 {
4056 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4057 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
4058 QOMX_EXTRADATA_ENABLE *pParam =
4059 (QOMX_EXTRADATA_ENABLE *)paramData;
4060 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4061 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE;
4062 eRet = OMX_ErrorNone;
4063 } else {
4064 eRet = OMX_ErrorUnsupportedIndex;
4065 }
4066 break;
4067 }
4068 case OMX_QTIIndexParamDitherControl:
4069 {
4070 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4071 DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
4072 QOMX_VIDEO_DITHER_CONTROL *pParam =
4073 (QOMX_VIDEO_DITHER_CONTROL *) paramData;
4074 pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
4075 eRet = OMX_ErrorNone;
4076 break;
4077 }
4078 default: {
4079 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
4080 eRet =OMX_ErrorUnsupportedIndex;
4081 }
4082
4083 }
4084
4085 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
4086 drv_ctx.video_resolution.frame_width,
4087 drv_ctx.video_resolution.frame_height,
4088 drv_ctx.video_resolution.stride,
4089 drv_ctx.video_resolution.scan_lines);
4090
4091 return eRet;
4092 }
4093
4094 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)4095 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
4096 {
4097 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
4098 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4099 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
4100
4101 if ((params == NULL) ||
4102 (params->nativeBuffer == NULL) ||
4103 (params->nativeBuffer->handle == NULL) ||
4104 !m_enable_android_native_buffers)
4105 return OMX_ErrorBadParameter;
4106 m_use_android_native_buffers = OMX_TRUE;
4107 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4108 private_handle_t *handle = (private_handle_t *)nBuf->handle;
4109 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
4110 OMX_U8 *buffer = NULL;
4111 if (!secure_mode) {
4112 buffer = (OMX_U8*)mmap(0, handle->size,
4113 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4114 if (buffer == MAP_FAILED) {
4115 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4116 return OMX_ErrorInsufficientResources;
4117 }
4118 }
4119 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
4120 } else {
4121 eRet = OMX_ErrorBadParameter;
4122 }
4123 return eRet;
4124 }
4125 #endif
4126
enable_smoothstreaming()4127 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
4128 struct v4l2_control control;
4129 struct v4l2_format fmt;
4130 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
4131 control.value = 1;
4132 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4133 if (rc < 0) {
4134 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
4135 return OMX_ErrorHardware;
4136 }
4137 m_smoothstreaming_mode = true;
4138 return OMX_ErrorNone;
4139 }
4140
4141 /* ======================================================================
4142 FUNCTION
4143 omx_vdec::Setparameter
4144
4145 DESCRIPTION
4146 OMX Set Parameter method implementation.
4147
4148 PARAMETERS
4149 <TBD>.
4150
4151 RETURN VALUE
4152 OMX Error None if successful.
4153
4154 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)4155 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
4156 OMX_IN OMX_INDEXTYPE paramIndex,
4157 OMX_IN OMX_PTR paramData)
4158 {
4159 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4160 int ret=0;
4161 struct v4l2_format fmt;
4162 #ifdef _ANDROID_
4163 char property_value[PROPERTY_VALUE_MAX] = {0};
4164 #endif
4165 if (m_state == OMX_StateInvalid) {
4166 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4167 return OMX_ErrorInvalidState;
4168 }
4169 if (paramData == NULL) {
4170 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4171 return OMX_ErrorBadParameter;
4172 }
4173 if ((m_state != OMX_StateLoaded) &&
4174 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4175 (m_out_bEnabled == OMX_TRUE) &&
4176 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4177 (m_inp_bEnabled == OMX_TRUE)) {
4178 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4179 return OMX_ErrorIncorrectStateOperation;
4180 }
4181 switch ((unsigned long)paramIndex) {
4182 case OMX_IndexParamPortDefinition: {
4183 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4184 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4185 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4186 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4187 //been called.
4188 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
4189 (int)portDefn->format.video.nFrameHeight,
4190 (int)portDefn->format.video.nFrameWidth);
4191
4192 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4193 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4194 portDefn->nBufferCountActual);
4195 eRet = OMX_ErrorBadParameter;
4196 break;
4197 }
4198 if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
4199 if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS ||
4200 portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
4201 DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
4202 portDefn->nBufferCountActual, portDefn->nBufferSize);
4203 eRet = OMX_ErrorBadParameter;
4204 break;
4205 }
4206 m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
4207 portDefn->nBufferCountActual);
4208 break;
4209 }
4210
4211 if (OMX_DirOutput == portDefn->eDir) {
4212 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4213 bool port_format_changed = false;
4214 m_display_id = portDefn->format.video.pNativeWindow;
4215 unsigned int buffer_size;
4216 /* update output port resolution with client supplied dimensions
4217 in case scaling is enabled, else it follows input resolution set
4218 */
4219 decide_dpb_buffer_mode(is_down_scalar_enabled);
4220 if (is_down_scalar_enabled) {
4221 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4222 (unsigned int)portDefn->format.video.nFrameWidth,
4223 (unsigned int)portDefn->format.video.nFrameHeight);
4224 if (portDefn->format.video.nFrameHeight != 0x0 &&
4225 portDefn->format.video.nFrameWidth != 0x0) {
4226 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4227 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4228 fmt.fmt.pix_mp.pixelformat = capture_capability;
4229 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4230 if (ret) {
4231 DEBUG_PRINT_ERROR("Get Resolution failed");
4232 eRet = OMX_ErrorHardware;
4233 break;
4234 }
4235 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4236 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4237 port_format_changed = true;
4238 }
4239
4240 /* set crop info */
4241 rectangle.nLeft = 0;
4242 rectangle.nTop = 0;
4243 rectangle.nWidth = portDefn->format.video.nFrameWidth;
4244 rectangle.nHeight = portDefn->format.video.nFrameHeight;
4245
4246 m_extradata_info.output_crop_rect.nLeft = 0;
4247 m_extradata_info.output_crop_rect.nTop = 0;
4248 m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4249 m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4250
4251 eRet = is_video_session_supported();
4252 if (eRet)
4253 break;
4254 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4255 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4256 fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4257 fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4258 fmt.fmt.pix_mp.pixelformat = capture_capability;
4259 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4260 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4261 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4262 if (ret) {
4263 DEBUG_PRINT_ERROR("Set Resolution failed");
4264 eRet = OMX_ErrorUnsupportedSetting;
4265 } else
4266 eRet = get_buffer_req(&drv_ctx.op_buf);
4267 }
4268
4269 if (eRet) {
4270 break;
4271 }
4272
4273 if (secure_mode) {
4274 struct v4l2_control control;
4275 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
4276 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4277 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
4278 eRet = OMX_ErrorHardware;
4279 } else {
4280 /* This is a workaround for a bug in fw which uses stride
4281 * and slice instead of width and height to check against
4282 * the threshold.
4283 */
4284 OMX_U32 stride, slice;
4285 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
4286 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
4287 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
4288 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
4289 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
4290 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
4291 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
4292 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameWidth);
4293 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, portDefn->format.video.nFrameHeight);
4294 } else {
4295 stride = portDefn->format.video.nFrameWidth;
4296 slice = portDefn->format.video.nFrameHeight;
4297 }
4298
4299 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
4300 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
4301
4302 if (stride * slice <= (OMX_U32)control.value) {
4303 secure_scaling_to_non_secure_opb = true;
4304 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
4305 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
4306 control.value = 1;
4307 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4308 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4309 eRet = OMX_ErrorUnsupportedSetting;
4310 }
4311 }
4312 }
4313 }
4314 }
4315
4316 if (eRet) {
4317 break;
4318 }
4319
4320 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4321 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4322 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4323 eRet = OMX_ErrorBadParameter;
4324 } else if (!client_buffers.get_buffer_req(buffer_size)) {
4325 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4326 eRet = OMX_ErrorBadParameter;
4327 } else if (!port_format_changed) {
4328
4329 // Buffer count can change only when port is unallocated
4330 if (m_out_mem_ptr &&
4331 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4332 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4333
4334 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4335 eRet = OMX_ErrorInvalidState;
4336 break;
4337 }
4338
4339 // route updating of buffer requirements via c2d proxy.
4340 // Based on whether c2d is enabled, requirements will be handed
4341 // to the vidc driver appropriately
4342 eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4343 portDefn->nBufferCountActual);
4344 if (eRet == OMX_ErrorNone) {
4345 m_port_def = *portDefn;
4346 } else {
4347 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4348 drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4349 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4350 eRet = OMX_ErrorBadParameter;
4351 }
4352 }
4353 } else if (OMX_DirInput == portDefn->eDir) {
4354 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4355 bool port_format_changed = false;
4356 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4357 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4358 // Frame rate only should be set if this is a "known value" or to
4359 // activate ts prediction logic (arbitrary mode only) sending input
4360 // timestamps with max value (LLONG_MAX).
4361 m_fps_received = portDefn->format.video.xFramerate;
4362 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4363 (unsigned int)portDefn->format.video.xFramerate >> 16);
4364 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4365 drv_ctx.frame_rate.fps_denominator);
4366 if (!drv_ctx.frame_rate.fps_numerator) {
4367 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4368 drv_ctx.frame_rate.fps_numerator = 30;
4369 }
4370 if (drv_ctx.frame_rate.fps_denominator)
4371 drv_ctx.frame_rate.fps_numerator = (int)
4372 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4373 drv_ctx.frame_rate.fps_denominator = 1;
4374 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4375 drv_ctx.frame_rate.fps_numerator;
4376 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4377 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4378 (float)drv_ctx.frame_rate.fps_denominator);
4379
4380 struct v4l2_outputparm oparm;
4381 /*XXX: we're providing timing info as seconds per frame rather than frames
4382 * per second.*/
4383 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4384 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4385
4386 struct v4l2_streamparm sparm;
4387 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4388 sparm.parm.output = oparm;
4389 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4390 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4391 eRet = OMX_ErrorHardware;
4392 break;
4393 }
4394 m_perf_control.request_cores(frm_int);
4395 }
4396
4397 if (drv_ctx.video_resolution.frame_height !=
4398 portDefn->format.video.nFrameHeight ||
4399 drv_ctx.video_resolution.frame_width !=
4400 portDefn->format.video.nFrameWidth) {
4401 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4402 (unsigned int)portDefn->format.video.nFrameWidth,
4403 (unsigned int)portDefn->format.video.nFrameHeight);
4404 port_format_changed = true;
4405 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4406 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4407 if (frameHeight != 0x0 && frameWidth != 0x0) {
4408 if (m_smoothstreaming_mode &&
4409 ((frameWidth * frameHeight) <
4410 (m_smoothstreaming_width * m_smoothstreaming_height))) {
4411 frameWidth = m_smoothstreaming_width;
4412 frameHeight = m_smoothstreaming_height;
4413 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4414 "for adaptive-playback/smooth-streaming",
4415 (unsigned int)frameWidth, (unsigned int)frameHeight);
4416 }
4417
4418 m_extradata_info.output_crop_rect.nLeft = 0;
4419 m_extradata_info.output_crop_rect.nTop = 0;
4420 m_extradata_info.output_crop_rect.nWidth = frameWidth;
4421 m_extradata_info.output_crop_rect.nHeight = frameHeight;
4422
4423 update_resolution(frameWidth, frameHeight,
4424 frameWidth, frameHeight);
4425 eRet = is_video_session_supported();
4426 if (eRet)
4427 break;
4428 if (is_down_scalar_enabled) {
4429 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4430 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4431 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4432 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4433 fmt.fmt.pix_mp.pixelformat = output_capability;
4434 DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4435 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4436 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4437 } else {
4438 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4439 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4440 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4441 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4442 fmt.fmt.pix_mp.pixelformat = output_capability;
4443 DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4444 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4445 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4446 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4447 fmt.fmt.pix_mp.pixelformat = capture_capability;
4448 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4449 }
4450 if (ret) {
4451 DEBUG_PRINT_ERROR("Set Resolution failed");
4452 eRet = OMX_ErrorUnsupportedSetting;
4453 } else {
4454 if (!is_down_scalar_enabled)
4455 eRet = get_buffer_req(&drv_ctx.op_buf);
4456 }
4457 }
4458 }
4459 if (m_custom_buffersize.input_buffersize
4460 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4461 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4462 m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4463 eRet = OMX_ErrorBadParameter;
4464 break;
4465 }
4466 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4467 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4468 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4469 eRet = OMX_ErrorBadParameter;
4470 break;
4471 }
4472 // Buffer count can change only when port is unallocated
4473 if (m_inp_mem_ptr &&
4474 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4475 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4476 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4477 eRet = OMX_ErrorInvalidState;
4478 break;
4479 }
4480
4481 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4482 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4483 port_format_changed = true;
4484 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4485 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4486 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4487 (~(buffer_prop->alignment - 1));
4488 eRet = set_buffer_req(buffer_prop);
4489 }
4490 if (false == port_format_changed) {
4491 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4492 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4493 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4494 eRet = OMX_ErrorBadParameter;
4495 }
4496 } else if (portDefn->eDir == OMX_DirMax) {
4497 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4498 (int)portDefn->nPortIndex);
4499 eRet = OMX_ErrorBadPortIndex;
4500 }
4501 }
4502 break;
4503 case OMX_IndexParamVideoPortFormat: {
4504 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4505 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4506 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4507 int ret=0;
4508 struct v4l2_format fmt;
4509 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4510 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4511
4512 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4513 if (1 == portFmt->nPortIndex) {
4514 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4515 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4516 if (ret < 0) {
4517 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4518 return OMX_ErrorBadParameter;
4519 }
4520 enum vdec_output_fromat op_format;
4521 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4522 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4523 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4524 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4525 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4526 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4527 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4528 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4529 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4530 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4531 } else
4532 eRet = OMX_ErrorBadParameter;
4533
4534 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4535 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4536 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4537 } else {
4538 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4539 }
4540
4541 if (eRet == OMX_ErrorNone) {
4542 drv_ctx.output_format = op_format;
4543 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4544 if (ret) {
4545 DEBUG_PRINT_ERROR("Set output format failed");
4546 eRet = OMX_ErrorUnsupportedSetting;
4547 /*TODO: How to handle this case */
4548 } else {
4549 eRet = get_buffer_req(&drv_ctx.op_buf);
4550 }
4551 }
4552 if (eRet == OMX_ErrorNone) {
4553 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4554 DEBUG_PRINT_ERROR("Set color format failed");
4555 eRet = OMX_ErrorBadParameter;
4556 }
4557 }
4558 }
4559 }
4560 break;
4561
4562 case OMX_QcomIndexPortDefn: {
4563 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4564 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4565 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4566 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4567 (unsigned int)portFmt->nFramePackingFormat);
4568
4569 /* Input port */
4570 if (portFmt->nPortIndex == 0) {
4571 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4572 // - headers are allocated and
4573 // - headers-indices are derived
4574 // Avoid changing arbitrary_bytes when the port is already allocated
4575 if (m_inp_mem_ptr) {
4576 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4577 return OMX_ErrorUnsupportedSetting;
4578 }
4579 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4580 if (secure_mode || m_input_pass_buffer_fd) {
4581 arbitrary_bytes = false;
4582 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4583 eRet = OMX_ErrorUnsupportedSetting;
4584 } else {
4585 arbitrary_bytes = true;
4586 }
4587 } else if (portFmt->nFramePackingFormat ==
4588 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4589 arbitrary_bytes = false;
4590 #ifdef _ANDROID_
4591 property_get("vendor.vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4592 if (atoi(property_value)) {
4593 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4594 arbitrary_bytes = true;
4595 }
4596 #endif
4597 } else {
4598 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4599 (unsigned int)portFmt->nFramePackingFormat);
4600 eRet = OMX_ErrorUnsupportedSetting;
4601 }
4602 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4603 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4604 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4605 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4606 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4607 m_out_mem_region_smi = OMX_TRUE;
4608 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4609 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4610 m_use_output_pmem = OMX_TRUE;
4611 }
4612 }
4613 }
4614 }
4615 if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4616 OMX_MAX_STRINGNAME_SIZE)) {
4617 arbitrary_bytes = true;
4618 DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4619 }
4620 break;
4621
4622 case OMX_QTIIndexParamVideoClientExtradata: {
4623 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4624 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
4625 QOMX_EXTRADATA_ENABLE *pParam =
4626 (QOMX_EXTRADATA_ENABLE *)paramData;
4627
4628 if (m_state != OMX_StateLoaded) {
4629 DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
4630 return OMX_ErrorIncorrectStateOperation;
4631 }
4632
4633 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4634 m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
4635 } else {
4636 DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
4637 eRet = OMX_ErrorUnsupportedIndex;
4638 }
4639 break;
4640 }
4641 case OMX_IndexParamStandardComponentRole: {
4642 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4643 OMX_PARAM_COMPONENTROLETYPE *comp_role;
4644 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4645 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4646 comp_role->cRole);
4647
4648 if ((m_state == OMX_StateLoaded)&&
4649 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4650 DEBUG_PRINT_LOW("Set Parameter called in valid state");
4651 } else {
4652 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4653 return OMX_ErrorIncorrectStateOperation;
4654 }
4655
4656 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4657 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4658 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4659 } else {
4660 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4661 eRet =OMX_ErrorUnsupportedSetting;
4662 }
4663 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4664 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4665 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4666 } else {
4667 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4668 eRet = OMX_ErrorUnsupportedSetting;
4669 }
4670 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4671 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4672 strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4673 } else {
4674 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4675 eRet = OMX_ErrorUnsupportedSetting;
4676 }
4677 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4678 if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4679 strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4680 } else {
4681 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4682 eRet =OMX_ErrorUnsupportedSetting;
4683 }
4684 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4685 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4686 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4687 } else {
4688 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4689 eRet = OMX_ErrorUnsupportedSetting;
4690 }
4691 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4692 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4693 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4694 ) {
4695 if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4696 strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4697 } else {
4698 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4699 eRet =OMX_ErrorUnsupportedSetting;
4700 }
4701 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4702 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4703 ) {
4704 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4705 strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4706 } else {
4707 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4708 eRet =OMX_ErrorUnsupportedSetting;
4709 }
4710 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4711 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4712 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4713 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4714 } else {
4715 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4716 eRet = OMX_ErrorUnsupportedSetting;
4717 }
4718 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4719 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4720 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4721 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4722 } else {
4723 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4724 eRet = OMX_ErrorUnsupportedSetting;
4725 }
4726 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4727 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4728 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4729 } else {
4730 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4731 eRet = OMX_ErrorUnsupportedSetting;
4732 }
4733 } else {
4734 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4735 eRet = OMX_ErrorInvalidComponentName;
4736 }
4737 break;
4738 }
4739
4740 case OMX_IndexParamPriorityMgmt: {
4741 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4742 if (m_state != OMX_StateLoaded) {
4743 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4744 return OMX_ErrorIncorrectStateOperation;
4745 }
4746 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4747 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4748 (unsigned int)priorityMgmtype->nGroupID);
4749
4750 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4751 (unsigned int)priorityMgmtype->nGroupPriority);
4752
4753 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4754 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4755
4756 break;
4757 }
4758
4759 case OMX_IndexParamCompBufferSupplier: {
4760 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4761 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4762 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4763 bufferSupplierType->eBufferSupplier);
4764 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4765 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4766
4767 else
4768
4769 eRet = OMX_ErrorBadPortIndex;
4770
4771 break;
4772
4773 }
4774 case OMX_IndexParamVideoAvc: {
4775 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4776 paramIndex);
4777 break;
4778 }
4779 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4780 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4781 paramIndex);
4782 break;
4783 }
4784 case OMX_IndexParamVideoH263: {
4785 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4786 paramIndex);
4787 break;
4788 }
4789 case OMX_IndexParamVideoMpeg4: {
4790 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4791 paramIndex);
4792 break;
4793 }
4794 case OMX_IndexParamVideoMpeg2: {
4795 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4796 paramIndex);
4797 break;
4798 }
4799 case OMX_QTIIndexParamLowLatencyMode: {
4800 struct v4l2_control control;
4801 int rc = 0;
4802 QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam =
4803 (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData;
4804 if (pParam->bLowLatencyMode) {
4805 DEBUG_PRINT_HIGH("Enabling DECODE order");
4806 time_stamp_dts.set_timestamp_reorder_mode(false);
4807 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4808 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4809 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4810 if (rc) {
4811 DEBUG_PRINT_ERROR("Set picture order failed");
4812 eRet = OMX_ErrorUnsupportedSetting;
4813 }
4814 }
4815 break;
4816 }
4817 case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4818 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4819 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4820 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4821 struct v4l2_control control;
4822 int pic_order,rc=0;
4823 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4824 pictureOrder->eOutputPictureOrder);
4825 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4826 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4827 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4828 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4829 time_stamp_dts.set_timestamp_reorder_mode(false);
4830 } else
4831 eRet = OMX_ErrorBadParameter;
4832 if (eRet == OMX_ErrorNone) {
4833 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4834 control.value = pic_order;
4835 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4836 if (rc) {
4837 DEBUG_PRINT_ERROR("Set picture order failed");
4838 eRet = OMX_ErrorUnsupportedSetting;
4839 }
4840 }
4841 m_decode_order_mode =
4842 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4843 break;
4844 }
4845 case OMX_QcomIndexParamConcealMBMapExtraData:
4846 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4847 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4848 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4849 break;
4850 case OMX_QcomIndexParamFrameInfoExtraData:
4851 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4852 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4853 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4854 break;
4855 case OMX_ExtraDataFrameDimension:
4856 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4857 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4858 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4859 break;
4860 case OMX_QcomIndexParamInterlaceExtraData:
4861 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4862 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4863 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4864 break;
4865 case OMX_QcomIndexParamH264TimeInfo:
4866 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4867 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4868 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4869 break;
4870 case OMX_QcomIndexParamVideoFramePackingExtradata:
4871 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4872 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4873 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4874 break;
4875 case OMX_QcomIndexParamVideoQPExtraData:
4876 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4877 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4878 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4879 break;
4880 case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4881 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4882 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4883 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4884 break;
4885 case OMX_QcomIndexEnableExtnUserData:
4886 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4887 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4888 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4889 break;
4890 case OMX_QTIIndexParamVQZipSEIExtraData:
4891 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4892 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4893 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4894 break;
4895 case OMX_QcomIndexParamVideoDivx: {
4896 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4897 }
4898 break;
4899 case OMX_QcomIndexPlatformPvt: {
4900 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4901 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4902 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4903 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4904 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4905 eRet = OMX_ErrorUnsupportedSetting;
4906 } else {
4907 m_out_pvt_entry_pmem = OMX_TRUE;
4908 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4909 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4910 m_use_output_pmem = OMX_TRUE;
4911 }
4912 }
4913
4914 }
4915 break;
4916 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4917 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4918 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4919 struct v4l2_control control;
4920 int rc;
4921 drv_ctx.idr_only_decoding = 1;
4922 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4923 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4924 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4925 if (rc) {
4926 DEBUG_PRINT_ERROR("Set picture order failed");
4927 eRet = OMX_ErrorUnsupportedSetting;
4928 } else {
4929 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4930 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4931 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4932 if (rc) {
4933 DEBUG_PRINT_ERROR("Sync frame setting failed");
4934 eRet = OMX_ErrorUnsupportedSetting;
4935 }
4936 /*Setting sync frame decoding on driver might change buffer
4937 * requirements so update them here*/
4938 if (get_buffer_req(&drv_ctx.ip_buf)) {
4939 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4940 eRet = OMX_ErrorUnsupportedSetting;
4941 }
4942 if (get_buffer_req(&drv_ctx.op_buf)) {
4943 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4944 eRet = OMX_ErrorUnsupportedSetting;
4945 }
4946 }
4947 }
4948 break;
4949
4950 case OMX_QcomIndexParamIndexExtraDataType: {
4951 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4952 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4953 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4954 (extradataIndexType->bEnabled == OMX_TRUE) &&
4955 (extradataIndexType->nPortIndex == 1)) {
4956 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4957 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4958
4959 }
4960 }
4961 break;
4962 case OMX_QcomIndexParamEnableSmoothStreaming: {
4963 #ifndef SMOOTH_STREAMING_DISABLED
4964 eRet = enable_smoothstreaming();
4965 #else
4966 eRet = OMX_ErrorUnsupportedSetting;
4967 #endif
4968 }
4969 break;
4970 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4971 /* Need to allow following two set_parameters even in Idle
4972 * state. This is ANDROID architecture which is not in sync
4973 * with openmax standard. */
4974 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4975 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4976 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4977 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4978 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4979 eRet = OMX_ErrorUnsupportedSetting;
4980 break;
4981 } else if (m_out_mem_ptr) {
4982 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4983 eRet = OMX_ErrorInvalidState;
4984 break;
4985 }
4986 if (enableNativeBuffers) {
4987 m_enable_android_native_buffers = enableNativeBuffers->enable;
4988 }
4989 #if !defined(FLEXYUV_SUPPORTED)
4990 if (m_enable_android_native_buffers) {
4991 // Use the most-preferred-native-color-format as surface-mode is hinted here
4992 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4993 DEBUG_PRINT_ERROR("Failed to set native color format!");
4994 eRet = OMX_ErrorUnsupportedSetting;
4995 }
4996 }
4997 #endif
4998 }
4999 break;
5000 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
5001 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
5002 eRet = use_android_native_buffer(hComp, paramData);
5003 }
5004 break;
5005 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5006 case OMX_GoogleAndroidIndexAllocateNativeHandle: {
5007
5008 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
5009 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
5010
5011 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
5012 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
5013 eRet = OMX_ErrorUnsupportedSetting;
5014 break;
5015 } else if (m_inp_mem_ptr) {
5016 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
5017 eRet = OMX_ErrorInvalidState;
5018 break;
5019 }
5020
5021 if (allocateNativeHandleParams != NULL) {
5022 allocate_native_handle = allocateNativeHandleParams->enable;
5023 }
5024 }
5025 break;
5026 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5027 #endif
5028 case OMX_QcomIndexParamEnableTimeStampReorder: {
5029 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
5030 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
5031 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
5032 if (reorder->bEnable == OMX_TRUE) {
5033 frm_int =0;
5034 time_stamp_dts.set_timestamp_reorder_mode(true);
5035 } else
5036 time_stamp_dts.set_timestamp_reorder_mode(false);
5037 } else {
5038 time_stamp_dts.set_timestamp_reorder_mode(false);
5039 if (reorder->bEnable == OMX_TRUE) {
5040 eRet = OMX_ErrorUnsupportedSetting;
5041 }
5042 }
5043 }
5044 break;
5045 case OMX_IndexParamVideoProfileLevelCurrent: {
5046 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
5047 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
5048 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
5049 if (pParam) {
5050 m_profile_lvl.eProfile = pParam->eProfile;
5051 m_profile_lvl.eLevel = pParam->eLevel;
5052 }
5053 break;
5054
5055 }
5056 case OMX_QcomIndexParamVideoMetaBufferMode:
5057 {
5058 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
5059 StoreMetaDataInBuffersParams *metabuffer =
5060 (StoreMetaDataInBuffersParams *)paramData;
5061 if (!metabuffer) {
5062 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
5063 eRet = OMX_ErrorBadParameter;
5064 break;
5065 }
5066 if (m_disable_dynamic_buf_mode) {
5067 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
5068 eRet = OMX_ErrorUnsupportedSetting;
5069 break;
5070 }
5071 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5072
5073 if (m_out_mem_ptr) {
5074 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
5075 eRet = OMX_ErrorInvalidState;
5076 break;
5077 }
5078 //set property dynamic buffer mode to driver.
5079 struct v4l2_control control;
5080 struct v4l2_format fmt;
5081 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
5082 if (metabuffer->bStoreMetaData == true) {
5083 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
5084 } else {
5085 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
5086 }
5087 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
5088 if (!rc) {
5089 DEBUG_PRINT_HIGH("%s buffer mode",
5090 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
5091 } else {
5092 DEBUG_PRINT_ERROR("Failed to %s buffer mode",
5093 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
5094 }
5095 dynamic_buf_mode = metabuffer->bStoreMetaData;
5096 } else {
5097 DEBUG_PRINT_ERROR(
5098 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
5099 (unsigned int)metabuffer->nPortIndex);
5100 eRet = OMX_ErrorUnsupportedSetting;
5101 }
5102 break;
5103 }
5104 case OMX_QcomIndexParamVideoDownScalar:
5105 {
5106 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
5107 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
5108 struct v4l2_control control;
5109 int rc;
5110 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
5111
5112 if (pParam && pParam->bEnable) {
5113 rc = enable_downscalar();
5114 if (rc < 0) {
5115 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
5116 return OMX_ErrorUnsupportedSetting;
5117 }
5118 m_force_down_scalar = pParam->bEnable;
5119 } else {
5120 rc = disable_downscalar();
5121 if (rc < 0) {
5122 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
5123 return OMX_ErrorUnsupportedSetting;
5124 }
5125 m_force_down_scalar = pParam->bEnable;
5126 }
5127 break;
5128 }
5129 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5130 case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
5131 {
5132 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
5133 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
5134 PrepareForAdaptivePlaybackParams* pParams =
5135 (PrepareForAdaptivePlaybackParams *) paramData;
5136 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5137 if (!pParams->bEnable) {
5138 return OMX_ErrorNone;
5139 }
5140 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
5141 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
5142 DEBUG_PRINT_ERROR(
5143 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
5144 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
5145 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
5146 eRet = OMX_ErrorBadParameter;
5147 } else {
5148 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
5149 }
5150 } else {
5151 DEBUG_PRINT_ERROR(
5152 "Prepare for adaptive playback supported only on output port");
5153 eRet = OMX_ErrorBadParameter;
5154 }
5155 break;
5156 }
5157
5158 case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
5159 {
5160 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5161 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
5162 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5163 if (m_disable_dynamic_buf_mode) {
5164 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
5165 }
5166 break;
5167 }
5168 #endif
5169 case OMX_QcomIndexParamVideoCustomBufferSize:
5170 {
5171 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
5172 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
5173 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
5174 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5175 struct v4l2_control control;
5176 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
5177 control.value = pParam->nBufferSize;
5178 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5179 DEBUG_PRINT_ERROR("Failed to set input buffer size");
5180 eRet = OMX_ErrorUnsupportedSetting;
5181 } else {
5182 eRet = get_buffer_req(&drv_ctx.ip_buf);
5183 if (eRet == OMX_ErrorNone) {
5184 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
5185 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
5186 m_custom_buffersize.input_buffersize);
5187 } else {
5188 DEBUG_PRINT_ERROR("Failed to get buffer requirement");
5189 }
5190 }
5191 } else {
5192 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
5193 eRet = OMX_ErrorBadParameter;
5194 }
5195 break;
5196 }
5197 case OMX_QTIIndexParamVQZIPSEIType:
5198 {
5199 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
5200 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
5201 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
5202 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
5203 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
5204
5205 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
5206 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5207 if (eRet != OMX_ErrorNone) {
5208 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
5209 eRet = OMX_ErrorBadParameter;
5210 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5211 break;
5212 }
5213 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
5214 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5215 if (eRet != OMX_ErrorNone) {
5216 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
5217 eRet = OMX_ErrorBadParameter;
5218 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5219 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5220 break;
5221 }
5222 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
5223 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5224 if (eRet != OMX_ErrorNone) {
5225 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
5226 eRet = OMX_ErrorBadParameter;
5227 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5228 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5229 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
5230 }
5231 break;
5232 }
5233 case OMX_QTIIndexParamPassInputBufferFd:
5234 {
5235 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5236 if (arbitrary_bytes) {
5237 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
5238 eRet = OMX_ErrorUnsupportedSetting;
5239 break;
5240 }
5241
5242 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5243 if (m_input_pass_buffer_fd)
5244 DEBUG_PRINT_LOW("Enable passing input buffer FD");
5245 break;
5246 }
5247 case OMX_QTIIndexParamForceCompressedForDPB:
5248 {
5249 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
5250 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
5251 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
5252 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
5253 if (m_disable_ubwc_mode) {
5254 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
5255 eRet = OMX_ErrorUnsupportedSetting;
5256 break;
5257 }
5258 if (!paramData) {
5259 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
5260 eRet = OMX_ErrorBadParameter;
5261 break;
5262 }
5263
5264 m_force_compressed_for_dpb = pParam->bEnable;
5265 break;
5266 }
5267 case OMX_QTIIndexParamForceUnCompressedForOPB:
5268 {
5269 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
5270 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
5271 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
5272 if (!paramData) {
5273 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
5274 eRet = OMX_ErrorBadParameter;
5275 break;
5276 }
5277 m_disable_ubwc_mode = pParam->bEnable;
5278 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
5279 break;
5280 }
5281 case OMX_QTIIndexParamDitherControl:
5282 {
5283 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
5284 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
5285 QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
5286 DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
5287 if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
5288 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
5289 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
5290 eRet = OMX_ErrorBadParameter;
5291 break;
5292 }
5293 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
5294 DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
5295 break;
5296 }
5297 default: {
5298 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
5299 eRet = OMX_ErrorUnsupportedIndex;
5300 }
5301 }
5302 if (eRet != OMX_ErrorNone)
5303 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
5304 return eRet;
5305 }
5306
5307 /* ======================================================================
5308 FUNCTION
5309 omx_vdec::GetConfig
5310
5311 DESCRIPTION
5312 OMX Get Config Method implementation.
5313
5314 PARAMETERS
5315 <TBD>.
5316
5317 RETURN VALUE
5318 OMX Error None if successful.
5319
5320 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)5321 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
5322 OMX_IN OMX_INDEXTYPE configIndex,
5323 OMX_INOUT OMX_PTR configData)
5324 {
5325 (void) hComp;
5326 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5327
5328 if (m_state == OMX_StateInvalid) {
5329 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5330 return OMX_ErrorInvalidState;
5331 }
5332
5333 switch ((unsigned long)configIndex) {
5334 case OMX_QcomIndexConfigInterlaced: {
5335 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
5336 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
5337 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
5338 if (configFmt->nPortIndex == 1) {
5339 if (configFmt->nIndex == 0) {
5340 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
5341 } else if (configFmt->nIndex == 1) {
5342 configFmt->eInterlaceType =
5343 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
5344 } else if (configFmt->nIndex == 2) {
5345 configFmt->eInterlaceType =
5346 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
5347 } else {
5348 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
5349 " NoMore Interlaced formats");
5350 eRet = OMX_ErrorNoMore;
5351 }
5352
5353 } else {
5354 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
5355 (int)configFmt->nPortIndex);
5356 eRet = OMX_ErrorBadPortIndex;
5357 }
5358 break;
5359 }
5360 case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5361 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5362 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5363 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5364 decoderinstances->nNumOfInstances = 16;
5365 /*TODO: How to handle this case */
5366 break;
5367 }
5368 case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5369 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5370 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5371 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5372 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5373 memcpy(configFmt, &m_frame_pack_arrangement,
5374 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5375 } else {
5376 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5377 }
5378 break;
5379 }
5380 case OMX_IndexConfigCommonOutputCrop: {
5381 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5382 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5383 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5384 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5385 rectangle.nLeft, rectangle.nTop,
5386 rectangle.nWidth, rectangle.nHeight);
5387 break;
5388 }
5389 case OMX_QcomIndexConfigPerfLevel: {
5390 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
5391 struct v4l2_control control;
5392 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5393 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5394
5395 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5396 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
5397 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
5398 eRet = OMX_ErrorHardware;
5399 }
5400
5401 if (eRet == OMX_ErrorNone) {
5402 switch (control.value) {
5403 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
5404 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
5405 break;
5406 default:
5407 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
5408 /* Fall through */
5409 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
5410 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
5411 break;
5412 }
5413 }
5414
5415 break;
5416 }
5417 case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5418 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5419 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5420 struct v4l2_control control;
5421
5422 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5423 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5424 eRet = OMX_ErrorNotImplemented;
5425 break;
5426 }
5427
5428 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5429 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5430 coding->bCabac = (OMX_BOOL)
5431 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5432 /* We can't query driver at the moment for the cabac mode, so
5433 * just use 0xff...f as a place holder for future improvement */
5434 coding->nCabacInitIdc = ~0;
5435 } else {
5436 eRet = OMX_ErrorUnsupportedIndex;
5437 }
5438
5439 break;
5440 }
5441 case OMX_QTIIndexConfigDescribeColorAspects:
5442 {
5443 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5444 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5445
5446 if (params->bRequestingDataSpace) {
5447 DEBUG_PRINT_HIGH("Does not handle dataspace request");
5448 return OMX_ErrorUnsupportedSetting;
5449 }
5450
5451 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5452 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5453
5454 // For VPX, use client-color if specified.
5455 // For the rest, try to use the stream-color if present
5456 bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
5457 output_capability == V4L2_PIX_FMT_VP9);
5458
5459 const ColorAspects &preferredColor = preferClientColor ?
5460 m_client_color_space.sAspects : m_internal_color_space.sAspects;
5461 const ColorAspects &defaultColor = preferClientColor ?
5462 m_internal_color_space.sAspects : m_client_color_space.sAspects;
5463
5464 params->sAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
5465 preferredColor.mPrimaries : defaultColor.mPrimaries;
5466 params->sAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
5467 preferredColor.mTransfer : defaultColor.mTransfer;
5468 params->sAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
5469 preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
5470 params->sAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
5471 preferredColor.mRange : defaultColor.mRange;
5472
5473 print_debug_color_aspects(&(params->sAspects), "GetConfig");
5474
5475 break;
5476 }
5477 case OMX_QTIIndexConfigDescribeHDRColorInfo:
5478 {
5479 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5480 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5481 auto_lock lock(m_hdr_info_client_lock);
5482
5483 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5484 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5485
5486 if (m_change_client_hdr_info) {
5487 DEBUG_PRINT_LOW("Updating Client's HDR Info with internal");
5488 memcpy(&m_client_hdr_info.sInfo,
5489 &m_internal_hdr_info.sInfo, sizeof(HDRStaticInfo));
5490 m_change_client_hdr_info = false;
5491 }
5492
5493 memcpy(&(params->sInfo), &(m_client_hdr_info.sInfo), sizeof(HDRStaticInfo));
5494
5495 break;
5496 }
5497 case OMX_IndexConfigAndroidVendorExtension:
5498 {
5499 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5500
5501 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5502 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5503 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5504 return get_vendor_extension_config(ext);
5505 }
5506 default:
5507 {
5508 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5509 eRet = OMX_ErrorBadParameter;
5510 }
5511
5512 }
5513
5514 return eRet;
5515 }
5516
5517 /* ======================================================================
5518 FUNCTION
5519 omx_vdec::SetConfig
5520
5521 DESCRIPTION
5522 OMX Set Config method implementation
5523
5524 PARAMETERS
5525 <TBD>.
5526
5527 RETURN VALUE
5528 OMX Error None if successful.
5529 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5530 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
5531 OMX_IN OMX_INDEXTYPE configIndex,
5532 OMX_IN OMX_PTR configData)
5533 {
5534 (void) hComp;
5535 if (m_state == OMX_StateInvalid) {
5536 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5537 return OMX_ErrorInvalidState;
5538 }
5539
5540 OMX_ERRORTYPE ret = OMX_ErrorNone;
5541 OMX_VIDEO_CONFIG_NALSIZE *pNal;
5542
5543 DEBUG_PRINT_LOW("Set Config Called");
5544
5545 if (configIndex == OMX_IndexConfigVideoNalSize) {
5546 struct v4l2_control temp;
5547 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5548
5549 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5550 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5551 switch (pNal->nNaluBytes) {
5552 case 0:
5553 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5554 break;
5555 case 2:
5556 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5557 break;
5558 case 4:
5559 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5560 break;
5561 default:
5562 return OMX_ErrorUnsupportedSetting;
5563 }
5564
5565 if (!arbitrary_bytes) {
5566 /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5567 * with start code, so only need to notify driver in frame by frame mode */
5568 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5569 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5570 return OMX_ErrorHardware;
5571 }
5572 }
5573
5574 nal_length = pNal->nNaluBytes;
5575 m_frame_parser.init_nal_length(nal_length);
5576
5577 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5578 return ret;
5579 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5580 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5581 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5582
5583 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5584 if (config->bEnabled) {
5585 if ((config->nFps >> 16) > 0 &&
5586 (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5587 m_fps_received = config->nFps;
5588 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5589 (unsigned int)config->nFps >> 16);
5590 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5591 drv_ctx.frame_rate.fps_denominator);
5592
5593 if (!drv_ctx.frame_rate.fps_numerator) {
5594 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5595 drv_ctx.frame_rate.fps_numerator = 30;
5596 }
5597
5598 if (drv_ctx.frame_rate.fps_denominator) {
5599 drv_ctx.frame_rate.fps_numerator = (int)
5600 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5601 }
5602
5603 drv_ctx.frame_rate.fps_denominator = 1;
5604 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5605 drv_ctx.frame_rate.fps_numerator;
5606
5607 struct v4l2_outputparm oparm;
5608 /*XXX: we're providing timing info as seconds per frame rather than frames
5609 * per second.*/
5610 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5611 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5612
5613 struct v4l2_streamparm sparm;
5614 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5615 sparm.parm.output = oparm;
5616 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5617 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5618 performance might be affected");
5619 ret = OMX_ErrorHardware;
5620 }
5621 client_set_fps = true;
5622 } else {
5623 DEBUG_PRINT_ERROR("Frame rate not supported.");
5624 ret = OMX_ErrorUnsupportedSetting;
5625 }
5626 } else {
5627 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5628 client_set_fps = false;
5629 }
5630 } else {
5631 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5632 (int)config->nPortIndex);
5633 ret = OMX_ErrorBadPortIndex;
5634 }
5635
5636 return ret;
5637 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5638 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5639 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5640 struct v4l2_control control;
5641
5642 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5643 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5644
5645 switch (perf->ePerfLevel) {
5646 case OMX_QCOM_PerfLevelNominal:
5647 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5648 m_need_turbo &= ~TURBO_MODE_CLIENT_REQUESTED;
5649 break;
5650 case OMX_QCOM_PerfLevelTurbo:
5651 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5652 m_need_turbo |= TURBO_MODE_CLIENT_REQUESTED;
5653 break;
5654 default:
5655 ret = OMX_ErrorUnsupportedSetting;
5656 break;
5657 }
5658
5659 if (ret == OMX_ErrorNone) {
5660 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5661 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5662 }
5663
5664 return ret;
5665 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5666 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5667 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5668 struct v4l2_control control;
5669 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5670 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5671
5672 switch (config->eDecodeType) {
5673 case OMX_QCOM_PictypeDecode_I:
5674 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5675 break;
5676 case OMX_QCOM_PictypeDecode_IPB:
5677 default:
5678 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5679 break;
5680 }
5681
5682 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5683 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5684 if (ret)
5685 DEBUG_PRINT_ERROR("Failed to set picture type decode");
5686
5687 return ret;
5688 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5689 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5690 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5691
5692 struct v4l2_control control;
5693
5694 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5695 if (priority->nU32 == 0)
5696 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5697 else
5698 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5699
5700 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5701 DEBUG_PRINT_ERROR("Failed to set Priority");
5702 ret = OMX_ErrorUnsupportedSetting;
5703 }
5704 return ret;
5705 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5706 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5707 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5708
5709 struct v4l2_control control;
5710
5711 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5712 control.value = rate->nU32;
5713
5714 operating_frame_rate = rate->nU32 >> 16;
5715
5716 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5717 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5718 OMX_ErrorUnsupportedSetting;
5719 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5720 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5721 }
5722 return ret;
5723
5724 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5725 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5726 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5727 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5728 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5729 }
5730
5731 print_debug_color_aspects(&(params->sAspects), "Set Config");
5732 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5733 return ret;
5734 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5735 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5736 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5737 if (!DEFAULT_EXTRADATA & OMX_HDR_COLOR_INFO_EXTRADATA) {
5738 ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, true, true);
5739 if (ret != OMX_ErrorNone) {
5740 DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5741 return ret;
5742 }
5743 }
5744
5745 print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5746 memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5747 return ret;
5748
5749 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5750 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5751
5752 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5753 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5754 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5755
5756 return set_vendor_extension_config(ext);
5757 }
5758
5759 return OMX_ErrorNotImplemented;
5760 }
5761
5762 #define extn_equals(param, extn) (!strcmp(param, extn))
5763
5764 /* ======================================================================
5765 FUNCTION
5766 omx_vdec::GetExtensionIndex
5767
5768 DESCRIPTION
5769 OMX GetExtensionIndex method implementaion. <TBD>
5770
5771 PARAMETERS
5772 <TBD>.
5773
5774 RETURN VALUE
5775 OMX Error None if everything successful.
5776
5777 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5778 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
5779 OMX_IN OMX_STRING paramName,
5780 OMX_OUT OMX_INDEXTYPE* indexType)
5781 {
5782 (void) hComp;
5783 if (m_state == OMX_StateInvalid) {
5784 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5785 return OMX_ErrorInvalidState;
5786 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5787 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5788 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5789 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5790 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5791 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5792 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5793 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5794 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5795 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5796 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5797 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5798 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5799 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5800 }
5801 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5802 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5803 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5804 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5805 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5806 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5807 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5808 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5809 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5810 }
5811 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5812 else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5813 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5814 }
5815 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5816 #endif
5817 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5818 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5819 }
5820 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5821 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5822 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5823 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5824 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5825 }
5826 #endif
5827 #ifdef FLEXYUV_SUPPORTED
5828 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5829 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5830 }
5831 #endif
5832 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5833 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5834 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5835 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5836 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5837 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5838 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5839 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5840 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5841 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5842 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5843 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5844 } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5845 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5846 } else {
5847 DEBUG_PRINT_HIGH("Extension: %s not implemented", paramName);
5848 return OMX_ErrorNotImplemented;
5849 }
5850 return OMX_ErrorNone;
5851 }
5852
5853 /* ======================================================================
5854 FUNCTION
5855 omx_vdec::GetState
5856
5857 DESCRIPTION
5858 Returns the state information back to the caller.<TBD>
5859
5860 PARAMETERS
5861 <TBD>.
5862
5863 RETURN VALUE
5864 Error None if everything is successful.
5865 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5866 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
5867 OMX_OUT OMX_STATETYPE* state)
5868 {
5869 (void) hComp;
5870 *state = m_state;
5871 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5872 return OMX_ErrorNone;
5873 }
5874
5875 /* ======================================================================
5876 FUNCTION
5877 omx_vdec::ComponentTunnelRequest
5878
5879 DESCRIPTION
5880 OMX Component Tunnel Request method implementation. <TBD>
5881
5882 PARAMETERS
5883 None.
5884
5885 RETURN VALUE
5886 OMX Error None if everything successful.
5887
5888 ========================================================================== */
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)5889 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
5890 OMX_IN OMX_U32 port,
5891 OMX_IN OMX_HANDLETYPE peerComponent,
5892 OMX_IN OMX_U32 peerPort,
5893 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5894 {
5895 (void) hComp;
5896 (void) port;
5897 (void) peerComponent;
5898 (void) peerPort;
5899 (void) tunnelSetup;
5900 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5901 return OMX_ErrorNotImplemented;
5902 }
5903
5904 /* ======================================================================
5905 FUNCTION
5906 omx_vdec::UseOutputBuffer
5907
5908 DESCRIPTION
5909 Helper function for Use buffer in the input pin
5910
5911 PARAMETERS
5912 None.
5913
5914 RETURN VALUE
5915 true/false
5916
5917 ========================================================================== */
allocate_extradata()5918 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5919 {
5920 #ifdef USE_ION
5921 if (drv_ctx.extradata_info.buffer_size) {
5922 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5923 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5924 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5925 free_ion_memory(&drv_ctx.extradata_info.ion);
5926 }
5927 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5928 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5929 drv_ctx.extradata_info.size, 4096,
5930 &drv_ctx.extradata_info.ion.ion_alloc_data,
5931 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5932 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5933 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5934 return OMX_ErrorInsufficientResources;
5935 }
5936 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5937 drv_ctx.extradata_info.size,
5938 PROT_READ|PROT_WRITE, MAP_SHARED,
5939 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5940 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5941 DEBUG_PRINT_ERROR("Failed to map extradata memory");
5942 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5943 free_ion_memory(&drv_ctx.extradata_info.ion);
5944 return OMX_ErrorInsufficientResources;
5945 }
5946 }
5947 #endif
5948 if (!m_other_extradata) {
5949 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5950 if (!m_other_extradata) {
5951 DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5952 return OMX_ErrorInsufficientResources;
5953 }
5954 }
5955 return OMX_ErrorNone;
5956 }
5957
free_extradata()5958 void omx_vdec::free_extradata()
5959 {
5960 #ifdef USE_ION
5961 if (drv_ctx.extradata_info.uaddr) {
5962 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5963 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5964 free_ion_memory(&drv_ctx.extradata_info.ion);
5965 }
5966 #endif
5967 if (m_other_extradata) {
5968 free(m_other_extradata);
5969 m_other_extradata = NULL;
5970 }
5971 }
5972
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)5973 OMX_ERRORTYPE omx_vdec::use_output_buffer(
5974 OMX_IN OMX_HANDLETYPE hComp,
5975 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5976 OMX_IN OMX_U32 port,
5977 OMX_IN OMX_PTR appData,
5978 OMX_IN OMX_U32 bytes,
5979 OMX_IN OMX_U8* buffer)
5980 {
5981 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5982 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
5983 unsigned i= 0; // Temporary counter
5984 struct vdec_setbuffer_cmd setbuffers;
5985 OMX_PTR privateAppData = NULL;
5986 private_handle_t *handle = NULL;
5987 OMX_U8 *buff = buffer;
5988 struct v4l2_buffer buf;
5989 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5990 int extra_idx = 0;
5991 (void) hComp;
5992 (void) port;
5993
5994 if (!m_out_mem_ptr) {
5995 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5996 eRet = allocate_output_headers();
5997 if (eRet == OMX_ErrorNone)
5998 eRet = allocate_extradata();
5999 output_use_buffer = true;
6000 }
6001
6002 if (eRet == OMX_ErrorNone) {
6003 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6004 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6005 break;
6006 }
6007 }
6008 }
6009
6010 if (i >= drv_ctx.op_buf.actualcount) {
6011 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
6012 eRet = OMX_ErrorInsufficientResources;
6013 }
6014
6015 if (eRet != OMX_ErrorNone)
6016 return eRet;
6017
6018 if (dynamic_buf_mode) {
6019 *bufferHdr = (m_out_mem_ptr + i );
6020 (*bufferHdr)->pBuffer = NULL;
6021 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
6022 enum v4l2_buf_type buf_type;
6023 int rr = 0;
6024 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6025 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
6026 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
6027 return OMX_ErrorInsufficientResources;
6028 } else {
6029 streaming[CAPTURE_PORT] = true;
6030 DEBUG_PRINT_LOW("STREAMON Successful");
6031 }
6032
6033 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6034 request_perf_level(VIDC_TURBO);
6035 }
6036 BITMASK_SET(&m_out_bm_count,i);
6037 (*bufferHdr)->pAppPrivate = appData;
6038 (*bufferHdr)->pBuffer = buffer;
6039 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
6040 return eRet;
6041 }
6042
6043 if (eRet == OMX_ErrorNone) {
6044 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
6045 if (m_enable_android_native_buffers) {
6046 if (m_use_android_native_buffers) {
6047 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
6048 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
6049 handle = (private_handle_t *)nBuf->handle;
6050 privateAppData = params->pAppPrivate;
6051 } else {
6052 handle = (private_handle_t *)buff;
6053 privateAppData = appData;
6054 }
6055 if (!handle) {
6056 DEBUG_PRINT_ERROR("handle is invalid");
6057 return OMX_ErrorBadParameter;
6058 }
6059
6060 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
6061 if (secure_mode && secure_scaling_to_non_secure_opb) {
6062 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
6063 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6064 } else {
6065 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
6066 " expected %u, got %u",
6067 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6068 return OMX_ErrorBadParameter;
6069 }
6070 }
6071
6072 drv_ctx.op_buf.buffer_size = handle->size;
6073
6074 if (!m_use_android_native_buffers) {
6075 if (!secure_mode) {
6076 buff = (OMX_U8*)mmap(0, handle->size,
6077 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
6078 if (buff == MAP_FAILED) {
6079 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
6080 return OMX_ErrorInsufficientResources;
6081 }
6082 }
6083 }
6084 #if defined(_ANDROID_ICS_)
6085 native_buffer[i].nativehandle = handle;
6086 native_buffer[i].privatehandle = handle;
6087 #endif
6088 if (!handle) {
6089 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
6090 return OMX_ErrorBadParameter;
6091 }
6092 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
6093 drv_ctx.ptr_outputbuffer[i].offset = 0;
6094 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6095 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6096 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
6097 } else
6098 #endif
6099
6100 if (!ouput_egl_buffers && !m_use_output_pmem) {
6101 #ifdef USE_ION
6102 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6103 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
6104 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
6105 &drv_ctx.op_buf_ion_info[i].fd_ion_data,
6106 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
6107 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
6108 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
6109 return OMX_ErrorInsufficientResources;
6110 }
6111 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6112 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6113 #else
6114 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6115 open (MEM_DEVICE,O_RDWR);
6116
6117 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6118 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6119 return OMX_ErrorInsufficientResources;
6120 }
6121
6122 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
6123 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
6124 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6125 open (MEM_DEVICE,O_RDWR);
6126 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
6127 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
6128 return OMX_ErrorInsufficientResources;
6129 }
6130 }
6131
6132 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
6133 drv_ctx.op_buf.buffer_size,
6134 drv_ctx.op_buf.alignment)) {
6135 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6136 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6137 return OMX_ErrorInsufficientResources;
6138 }
6139 #endif
6140 if (!secure_mode) {
6141 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6142 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
6143 PROT_READ|PROT_WRITE, MAP_SHARED,
6144 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
6145 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
6146 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
6147 #ifdef USE_ION
6148 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6149 #endif
6150 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
6151 return OMX_ErrorInsufficientResources;
6152 }
6153 }
6154 drv_ctx.ptr_outputbuffer[i].offset = 0;
6155 privateAppData = appData;
6156 } else {
6157
6158 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
6159 if (!appData || !bytes ) {
6160 if (!secure_mode && !buffer) {
6161 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
6162 return OMX_ErrorBadParameter;
6163 }
6164 }
6165
6166 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
6167 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
6168 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
6169 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
6170 !pmem_list->nEntries ||
6171 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
6172 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
6173 return OMX_ErrorBadParameter;
6174 }
6175 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6176 pmem_list->entryList->entry;
6177 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
6178 pmem_info->pmem_fd);
6179 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
6180 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
6181 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6182 drv_ctx.ptr_outputbuffer[i].mmaped_size =
6183 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6184 privateAppData = appData;
6185 }
6186 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6187 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6188 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6189 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6190 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6191
6192 *bufferHdr = (m_out_mem_ptr + i );
6193 if (secure_mode)
6194 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6195 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6196 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
6197 sizeof (vdec_bufferpayload));
6198
6199 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
6200 drv_ctx.ptr_outputbuffer[i].bufferaddr,
6201 drv_ctx.ptr_outputbuffer[i].pmem_fd );
6202
6203 buf.index = i;
6204 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6205 buf.memory = V4L2_MEMORY_USERPTR;
6206 plane[0].length = drv_ctx.op_buf.buffer_size;
6207 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6208 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6209 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6210 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6211 plane[0].data_offset = 0;
6212 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6213 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6214 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6215 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6216 #ifdef USE_ION
6217 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6218 #endif
6219 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6220 plane[extra_idx].data_offset = 0;
6221 } else if (extra_idx >= VIDEO_MAX_PLANES) {
6222 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
6223 return OMX_ErrorBadParameter;
6224 }
6225 buf.m.planes = plane;
6226 buf.length = drv_ctx.num_planes;
6227
6228 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
6229 DEBUG_PRINT_ERROR("Failed to prepare bufs");
6230 /*TODO: How to handle this case */
6231 return OMX_ErrorInsufficientResources;
6232 }
6233
6234 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
6235 enum v4l2_buf_type buf_type;
6236 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6237 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
6238 return OMX_ErrorInsufficientResources;
6239 } else {
6240 streaming[CAPTURE_PORT] = true;
6241 DEBUG_PRINT_LOW("STREAMON Successful");
6242 }
6243
6244 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6245 request_perf_level(VIDC_TURBO);
6246 }
6247
6248 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
6249 if (m_enable_android_native_buffers) {
6250 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
6251 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
6252 } else {
6253 (*bufferHdr)->pBuffer = buff;
6254 }
6255 (*bufferHdr)->pAppPrivate = privateAppData;
6256 BITMASK_SET(&m_out_bm_count,i);
6257 }
6258 return eRet;
6259 }
6260
allocate_client_output_extradata_headers()6261 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() {
6262 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6263 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
6264 int i = 0;
6265
6266 if (!m_client_output_extradata_mem_ptr) {
6267 int nBufferCount = 0;
6268
6269 nBufferCount = m_client_out_extradata_info.getBufferCount();
6270 DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
6271
6272 m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
6273
6274 if (m_client_output_extradata_mem_ptr) {
6275 bufHdr = m_client_output_extradata_mem_ptr;
6276 for (i=0; i < nBufferCount; i++) {
6277 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6278 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
6279 // Set the values when we determine the right HxW param
6280 bufHdr->nAllocLen = 0;
6281 bufHdr->nFilledLen = 0;
6282 bufHdr->pAppPrivate = NULL;
6283 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
6284 bufHdr->pBuffer = NULL;
6285 bufHdr->pOutputPortPrivate = NULL;
6286 bufHdr++;
6287 }
6288 } else {
6289 DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
6290 m_client_output_extradata_mem_ptr);
6291 eRet = OMX_ErrorInsufficientResources;
6292 }
6293 }
6294 return eRet;
6295 }
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)6296 OMX_ERRORTYPE omx_vdec::use_client_output_extradata_buffer(
6297 OMX_IN OMX_HANDLETYPE hComp,
6298 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6299 OMX_IN OMX_U32 port,
6300 OMX_IN OMX_PTR appData,
6301 OMX_IN OMX_U32 bytes,
6302 OMX_IN OMX_U8* buffer)
6303 {
6304 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6305 unsigned i = 0; // Temporary counter
6306 unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
6307 OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
6308 (void) hComp;
6309
6310 if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
6311 !client_extradata || bytes != buffer_size|| bufferHdr == NULL) {
6312 DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
6313 "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
6314 OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr);
6315 eRet = OMX_ErrorBadParameter;
6316 return eRet;
6317 }
6318
6319 if (!m_client_output_extradata_mem_ptr) {
6320 eRet = allocate_client_output_extradata_headers();
6321 }
6322
6323 if (eRet == OMX_ErrorNone) {
6324 for (i = 0; i < buffer_count; i++) {
6325 if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
6326 break;
6327 }
6328 }
6329 }
6330
6331 if (i >= buffer_count) {
6332 DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
6333 eRet = OMX_ErrorInsufficientResources;
6334 }
6335
6336 if (eRet == OMX_ErrorNone) {
6337 BITMASK_SET(&m_out_extradata_bm_count,i);
6338 *bufferHdr = (m_client_output_extradata_mem_ptr + i );
6339 (*bufferHdr)->pAppPrivate = appData;
6340 (*bufferHdr)->pBuffer = buffer;
6341 (*bufferHdr)->nAllocLen = bytes;
6342 }
6343
6344 return eRet;
6345 }
6346 /* ======================================================================
6347 FUNCTION
6348 omx_vdec::use_input_heap_buffers
6349
6350 DESCRIPTION
6351 OMX Use Buffer Heap allocation method implementation.
6352
6353 PARAMETERS
6354 <TBD>.
6355
6356 RETURN VALUE
6357 OMX Error None , if everything successful.
6358
6359 ========================================================================== */
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)6360 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
6361 OMX_IN OMX_HANDLETYPE hComp,
6362 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6363 OMX_IN OMX_U32 port,
6364 OMX_IN OMX_PTR appData,
6365 OMX_IN OMX_U32 bytes,
6366 OMX_IN OMX_U8* buffer)
6367 {
6368 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
6369 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6370
6371 if (secure_mode) {
6372 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
6373 return OMX_ErrorUndefined;
6374 }
6375
6376 if (!m_inp_heap_ptr)
6377 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
6378 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6379 drv_ctx.ip_buf.actualcount);
6380 if (!m_phdr_pmem_ptr)
6381 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
6382 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6383 drv_ctx.ip_buf.actualcount);
6384 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
6385 DEBUG_PRINT_ERROR("Insufficent memory");
6386 eRet = OMX_ErrorInsufficientResources;
6387 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
6388 input_use_buffer = true;
6389 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
6390 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
6391 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
6392 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
6393 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
6394 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
6395 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
6396 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
6397 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
6398 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
6399 (unsigned)NULL, (unsigned)NULL)) {
6400 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6401 return OMX_ErrorInsufficientResources;
6402 }
6403 m_in_alloc_cnt++;
6404 } else {
6405 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
6406 eRet = OMX_ErrorInsufficientResources;
6407 }
6408 return eRet;
6409 }
6410
6411 /* ======================================================================
6412 FUNCTION
6413 omx_vdec::UseBuffer
6414
6415 DESCRIPTION
6416 OMX Use Buffer method implementation.
6417
6418 PARAMETERS
6419 <TBD>.
6420
6421 RETURN VALUE
6422 OMX Error None , if everything successful.
6423
6424 ========================================================================== */
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)6425 OMX_ERRORTYPE omx_vdec::use_buffer(
6426 OMX_IN OMX_HANDLETYPE hComp,
6427 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6428 OMX_IN OMX_U32 port,
6429 OMX_IN OMX_PTR appData,
6430 OMX_IN OMX_U32 bytes,
6431 OMX_IN OMX_U8* buffer)
6432 {
6433 OMX_ERRORTYPE error = OMX_ErrorNone;
6434 struct vdec_setbuffer_cmd setbuffers;
6435
6436 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
6437 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
6438 return OMX_ErrorBadParameter;
6439 }
6440 if (m_state == OMX_StateInvalid) {
6441 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
6442 return OMX_ErrorInvalidState;
6443 }
6444 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6445 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6446 // ensure that use-buffer was called for previous allocation.
6447 // Mix-and-match of useBuffer and allocateBuffer is not allowed
6448 if (m_inp_mem_ptr && !input_use_buffer) {
6449 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
6450 return OMX_ErrorUndefined;
6451 }
6452 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
6453 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6454 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
6455 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
6456 error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
6457 } else {
6458 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6459 error = OMX_ErrorBadPortIndex;
6460 }
6461 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
6462 if (error == OMX_ErrorNone) {
6463 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6464 // Send the callback now
6465 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6466 post_event(OMX_CommandStateSet,OMX_StateIdle,
6467 OMX_COMPONENT_GENERATE_EVENT);
6468 }
6469 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
6470 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6471 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6472 post_event(OMX_CommandPortEnable,
6473 OMX_CORE_INPUT_PORT_INDEX,
6474 OMX_COMPONENT_GENERATE_EVENT);
6475 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6476 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6477 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6478 post_event(OMX_CommandPortEnable,
6479 OMX_CORE_OUTPUT_PORT_INDEX,
6480 OMX_COMPONENT_GENERATE_EVENT);
6481 }
6482 }
6483 return error;
6484 }
6485
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)6486 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6487 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6488 {
6489 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
6490 if (m_inp_heap_ptr[bufferindex].pBuffer)
6491 free(m_inp_heap_ptr[bufferindex].pBuffer);
6492 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
6493 }
6494 if (pmem_bufferHdr)
6495 free_input_buffer(pmem_bufferHdr);
6496 return OMX_ErrorNone;
6497 }
6498
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6499 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6500 {
6501 unsigned int index = 0;
6502 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6503 return OMX_ErrorBadParameter;
6504 }
6505
6506 index = bufferHdr - m_inp_mem_ptr;
6507 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6508
6509 bufferHdr->pInputPortPrivate = NULL;
6510
6511 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6512 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6513 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6514 struct vdec_setbuffer_cmd setbuffers;
6515 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
6516 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
6517 sizeof (vdec_bufferpayload));
6518 if (!secure_mode) {
6519 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
6520 drv_ctx.ptr_inputbuffer[index].pmem_fd);
6521 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p",
6522 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
6523 drv_ctx.ptr_inputbuffer[index].bufferaddr);
6524 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6525 drv_ctx.ptr_inputbuffer[index].mmaped_size);
6526 }
6527
6528 if (allocate_native_handle){
6529 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6530 native_handle_close(nh);
6531 native_handle_delete(nh);
6532 } else {
6533 // Close fd for non-secure and secure non-native-handle case
6534 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6535 }
6536 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6537
6538 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6539 free(m_desc_buffer_ptr[index].buf_addr);
6540 m_desc_buffer_ptr[index].buf_addr = NULL;
6541 m_desc_buffer_ptr[index].desc_data_size = 0;
6542 }
6543 #ifdef USE_ION
6544 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6545 #endif
6546 m_in_alloc_cnt--;
6547 }
6548 }
6549
6550 return OMX_ErrorNone;
6551 }
6552
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6553 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6554 {
6555 unsigned int index = 0;
6556
6557 if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6558 return OMX_ErrorBadParameter;
6559 }
6560
6561 index = bufferHdr - m_out_mem_ptr;
6562 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
6563
6564 if (index < drv_ctx.op_buf.actualcount
6565 && drv_ctx.ptr_outputbuffer) {
6566 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6567 drv_ctx.ptr_outputbuffer[index].bufferaddr);
6568
6569 struct vdec_setbuffer_cmd setbuffers;
6570 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6571 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
6572 sizeof (vdec_bufferpayload));
6573
6574 if (!dynamic_buf_mode) {
6575 if (streaming[CAPTURE_PORT] &&
6576 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6577 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6578 DEBUG_PRINT_ERROR("STREAMOFF Failed");
6579 } else {
6580 DEBUG_PRINT_LOW("STREAMOFF Successful");
6581 }
6582 }
6583 #ifdef _ANDROID_
6584 if (m_enable_android_native_buffers) {
6585 if (!secure_mode) {
6586 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6587 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6588 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6589 }
6590 }
6591 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6592 } else {
6593 #endif
6594 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0
6595 && !ouput_egl_buffers && !m_use_output_pmem) {
6596 if (drv_ctx.op_buf_map_info[index].free_buffer) {
6597 if (!secure_mode) {
6598 DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
6599 drv_ctx.ptr_outputbuffer[0].pmem_fd);
6600 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p",
6601 (unsigned int)drv_ctx.op_buf_map_info[index].map_size,
6602 drv_ctx.op_buf_map_info[index].base_address);
6603 munmap (drv_ctx.op_buf_map_info[index].base_address,
6604 drv_ctx.op_buf_map_info[index].map_size);
6605 }
6606 close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
6607 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6608 #ifdef USE_ION
6609 free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
6610 #endif
6611 } else {
6612 drv_ctx.op_buf_ion_info[index].ion_device_fd = -1;
6613 drv_ctx.op_buf_ion_info[index].ion_alloc_data.handle = 0;
6614 drv_ctx.op_buf_ion_info[index].fd_ion_data.fd = -1;
6615 }
6616 drv_ctx.op_buf_map_info[index].free_buffer = false;
6617 drv_ctx.op_buf_map_info[index].base_address = NULL;
6618 drv_ctx.op_buf_map_info[index].map_size = 0;
6619 drv_ctx.op_buf_map_info[index].offset = 0;
6620 }
6621 #ifdef _ANDROID_
6622 }
6623 #endif
6624 } //!dynamic_buf_mode
6625 if (release_output_done()) {
6626 free_extradata();
6627 }
6628 }
6629
6630 return OMX_ErrorNone;
6631
6632 }
6633
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6634 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
6635 OMX_BUFFERHEADERTYPE **bufferHdr,
6636 OMX_U32 port,
6637 OMX_PTR appData,
6638 OMX_U32 bytes)
6639 {
6640 OMX_BUFFERHEADERTYPE *input = NULL;
6641 unsigned char *buf_addr = NULL;
6642 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6643 unsigned i = 0;
6644
6645 /* Sanity Check*/
6646 if (bufferHdr == NULL) {
6647 return OMX_ErrorBadParameter;
6648 }
6649
6650 if (m_inp_heap_ptr == NULL) {
6651 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6652 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6653 drv_ctx.ip_buf.actualcount);
6654 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6655 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6656 drv_ctx.ip_buf.actualcount);
6657
6658 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6659 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6660 return OMX_ErrorInsufficientResources;
6661 }
6662 }
6663
6664 /*Find a Free index*/
6665 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6666 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6667 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6668 break;
6669 }
6670 }
6671
6672 if (i < drv_ctx.ip_buf.actualcount) {
6673 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6674
6675 if (buf_addr == NULL) {
6676 return OMX_ErrorInsufficientResources;
6677 }
6678
6679 *bufferHdr = (m_inp_heap_ptr + i);
6680 input = *bufferHdr;
6681 BITMASK_SET(&m_heap_inp_bm_count,i);
6682
6683 input->pBuffer = (OMX_U8 *)buf_addr;
6684 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6685 input->nVersion.nVersion = OMX_SPEC_VERSION;
6686 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6687 input->pAppPrivate = appData;
6688 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6689 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6690 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6691 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6692 /*Add the Buffers to freeq*/
6693 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6694 (unsigned)NULL, (unsigned)NULL)) {
6695 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6696 return OMX_ErrorInsufficientResources;
6697 }
6698 } else {
6699 return OMX_ErrorBadParameter;
6700 }
6701
6702 return eRet;
6703
6704 }
6705
6706
6707 /* ======================================================================
6708 FUNCTION
6709 omx_vdec::AllocateInputBuffer
6710
6711 DESCRIPTION
6712 Helper function for allocate buffer in the input pin
6713
6714 PARAMETERS
6715 None.
6716
6717 RETURN VALUE
6718 true/false
6719
6720 ========================================================================== */
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)6721 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
6722 OMX_IN OMX_HANDLETYPE hComp,
6723 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6724 OMX_IN OMX_U32 port,
6725 OMX_IN OMX_PTR appData,
6726 OMX_IN OMX_U32 bytes)
6727 {
6728 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6729 struct vdec_setbuffer_cmd setbuffers;
6730 OMX_BUFFERHEADERTYPE *input = NULL;
6731 unsigned i = 0;
6732 unsigned char *buf_addr = NULL;
6733 int pmem_fd = -1, ret = 0;
6734 unsigned int align_size = 0;
6735
6736 (void) hComp;
6737 (void) port;
6738
6739
6740 if (bytes != drv_ctx.ip_buf.buffer_size) {
6741 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6742 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6743 return OMX_ErrorBadParameter;
6744 }
6745
6746 if (!m_inp_mem_ptr) {
6747 struct v4l2_requestbuffers bufreq;
6748 bufreq.memory = V4L2_MEMORY_USERPTR;
6749 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6750 bufreq.count = drv_ctx.ip_buf.actualcount;
6751 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6752 if (ret) {
6753 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %s", strerror(errno));
6754 /*TODO: How to handle this case */
6755 eRet = OMX_ErrorInsufficientResources;
6756 } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6757 DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6758 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6759 eRet = OMX_ErrorInsufficientResources;
6760 }
6761
6762 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6763 drv_ctx.ip_buf.actualcount,
6764 (unsigned int)drv_ctx.ip_buf.buffer_size);
6765
6766 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6767 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6768
6769 if (m_inp_mem_ptr == NULL) {
6770 return OMX_ErrorInsufficientResources;
6771 }
6772
6773 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6774 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6775
6776 if (drv_ctx.ptr_inputbuffer == NULL) {
6777 return OMX_ErrorInsufficientResources;
6778 }
6779 #ifdef USE_ION
6780 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6781 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6782
6783 if (drv_ctx.ip_buf_ion_info == NULL) {
6784 return OMX_ErrorInsufficientResources;
6785 }
6786 #endif
6787
6788 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6789 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6790 #ifdef USE_ION
6791 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6792 #endif
6793 }
6794 }
6795
6796 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6797 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6798 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6799 break;
6800 }
6801 }
6802
6803 if (i < drv_ctx.ip_buf.actualcount) {
6804 struct v4l2_buffer buf;
6805 struct v4l2_plane plane;
6806 int rc;
6807 DEBUG_PRINT_LOW("Allocate input Buffer");
6808 #ifdef USE_ION
6809 align_size = drv_ctx.ip_buf.buffer_size + 512;
6810 align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6811 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6812 align_size, drv_ctx.op_buf.alignment,
6813 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6814 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6815 SECURE_FLAGS_INPUT_BUFFER : 0);
6816 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6817 return OMX_ErrorInsufficientResources;
6818 }
6819 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6820 #else
6821 pmem_fd = open (MEM_DEVICE,O_RDWR);
6822
6823 if (pmem_fd < 0) {
6824 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6825 return OMX_ErrorInsufficientResources;
6826 }
6827
6828 if (pmem_fd == 0) {
6829 pmem_fd = open (MEM_DEVICE,O_RDWR);
6830
6831 if (pmem_fd < 0) {
6832 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6833 return OMX_ErrorInsufficientResources;
6834 }
6835 }
6836
6837 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6838 drv_ctx.ip_buf.alignment)) {
6839 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6840 close(pmem_fd);
6841 return OMX_ErrorInsufficientResources;
6842 }
6843 #endif
6844 if (!secure_mode) {
6845 buf_addr = (unsigned char *)mmap(NULL,
6846 drv_ctx.ip_buf.buffer_size,
6847 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6848
6849 if (buf_addr == MAP_FAILED) {
6850 close(pmem_fd);
6851 #ifdef USE_ION
6852 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6853 #endif
6854 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6855 return OMX_ErrorInsufficientResources;
6856 }
6857 }
6858 *bufferHdr = (m_inp_mem_ptr + i);
6859 if (secure_mode)
6860 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6861 else
6862 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6863 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6864 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6865 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6866 drv_ctx.ptr_inputbuffer [i].offset = 0;
6867
6868
6869 buf.index = i;
6870 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6871 buf.memory = V4L2_MEMORY_USERPTR;
6872 plane.bytesused = 0;
6873 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6874 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6875 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6876 plane.reserved[1] = 0;
6877 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6878 buf.m.planes = &plane;
6879 buf.length = 1;
6880
6881 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6882 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6883
6884 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6885
6886 if (rc) {
6887 DEBUG_PRINT_ERROR("Failed to prepare bufs");
6888 /*TODO: How to handle this case */
6889 return OMX_ErrorInsufficientResources;
6890 }
6891
6892 input = *bufferHdr;
6893 BITMASK_SET(&m_inp_bm_count,i);
6894 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6895 if (allocate_native_handle) {
6896 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6897 if (!nh) {
6898 DEBUG_PRINT_ERROR("Native handle create failed");
6899 return OMX_ErrorInsufficientResources;
6900 }
6901 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6902 input->pBuffer = (OMX_U8 *)nh;
6903 } else if (secure_mode || m_input_pass_buffer_fd) {
6904 /*Legacy method, pass ion fd stashed directly in pBuffer*/
6905 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6906 } else {
6907 input->pBuffer = (OMX_U8 *)buf_addr;
6908 }
6909 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6910 input->nVersion.nVersion = OMX_SPEC_VERSION;
6911 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6912 input->pAppPrivate = appData;
6913 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6914 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6915
6916 if (drv_ctx.disable_dmx) {
6917 eRet = allocate_desc_buffer(i);
6918 }
6919 } else {
6920 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6921 eRet = OMX_ErrorInsufficientResources;
6922 }
6923 return eRet;
6924 }
6925
6926
6927 /* ======================================================================
6928 FUNCTION
6929 omx_vdec::AllocateOutputBuffer
6930
6931 DESCRIPTION
6932 Helper fn for AllocateBuffer in the output pin
6933
6934 PARAMETERS
6935 <TBD>.
6936
6937 RETURN VALUE
6938 OMX Error None if everything went well.
6939
6940 ========================================================================== */
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)6941 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
6942 OMX_IN OMX_HANDLETYPE hComp,
6943 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6944 OMX_IN OMX_U32 port,
6945 OMX_IN OMX_PTR appData,
6946 OMX_IN OMX_U32 bytes)
6947 {
6948 (void)hComp;
6949 (void)port;
6950 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6951 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
6952 unsigned i= 0; // Temporary counter
6953 struct vdec_setbuffer_cmd setbuffers;
6954 int extra_idx = 0;
6955 #ifdef USE_ION
6956 int ion_device_fd =-1;
6957 struct ion_allocation_data ion_alloc_data;
6958 struct ion_fd_data fd_ion_data;
6959 #endif
6960 if (!m_out_mem_ptr) {
6961 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6962 drv_ctx.op_buf.actualcount,
6963 (unsigned int)drv_ctx.op_buf.buffer_size);
6964 int nBufHdrSize = 0;
6965 int nPlatformEntrySize = 0;
6966 int nPlatformListSize = 0;
6967 int nPMEMInfoSize = 0;
6968
6969 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
6970 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
6971 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6972
6973 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6974 drv_ctx.op_buf.actualcount);
6975 nBufHdrSize = drv_ctx.op_buf.actualcount *
6976 sizeof(OMX_BUFFERHEADERTYPE);
6977
6978 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
6979 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6980 nPlatformListSize = drv_ctx.op_buf.actualcount *
6981 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6982 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6983 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6984
6985 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6986 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6987 nPMEMInfoSize,
6988 nPlatformListSize);
6989 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6990 drv_ctx.op_buf.actualcount);
6991 unsigned char *pmem_baseaddress_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {NULL};
6992 int pmem_fd[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {-1};
6993 int alloc_size[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {0};
6994 static const int block_max_size = 128 * 1024 * 1024;
6995 unsigned int block_buf_count = block_max_size / drv_ctx.op_buf.buffer_size;
6996 unsigned int last_block_buf_count = 0, block_count = 1;
6997 if (drv_ctx.op_buf.actualcount <= block_buf_count) {
6998 block_buf_count = drv_ctx.op_buf.actualcount;
6999 } else {
7000 last_block_buf_count = drv_ctx.op_buf.actualcount % block_buf_count;
7001 block_count = (drv_ctx.op_buf.actualcount + block_buf_count - 1) / block_buf_count;
7002 }
7003 unsigned int idx = 0;
7004 DEBUG_PRINT_LOW("block_count = %d block_buf_count = %d last_block_buf_count = %d",
7005 block_count, block_buf_count, last_block_buf_count);
7006 #ifdef USE_ION
7007 struct vdec_ion op_buf_ion_info_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS];
7008 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
7009 for (; idx < block_count; idx++) {
7010 int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
7011 last_block_buf_count : block_buf_count;
7012 alloc_size[idx] = drv_ctx.op_buf.buffer_size * cnt;
7013 // Allocate output buffers as cached to improve performance of software-reading
7014 // of the YUVs. Output buffers are cache-invalidated in driver.
7015 // If color-conversion is involved, Only the C2D output buffers are cached, no
7016 // need to cache the decoder's output buffers
7017 op_buf_ion_info_temp[idx].ion_device_fd = alloc_map_ion_memory(
7018 alloc_size[idx],
7019 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
7020 &op_buf_ion_info_temp[idx].ion_alloc_data, &op_buf_ion_info_temp[idx].fd_ion_data,
7021 (secure_mode && !secure_scaling_to_non_secure_opb) ?
7022 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
7023 if (op_buf_ion_info_temp[idx].ion_device_fd < 0) {
7024 DEBUG_PRINT_LOW("Failed to allocate chunk %ul size = %d", idx, alloc_size[idx]);
7025 break;
7026 }
7027 pmem_fd[idx] = op_buf_ion_info_temp[idx].fd_ion_data.fd;
7028 DEBUG_PRINT_LOW("Allocated chunk %ul fd = %ul size = %d", idx, pmem_fd[idx], alloc_size[idx]);
7029 }
7030 if (idx != block_count) {
7031 for (OMX_U32 i = 0; i < idx; i++) {
7032 close(pmem_fd[i]);
7033 free_ion_memory(&op_buf_ion_info_temp[i]);
7034 }
7035 return OMX_ErrorInsufficientResources;
7036 }
7037
7038 #else
7039 for (idx = 0; idx < block_count; idx++) {
7040 pmem_fd[idx] = open (MEM_DEVICE,O_RDWR);
7041
7042 if (pmem_fd[idx] < 0) {
7043 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
7044 drv_ctx.op_buf.buffer_size);
7045 break;
7046 }
7047 int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
7048 last_block_buf_count : block_buf_count;
7049 if (!align_pmem_buffers(pmem_fd[idx], drv_ctx.op_buf.buffer_size * cnt,
7050 drv_ctx.op_buf.alignment)) {
7051 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
7052 close(pmem_fd[idx]);
7053 break;
7054 }
7055 }
7056 if (idx != block_count) {
7057 for (i = 0; i < idx; i++) {
7058 close(pmem_fd[i]);
7059 }
7060 return OMX_ErrorInsufficientResources;
7061 }
7062 #endif
7063 if (!secure_mode) {
7064 idx = 0;
7065 for (; idx < block_count; idx++) {
7066 pmem_baseaddress_temp[idx] = (unsigned char *)mmap(NULL,
7067 alloc_size[idx],
7068 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd[idx], 0);
7069
7070 if (pmem_baseaddress_temp[idx] == MAP_FAILED) {
7071 DEBUG_PRINT_ERROR("MMAP failed for Size %u for fd = %d",
7072 (unsigned int)alloc_size[idx], pmem_fd[idx]);
7073 close(pmem_fd[idx]);
7074 #ifdef USE_ION
7075 free_ion_memory(&op_buf_ion_info_temp[idx]);
7076 #endif
7077 break;
7078 }
7079 }
7080 if (idx != block_count) {
7081 for (i = 0; i < idx; i++) {
7082 munmap(pmem_baseaddress_temp[idx], alloc_size[idx]);
7083 close(pmem_fd[i]);
7084 #ifdef USE_ION
7085 free_ion_memory(&op_buf_ion_info_temp[i]);
7086 #endif
7087 }
7088 return OMX_ErrorInsufficientResources;
7089 }
7090 }
7091 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
7092 // Alloc mem for platform specific info
7093 char *pPtr=NULL;
7094 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7095 nPMEMInfoSize,1);
7096 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
7097 calloc (sizeof(struct vdec_bufferpayload),
7098 drv_ctx.op_buf.actualcount);
7099 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
7100 calloc (sizeof (struct vdec_output_frameinfo),
7101 drv_ctx.op_buf.actualcount);
7102 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
7103 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
7104 return OMX_ErrorInsufficientResources;
7105 }
7106
7107 #ifdef USE_ION
7108 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
7109 calloc (sizeof(struct vdec_ion),
7110 drv_ctx.op_buf.actualcount);
7111 if (!drv_ctx.op_buf_ion_info) {
7112 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
7113 return OMX_ErrorInsufficientResources;
7114 }
7115 #endif
7116 drv_ctx.op_buf_map_info = (struct vdec_ion_map_info *)\
7117 calloc (sizeof(struct vdec_ion_map_info),
7118 drv_ctx.op_buf.actualcount);
7119 if (!drv_ctx.op_buf_map_info) {
7120 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_map_info");
7121 return OMX_ErrorInsufficientResources;
7122 }
7123
7124 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
7125 && drv_ctx.ptr_respbuffer) {
7126 drv_ctx.ptr_outputbuffer[0].mmaped_size =
7127 (drv_ctx.op_buf.buffer_size *
7128 drv_ctx.op_buf.actualcount);
7129 bufHdr = m_out_mem_ptr;
7130 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7131 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7132 (((char *) m_platform_list) + nPlatformListSize);
7133 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7134 (((char *) m_platform_entry) + nPlatformEntrySize);
7135 pPlatformList = m_platform_list;
7136 pPlatformEntry = m_platform_entry;
7137 pPMEMInfo = m_pmem_info;
7138
7139 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
7140
7141 // Settting the entire storage nicely
7142 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
7143 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
7144 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
7145 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
7146 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
7147 // Set the values when we determine the right HxW param
7148 bufHdr->nAllocLen = bytes;
7149 bufHdr->nFilledLen = 0;
7150 bufHdr->pAppPrivate = appData;
7151 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7152 // Platform specific PMEM Information
7153 // Initialize the Platform Entry
7154 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
7155 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7156 pPlatformEntry->entry = pPMEMInfo;
7157 // Initialize the Platform List
7158 pPlatformList->nEntries = 1;
7159 pPlatformList->entryList = pPlatformEntry;
7160 // Keep pBuffer NULL till vdec is opened
7161 bufHdr->pBuffer = NULL;
7162 bufHdr->nOffset = 0;
7163
7164 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
7165 pPMEMInfo->pmem_fd = -1;
7166 bufHdr->pPlatformPrivate = pPlatformList;
7167
7168 int block_idx = i / block_buf_count;
7169 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd[block_idx];
7170 m_pmem_info[i].pmem_fd = pmem_fd[block_idx];
7171 #ifdef USE_ION
7172 drv_ctx.op_buf_ion_info[i].ion_device_fd = op_buf_ion_info_temp[block_idx].ion_device_fd;
7173 drv_ctx.op_buf_ion_info[i].ion_alloc_data = op_buf_ion_info_temp[block_idx].ion_alloc_data;
7174 drv_ctx.op_buf_ion_info[i].fd_ion_data = op_buf_ion_info_temp[block_idx].fd_ion_data;
7175 #endif
7176 drv_ctx.op_buf_map_info[i].free_buffer = !(i % block_buf_count);
7177 drv_ctx.op_buf_map_info[i].base_address = pmem_baseaddress_temp[block_idx];
7178 drv_ctx.op_buf_map_info[i].map_size = alloc_size[block_idx];
7179 drv_ctx.op_buf_map_info[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7180
7181 /*Create a mapping between buffers*/
7182 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7183 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
7184 &drv_ctx.ptr_outputbuffer[i];
7185 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
7186 drv_ctx.ptr_outputbuffer[i].bufferaddr =
7187 pmem_baseaddress_temp[block_idx] + (drv_ctx.op_buf.buffer_size * (i % block_buf_count));
7188 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
7189 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
7190 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
7191
7192 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
7193 pmem_fd[block_idx], (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
7194 drv_ctx.ptr_outputbuffer[i].bufferaddr);
7195 // Move the buffer and buffer header pointers
7196 bufHdr++;
7197 pPMEMInfo++;
7198 pPlatformEntry++;
7199 pPlatformList++;
7200 }
7201 } else {
7202 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7203 m_out_mem_ptr, pPtr);
7204 if (m_out_mem_ptr) {
7205 free(m_out_mem_ptr);
7206 m_out_mem_ptr = NULL;
7207 }
7208 if (pPtr) {
7209 free(pPtr);
7210 pPtr = NULL;
7211 }
7212 if (drv_ctx.ptr_outputbuffer) {
7213 free(drv_ctx.ptr_outputbuffer);
7214 drv_ctx.ptr_outputbuffer = NULL;
7215 }
7216 if (drv_ctx.ptr_respbuffer) {
7217 free(drv_ctx.ptr_respbuffer);
7218 drv_ctx.ptr_respbuffer = NULL;
7219 }
7220 #ifdef USE_ION
7221 if (drv_ctx.op_buf_ion_info) {
7222 DEBUG_PRINT_LOW("Free o/p ion context");
7223 free(drv_ctx.op_buf_ion_info);
7224 drv_ctx.op_buf_ion_info = NULL;
7225 }
7226 #endif
7227 free(drv_ctx.op_buf_map_info);
7228 drv_ctx.op_buf_map_info = NULL;
7229 eRet = OMX_ErrorInsufficientResources;
7230 }
7231 if (eRet == OMX_ErrorNone)
7232 eRet = allocate_extradata();
7233 }
7234
7235 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
7236 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
7237 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
7238 break;
7239 }
7240 }
7241
7242 if (eRet == OMX_ErrorNone) {
7243 if (i < drv_ctx.op_buf.actualcount) {
7244 struct v4l2_buffer buf;
7245 struct v4l2_plane plane[VIDEO_MAX_PLANES];
7246 int rc;
7247 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
7248
7249 drv_ctx.ptr_outputbuffer[i].buffer_len =
7250 drv_ctx.op_buf.buffer_size;
7251
7252 *bufferHdr = (m_out_mem_ptr + i );
7253 if (secure_mode) {
7254 #ifdef USE_ION
7255 drv_ctx.ptr_outputbuffer[i].bufferaddr =
7256 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7257 #else
7258 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
7259 #endif
7260 }
7261 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
7262
7263 buf.index = i;
7264 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7265 buf.memory = V4L2_MEMORY_USERPTR;
7266 plane[0].length = drv_ctx.op_buf.buffer_size;
7267 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
7268 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
7269 #ifdef USE_ION
7270 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
7271 #endif
7272 plane[0].reserved[1] = drv_ctx.op_buf_map_info[i].offset;
7273 plane[0].data_offset = 0;
7274 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7275 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7276 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7277 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
7278 #ifdef USE_ION
7279 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7280 #endif
7281 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
7282 plane[extra_idx].data_offset = 0;
7283 } else if (extra_idx >= VIDEO_MAX_PLANES) {
7284 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
7285 return OMX_ErrorBadParameter;
7286 }
7287 buf.m.planes = plane;
7288 buf.length = drv_ctx.num_planes;
7289 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
7290 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
7291 if (rc) {
7292 /*TODO: How to handle this case */
7293 return OMX_ErrorInsufficientResources;
7294 }
7295
7296 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
7297 enum v4l2_buf_type buf_type;
7298 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7299 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7300 if (rc) {
7301 return OMX_ErrorInsufficientResources;
7302 } else {
7303 streaming[CAPTURE_PORT] = true;
7304 DEBUG_PRINT_LOW("STREAMON Successful");
7305 }
7306
7307 DEBUG_PRINT_HIGH("Enabling Turbo mode");
7308 request_perf_level(VIDC_TURBO);
7309 }
7310
7311 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
7312 (*bufferHdr)->pAppPrivate = appData;
7313 BITMASK_SET(&m_out_bm_count,i);
7314 } else {
7315 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
7316 eRet = OMX_ErrorInsufficientResources;
7317 }
7318 }
7319
7320 return eRet;
7321 }
7322
7323
7324 // AllocateBuffer -- API Call
7325 /* ======================================================================
7326 FUNCTION
7327 omx_vdec::AllocateBuffer
7328
7329 DESCRIPTION
7330 Returns zero if all the buffers released..
7331
7332 PARAMETERS
7333 None.
7334
7335 RETURN VALUE
7336 true/false
7337
7338 ========================================================================== */
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)7339 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
7340 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7341 OMX_IN OMX_U32 port,
7342 OMX_IN OMX_PTR appData,
7343 OMX_IN OMX_U32 bytes)
7344 {
7345 unsigned i = 0;
7346 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
7347
7348 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
7349 if (m_state == OMX_StateInvalid) {
7350 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
7351 return OMX_ErrorInvalidState;
7352 }
7353
7354 if (port == OMX_CORE_INPUT_PORT_INDEX) {
7355 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
7356 // ensure that use-buffer was never called.
7357 // Mix-and-match of useBuffer and allocateBuffer is not allowed
7358 if (m_inp_mem_ptr && input_use_buffer) {
7359 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
7360 return OMX_ErrorUndefined;
7361 }
7362 if (arbitrary_bytes) {
7363 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
7364 } else {
7365 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
7366 }
7367 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7368 if (output_use_buffer) {
7369 DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
7370 return OMX_ErrorBadParameter;
7371 }
7372 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
7373 appData,bytes);
7374 } else {
7375 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
7376 eRet = OMX_ErrorBadPortIndex;
7377 }
7378 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
7379 if (eRet == OMX_ErrorNone) {
7380 if (allocate_done()) {
7381 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
7382 // Send the callback now
7383 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
7384 post_event(OMX_CommandStateSet,OMX_StateIdle,
7385 OMX_COMPONENT_GENERATE_EVENT);
7386 }
7387 }
7388 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
7389 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
7390 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
7391 post_event(OMX_CommandPortEnable,
7392 OMX_CORE_INPUT_PORT_INDEX,
7393 OMX_COMPONENT_GENERATE_EVENT);
7394 }
7395 }
7396 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
7397 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
7398 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
7399 post_event(OMX_CommandPortEnable,
7400 OMX_CORE_OUTPUT_PORT_INDEX,
7401 OMX_COMPONENT_GENERATE_EVENT);
7402 }
7403 }
7404 }
7405 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
7406 return eRet;
7407 }
7408
7409 // Free Buffer - API call
7410 /* ======================================================================
7411 FUNCTION
7412 omx_vdec::FreeBuffer
7413
7414 DESCRIPTION
7415
7416 PARAMETERS
7417 None.
7418
7419 RETURN VALUE
7420 true/false
7421
7422 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7423 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
7424 OMX_IN OMX_U32 port,
7425 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7426 {
7427 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7428 unsigned int nPortIndex;
7429 (void) hComp;
7430 DEBUG_PRINT_LOW("In for decoder free_buffer");
7431
7432 auto_lock l(buf_lock);
7433 if (m_state == OMX_StateIdle &&
7434 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7435 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
7436 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
7437 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
7438 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
7439 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
7440 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
7441 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
7442 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
7443 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
7444 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
7445 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
7446 post_event(OMX_EventError,
7447 OMX_ErrorPortUnpopulated,
7448 OMX_COMPONENT_GENERATE_EVENT);
7449 m_buffer_error = true;
7450 return OMX_ErrorIncorrectStateOperation;
7451 } else if (m_state != OMX_StateInvalid) {
7452 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
7453 post_event(OMX_EventError,
7454 OMX_ErrorPortUnpopulated,
7455 OMX_COMPONENT_GENERATE_EVENT);
7456 }
7457
7458 if (port == OMX_CORE_INPUT_PORT_INDEX) {
7459 /*Check if arbitrary bytes*/
7460 if (!arbitrary_bytes && !input_use_buffer)
7461 nPortIndex = buffer - m_inp_mem_ptr;
7462 else
7463 nPortIndex = buffer - m_inp_heap_ptr;
7464
7465 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
7466 if (nPortIndex < drv_ctx.ip_buf.actualcount &&
7467 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
7468 // Clear the bit associated with it.
7469 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
7470 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
7471 if (input_use_buffer == true) {
7472
7473 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
7474 if (m_phdr_pmem_ptr)
7475 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
7476 } else {
7477 if (arbitrary_bytes) {
7478 if (m_phdr_pmem_ptr)
7479 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
7480 else
7481 free_input_buffer(nPortIndex,NULL);
7482 } else
7483 free_input_buffer(buffer);
7484 }
7485 m_inp_bPopulated = OMX_FALSE;
7486 if(release_input_done())
7487 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
7488 /*Free the Buffer Header*/
7489 if (release_input_done()) {
7490 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
7491 free_input_buffer_header();
7492 }
7493 } else {
7494 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
7495 eRet = OMX_ErrorBadPortIndex;
7496 }
7497
7498 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
7499 && release_input_done()) {
7500 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7501 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
7502 post_event(OMX_CommandPortDisable,
7503 OMX_CORE_INPUT_PORT_INDEX,
7504 OMX_COMPONENT_GENERATE_EVENT);
7505 }
7506 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7507 // check if the buffer is valid
7508 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7509 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7510 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
7511 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
7512 // Clear the bit associated with it.
7513 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
7514 m_out_bPopulated = OMX_FALSE;
7515 client_buffers.free_output_buffer (buffer);
7516
7517 if(release_output_done()) {
7518 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
7519 }
7520 if (release_output_done()) {
7521 free_output_buffer_header();
7522 }
7523 } else {
7524 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
7525 eRet = OMX_ErrorBadPortIndex;
7526 }
7527 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
7528 && release_output_done()) {
7529 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
7530
7531 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7532 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
7533 #ifdef _ANDROID_ICS_
7534 if (m_enable_android_native_buffers) {
7535 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
7536 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7537 }
7538 #endif
7539
7540 post_event(OMX_CommandPortDisable,
7541 OMX_CORE_OUTPUT_PORT_INDEX,
7542 OMX_COMPONENT_GENERATE_EVENT);
7543 }
7544 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
7545 nPortIndex = buffer - m_client_output_extradata_mem_ptr;
7546 DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
7547
7548 BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
7549
7550 if (release_output_extradata_done()) {
7551 free_output_extradata_buffer_header();
7552 }
7553 } else {
7554 eRet = OMX_ErrorBadPortIndex;
7555 }
7556 if ((eRet == OMX_ErrorNone) &&
7557 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7558 if (release_done()) {
7559 /*
7560 * Reset buffer requirements here to ensure setting buffer requirement
7561 * when component move to executing state from loaded state via idle.
7562 */
7563 drv_ctx.op_buf.buffer_size = 0;
7564 drv_ctx.op_buf.actualcount = 0;
7565
7566 // Send the callback now
7567 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
7568 post_event(OMX_CommandStateSet, OMX_StateLoaded,
7569 OMX_COMPONENT_GENERATE_EVENT);
7570 m_buffer_error = false;
7571 }
7572 }
7573 return eRet;
7574 }
7575
7576
7577 /* ======================================================================
7578 FUNCTION
7579 omx_vdec::EmptyThisBuffer
7580
7581 DESCRIPTION
7582 This routine is used to push the encoded video frames to
7583 the video decoder.
7584
7585 PARAMETERS
7586 None.
7587
7588 RETURN VALUE
7589 OMX Error None if everything went successful.
7590
7591 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7592 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7593 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7594 {
7595 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
7596 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
7597
7598 if (m_state != OMX_StateExecuting &&
7599 m_state != OMX_StatePause &&
7600 m_state != OMX_StateIdle) {
7601 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
7602 return OMX_ErrorInvalidState;
7603 }
7604
7605 if (buffer == NULL) {
7606 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
7607 return OMX_ErrorBadParameter;
7608 }
7609
7610 if (!m_inp_bEnabled) {
7611 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7612 return OMX_ErrorIncorrectStateOperation;
7613 }
7614
7615 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7616 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7617 return OMX_ErrorBadPortIndex;
7618 }
7619
7620 if (perf_flag) {
7621 if (!latency) {
7622 dec_time.stop();
7623 latency = dec_time.processing_time_us();
7624 dec_time.start();
7625 }
7626 }
7627
7628 if (arbitrary_bytes) {
7629 nBufferIndex = buffer - m_inp_heap_ptr;
7630 } else {
7631 if (input_use_buffer == true) {
7632 nBufferIndex = buffer - m_inp_heap_ptr;
7633 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7634 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7635 return OMX_ErrorBadParameter;
7636 }
7637 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7638 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7639 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7640 buffer = &m_inp_mem_ptr[nBufferIndex];
7641 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7642 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7643 } else {
7644 nBufferIndex = buffer - m_inp_mem_ptr;
7645 }
7646 }
7647
7648 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7649 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7650 return OMX_ErrorBadParameter;
7651 }
7652
7653 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7654 codec_config_flag = true;
7655 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7656 }
7657
7658 /* The client should not set this when codec is in arbitrary bytes mode */
7659 if (m_input_pass_buffer_fd) {
7660 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7661 }
7662
7663 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7664 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7665 if (arbitrary_bytes) {
7666 post_event ((unsigned long)hComp,(unsigned long)buffer,
7667 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7668 } else {
7669 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7670 }
7671 time_stamp_dts.insert_timestamp(buffer);
7672 return OMX_ErrorNone;
7673 }
7674
7675 /* ======================================================================
7676 FUNCTION
7677 omx_vdec::empty_this_buffer_proxy
7678
7679 DESCRIPTION
7680 This routine is used to push the encoded video frames to
7681 the video decoder.
7682
7683 PARAMETERS
7684 None.
7685
7686 RETURN VALUE
7687 OMX Error None if everything went successful.
7688
7689 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7690 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
7691 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7692 {
7693 VIDC_TRACE_NAME_HIGH("ETB");
7694 (void) hComp;
7695 int push_cnt = 0,i=0;
7696 unsigned nPortIndex = 0;
7697 OMX_ERRORTYPE ret = OMX_ErrorNone;
7698 struct vdec_input_frameinfo frameinfo;
7699 struct vdec_bufferpayload *temp_buffer;
7700 struct vdec_seqheader seq_header;
7701 bool port_setting_changed = true;
7702
7703 /*Should we generate a Aync error event*/
7704 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7705 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7706 return OMX_ErrorBadParameter;
7707 }
7708
7709 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7710
7711 if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7712 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7713 nPortIndex);
7714 return OMX_ErrorBadParameter;
7715 }
7716
7717 pending_input_buffers++;
7718 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
7719
7720 /* return zero length and not an EOS buffer */
7721 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7722 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7723 DEBUG_PRINT_HIGH("return zero legth buffer");
7724 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7725 OMX_COMPONENT_GENERATE_EBD);
7726 return OMX_ErrorNone;
7727 }
7728
7729 if (input_flush_progress == true) {
7730 DEBUG_PRINT_LOW("Flush in progress return buffer ");
7731 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7732 OMX_COMPONENT_GENERATE_EBD);
7733 return OMX_ErrorNone;
7734 }
7735
7736 auto_lock l(buf_lock);
7737 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7738
7739 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7740 return OMX_ErrorBadParameter;
7741 }
7742
7743 if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7744 DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7745 return OMX_ErrorBadParameter;
7746 }
7747 /* If its first frame, H264 codec and reject is true, then parse the nal
7748 and get the profile. Based on this, reject the clip playback */
7749 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
7750 m_reject_avc_1080p_mp) {
7751 first_frame = 1;
7752 DEBUG_PRINT_ERROR("Parse nal to get the profile");
7753 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
7754 NALU_TYPE_SPS);
7755 m_profile = h264_parser->get_profile();
7756 ret = is_video_session_supported();
7757 if (ret) {
7758 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7759 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7760 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7761 m_state = OMX_StateInvalid;
7762 return OMX_ErrorNone;
7763 }
7764 }
7765
7766 VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7767 VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7768 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7769 /*for use buffer we need to memcpy the data*/
7770 temp_buffer->buffer_len = buffer->nFilledLen;
7771
7772 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7773 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7774 if (arbitrary_bytes) {
7775 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7776 } else {
7777 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7778 buffer->nFilledLen);
7779 }
7780 } else {
7781 return OMX_ErrorBadParameter;
7782 }
7783
7784 }
7785
7786 frameinfo.bufferaddr = temp_buffer->bufferaddr;
7787 frameinfo.client_data = (void *) buffer;
7788 frameinfo.datalen = temp_buffer->buffer_len;
7789 frameinfo.flags = 0;
7790 frameinfo.offset = buffer->nOffset;
7791 frameinfo.pmem_fd = temp_buffer->pmem_fd;
7792 frameinfo.pmem_offset = temp_buffer->offset;
7793 frameinfo.timestamp = buffer->nTimeStamp;
7794 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7795 DEBUG_PRINT_LOW("ETB: dmx enabled");
7796 if (m_demux_entries == 0) {
7797 extract_demux_addr_offsets(buffer);
7798 }
7799
7800 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7801 handle_demux_data(buffer);
7802 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7803 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7804 } else {
7805 frameinfo.desc_addr = NULL;
7806 frameinfo.desc_size = 0;
7807 }
7808 if (!arbitrary_bytes) {
7809 frameinfo.flags |= buffer->nFlags;
7810 }
7811
7812 #ifdef _ANDROID_
7813 if (m_debug_timestamp) {
7814 if (arbitrary_bytes) {
7815 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7816 m_timestamp_list.insert_ts(buffer->nTimeStamp);
7817 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7818 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7819 m_timestamp_list.insert_ts(buffer->nTimeStamp);
7820 }
7821 }
7822 #endif
7823
7824 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7825
7826 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7827 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7828 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7829 }
7830
7831 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7832 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7833 frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7834 h264_scratch.nFilledLen = 0;
7835 nal_count = 0;
7836 look_ahead_nal = false;
7837 frame_count = 0;
7838 if (m_frame_parser.mutils)
7839 m_frame_parser.mutils->initialize_frame_checking_environment();
7840 m_frame_parser.flush();
7841 h264_last_au_ts = LLONG_MAX;
7842 h264_last_au_flags = 0;
7843 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7844 m_demux_entries = 0;
7845 }
7846 struct v4l2_buffer buf;
7847 struct v4l2_plane plane;
7848 memset( (void *)&buf, 0, sizeof(buf));
7849 memset( (void *)&plane, 0, sizeof(plane));
7850 int rc;
7851 unsigned long print_count;
7852 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7853 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7854 DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7855 }
7856 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7857 buf.index = nPortIndex;
7858 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7859 buf.memory = V4L2_MEMORY_USERPTR;
7860 plane.bytesused = temp_buffer->buffer_len;
7861 plane.length = drv_ctx.ip_buf.buffer_size;
7862 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7863 (unsigned long)temp_buffer->offset;
7864 plane.reserved[0] = temp_buffer->pmem_fd;
7865 plane.reserved[1] = temp_buffer->offset;
7866 plane.data_offset = 0;
7867 buf.m.planes = &plane;
7868 buf.length = 1;
7869 if (frameinfo.timestamp >= LLONG_MAX) {
7870 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7871 }
7872 //assumption is that timestamp is in milliseconds
7873 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7874 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7875 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7876 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7877
7878 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7879 DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7880 android_atomic_inc(&m_queued_codec_config_count);
7881 }
7882
7883 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7884 if (rc) {
7885 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7886 m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7887 return OMX_ErrorHardware;
7888 }
7889
7890 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7891 codec_config_flag = false;
7892 }
7893 if (!streaming[OUTPUT_PORT]) {
7894 enum v4l2_buf_type buf_type;
7895 int ret,r;
7896
7897 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7898 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7899 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7900 if (!ret) {
7901 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7902 streaming[OUTPUT_PORT] = true;
7903 } else if (errno == EBUSY) {
7904 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7905 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7906 OMX_COMPONENT_GENERATE_EBD);
7907 return OMX_ErrorInsufficientResources;
7908 } else {
7909 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7910 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7911 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7912 OMX_COMPONENT_GENERATE_EBD);
7913 return OMX_ErrorBadParameter;
7914 }
7915 }
7916 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7917 frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7918 (unsigned int)frameinfo.datalen);
7919
7920 return ret;
7921 }
7922
7923 /* ======================================================================
7924 FUNCTION
7925 omx_vdec::FillThisBuffer
7926
7927 DESCRIPTION
7928 IL client uses this method to release the frame buffer
7929 after displaying them.
7930
7931 PARAMETERS
7932 None.
7933
7934 RETURN VALUE
7935 true/false
7936
7937 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7938 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7939 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7940 {
7941 if (m_state != OMX_StateExecuting &&
7942 m_state != OMX_StatePause &&
7943 m_state != OMX_StateIdle) {
7944 DEBUG_PRINT_ERROR("FTB in Invalid State");
7945 return OMX_ErrorInvalidState;
7946 }
7947
7948 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7949 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7950 return OMX_ErrorBadPortIndex;
7951 }
7952
7953 if (!m_out_bEnabled) {
7954 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7955 return OMX_ErrorIncorrectStateOperation;
7956 }
7957
7958 unsigned nPortIndex = 0;
7959 if (dynamic_buf_mode) {
7960 private_handle_t *handle = NULL;
7961 struct VideoDecoderOutputMetaData *meta;
7962 unsigned int nPortIndex = 0;
7963
7964 if (!buffer || !buffer->pBuffer) {
7965 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7966 return OMX_ErrorBadParameter;
7967 }
7968
7969 //get the buffer type and fd info
7970 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7971 handle = (private_handle_t *)meta->pHandle;
7972 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7973
7974 if (!handle) {
7975 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7976 return OMX_ErrorBadParameter;
7977 }
7978 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7979 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7980 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7981 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7982 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7983 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7984
7985 //Store private handle from GraphicBuffer
7986 native_buffer[nPortIndex].privatehandle = handle;
7987 native_buffer[nPortIndex].nativehandle = handle;
7988 } else {
7989 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7990 return OMX_ErrorBadParameter;
7991 }
7992
7993 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7994 //this with a more sane size so that we don't compensate in rest of code
7995 //We'll restore this size later on, so that it's transparent to client
7996 buffer->nFilledLen = 0;
7997 buffer->nAllocLen = handle->size;
7998
7999 if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
8000 m_is_display_session = true;
8001 } else {
8002 m_is_display_session = false;
8003 }
8004 DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
8005
8006 drv_ctx.op_buf.buffer_size = handle->size;
8007 }
8008
8009 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
8010 if (buffer == NULL ||
8011 (nPortIndex >= drv_ctx.op_buf.actualcount)) {
8012 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
8013 nPortIndex, drv_ctx.op_buf.actualcount);
8014 return OMX_ErrorBadParameter;
8015 }
8016
8017 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8018 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
8019 return OMX_ErrorNone;
8020 }
8021 /* ======================================================================
8022 FUNCTION
8023 omx_vdec::fill_this_buffer_proxy
8024
8025 DESCRIPTION
8026 IL client uses this method to release the frame buffer
8027 after displaying them.
8028
8029 PARAMETERS
8030 None.
8031
8032 RETURN VALUE
8033 true/false
8034
8035 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)8036 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
8037 OMX_IN OMX_HANDLETYPE hComp,
8038 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
8039 {
8040 VIDC_TRACE_NAME_HIGH("FTB");
8041 OMX_ERRORTYPE nRet = OMX_ErrorNone;
8042 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
8043 unsigned nPortIndex = 0;
8044 struct vdec_fillbuffer_cmd fillbuffer;
8045 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
8046 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
8047
8048 auto_lock l(buf_lock);
8049 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8050
8051 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
8052 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
8053 nPortIndex, drv_ctx.op_buf.actualcount);
8054 return OMX_ErrorBadParameter;
8055 }
8056
8057 if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
8058 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
8059 return OMX_ErrorBadParameter;
8060 }
8061 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
8062 bufferAdd, bufferAdd->pBuffer);
8063 /*Return back the output buffer to client*/
8064 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
8065 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
8066 buffer->nFilledLen = 0;
8067 m_cb.FillBufferDone (hComp,m_app_data,buffer);
8068 return OMX_ErrorNone;
8069 }
8070
8071 if (dynamic_buf_mode) {
8072 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
8073 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
8074 buf_ref_add(nPortIndex);
8075 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
8076 }
8077
8078 pending_output_buffers++;
8079 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8080 buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
8081 if (!buffer) {
8082 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
8083 return OMX_ErrorBadParameter;
8084 }
8085 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
8086 if (ptr_respbuffer) {
8087 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
8088 }
8089
8090 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
8091 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
8092 buffer->nFilledLen = 0;
8093 m_cb.FillBufferDone (hComp,m_app_data,buffer);
8094 pending_output_buffers--;
8095 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8096 return OMX_ErrorBadParameter;
8097 }
8098
8099 int rc = 0;
8100 struct v4l2_buffer buf;
8101 struct v4l2_plane plane[VIDEO_MAX_PLANES];
8102 memset( (void *)&buf, 0, sizeof(buf));
8103 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
8104 unsigned int extra_idx = 0;
8105
8106 buf.index = nPortIndex;
8107 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8108 buf.memory = V4L2_MEMORY_USERPTR;
8109 plane[0].bytesused = buffer->nFilledLen;
8110 plane[0].length = buffer->nAllocLen;
8111 plane[0].m.userptr =
8112 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
8113 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
8114 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
8115 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
8116 plane[0].data_offset = 0;
8117 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
8118 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8119 plane[extra_idx].bytesused = 0;
8120 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
8121 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
8122 #ifdef USE_ION
8123 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
8124 #endif
8125 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
8126 plane[extra_idx].data_offset = 0;
8127 } else if (extra_idx >= VIDEO_MAX_PLANES) {
8128 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8129 return OMX_ErrorBadParameter;
8130 }
8131 buf.m.planes = plane;
8132 buf.length = drv_ctx.num_planes;
8133 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8134 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
8135
8136 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
8137 if (rc) {
8138 buffer->nFilledLen = 0;
8139 DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
8140 m_cb.FillBufferDone(hComp, m_app_data, buffer);
8141 return OMX_ErrorHardware;
8142 }
8143
8144 return OMX_ErrorNone;
8145 }
8146
8147 /* ======================================================================
8148 FUNCTION
8149 omx_vdec::SetCallbacks
8150
8151 DESCRIPTION
8152 Set the callbacks.
8153
8154 PARAMETERS
8155 None.
8156
8157 RETURN VALUE
8158 OMX Error None if everything successful.
8159
8160 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)8161 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
8162 OMX_IN OMX_CALLBACKTYPE* callbacks,
8163 OMX_IN OMX_PTR appData)
8164 {
8165 (void) hComp;
8166 m_cb = *callbacks;
8167 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
8168 m_cb.EventHandler,m_cb.FillBufferDone);
8169 m_app_data = appData;
8170 return OMX_ErrorNotImplemented;
8171 }
8172
8173 /* ======================================================================
8174 FUNCTION
8175 omx_vdec::ComponentDeInit
8176
8177 DESCRIPTION
8178 Destroys the component and release memory allocated to the heap.
8179
8180 PARAMETERS
8181 <TBD>.
8182
8183 RETURN VALUE
8184 OMX Error None if everything successful.
8185
8186 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)8187 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
8188 {
8189 (void) hComp;
8190
8191 unsigned i = 0;
8192 if (OMX_StateLoaded != m_state) {
8193 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
8194 m_state);
8195 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
8196 } else {
8197 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
8198 }
8199
8200 /*Check if the output buffers have to be cleaned up*/
8201 if (m_out_mem_ptr) {
8202 DEBUG_PRINT_LOW("Freeing the Output Memory");
8203 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
8204 if (BITMASK_PRESENT(&m_out_bm_count, i)) {
8205 BITMASK_CLEAR(&m_out_bm_count, i);
8206 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
8207 }
8208
8209 if (release_output_done()) {
8210 break;
8211 }
8212 }
8213 #ifdef _ANDROID_ICS_
8214 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
8215 #endif
8216 }
8217
8218 /*Check if the input buffers have to be cleaned up*/
8219 if (m_inp_mem_ptr || m_inp_heap_ptr) {
8220 DEBUG_PRINT_LOW("Freeing the Input Memory");
8221 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
8222
8223 if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
8224 BITMASK_CLEAR(&m_inp_bm_count, i);
8225 if (m_inp_mem_ptr)
8226 free_input_buffer (i,&m_inp_mem_ptr[i]);
8227 else
8228 free_input_buffer (i,NULL);
8229 }
8230
8231 if (release_input_done()) {
8232 break;
8233 }
8234 }
8235 }
8236 free_input_buffer_header();
8237 free_output_buffer_header();
8238 if (h264_scratch.pBuffer) {
8239 free(h264_scratch.pBuffer);
8240 h264_scratch.pBuffer = NULL;
8241 }
8242
8243 if (h264_parser) {
8244 delete h264_parser;
8245 h264_parser = NULL;
8246 }
8247
8248 if (m_frame_parser.mutils) {
8249 DEBUG_PRINT_LOW("Free utils parser");
8250 delete (m_frame_parser.mutils);
8251 m_frame_parser.mutils = NULL;
8252 }
8253
8254 if (m_platform_list) {
8255 free(m_platform_list);
8256 m_platform_list = NULL;
8257 }
8258 if (m_vendor_config.pData) {
8259 free(m_vendor_config.pData);
8260 m_vendor_config.pData = NULL;
8261 }
8262
8263 // Reset counters in mesg queues
8264 m_ftb_q.m_size=0;
8265 m_cmd_q.m_size=0;
8266 m_etb_q.m_size=0;
8267 m_ftb_q.m_read = m_ftb_q.m_write =0;
8268 m_cmd_q.m_read = m_cmd_q.m_write =0;
8269 m_etb_q.m_read = m_etb_q.m_write =0;
8270 #ifdef _ANDROID_
8271 if (m_debug_timestamp) {
8272 m_timestamp_list.reset_ts_list();
8273 }
8274 #endif
8275
8276 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
8277 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
8278 // NULL);
8279 DEBUG_PRINT_HIGH("Close the driver instance");
8280
8281 if (m_debug.infile) {
8282 fclose(m_debug.infile);
8283 m_debug.infile = NULL;
8284 }
8285 if (m_debug.outfile) {
8286 fclose(m_debug.outfile);
8287 m_debug.outfile = NULL;
8288 }
8289 if (m_debug.out_ymeta_file) {
8290 fclose(m_debug.out_ymeta_file);
8291 m_debug.out_ymeta_file = NULL;
8292 }
8293 if (m_debug.out_uvmeta_file) {
8294 fclose(m_debug.out_uvmeta_file);
8295 m_debug.out_uvmeta_file = NULL;
8296 }
8297 #ifdef OUTPUT_EXTRADATA_LOG
8298 if (outputExtradataFile)
8299 fclose (outputExtradataFile);
8300 #endif
8301 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
8302 return OMX_ErrorNone;
8303 }
8304
8305 /* ======================================================================
8306 FUNCTION
8307 omx_vdec::UseEGLImage
8308
8309 DESCRIPTION
8310 OMX Use EGL Image method implementation <TBD>.
8311
8312 PARAMETERS
8313 <TBD>.
8314
8315 RETURN VALUE
8316 Not Implemented error.
8317
8318 ========================================================================== */
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)8319 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
8320 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
8321 OMX_IN OMX_U32 port,
8322 OMX_IN OMX_PTR appData,
8323 OMX_IN void* eglImage)
8324 {
8325 (void) appData;
8326 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
8327 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
8328 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
8329
8330 #ifdef USE_EGL_IMAGE_GPU
8331 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
8332 EGLint fd = -1, offset = 0,pmemPtr = 0;
8333 #else
8334 int fd = -1, offset = 0;
8335 #endif
8336 DEBUG_PRINT_HIGH("use EGL image support for decoder");
8337 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
8338 DEBUG_PRINT_ERROR("Invalid EGL image");
8339 }
8340 #ifdef USE_EGL_IMAGE_GPU
8341 if (m_display_id == NULL) {
8342 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
8343 return OMX_ErrorInsufficientResources;
8344 }
8345 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
8346 eglGetProcAddress("eglQueryImageKHR");
8347 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
8348 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
8349 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
8350 #else //with OMX test app
8351 struct temp_egl {
8352 int pmem_fd;
8353 int offset;
8354 };
8355 struct temp_egl *temp_egl_id = NULL;
8356 void * pmemPtr = (void *) eglImage;
8357 temp_egl_id = (struct temp_egl *)eglImage;
8358 if (temp_egl_id != NULL) {
8359 fd = temp_egl_id->pmem_fd;
8360 offset = temp_egl_id->offset;
8361 }
8362 #endif
8363 if (fd < 0) {
8364 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
8365 return OMX_ErrorInsufficientResources;
8366 }
8367 pmem_info.pmem_fd = (OMX_U32) fd;
8368 pmem_info.offset = (OMX_U32) offset;
8369 pmem_entry.entry = (void *) &pmem_info;
8370 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8371 pmem_list.entryList = &pmem_entry;
8372 pmem_list.nEntries = 1;
8373 ouput_egl_buffers = true;
8374 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
8375 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
8376 (OMX_U8 *)pmemPtr)) {
8377 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
8378 return OMX_ErrorInsufficientResources;
8379 }
8380 return OMX_ErrorNone;
8381 }
8382
8383 /* ======================================================================
8384 FUNCTION
8385 omx_vdec::ComponentRoleEnum
8386
8387 DESCRIPTION
8388 OMX Component Role Enum method implementation.
8389
8390 PARAMETERS
8391 <TBD>.
8392
8393 RETURN VALUE
8394 OMX Error None if everything is successful.
8395 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)8396 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
8397 OMX_OUT OMX_U8* role,
8398 OMX_IN OMX_U32 index)
8399 {
8400 (void) hComp;
8401 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8402
8403 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
8404 if ((0 == index) && role) {
8405 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
8406 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8407 } else {
8408 eRet = OMX_ErrorNoMore;
8409 }
8410 }
8411 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
8412 if ((0 == index) && role) {
8413 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
8414 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8415 } else {
8416 eRet = OMX_ErrorNoMore;
8417 }
8418 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
8419 if ((0 == index) && role) {
8420 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
8421 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8422 } else {
8423 DEBUG_PRINT_LOW("No more roles");
8424 eRet = OMX_ErrorNoMore;
8425 }
8426 }
8427
8428 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
8429 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
8430 if ((0 == index) && role) {
8431 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
8432 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8433 } else {
8434 DEBUG_PRINT_LOW("No more roles");
8435 eRet = OMX_ErrorNoMore;
8436 }
8437 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
8438 if ((0 == index) && role) {
8439 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
8440 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8441 } else {
8442 DEBUG_PRINT_LOW("No more roles");
8443 eRet = OMX_ErrorNoMore;
8444 }
8445 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
8446 if ((0 == index) && role) {
8447 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
8448 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8449 } else {
8450 DEBUG_PRINT_LOW("No more roles");
8451 eRet = OMX_ErrorNoMore;
8452 }
8453 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
8454 if ((0 == index) && role) {
8455 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
8456 DEBUG_PRINT_LOW("component_role_enum: role %s", role);
8457 } else {
8458 DEBUG_PRINT_LOW("No more roles");
8459 eRet = OMX_ErrorNoMore;
8460 }
8461 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
8462 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
8463 ) {
8464 if ((0 == index) && role) {
8465 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
8466 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8467 } else {
8468 DEBUG_PRINT_LOW("No more roles");
8469 eRet = OMX_ErrorNoMore;
8470 }
8471 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
8472 if ((0 == index) && role) {
8473 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
8474 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8475 } else {
8476 DEBUG_PRINT_LOW("No more roles");
8477 eRet = OMX_ErrorNoMore;
8478 }
8479 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
8480 if ((0 == index) && role) {
8481 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
8482 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8483 } else {
8484 DEBUG_PRINT_LOW("No more roles");
8485 eRet = OMX_ErrorNoMore;
8486 }
8487 } else {
8488 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
8489 eRet = OMX_ErrorInvalidComponentName;
8490 }
8491 return eRet;
8492 }
8493
8494
8495
8496
8497 /* ======================================================================
8498 FUNCTION
8499 omx_vdec::AllocateDone
8500
8501 DESCRIPTION
8502 Checks if entire buffer pool is allocated by IL Client or not.
8503 Need this to move to IDLE state.
8504
8505 PARAMETERS
8506 None.
8507
8508 RETURN VALUE
8509 true/false.
8510
8511 ========================================================================== */
allocate_done(void)8512 bool omx_vdec::allocate_done(void)
8513 {
8514 bool bRet = false;
8515 bool bRet_In = false;
8516 bool bRet_Out = false;
8517 bool bRet_Out_Extra = false;
8518
8519 bRet_In = allocate_input_done();
8520 bRet_Out = allocate_output_done();
8521 bRet_Out_Extra = allocate_output_extradata_done();
8522
8523 if (bRet_In && bRet_Out && bRet_Out_Extra) {
8524 bRet = true;
8525 }
8526
8527 return bRet;
8528 }
8529 /* ======================================================================
8530 FUNCTION
8531 omx_vdec::AllocateInputDone
8532
8533 DESCRIPTION
8534 Checks if I/P buffer pool is allocated by IL Client or not.
8535
8536 PARAMETERS
8537 None.
8538
8539 RETURN VALUE
8540 true/false.
8541
8542 ========================================================================== */
allocate_input_done(void)8543 bool omx_vdec::allocate_input_done(void)
8544 {
8545 bool bRet = false;
8546 unsigned i=0;
8547
8548 if (m_inp_mem_ptr == NULL) {
8549 return bRet;
8550 }
8551 if (m_inp_mem_ptr ) {
8552 for (; i<drv_ctx.ip_buf.actualcount; i++) {
8553 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
8554 break;
8555 }
8556 }
8557 }
8558 if (i == drv_ctx.ip_buf.actualcount) {
8559 bRet = true;
8560 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
8561 }
8562 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
8563 m_inp_bPopulated = OMX_TRUE;
8564 }
8565 return bRet;
8566 }
8567 /* ======================================================================
8568 FUNCTION
8569 omx_vdec::AllocateOutputDone
8570
8571 DESCRIPTION
8572 Checks if entire O/P buffer pool is allocated by IL Client or not.
8573
8574 PARAMETERS
8575 None.
8576
8577 RETURN VALUE
8578 true/false.
8579
8580 ========================================================================== */
allocate_output_done(void)8581 bool omx_vdec::allocate_output_done(void)
8582 {
8583 bool bRet = false;
8584 unsigned j=0;
8585
8586 if (m_out_mem_ptr == NULL) {
8587 return bRet;
8588 }
8589
8590 if (m_out_mem_ptr) {
8591 for (; j < drv_ctx.op_buf.actualcount; j++) {
8592 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
8593 break;
8594 }
8595 }
8596 }
8597
8598 if (j == drv_ctx.op_buf.actualcount) {
8599 bRet = true;
8600 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
8601 if (m_out_bEnabled)
8602 m_out_bPopulated = OMX_TRUE;
8603 }
8604
8605 return bRet;
8606 }
8607
allocate_output_extradata_done(void)8608 bool omx_vdec::allocate_output_extradata_done(void) {
8609 bool bRet = false;
8610 unsigned j=0;
8611 unsigned nBufferCount = 0;
8612
8613 nBufferCount = m_client_out_extradata_info.getBufferCount();
8614
8615 if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
8616 return true;
8617 }
8618
8619 if (m_client_output_extradata_mem_ptr) {
8620 for (; j < nBufferCount; j++) {
8621 if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
8622 break;
8623 }
8624 }
8625
8626 if (j == nBufferCount) {
8627 bRet = true;
8628 DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
8629 }
8630 }
8631
8632 return bRet;
8633 }
8634 /* ======================================================================
8635 FUNCTION
8636 omx_vdec::ReleaseDone
8637
8638 DESCRIPTION
8639 Checks if IL client has released all the buffers.
8640
8641 PARAMETERS
8642 None.
8643
8644 RETURN VALUE
8645 true/false
8646
8647 ========================================================================== */
release_done(void)8648 bool omx_vdec::release_done(void)
8649 {
8650 bool bRet = false;
8651
8652 if (release_input_done()) {
8653 if (release_output_done()) {
8654 if (release_output_extradata_done()) {
8655 bRet = true;
8656 }
8657 }
8658 }
8659 return bRet;
8660 }
8661
8662
8663 /* ======================================================================
8664 FUNCTION
8665 omx_vdec::ReleaseOutputDone
8666
8667 DESCRIPTION
8668 Checks if IL client has released all the buffers.
8669
8670 PARAMETERS
8671 None.
8672
8673 RETURN VALUE
8674 true/false
8675
8676 ========================================================================== */
release_output_done(void)8677 bool omx_vdec::release_output_done(void)
8678 {
8679 bool bRet = false;
8680 unsigned i=0,j=0;
8681
8682 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
8683 if (m_out_mem_ptr) {
8684 for (; j < drv_ctx.op_buf.actualcount ; j++) {
8685 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8686 break;
8687 }
8688 }
8689 if (j == drv_ctx.op_buf.actualcount) {
8690 m_out_bm_count = 0;
8691 bRet = true;
8692 }
8693 } else {
8694 m_out_bm_count = 0;
8695 bRet = true;
8696 }
8697 return bRet;
8698 }
8699 /* ======================================================================
8700 FUNCTION
8701 omx_vdec::ReleaseInputDone
8702
8703 DESCRIPTION
8704 Checks if IL client has released all the buffers.
8705
8706 PARAMETERS
8707 None.
8708
8709 RETURN VALUE
8710 true/false
8711
8712 ========================================================================== */
release_input_done(void)8713 bool omx_vdec::release_input_done(void)
8714 {
8715 bool bRet = false;
8716 unsigned i=0,j=0;
8717
8718 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
8719 if (m_inp_mem_ptr) {
8720 for (; j<drv_ctx.ip_buf.actualcount; j++) {
8721 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8722 break;
8723 }
8724 }
8725 if (j==drv_ctx.ip_buf.actualcount) {
8726 bRet = true;
8727 }
8728 } else {
8729 bRet = true;
8730 }
8731 return bRet;
8732 }
8733
release_output_extradata_done(void)8734 bool omx_vdec::release_output_extradata_done(void) {
8735 bool bRet = false;
8736 unsigned i=0,j=0, buffer_count=0;
8737
8738 buffer_count = m_client_out_extradata_info.getBufferCount();
8739 DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
8740 m_client_output_extradata_mem_ptr, buffer_count);
8741
8742 if (m_client_output_extradata_mem_ptr) {
8743 for (; j<buffer_count; j++) {
8744 if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
8745 break;
8746 }
8747 }
8748 if (j == buffer_count) {
8749 bRet = true;
8750 }
8751 } else {
8752 bRet = true;
8753 }
8754 return bRet;
8755 }
8756
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8757 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8758 OMX_BUFFERHEADERTYPE * buffer)
8759 {
8760 VIDC_TRACE_NAME_HIGH("FBD");
8761 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8762 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
8763 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8764 return OMX_ErrorBadParameter;
8765 } else if (output_flush_progress) {
8766 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8767 buffer->nFilledLen = 0;
8768 buffer->nTimeStamp = 0;
8769 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8770 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8771 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8772 }
8773
8774 if (m_debug_extradata) {
8775 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8776 DEBUG_PRINT_HIGH("***************************************************");
8777 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8778 DEBUG_PRINT_HIGH("***************************************************");
8779 }
8780
8781 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8782 DEBUG_PRINT_HIGH("***************************************************");
8783 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8784 DEBUG_PRINT_HIGH("***************************************************");
8785 }
8786 }
8787
8788
8789 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
8790 buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
8791 pending_output_buffers --;
8792 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8793
8794 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8795 DEBUG_PRINT_HIGH("Output EOS has been reached");
8796 if (!output_flush_progress)
8797 post_event((unsigned)NULL, (unsigned)NULL,
8798 OMX_COMPONENT_GENERATE_EOS_DONE);
8799
8800 if (psource_frame) {
8801 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8802 psource_frame = NULL;
8803 }
8804 if (pdest_frame) {
8805 pdest_frame->nFilledLen = 0;
8806 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8807 (unsigned)NULL);
8808 pdest_frame = NULL;
8809 }
8810 }
8811
8812 #ifdef OUTPUT_EXTRADATA_LOG
8813 if (outputExtradataFile) {
8814 int buf_index = buffer - m_out_mem_ptr;
8815 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8816
8817 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8818 p_extra = (OMX_OTHER_EXTRADATATYPE *)
8819 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8820
8821 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8822 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8823 p_extra->nSize, p_extra->eType);
8824 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8825
8826 if (p_extra->eType == OMX_ExtraDataNone) {
8827 break;
8828 }
8829 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8830 }
8831 }
8832 #endif
8833
8834 /* For use buffer we need to copy the data */
8835 if (!output_flush_progress) {
8836 /* This is the error check for non-recoverable errros */
8837 bool is_duplicate_ts_valid = true;
8838 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8839
8840 if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8841 output_capability == V4L2_PIX_FMT_MPEG2 ||
8842 output_capability == V4L2_PIX_FMT_DIVX ||
8843 output_capability == V4L2_PIX_FMT_DIVX_311)
8844 is_duplicate_ts_valid = false;
8845
8846 if ((output_capability == V4L2_PIX_FMT_H264 ||
8847 output_capability == V4L2_PIX_FMT_H264_MVC) &&
8848 is_interlaced) {
8849 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8850 is_interlaced = false;
8851 }
8852 }
8853
8854 if (buffer->nFilledLen > 0) {
8855 time_stamp_dts.get_next_timestamp(buffer,
8856 is_interlaced && is_duplicate_ts_valid);
8857 if (m_debug_timestamp) {
8858 {
8859 OMX_TICKS expected_ts = 0;
8860 m_timestamp_list.pop_min_ts(expected_ts);
8861 if (is_interlaced && is_duplicate_ts_valid) {
8862 m_timestamp_list.pop_min_ts(expected_ts);
8863 }
8864 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8865 buffer->nTimeStamp, expected_ts);
8866
8867 if (buffer->nTimeStamp != expected_ts) {
8868 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8869 }
8870 }
8871 }
8872 }
8873 }
8874 VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8875
8876 if (m_cb.FillBufferDone) {
8877 if (buffer->nFilledLen > 0) {
8878 if (arbitrary_bytes)
8879 adjust_timestamp(buffer->nTimeStamp);
8880 else
8881 set_frame_rate(buffer->nTimeStamp);
8882
8883 proc_frms++;
8884 if (perf_flag) {
8885 if (1 == proc_frms) {
8886 dec_time.stop();
8887 latency = dec_time.processing_time_us() - latency;
8888 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8889 dec_time.start();
8890 fps_metrics.start();
8891 }
8892 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8893 OMX_U64 proc_time = 0;
8894 fps_metrics.stop();
8895 proc_time = fps_metrics.processing_time_us();
8896 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8897 (unsigned int)proc_frms, (float)proc_time / 1e6,
8898 (float)(1e6 * proc_frms) / proc_time);
8899 }
8900 }
8901 }
8902 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8903 prev_ts = LLONG_MAX;
8904 rst_prev_ts = true;
8905 proc_frms = 0;
8906 }
8907
8908 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8909 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8910 buffer->pPlatformPrivate)->entryList->entry;
8911 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8912 OMX_BUFFERHEADERTYPE *il_buffer;
8913 il_buffer = client_buffers.get_il_buf_hdr(buffer);
8914 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8915
8916 if (il_buffer && m_last_rendered_TS >= 0) {
8917 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8918
8919 // Current frame can be send for rendering if
8920 // (a) current FPS is <= 60
8921 // (b) is the next frame after the frame with TS 0
8922 // (c) is the first frame after seek
8923 // (d) the delta TS b\w two consecutive frames is > 16 ms
8924 // (e) its TS is equal to previous frame TS
8925 // (f) if marked EOS
8926
8927 if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8928 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8929 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8930 m_last_rendered_TS = il_buffer->nTimeStamp;
8931 } else {
8932 //mark for droping
8933 buffer->nFilledLen = 0;
8934 }
8935
8936 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8937 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8938 il_buffer->nTimeStamp,ts_delta);
8939
8940 //above code makes sure that delta b\w two consecutive frames is not
8941 //greater than 16ms, slow-mo feature, so cap fps to max 60
8942 if (current_framerate > 60 ) {
8943 current_framerate = 60;
8944 }
8945 }
8946
8947 // add current framerate to gralloc meta data
8948 if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && m_out_mem_ptr) {
8949 // If valid fps was received, directly send it to display for the 1st fbd.
8950 // Otherwise, calculate fps using fbd timestamps
8951 float refresh_rate = m_fps_prev;
8952 if (m_fps_received) {
8953 if (1 == proc_frms) {
8954 refresh_rate = m_fps_received / (float)(1<<16);
8955 }
8956 } else {
8957 // check if dynamic refresh rate change feature enabled or not
8958 if (m_drc_enable) {
8959 // set coarse fps when 2 fbds received and
8960 // set fps again when 30 fbds received as it should be
8961 // more accurate than the one set when only 2 fbds received.
8962 if (2 == proc_frms || 30 == proc_frms) {
8963 if (drv_ctx.frame_rate.fps_denominator) {
8964 refresh_rate = drv_ctx.frame_rate.fps_numerator /
8965 (float) drv_ctx.frame_rate.fps_denominator;
8966 }
8967 }
8968 } else {
8969 // calculate and set refresh rate for every frame from second frame onwards
8970 // display will assume the default refresh rate for first frame (which is 60 fps)
8971 if (m_fps_prev) {
8972 if (drv_ctx.frame_rate.fps_denominator) {
8973 refresh_rate = drv_ctx.frame_rate.fps_numerator /
8974 (float) drv_ctx.frame_rate.fps_denominator;
8975 }
8976 }
8977 }
8978 }
8979 if (refresh_rate > 60) {
8980 refresh_rate = 60;
8981 }
8982 DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8983 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8984 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8985 UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8986 m_fps_prev = refresh_rate;
8987 }
8988
8989 if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) {
8990 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8991 DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8992 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8993 S3D_FORMAT, (void*)&stereo_output_mode);
8994 }
8995
8996 if (il_buffer) {
8997 log_output_buffers(il_buffer);
8998 if (dynamic_buf_mode) {
8999 unsigned int nPortIndex = 0;
9000 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
9001
9002 // Since we're passing around handles, adjust nFilledLen and nAllocLen
9003 // to size of the handle. Do it _after_ log_output_buffers which
9004 // requires the respective sizes to be accurate.
9005
9006 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
9007 buffer->nFilledLen = buffer->nFilledLen ?
9008 sizeof(struct VideoDecoderOutputMetaData) : 0;
9009
9010 //Clear graphic buffer handles in dynamic mode
9011 if (nPortIndex < drv_ctx.op_buf.actualcount &&
9012 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
9013 native_buffer[nPortIndex].privatehandle = NULL;
9014 native_buffer[nPortIndex].nativehandle = NULL;
9015 } else {
9016 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
9017 return OMX_ErrorBadParameter;
9018 }
9019 }
9020 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
9021 } else {
9022 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
9023 return OMX_ErrorBadParameter;
9024 }
9025 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
9026 } else {
9027 return OMX_ErrorBadParameter;
9028 }
9029
9030 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
9031 if (m_smoothstreaming_mode && m_out_mem_ptr) {
9032 OMX_U32 buf_index = buffer - m_out_mem_ptr;
9033 BufferDim_t dim;
9034 private_handle_t *private_handle = NULL;
9035 dim.sliceWidth = framesize.nWidth;
9036 dim.sliceHeight = framesize.nHeight;
9037 if (buf_index < drv_ctx.op_buf.actualcount &&
9038 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
9039 native_buffer[buf_index].privatehandle)
9040 private_handle = native_buffer[buf_index].privatehandle;
9041 if (private_handle) {
9042 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
9043 dim.sliceWidth, dim.sliceHeight);
9044 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
9045 }
9046 }
9047 #endif
9048
9049 return OMX_ErrorNone;
9050 }
9051
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9052 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
9053 OMX_BUFFERHEADERTYPE* buffer)
9054 {
9055 VIDC_TRACE_NAME_HIGH("EBD");
9056 int nBufferIndex = buffer - m_inp_mem_ptr;
9057
9058 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
9059 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
9060 return OMX_ErrorBadParameter;
9061 }
9062
9063 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
9064 buffer, buffer->pBuffer, buffer->nFlags);
9065 pending_input_buffers--;
9066 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
9067
9068 if (arbitrary_bytes) {
9069 if (pdest_frame == NULL && input_flush_progress == false) {
9070 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
9071 pdest_frame = buffer;
9072 buffer->nFilledLen = 0;
9073 buffer->nTimeStamp = LLONG_MAX;
9074 push_input_buffer (hComp);
9075 } else {
9076 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
9077 buffer->nFilledLen = 0;
9078 if (!m_input_free_q.insert_entry((unsigned long)buffer,
9079 (unsigned)NULL, (unsigned)NULL)) {
9080 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
9081 }
9082 }
9083 } else if (m_cb.EmptyBufferDone) {
9084 buffer->nFilledLen = 0;
9085 if (input_use_buffer == true) {
9086 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
9087 }
9088
9089 /* Restore the FD that we over-wrote in ETB */
9090 if (m_input_pass_buffer_fd) {
9091 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
9092 }
9093
9094 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
9095 }
9096 return OMX_ErrorNone;
9097 }
9098
async_message_process(void * context,void * message)9099 int omx_vdec::async_message_process (void *context, void* message)
9100 {
9101 omx_vdec* omx = NULL;
9102 struct vdec_msginfo *vdec_msg = NULL;
9103 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
9104 struct v4l2_buffer *v4l2_buf_ptr = NULL;
9105 struct v4l2_plane *plane = NULL;
9106 struct vdec_output_frameinfo *output_respbuf = NULL;
9107 int rc=1;
9108 if (context == NULL || message == NULL) {
9109 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
9110 return -1;
9111 }
9112 vdec_msg = (struct vdec_msginfo *)message;
9113
9114 omx = reinterpret_cast<omx_vdec*>(context);
9115
9116 switch (vdec_msg->msgcode) {
9117
9118 case VDEC_MSG_EVT_HW_ERROR:
9119 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9120 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9121 break;
9122
9123 case VDEC_MSG_EVT_HW_OVERLOAD:
9124 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9125 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
9126 break;
9127
9128 case VDEC_MSG_EVT_HW_UNSUPPORTED:
9129 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9130 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
9131 break;
9132
9133 case VDEC_MSG_RESP_START_DONE:
9134 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9135 OMX_COMPONENT_GENERATE_START_DONE);
9136 break;
9137
9138 case VDEC_MSG_RESP_STOP_DONE:
9139 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9140 OMX_COMPONENT_GENERATE_STOP_DONE);
9141 break;
9142
9143 case VDEC_MSG_RESP_RESUME_DONE:
9144 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9145 OMX_COMPONENT_GENERATE_RESUME_DONE);
9146 break;
9147
9148 case VDEC_MSG_RESP_PAUSE_DONE:
9149 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9150 OMX_COMPONENT_GENERATE_PAUSE_DONE);
9151 break;
9152
9153 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
9154 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9155 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
9156 break;
9157 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
9158 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9159 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
9160 break;
9161 case VDEC_MSG_RESP_INPUT_FLUSHED:
9162 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
9163
9164 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
9165 vdec_msg->msgdata.input_frame_clientdata; */
9166
9167 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
9168 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
9169 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
9170 omxhdr = NULL;
9171 vdec_msg->status_code = VDEC_S_EFATAL;
9172 break;
9173
9174 }
9175 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
9176
9177 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
9178 DEBUG_PRINT_HIGH("Unsupported input");
9179 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
9180 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9181 }
9182 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
9183 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9184 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
9185 }
9186 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
9187
9188 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
9189 android_atomic_dec(&omx->m_queued_codec_config_count);
9190 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
9191 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
9192 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
9193 sem_post(&omx->m_safe_flush);
9194 }
9195 }
9196 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
9197 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
9198 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9199 }
9200 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
9201 OMX_COMPONENT_GENERATE_EBD);
9202 break;
9203 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
9204 int64_t *timestamp;
9205 timestamp = (int64_t *) malloc(sizeof(int64_t));
9206 if (timestamp) {
9207 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
9208 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
9209 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
9210 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
9211 (long long)vdec_msg->msgdata.output_frame.time_stamp);
9212 }
9213 break;
9214 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
9215 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
9216
9217 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
9218 if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
9219 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
9220 omxhdr = NULL;
9221 vdec_msg->status_code = VDEC_S_EFATAL;
9222 break;
9223 }
9224 plane = v4l2_buf_ptr->m.planes;
9225 omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
9226
9227 if (omxhdr && omxhdr->pOutputPortPrivate &&
9228 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
9229 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
9230 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
9231
9232 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
9233 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
9234 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
9235 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
9236 omxhdr->nFlags = 0;
9237
9238 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
9239 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
9240 //rc = -1;
9241 }
9242 if (omxhdr->nFilledLen) {
9243 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
9244 }
9245 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
9246 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9247 } else {
9248 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
9249 }
9250 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
9251 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9252 }
9253 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
9254 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
9255 }
9256 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
9257 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
9258 }
9259 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
9260 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
9261 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
9262 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
9263 }
9264
9265 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
9266 !omx->output_flush_progress &&
9267 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
9268 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
9269 omx->time_stamp_dts.remove_time_stamp(
9270 omxhdr->nTimeStamp,
9271 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
9272 ?true:false);
9273
9274 omxhdr->nFilledLen = 0;
9275 omx->pending_output_buffers--;
9276 omx->post_event ((unsigned long)NULL,(unsigned long)omx->client_buffers.get_il_buf_hdr(omxhdr),
9277 OMX_COMPONENT_GENERATE_FTB);
9278 break;
9279 }
9280 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
9281 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9282 }
9283
9284 output_respbuf = (struct vdec_output_frameinfo *)\
9285 omxhdr->pOutputPortPrivate;
9286 if (!output_respbuf) {
9287 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
9288 return -1;
9289 }
9290 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
9291 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
9292
9293 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
9294 output_respbuf->pic_type = PICTURE_TYPE_I;
9295 }
9296 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
9297 output_respbuf->pic_type = PICTURE_TYPE_P;
9298 }
9299 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
9300 output_respbuf->pic_type = PICTURE_TYPE_B;
9301 }
9302
9303 if (vdec_msg->msgdata.output_frame.len) {
9304 if (!omx->output_flush_progress && (omxhdr->nFilledLen > 0)) {
9305 // set the default colorspace advised by client, since the bitstream may be
9306 // devoid of colorspace-info.
9307 if (omx->m_enable_android_native_buffers) {
9308 ColorSpace_t color_space = ITU_R_601;
9309
9310 // Disabled ?
9311 // WA for VP8. Vp8 encoder does not embed color-info (yet!).
9312 // Encoding RGBA results in 601-LR for all resolutions.
9313 // This conflicts with the client't defaults which are based on resolution.
9314 // Eg: 720p will be encoded as 601-LR. Client will say 709.
9315 // Re-enable this code once vp8 encoder generates color-info and hence the
9316 // decoder will be able to override with the correct source color.
9317 #if 0
9318 switch (omx->m_client_color_space.sAspects.mPrimaries) {
9319 case ColorAspects::PrimariesBT601_6_625:
9320 case ColorAspects::PrimariesBT601_6_525:
9321 {
9322 color_space = omx->m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
9323 ITU_R_601_FR : ITU_R_601;
9324 break;
9325 }
9326 case ColorAspects::PrimariesBT709_5:
9327 {
9328 color_space = ITU_R_709;
9329 break;
9330 }
9331 default:
9332 {
9333 break;
9334 }
9335 }
9336 #endif
9337 DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
9338 color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
9339 omx->set_colorspace_in_handle(color_space, omxhdr - omx->m_out_mem_ptr);
9340 }
9341 }
9342
9343 DEBUG_PRINT_LOW("Processing extradata");
9344 omx->handle_extradata(omxhdr);
9345
9346 if (omx->m_extradata_info.output_crop_updated) {
9347 DEBUG_PRINT_LOW("Read FBD crop from output extra data");
9348 vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
9349 vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
9350 vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
9351 vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
9352 vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
9353 vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
9354 } else {
9355 DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
9356 vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
9357 vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
9358 vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
9359 vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
9360 vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
9361 vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
9362
9363 /* Copy these values back to OMX internal variables to make both handlign same*/
9364
9365 omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
9366 omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
9367 omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
9368 omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
9369 omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9370 omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9371 }
9372 }
9373
9374 vdec_msg->msgdata.output_frame.bufferaddr =
9375 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
9376
9377 if (vdec_msg->msgdata.output_frame.len)
9378 memcpy(&omx->drv_ctx.frame_size,
9379 &vdec_msg->msgdata.output_frame.framesize,
9380 sizeof(struct vdec_framesize));
9381
9382 DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
9383 " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
9384 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
9385 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
9386 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
9387 (unsigned int)vdec_msg->msgdata.output_frame.len,
9388 vdec_msg->msgdata.output_frame.framesize.left,
9389 vdec_msg->msgdata.output_frame.framesize.top,
9390 vdec_msg->msgdata.output_frame.framesize.right,
9391 vdec_msg->msgdata.output_frame.framesize.bottom);
9392
9393 /* Post event if resolution OR crop changed */
9394 /* filled length will be changed if resolution changed */
9395 /* Crop parameters can be changed even without resolution change */
9396 if (omxhdr->nFilledLen
9397 && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
9398 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
9399 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
9400 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
9401 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
9402 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
9403 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
9404
9405 DEBUG_PRINT_HIGH("Parameters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
9406 omx->prev_n_filled_len,
9407 omx->drv_ctx.video_resolution.frame_width,
9408 omx->drv_ctx.video_resolution.frame_height,
9409 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
9410 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
9411 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
9412 vdec_msg->msgdata.output_frame.picsize.frame_height,
9413 vdec_msg->msgdata.output_frame.framesize.left,
9414 vdec_msg->msgdata.output_frame.framesize.top,
9415 vdec_msg->msgdata.output_frame.framesize.right,
9416 vdec_msg->msgdata.output_frame.framesize.bottom);
9417
9418 omx->drv_ctx.video_resolution.frame_width =
9419 vdec_msg->msgdata.output_frame.picsize.frame_width;
9420 omx->drv_ctx.video_resolution.frame_height =
9421 vdec_msg->msgdata.output_frame.picsize.frame_height;
9422 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
9423 omx->drv_ctx.video_resolution.stride =
9424 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
9425 omx->drv_ctx.video_resolution.scan_lines =
9426 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
9427 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
9428 omx->drv_ctx.video_resolution.stride =
9429 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
9430 omx->drv_ctx.video_resolution.scan_lines =
9431 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
9432 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
9433 omx->drv_ctx.video_resolution.stride =
9434 VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
9435 omx->drv_ctx.video_resolution.scan_lines =
9436 VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
9437 }
9438
9439 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9440 OMX_IndexConfigCommonOutputCrop,
9441 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9442 }
9443
9444 if (omxhdr->nFilledLen)
9445 omx->prev_n_filled_len = omxhdr->nFilledLen;
9446
9447 if (omxhdr && omxhdr->nFilledLen && !omx->m_need_turbo) {
9448 omx->request_perf_level(VIDC_NOMINAL);
9449 }
9450 if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
9451 vdec_msg->msgdata.output_frame.bufferaddr)
9452 memcpy ( omxhdr->pBuffer, (void *)
9453 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
9454 (unsigned long)vdec_msg->msgdata.output_frame.offset),
9455 vdec_msg->msgdata.output_frame.len);
9456 } else {
9457 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
9458 (unsigned int)vdec_msg->msgdata.output_frame.len,
9459 omxhdr->nAllocLen, omx->prev_n_filled_len);
9460 omxhdr->nFilledLen = 0;
9461 }
9462
9463 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
9464 OMX_COMPONENT_GENERATE_FBD);
9465
9466 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
9467 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
9468 OMX_COMPONENT_GENERATE_EOS_DONE);
9469 } else {
9470 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
9471 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9472 }
9473 break;
9474 case VDEC_MSG_EVT_CONFIG_CHANGED:
9475 DEBUG_PRINT_HIGH("Port settings changed");
9476 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9477 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9478 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
9479 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9480 if (!omx->m_need_turbo) {
9481 omx->request_perf_level(VIDC_NOMINAL);
9482 }
9483 break;
9484 default:
9485 break;
9486 }
9487 return rc;
9488 }
9489
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9490 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
9491 OMX_HANDLETYPE hComp,
9492 OMX_BUFFERHEADERTYPE *buffer
9493 )
9494 {
9495 unsigned address,p2,id;
9496 DEBUG_PRINT_LOW("Empty this arbitrary");
9497
9498 if (buffer == NULL) {
9499 return OMX_ErrorBadParameter;
9500 }
9501 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
9502 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
9503 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
9504
9505 /* return zero length and not an EOS buffer */
9506 /* return buffer if input flush in progress */
9507 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
9508 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
9509 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
9510 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
9511 return OMX_ErrorNone;
9512 }
9513
9514 if (psource_frame == NULL) {
9515 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
9516 psource_frame = buffer;
9517 DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
9518 push_input_buffer (hComp);
9519 } else {
9520 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
9521 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
9522 (unsigned)NULL)) {
9523 return OMX_ErrorBadParameter;
9524 }
9525 }
9526
9527 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
9528 codec_config_flag = false;
9529 }
9530 return OMX_ErrorNone;
9531 }
9532
push_input_buffer(OMX_HANDLETYPE hComp)9533 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
9534 {
9535 unsigned long address,p2,id;
9536 OMX_ERRORTYPE ret = OMX_ErrorNone;
9537
9538 if (pdest_frame == NULL || psource_frame == NULL) {
9539 /*Check if we have a destination buffer*/
9540 if (pdest_frame == NULL) {
9541 DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
9542 if (m_input_free_q.m_size) {
9543 m_input_free_q.pop_entry(&address,&p2,&id);
9544 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
9545 pdest_frame->nFilledLen = 0;
9546 pdest_frame->nTimeStamp = LLONG_MAX;
9547 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
9548 }
9549 }
9550
9551 /*Check if we have a destination buffer*/
9552 if (psource_frame == NULL) {
9553 DEBUG_PRINT_LOW("Get a source buffer from the queue");
9554 if (m_input_pending_q.m_size) {
9555 m_input_pending_q.pop_entry(&address,&p2,&id);
9556 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9557 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9558 psource_frame->nTimeStamp);
9559 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9560 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9561
9562 }
9563 }
9564
9565 }
9566
9567 while ((pdest_frame != NULL) && (psource_frame != NULL)) {
9568 switch (codec_type_parse) {
9569 case CODEC_TYPE_MPEG4:
9570 case CODEC_TYPE_H263:
9571 case CODEC_TYPE_MPEG2:
9572 ret = push_input_sc_codec(hComp);
9573 break;
9574 case CODEC_TYPE_H264:
9575 ret = push_input_h264(hComp);
9576 break;
9577 case CODEC_TYPE_HEVC:
9578 ret = push_input_hevc(hComp);
9579 break;
9580 case CODEC_TYPE_VC1:
9581 ret = push_input_vc1(hComp);
9582 break;
9583 default:
9584 break;
9585 }
9586 if (ret != OMX_ErrorNone) {
9587 DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
9588 omx_report_error ();
9589 break;
9590 }
9591 }
9592
9593 return ret;
9594 }
9595
push_input_sc_codec(OMX_HANDLETYPE hComp)9596 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
9597 {
9598 OMX_U32 partial_frame = 1;
9599 OMX_BOOL generate_ebd = OMX_TRUE;
9600 unsigned long address = 0, p2 = 0, id = 0;
9601
9602 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
9603 psource_frame,psource_frame->nTimeStamp);
9604 if (m_frame_parser.parse_sc_frame(psource_frame,
9605 pdest_frame,&partial_frame) == -1) {
9606 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9607 return OMX_ErrorBadParameter;
9608 }
9609
9610 if (partial_frame == 0) {
9611 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
9612 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
9613
9614
9615 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
9616 /*First Parsed buffer will have only header Hence skip*/
9617 if (frame_count == 0) {
9618 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
9619
9620 if (codec_type_parse == CODEC_TYPE_MPEG4 ||
9621 codec_type_parse == CODEC_TYPE_DIVX) {
9622 mp4StreamType psBits;
9623 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
9624 psBits.numBytes = pdest_frame->nFilledLen;
9625 mp4_headerparser.parseHeader(&psBits);
9626 }
9627
9628 frame_count++;
9629 } else {
9630 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9631 if (pdest_frame->nFilledLen) {
9632 /*Push the frame to the Decoder*/
9633 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9634 return OMX_ErrorBadParameter;
9635 }
9636 frame_count++;
9637 pdest_frame = NULL;
9638
9639 if (m_input_free_q.m_size) {
9640 m_input_free_q.pop_entry(&address,&p2,&id);
9641 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9642 pdest_frame->nFilledLen = 0;
9643 }
9644 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
9645 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
9646 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
9647 (unsigned)NULL);
9648 pdest_frame = NULL;
9649 }
9650 }
9651 } else {
9652 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
9653 /*Check if Destination Buffer is full*/
9654 if (pdest_frame->nAllocLen ==
9655 pdest_frame->nFilledLen + pdest_frame->nOffset) {
9656 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
9657 return OMX_ErrorStreamCorrupt;
9658 }
9659 }
9660
9661 if (psource_frame->nFilledLen == 0) {
9662 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9663 if (pdest_frame) {
9664 pdest_frame->nFlags |= psource_frame->nFlags;
9665 pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
9666 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
9667 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9668 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9669 (unsigned int)pdest_frame->nFilledLen,frame_count++);
9670 /*Push the frame to the Decoder*/
9671 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9672 return OMX_ErrorBadParameter;
9673 }
9674 frame_count++;
9675 pdest_frame = NULL;
9676 } else {
9677 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
9678 generate_ebd = OMX_FALSE;
9679 }
9680 }
9681 if (generate_ebd) {
9682 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
9683 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9684 psource_frame = NULL;
9685
9686 if (m_input_pending_q.m_size) {
9687 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9688 m_input_pending_q.pop_entry(&address,&p2,&id);
9689 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9690 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9691 psource_frame->nTimeStamp);
9692 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9693 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9694 }
9695 }
9696 }
9697 return OMX_ErrorNone;
9698 }
9699
push_input_h264(OMX_HANDLETYPE hComp)9700 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
9701 {
9702 OMX_U32 partial_frame = 1;
9703 unsigned long address = 0, p2 = 0, id = 0;
9704 OMX_BOOL isNewFrame = OMX_FALSE;
9705 OMX_BOOL generate_ebd = OMX_TRUE;
9706
9707 if (h264_scratch.pBuffer == NULL) {
9708 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
9709 return OMX_ErrorBadParameter;
9710 }
9711 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
9712 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
9713 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
9714 if (h264_scratch.nFilledLen && look_ahead_nal) {
9715 look_ahead_nal = false;
9716 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9717 h264_scratch.nFilledLen) {
9718 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9719 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9720 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9721 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
9722 h264_scratch.nFilledLen = 0;
9723 } else {
9724 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
9725 return OMX_ErrorBadParameter;
9726 }
9727 }
9728
9729 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
9730 in EOS flag getting associated with the destination
9731 */
9732 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
9733 pdest_frame->nFilledLen) {
9734 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
9735 generate_ebd = OMX_FALSE;
9736 }
9737
9738 if (nal_length == 0) {
9739 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
9740 if (m_frame_parser.parse_sc_frame(psource_frame,
9741 &h264_scratch,&partial_frame) == -1) {
9742 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9743 return OMX_ErrorBadParameter;
9744 }
9745 } else {
9746 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9747 if (m_frame_parser.parse_h264_nallength(psource_frame,
9748 &h264_scratch,&partial_frame) == -1) {
9749 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9750 return OMX_ErrorBadParameter;
9751 }
9752 }
9753
9754 if (partial_frame == 0) {
9755 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9756 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9757 nal_count++;
9758 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9759 h264_scratch.nFlags = psource_frame->nFlags;
9760 } else {
9761 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9762 if (h264_scratch.nFilledLen) {
9763 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9764 NALU_TYPE_SPS);
9765 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9766 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9767 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9768 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9769 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9770 // If timeinfo is present frame info from SEI is already processed
9771 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9772 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9773 #endif
9774 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9775 nal_count++;
9776 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9777 pdest_frame->nTimeStamp = h264_last_au_ts;
9778 pdest_frame->nFlags = h264_last_au_flags;
9779 #ifdef PANSCAN_HDLR
9780 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9781 h264_parser->update_panscan_data(h264_last_au_ts);
9782 #endif
9783 }
9784 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9785 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9786 h264_last_au_ts = h264_scratch.nTimeStamp;
9787 h264_last_au_flags = h264_scratch.nFlags;
9788 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9789 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9790 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9791 if (!VALID_TS(h264_last_au_ts))
9792 h264_last_au_ts = ts_in_sei;
9793 }
9794 #endif
9795 } else
9796 h264_last_au_ts = LLONG_MAX;
9797 }
9798
9799 if (!isNewFrame) {
9800 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9801 h264_scratch.nFilledLen) {
9802 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9803 (unsigned int)h264_scratch.nFilledLen);
9804 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9805 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9806 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9807 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9808 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9809 h264_scratch.nFilledLen = 0;
9810 } else {
9811 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9812 return OMX_ErrorBadParameter;
9813 }
9814 } else if(h264_scratch.nFilledLen) {
9815 look_ahead_nal = true;
9816 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9817 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9818 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9819 (unsigned int)pdest_frame->nFilledLen,frame_count++);
9820
9821 if (pdest_frame->nFilledLen == 0) {
9822 DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9823 look_ahead_nal = false;
9824 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9825 h264_scratch.nFilledLen) {
9826 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9827 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9828 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9829 h264_scratch.nFilledLen = 0;
9830 } else {
9831 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9832 return OMX_ErrorBadParameter;
9833 }
9834 } else {
9835 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9836 DEBUG_PRINT_LOW("Reset the EOS Flag");
9837 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9838 }
9839 /*Push the frame to the Decoder*/
9840 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9841 return OMX_ErrorBadParameter;
9842 }
9843 //frame_count++;
9844 pdest_frame = NULL;
9845 if (m_input_free_q.m_size) {
9846 m_input_free_q.pop_entry(&address,&p2,&id);
9847 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9848 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9849 pdest_frame->nFilledLen = 0;
9850 pdest_frame->nFlags = 0;
9851 pdest_frame->nTimeStamp = LLONG_MAX;
9852 }
9853 }
9854 }
9855 }
9856 } else {
9857 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9858 /*Check if Destination Buffer is full*/
9859 if (h264_scratch.nAllocLen ==
9860 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9861 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9862 return OMX_ErrorStreamCorrupt;
9863 }
9864 }
9865
9866 if (!psource_frame->nFilledLen) {
9867 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9868
9869 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9870 if (pdest_frame) {
9871 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9872 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9873 h264_scratch.nFilledLen) {
9874 if(pdest_frame->nFilledLen == 0) {
9875 /* No residual frame from before, send whatever
9876 * we have left */
9877 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9878 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9879 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9880 h264_scratch.nFilledLen = 0;
9881 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9882 } else {
9883 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9884 if(!isNewFrame) {
9885 /* Have a residual frame, but we know that the
9886 * AU in this frame is belonging to whatever
9887 * frame we had left over. So append it */
9888 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9889 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9890 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9891 h264_scratch.nFilledLen = 0;
9892 if (h264_last_au_ts != LLONG_MAX)
9893 pdest_frame->nTimeStamp = h264_last_au_ts;
9894 } else {
9895 /* Completely new frame, let's just push what
9896 * we have now. The resulting EBD would trigger
9897 * another push */
9898 generate_ebd = OMX_FALSE;
9899 pdest_frame->nTimeStamp = h264_last_au_ts;
9900 h264_last_au_ts = h264_scratch.nTimeStamp;
9901 }
9902 }
9903 } else {
9904 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9905 return OMX_ErrorBadParameter;
9906 }
9907
9908 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9909 if(generate_ebd == OMX_TRUE) {
9910 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9911 }
9912
9913 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9914 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9915 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9916 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9917 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9918 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9919 if (!VALID_TS(pdest_frame->nTimeStamp))
9920 pdest_frame->nTimeStamp = ts_in_sei;
9921 }
9922 #endif
9923 /*Push the frame to the Decoder*/
9924 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9925 return OMX_ErrorBadParameter;
9926 }
9927 frame_count++;
9928 pdest_frame = NULL;
9929 } else {
9930 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9931 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9932 generate_ebd = OMX_FALSE;
9933 }
9934 }
9935 }
9936 if (generate_ebd && !psource_frame->nFilledLen) {
9937 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9938 psource_frame = NULL;
9939 if (m_input_pending_q.m_size) {
9940 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9941 m_input_pending_q.pop_entry(&address,&p2,&id);
9942 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9943 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9944 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9945 }
9946 }
9947 return OMX_ErrorNone;
9948 }
9949
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9950 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9951 {
9952 OMX_ERRORTYPE rc = OMX_ErrorNone;
9953 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9954 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9955 if (pDst->nTimeStamp == LLONG_MAX) {
9956 pDst->nTimeStamp = pSrc->nTimeStamp;
9957 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9958 }
9959 pDst->nFilledLen += pSrc->nFilledLen;
9960 pSrc->nFilledLen = 0;
9961 } else {
9962 DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9963 rc = OMX_ErrorBadParameter;
9964 }
9965 return rc;
9966 }
9967
push_input_hevc(OMX_HANDLETYPE hComp)9968 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9969 {
9970 OMX_U32 partial_frame = 1;
9971 unsigned long address,p2,id;
9972 OMX_BOOL isNewFrame = OMX_FALSE;
9973 OMX_BOOL generate_ebd = OMX_TRUE;
9974 OMX_ERRORTYPE rc = OMX_ErrorNone;
9975 if (h264_scratch.pBuffer == NULL) {
9976 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9977 return OMX_ErrorBadParameter;
9978 }
9979
9980 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9981 pdest_frame nFilledLen %u nTimeStamp %lld",
9982 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9983
9984 if (h264_scratch.nFilledLen && look_ahead_nal) {
9985 look_ahead_nal = false;
9986 rc = copy_buffer(pdest_frame, &h264_scratch);
9987 if (rc != OMX_ErrorNone) {
9988 return rc;
9989 }
9990 }
9991
9992 if (nal_length == 0) {
9993 if (m_frame_parser.parse_sc_frame(psource_frame,
9994 &h264_scratch,&partial_frame) == -1) {
9995 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9996 return OMX_ErrorBadParameter;
9997 }
9998 } else {
9999 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
10000 if (m_frame_parser.parse_h264_nallength(psource_frame,
10001 &h264_scratch,&partial_frame) == -1) {
10002 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
10003 return OMX_ErrorBadParameter;
10004 }
10005 }
10006
10007 if (partial_frame == 0) {
10008 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
10009 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
10010 nal_count++;
10011 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
10012 h264_scratch.nFlags = psource_frame->nFlags;
10013 } else {
10014 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
10015 if (h264_scratch.nFilledLen) {
10016 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
10017 nal_count++;
10018 }
10019
10020 if (!isNewFrame) {
10021 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
10022 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
10023 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
10024 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
10025 rc = copy_buffer(pdest_frame, &h264_scratch);
10026 if (rc != OMX_ErrorNone) {
10027 return rc;
10028 }
10029 } else {
10030 look_ahead_nal = true;
10031 if (pdest_frame->nFilledLen == 0) {
10032 look_ahead_nal = false;
10033 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
10034 rc = copy_buffer(pdest_frame, &h264_scratch);
10035 if (rc != OMX_ErrorNone) {
10036 return OMX_ErrorBadParameter;
10037 }
10038 } else {
10039 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
10040 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
10041 }
10042 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
10043 nTimeStamp %lld, look_ahead_nal in h264_scratch \
10044 nFilledLen %u nTimeStamp %lld",
10045 frame_count++, (unsigned int)pdest_frame->nFilledLen,
10046 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
10047 h264_scratch.nTimeStamp);
10048 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
10049 return OMX_ErrorBadParameter;
10050 }
10051 pdest_frame = NULL;
10052 if (m_input_free_q.m_size) {
10053 m_input_free_q.pop_entry(&address, &p2, &id);
10054 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
10055 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
10056 pdest_frame->nFilledLen = 0;
10057 pdest_frame->nFlags = 0;
10058 pdest_frame->nTimeStamp = LLONG_MAX;
10059 }
10060 }
10061 }
10062 }
10063 } else {
10064 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
10065 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
10066 nFilledLen %u nTimeStamp %lld",
10067 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
10068 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
10069 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
10070
10071 if (h264_scratch.nAllocLen ==
10072 h264_scratch.nFilledLen + h264_scratch.nOffset) {
10073 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
10074 return OMX_ErrorStreamCorrupt;
10075 }
10076 }
10077
10078 if (!psource_frame->nFilledLen) {
10079 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
10080 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
10081 if (pdest_frame) {
10082 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
10083 rc = copy_buffer(pdest_frame, &h264_scratch);
10084 if ( rc != OMX_ErrorNone ) {
10085 return rc;
10086 }
10087 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
10088 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
10089 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
10090 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
10091 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
10092 return OMX_ErrorBadParameter;
10093 }
10094 frame_count++;
10095 pdest_frame = NULL;
10096 } else {
10097 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
10098 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
10099 generate_ebd = OMX_FALSE;
10100 }
10101 }
10102 }
10103
10104 if (generate_ebd && !psource_frame->nFilledLen) {
10105 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
10106 psource_frame = NULL;
10107 if (m_input_pending_q.m_size) {
10108 m_input_pending_q.pop_entry(&address, &p2, &id);
10109 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
10110 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
10111 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
10112 }
10113 }
10114 return OMX_ErrorNone;
10115 }
10116
push_input_vc1(OMX_HANDLETYPE hComp)10117 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
10118 {
10119 OMX_U8 *buf, *pdest;
10120 OMX_U32 partial_frame = 1;
10121 OMX_U32 buf_len, dest_len;
10122
10123 if (first_frame == 0) {
10124 first_frame = 1;
10125 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
10126 if (!m_vendor_config.pData) {
10127 DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
10128 buf = psource_frame->pBuffer;
10129 buf_len = psource_frame->nFilledLen;
10130
10131 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
10132 VC1_SP_MP_START_CODE) {
10133 m_vc1_profile = VC1_SP_MP_RCV;
10134 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
10135 m_vc1_profile = VC1_AP;
10136 } else {
10137 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
10138 return OMX_ErrorStreamCorrupt;
10139 }
10140 } else {
10141 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
10142 pdest_frame->nOffset;
10143 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
10144 pdest_frame->nOffset);
10145
10146 if (dest_len < m_vendor_config.nDataSize) {
10147 DEBUG_PRINT_ERROR("Destination buffer full");
10148 return OMX_ErrorBadParameter;
10149 } else {
10150 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
10151 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
10152 }
10153 }
10154 }
10155
10156 switch (m_vc1_profile) {
10157 case VC1_AP:
10158 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
10159 if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
10160 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
10161 return OMX_ErrorBadParameter;
10162 }
10163 break;
10164
10165 case VC1_SP_MP_RCV:
10166 default:
10167 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
10168 return OMX_ErrorBadParameter;
10169 }
10170 return OMX_ErrorNone;
10171 }
10172
10173 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)10174 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
10175 OMX_U32 alignment)
10176 {
10177 struct pmem_allocation allocation;
10178 allocation.size = buffer_size;
10179 allocation.align = clip2(alignment);
10180 if (allocation.align < 4096) {
10181 allocation.align = 4096;
10182 }
10183 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
10184 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
10185 allocation.align, allocation.size);
10186 return false;
10187 }
10188 return true;
10189 }
10190 #endif
10191 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,OMX_U32 alignment,struct ion_allocation_data * alloc_data,struct ion_fd_data * fd_data,int flag)10192 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
10193 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
10194 struct ion_fd_data *fd_data, int flag)
10195 {
10196 int fd = -EINVAL;
10197 int rc = -EINVAL;
10198 int ion_dev_flag;
10199 struct vdec_ion ion_buf_info;
10200 if (!alloc_data || buffer_size <= 0 || !fd_data) {
10201 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
10202 return -EINVAL;
10203 }
10204 ion_dev_flag = O_RDONLY;
10205 fd = open (MEM_DEVICE, ion_dev_flag);
10206 if (fd < 0) {
10207 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
10208 return fd;
10209 }
10210
10211 alloc_data->flags = flag;
10212 alloc_data->len = buffer_size;
10213 alloc_data->align = clip2(alignment);
10214 if (alloc_data->align < 4096) {
10215 alloc_data->align = 4096;
10216 }
10217
10218 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
10219 if (secure_mode && (alloc_data->flags & ION_SECURE)) {
10220 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
10221 }
10222
10223 /* Use secure display cma heap for obvious reasons. */
10224 if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
10225 alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
10226 }
10227
10228 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
10229 if (rc || !alloc_data->handle) {
10230 DEBUG_PRINT_ERROR("ION ALLOC memory failed");
10231 alloc_data->handle = 0;
10232 close(fd);
10233 fd = -ENOMEM;
10234 return fd;
10235 }
10236 fd_data->handle = alloc_data->handle;
10237 rc = ioctl(fd,ION_IOC_MAP,fd_data);
10238 if (rc) {
10239 DEBUG_PRINT_ERROR("ION MAP failed ");
10240 ion_buf_info.ion_alloc_data = *alloc_data;
10241 ion_buf_info.ion_device_fd = fd;
10242 ion_buf_info.fd_ion_data = *fd_data;
10243 free_ion_memory(&ion_buf_info);
10244 fd_data->fd =-1;
10245 fd = -ENOMEM;
10246 }
10247
10248 return fd;
10249 }
10250
free_ion_memory(struct vdec_ion * buf_ion_info)10251 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
10252 {
10253
10254 if (!buf_ion_info) {
10255 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
10256 return;
10257 }
10258 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
10259 &buf_ion_info->ion_alloc_data.handle)) {
10260 DEBUG_PRINT_ERROR("ION: free failed" );
10261 }
10262 close(buf_ion_info->ion_device_fd);
10263 buf_ion_info->ion_device_fd = -1;
10264 buf_ion_info->ion_alloc_data.handle = 0;
10265 buf_ion_info->fd_ion_data.fd = -1;
10266 }
10267 #endif
free_output_buffer_header()10268 void omx_vdec::free_output_buffer_header()
10269 {
10270 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
10271 output_use_buffer = false;
10272 ouput_egl_buffers = false;
10273
10274 if (m_out_mem_ptr) {
10275 free (m_out_mem_ptr);
10276 m_out_mem_ptr = NULL;
10277 }
10278
10279 if (m_platform_list) {
10280 free(m_platform_list);
10281 m_platform_list = NULL;
10282 }
10283
10284 if (drv_ctx.ptr_respbuffer) {
10285 free (drv_ctx.ptr_respbuffer);
10286 drv_ctx.ptr_respbuffer = NULL;
10287 }
10288 if (drv_ctx.ptr_outputbuffer) {
10289 free (drv_ctx.ptr_outputbuffer);
10290 drv_ctx.ptr_outputbuffer = NULL;
10291 }
10292 #ifdef USE_ION
10293 if (drv_ctx.op_buf_ion_info) {
10294 DEBUG_PRINT_LOW("Free o/p ion context");
10295 free(drv_ctx.op_buf_ion_info);
10296 drv_ctx.op_buf_ion_info = NULL;
10297 }
10298 #endif
10299 free(drv_ctx.op_buf_map_info);
10300 drv_ctx.op_buf_map_info = NULL;
10301 buf_ref_remove();
10302 }
10303
free_input_buffer_header()10304 void omx_vdec::free_input_buffer_header()
10305 {
10306 input_use_buffer = false;
10307 if (arbitrary_bytes) {
10308 if (m_inp_heap_ptr) {
10309 DEBUG_PRINT_LOW("Free input Heap Pointer");
10310 free (m_inp_heap_ptr);
10311 m_inp_heap_ptr = NULL;
10312 }
10313
10314 if (m_phdr_pmem_ptr) {
10315 DEBUG_PRINT_LOW("Free input pmem header Pointer");
10316 free (m_phdr_pmem_ptr);
10317 m_phdr_pmem_ptr = NULL;
10318 }
10319 }
10320 if (m_inp_mem_ptr) {
10321 DEBUG_PRINT_LOW("Free input pmem Pointer area");
10322 free (m_inp_mem_ptr);
10323 m_inp_mem_ptr = NULL;
10324 }
10325 /* We just freed all the buffer headers, every thing in m_input_free_q,
10326 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
10327 while (m_input_free_q.m_size) {
10328 unsigned long address, p2, id;
10329 m_input_free_q.pop_entry(&address, &p2, &id);
10330 }
10331 while (m_input_pending_q.m_size) {
10332 unsigned long address, p2, id;
10333 m_input_pending_q.pop_entry(&address, &p2, &id);
10334 }
10335 pdest_frame = NULL;
10336 psource_frame = NULL;
10337 if (drv_ctx.ptr_inputbuffer) {
10338 DEBUG_PRINT_LOW("Free Driver Context pointer");
10339 free (drv_ctx.ptr_inputbuffer);
10340 drv_ctx.ptr_inputbuffer = NULL;
10341 }
10342 #ifdef USE_ION
10343 if (drv_ctx.ip_buf_ion_info) {
10344 DEBUG_PRINT_LOW("Free ion context");
10345 free(drv_ctx.ip_buf_ion_info);
10346 drv_ctx.ip_buf_ion_info = NULL;
10347 }
10348 #endif
10349 }
10350
free_output_extradata_buffer_header()10351 void omx_vdec::free_output_extradata_buffer_header() {
10352 client_extradata = false;
10353 if (m_client_output_extradata_mem_ptr) {
10354 DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
10355 free(m_client_output_extradata_mem_ptr);
10356 m_client_output_extradata_mem_ptr = NULL;
10357 }
10358 }
10359
stream_off(OMX_U32 port)10360 int omx_vdec::stream_off(OMX_U32 port)
10361 {
10362 enum v4l2_buf_type btype;
10363 int rc = 0;
10364 enum v4l2_ports v4l2_port = OUTPUT_PORT;
10365
10366 if (port == OMX_CORE_INPUT_PORT_INDEX) {
10367 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10368 v4l2_port = OUTPUT_PORT;
10369 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10370 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10371 v4l2_port = CAPTURE_PORT;
10372 } else if (port == OMX_ALL) {
10373 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
10374 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
10375
10376 if (!rc_input)
10377 return rc_input;
10378 else
10379 return rc_output;
10380 }
10381
10382 if (!streaming[v4l2_port]) {
10383 // already streamed off, warn and move on
10384 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
10385 " which is already streamed off", v4l2_port);
10386 return 0;
10387 }
10388
10389 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
10390
10391 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
10392 if (rc) {
10393 /*TODO: How to handle this case */
10394 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
10395 } else {
10396 streaming[v4l2_port] = false;
10397 }
10398
10399 return rc;
10400 }
10401
get_buffer_req(vdec_allocatorproperty * buffer_prop)10402 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
10403 {
10404 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10405 struct v4l2_requestbuffers bufreq;
10406 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
10407 unsigned int final_extra_data_size = 0;
10408 struct v4l2_format fmt;
10409 int ret = 0;
10410 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10411 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10412 bufreq.memory = V4L2_MEMORY_USERPTR;
10413 bufreq.count = 1;
10414 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10415 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10416 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10417 fmt.fmt.pix_mp.pixelformat = output_capability;
10418 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10419 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10420 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10421 fmt.fmt.pix_mp.pixelformat = capture_capability;
10422 } else {
10423 eRet = OMX_ErrorBadParameter;
10424 }
10425 if (eRet==OMX_ErrorNone) {
10426 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10427 }
10428 if (ret) {
10429 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10430 /*TODO: How to handle this case */
10431 eRet = OMX_ErrorInsufficientResources;
10432 return eRet;
10433 } else {
10434 bool is_res_1080p_or_below = (drv_ctx.video_resolution.frame_width <= 1920 &&
10435 drv_ctx.video_resolution.frame_height <= 1088) ||
10436 (drv_ctx.video_resolution.frame_height <= 1088 &&
10437 drv_ctx.video_resolution.frame_width <= 1920);
10438
10439 int fps = drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator;
10440 bool fps_above_180 = (fps >= 180 || operating_frame_rate >= 180) ? true : false;
10441 bool increase_output = (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) && (bufreq.count >= 16);
10442
10443 if (increase_output && fps_above_180 &&
10444 output_capability == V4L2_PIX_FMT_H264 &&
10445 is_res_1080p_or_below) {
10446 m_need_turbo |= TURBO_MODE_HIGH_FPS;
10447 DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate);
10448 DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps",
10449 bufreq.count, bufreq.count + 10);
10450 bufreq.count += 10;
10451 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10452 if (ret) {
10453 DEBUG_PRINT_ERROR("(Failed to set updated buffer count to driver");
10454 eRet = OMX_ErrorInsufficientResources;
10455 return eRet;
10456 }
10457 DEBUG_PRINT_LOW("new buf count = %d set to driver", bufreq.count);
10458 request_perf_level(VIDC_TURBO);
10459 }
10460
10461 buffer_prop->actualcount = bufreq.count;
10462 buffer_prop->mincount = bufreq.count;
10463 DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
10464 }
10465 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10466 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10467
10468 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10469
10470 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
10471 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
10472 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
10473
10474 if (ret) {
10475 /*TODO: How to handle this case */
10476 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10477 eRet = OMX_ErrorInsufficientResources;
10478 } else {
10479 int extra_idx = 0;
10480
10481 eRet = is_video_session_supported();
10482 if (eRet)
10483 return eRet;
10484
10485 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10486 buf_size = buffer_prop->buffer_size;
10487 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
10488 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
10489 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
10490 } else if (extra_idx >= VIDEO_MAX_PLANES) {
10491 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
10492 return OMX_ErrorBadParameter;
10493 }
10494
10495 default_extra_data_size = VENUS_EXTRADATA_SIZE(
10496 drv_ctx.video_resolution.frame_height,
10497 drv_ctx.video_resolution.frame_width);
10498 final_extra_data_size = extra_data_size > default_extra_data_size ?
10499 extra_data_size : default_extra_data_size;
10500
10501 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
10502 (~(buffer_prop->alignment - 1));
10503
10504 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
10505 drv_ctx.extradata_info.count = buffer_prop->actualcount;
10506 drv_ctx.extradata_info.buffer_size = final_extra_data_size;
10507 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10508 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
10509 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
10510 if (extra_data_size)
10511 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
10512 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
10513
10514 if (in_reconfig) // BufReq will be set to driver when port is disabled
10515 buffer_prop->buffer_size = buf_size;
10516 else if (buf_size != buffer_prop->buffer_size) {
10517 buffer_prop->buffer_size = buf_size;
10518 eRet = set_buffer_req(buffer_prop);
10519 }
10520 }
10521 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
10522 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10523 return eRet;
10524 }
10525
set_buffer_req(vdec_allocatorproperty * buffer_prop)10526 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
10527 {
10528 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10529 unsigned buf_size = 0;
10530 struct v4l2_format fmt, c_fmt;
10531 struct v4l2_requestbuffers bufreq;
10532 int ret = 0;
10533 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
10534 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10535 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10536 if (buf_size != buffer_prop->buffer_size) {
10537 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
10538 (unsigned int)buffer_prop->buffer_size, buf_size);
10539 eRet = OMX_ErrorBadParameter;
10540 } else {
10541 memset(&fmt, 0x0, sizeof(struct v4l2_format));
10542 memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
10543 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10544 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10545 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10546
10547 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10548 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10549 fmt.fmt.pix_mp.pixelformat = output_capability;
10550 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10551 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10552 c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10553 c_fmt.fmt.pix_mp.pixelformat = capture_capability;
10554 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
10555 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10556 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
10557 } else {
10558 eRet = OMX_ErrorBadParameter;
10559 }
10560
10561 if (ret) {
10562 /*TODO: How to handle this case */
10563 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
10564 eRet = OMX_ErrorInsufficientResources;
10565 }
10566
10567 bufreq.memory = V4L2_MEMORY_USERPTR;
10568 bufreq.count = buffer_prop->actualcount;
10569 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10570 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10571 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10572 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10573 } else {
10574 eRet = OMX_ErrorBadParameter;
10575 }
10576
10577 if (eRet==OMX_ErrorNone) {
10578 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10579 }
10580
10581 if (ret) {
10582 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
10583 /*TODO: How to handle this case */
10584 eRet = OMX_ErrorInsufficientResources;
10585 } else if (bufreq.count < buffer_prop->actualcount) {
10586 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
10587 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
10588 buffer_prop->actualcount, bufreq.count);
10589 eRet = OMX_ErrorInsufficientResources;
10590 } else {
10591 if (!client_buffers.update_buffer_req()) {
10592 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
10593 eRet = OMX_ErrorInsufficientResources;
10594 }
10595 }
10596 }
10597 return eRet;
10598 }
10599
update_picture_resolution()10600 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
10601 {
10602 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10603 return eRet;
10604 }
10605
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)10606 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
10607 {
10608 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10609 struct v4l2_format fmt;
10610 if (!portDefn) {
10611 return OMX_ErrorBadParameter;
10612 }
10613 DEBUG_PRINT_LOW("omx_vdec::update_portdef");
10614 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
10615 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10616 portDefn->eDomain = OMX_PortDomainVideo;
10617 memset(&fmt, 0x0, sizeof(struct v4l2_format));
10618 if (0 == portDefn->nPortIndex) {
10619 portDefn->eDir = OMX_DirInput;
10620 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
10621 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
10622 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
10623 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10624 portDefn->format.video.eCompressionFormat = eCompressionFormat;
10625 //for input port, always report the fps value set by client,
10626 //to distinguish whether client got valid fps from parser.
10627 portDefn->format.video.xFramerate = m_fps_received;
10628 portDefn->bEnabled = m_inp_bEnabled;
10629 portDefn->bPopulated = m_inp_bPopulated;
10630
10631 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10632 fmt.fmt.pix_mp.pixelformat = output_capability;
10633 ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10634 } else if (1 == portDefn->nPortIndex) {
10635 unsigned int buf_size = 0;
10636 int ret = 0;
10637 if (in_reconfig && !is_down_scalar_enabled) {
10638 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10639 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10640 fmt.fmt.pix_mp.pixelformat = capture_capability;
10641 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10642 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10643 }
10644
10645 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10646 fmt.fmt.pix_mp.pixelformat = capture_capability;
10647 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10648 if (ret) {
10649 DEBUG_PRINT_ERROR("Get Resolution failed");
10650 return OMX_ErrorHardware;
10651 }
10652 drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10653 if (!client_buffers.update_buffer_req()) {
10654 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
10655 return OMX_ErrorHardware;
10656 }
10657
10658 if (!client_buffers.get_buffer_req(buf_size)) {
10659 DEBUG_PRINT_ERROR("update buffer requirements");
10660 return OMX_ErrorHardware;
10661 }
10662 portDefn->nBufferSize = buf_size;
10663 portDefn->eDir = OMX_DirOutput;
10664 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
10665 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
10666 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10667 if (drv_ctx.frame_rate.fps_denominator > 0)
10668 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
10669 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
10670 else {
10671 DEBUG_PRINT_ERROR("Error: Divide by zero");
10672 return OMX_ErrorBadParameter;
10673 }
10674 portDefn->bEnabled = m_out_bEnabled;
10675 portDefn->bPopulated = m_out_bPopulated;
10676 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
10677 DEBUG_PRINT_ERROR("Error in getting color format");
10678 return OMX_ErrorHardware;
10679 }
10680 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10681 fmt.fmt.pix_mp.pixelformat = capture_capability;
10682 } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
10683 portDefn->nBufferSize = m_client_out_extradata_info.getSize();
10684 portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10685 portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10686 portDefn->eDir = OMX_DirOutput;
10687 } else {
10688 portDefn->eDir = OMX_DirMax;
10689 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
10690 (int)portDefn->nPortIndex);
10691 eRet = OMX_ErrorBadPortIndex;
10692 }
10693 update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10694 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
10695
10696 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
10697 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
10698 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10699 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10700
10701 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
10702 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
10703 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
10704 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
10705 }
10706 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
10707 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
10708 (unsigned int)portDefn->nPortIndex,
10709 (unsigned int)portDefn->format.video.nFrameWidth,
10710 (unsigned int)portDefn->format.video.nFrameHeight,
10711 (int)portDefn->format.video.nStride,
10712 (unsigned int)portDefn->format.video.nSliceHeight,
10713 (unsigned int)portDefn->format.video.eColorFormat,
10714 (unsigned int)portDefn->nBufferSize,
10715 (unsigned int)portDefn->nBufferCountActual);
10716
10717 return eRet;
10718 }
10719
allocate_output_headers()10720 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
10721 {
10722 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10723 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
10724 unsigned i = 0;
10725
10726 if (!m_out_mem_ptr) {
10727 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
10728 int nBufHdrSize = 0;
10729 int nPlatformEntrySize = 0;
10730 int nPlatformListSize = 0;
10731 int nPMEMInfoSize = 0;
10732 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
10733 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
10734 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
10735
10736 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
10737 drv_ctx.op_buf.actualcount);
10738 nBufHdrSize = drv_ctx.op_buf.actualcount *
10739 sizeof(OMX_BUFFERHEADERTYPE);
10740
10741 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
10742 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
10743 nPlatformListSize = drv_ctx.op_buf.actualcount *
10744 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
10745 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
10746 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
10747
10748 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
10749 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
10750 nPMEMInfoSize,
10751 nPlatformListSize);
10752 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
10753 m_out_bm_count);
10754 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
10755 // Alloc mem for platform specific info
10756 char *pPtr=NULL;
10757 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
10758 nPMEMInfoSize,1);
10759 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
10760 calloc (sizeof(struct vdec_bufferpayload),
10761 drv_ctx.op_buf.actualcount);
10762 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
10763 calloc (sizeof (struct vdec_output_frameinfo),
10764 drv_ctx.op_buf.actualcount);
10765 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
10766 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
10767 return OMX_ErrorInsufficientResources;
10768 }
10769
10770 #ifdef USE_ION
10771 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
10772 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
10773 if (!drv_ctx.op_buf_ion_info) {
10774 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
10775 return OMX_ErrorInsufficientResources;
10776 }
10777 #endif
10778 if (dynamic_buf_mode) {
10779 out_dynamic_list = (struct dynamic_buf_list *) \
10780 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
10781 if (out_dynamic_list) {
10782 for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
10783 out_dynamic_list[i].dup_fd = -1;
10784 }
10785 }
10786
10787 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
10788 && drv_ctx.ptr_respbuffer) {
10789 bufHdr = m_out_mem_ptr;
10790 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
10791 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
10792 (((char *) m_platform_list) + nPlatformListSize);
10793 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10794 (((char *) m_platform_entry) + nPlatformEntrySize);
10795 pPlatformList = m_platform_list;
10796 pPlatformEntry = m_platform_entry;
10797 pPMEMInfo = m_pmem_info;
10798
10799 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
10800
10801 // Settting the entire storage nicely
10802 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10803 m_out_mem_ptr,pPlatformEntry);
10804 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10805 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10806 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
10807 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
10808 // Set the values when we determine the right HxW param
10809 bufHdr->nAllocLen = 0;
10810 bufHdr->nFilledLen = 0;
10811 bufHdr->pAppPrivate = NULL;
10812 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10813 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10814 pPlatformEntry->entry = pPMEMInfo;
10815 // Initialize the Platform List
10816 pPlatformList->nEntries = 1;
10817 pPlatformList->entryList = pPlatformEntry;
10818 // Keep pBuffer NULL till vdec is opened
10819 bufHdr->pBuffer = NULL;
10820 pPMEMInfo->offset = 0;
10821 pPMEMInfo->pmem_fd = -1;
10822 bufHdr->pPlatformPrivate = pPlatformList;
10823 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
10824 #ifdef USE_ION
10825 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
10826 #endif
10827 /*Create a mapping between buffers*/
10828 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
10829 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
10830 &drv_ctx.ptr_outputbuffer[i];
10831 // Move the buffer and buffer header pointers
10832 bufHdr++;
10833 pPMEMInfo++;
10834 pPlatformEntry++;
10835 pPlatformList++;
10836 }
10837 } else {
10838 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10839 m_out_mem_ptr, pPtr);
10840 if (m_out_mem_ptr) {
10841 free(m_out_mem_ptr);
10842 m_out_mem_ptr = NULL;
10843 }
10844 if (pPtr) {
10845 free(pPtr);
10846 pPtr = NULL;
10847 }
10848 if (drv_ctx.ptr_outputbuffer) {
10849 free(drv_ctx.ptr_outputbuffer);
10850 drv_ctx.ptr_outputbuffer = NULL;
10851 }
10852 if (drv_ctx.ptr_respbuffer) {
10853 free(drv_ctx.ptr_respbuffer);
10854 drv_ctx.ptr_respbuffer = NULL;
10855 }
10856 #ifdef USE_ION
10857 if (drv_ctx.op_buf_ion_info) {
10858 DEBUG_PRINT_LOW("Free o/p ion context");
10859 free(drv_ctx.op_buf_ion_info);
10860 drv_ctx.op_buf_ion_info = NULL;
10861 }
10862 #endif
10863 free(drv_ctx.op_buf_map_info);
10864 drv_ctx.op_buf_map_info = NULL;
10865 eRet = OMX_ErrorInsufficientResources;
10866 }
10867 } else {
10868 eRet = OMX_ErrorInsufficientResources;
10869 }
10870 return eRet;
10871 }
10872
complete_pending_buffer_done_cbs()10873 void omx_vdec::complete_pending_buffer_done_cbs()
10874 {
10875 unsigned long p1, p2, ident;
10876 omx_cmd_queue tmp_q, pending_bd_q;
10877 pthread_mutex_lock(&m_lock);
10878 // pop all pending GENERATE FDB from ftb queue
10879 while (m_ftb_q.m_size) {
10880 m_ftb_q.pop_entry(&p1,&p2,&ident);
10881 if (ident == OMX_COMPONENT_GENERATE_FBD) {
10882 pending_bd_q.insert_entry(p1,p2,ident);
10883 } else {
10884 tmp_q.insert_entry(p1,p2,ident);
10885 }
10886 }
10887 //return all non GENERATE FDB to ftb queue
10888 while (tmp_q.m_size) {
10889 tmp_q.pop_entry(&p1,&p2,&ident);
10890 m_ftb_q.insert_entry(p1,p2,ident);
10891 }
10892 // pop all pending GENERATE EDB from etb queue
10893 while (m_etb_q.m_size) {
10894 m_etb_q.pop_entry(&p1,&p2,&ident);
10895 if (ident == OMX_COMPONENT_GENERATE_EBD) {
10896 pending_bd_q.insert_entry(p1,p2,ident);
10897 } else {
10898 tmp_q.insert_entry(p1,p2,ident);
10899 }
10900 }
10901 //return all non GENERATE FDB to etb queue
10902 while (tmp_q.m_size) {
10903 tmp_q.pop_entry(&p1,&p2,&ident);
10904 m_etb_q.insert_entry(p1,p2,ident);
10905 }
10906 pthread_mutex_unlock(&m_lock);
10907 // process all pending buffer dones
10908 while (pending_bd_q.m_size) {
10909 pending_bd_q.pop_entry(&p1,&p2,&ident);
10910 switch (ident) {
10911 case OMX_COMPONENT_GENERATE_EBD:
10912 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10913 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10914 omx_report_error ();
10915 }
10916 break;
10917
10918 case OMX_COMPONENT_GENERATE_FBD:
10919 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10920 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10921 omx_report_error ();
10922 }
10923 break;
10924 }
10925 }
10926 }
10927
set_frame_rate(OMX_S64 act_timestamp)10928 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10929 {
10930 OMX_U32 new_frame_interval = 0;
10931 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10932 && llabs(act_timestamp - prev_ts) > 2000) {
10933 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10934 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10935 if (new_frame_interval != frm_int || frm_int == 0) {
10936 frm_int = new_frame_interval;
10937 if (frm_int) {
10938 drv_ctx.frame_rate.fps_numerator = 1e6;
10939 drv_ctx.frame_rate.fps_denominator = frm_int;
10940 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10941 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10942 (float)drv_ctx.frame_rate.fps_denominator);
10943 m_perf_control.request_cores(frm_int);
10944 /* We need to report the difference between this FBD and the previous FBD
10945 * back to the driver for clock scaling purposes. */
10946 struct v4l2_outputparm oparm;
10947 /*XXX: we're providing timing info as seconds per frame rather than frames
10948 * per second.*/
10949 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10950 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10951
10952 struct v4l2_streamparm sparm;
10953 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10954 sparm.parm.output = oparm;
10955 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10956 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10957 performance might be affected");
10958 }
10959
10960 }
10961 }
10962 }
10963 prev_ts = act_timestamp;
10964 }
10965
adjust_timestamp(OMX_S64 & act_timestamp)10966 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10967 {
10968 if (rst_prev_ts && VALID_TS(act_timestamp)) {
10969 prev_ts = act_timestamp;
10970 prev_ts_actual = act_timestamp;
10971 rst_prev_ts = false;
10972 } else if (VALID_TS(prev_ts)) {
10973 bool codec_cond = (drv_ctx.timestamp_adjust)?
10974 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10975 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10976 prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10977 if (frm_int > 0 && codec_cond) {
10978 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10979 act_timestamp = prev_ts + frm_int;
10980 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10981 prev_ts = act_timestamp;
10982 } else {
10983 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10984 // ensure that timestamps can never step backwards when in display order
10985 act_timestamp = prev_ts;
10986 }
10987 set_frame_rate(act_timestamp);
10988 }
10989 } else if (frm_int > 0) // In this case the frame rate was set along
10990 { // with the port definition, start ts with 0
10991 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
10992 rst_prev_ts = true;
10993 }
10994 }
10995
get_omx_output_buffer_header(int index)10996 OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index)
10997 {
10998 return m_out_mem_ptr + index;
10999 }
11000
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorSpace_t * color_space,ColorAspects * aspects)11001 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
11002 OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
11003 {
11004 switch (primaries) {
11005 case MSM_VIDC_BT709_5:
11006 *color_space = ITU_R_709;
11007 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
11008 break;
11009 case MSM_VIDC_BT470_6_M:
11010 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
11011 break;
11012 case MSM_VIDC_BT601_6_625:
11013 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
11014 break;
11015 case MSM_VIDC_BT601_6_525:
11016 *color_space = range ? ITU_R_601_FR : ITU_R_601;
11017 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
11018 break;
11019 case MSM_VIDC_GENERIC_FILM:
11020 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
11021 break;
11022 case MSM_VIDC_BT2020:
11023 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
11024 break;
11025 case MSM_VIDC_UNSPECIFIED:
11026 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
11027 default:
11028 //aspects->mPrimaries = ColorAspects::PrimariesOther;
11029 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11030 break;
11031 }
11032
11033 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
11034
11035 switch (transfer) {
11036 case MSM_VIDC_TRANSFER_BT709_5:
11037 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
11038 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11039 break;
11040 case MSM_VIDC_TRANSFER_BT_470_6_M:
11041 aspects->mTransfer = ColorAspects::TransferGamma22;
11042 break;
11043 case MSM_VIDC_TRANSFER_BT_470_6_BG:
11044 aspects->mTransfer = ColorAspects::TransferGamma28;
11045 break;
11046 case MSM_VIDC_TRANSFER_SMPTE_240M:
11047 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
11048 break;
11049 case MSM_VIDC_TRANSFER_LINEAR:
11050 aspects->mTransfer = ColorAspects::TransferLinear;
11051 break;
11052 case MSM_VIDC_TRANSFER_IEC_61966:
11053 aspects->mTransfer = ColorAspects::TransferXvYCC;
11054 break;
11055 case MSM_VIDC_TRANSFER_BT_1361:
11056 aspects->mTransfer = ColorAspects::TransferBT1361;
11057 break;
11058 case MSM_VIDC_TRANSFER_SRGB:
11059 aspects->mTransfer = ColorAspects::TransferSRGB;
11060 break;
11061 case MSM_VIDC_TRANSFER_SMPTE_ST2084:
11062 aspects->mTransfer = ColorAspects::TransferST2084;
11063 break;
11064 case MSM_VIDC_TRANSFER_HLG:
11065 aspects->mTransfer = ColorAspects::TransferHLG;
11066 break;
11067 default:
11068 //aspects->mTransfer = ColorAspects::TransferOther;
11069 aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
11070 break;
11071 }
11072
11073 switch (matrix) {
11074 case MSM_VIDC_MATRIX_BT_709_5:
11075 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11076 break;
11077 case MSM_VIDC_MATRIX_FCC_47:
11078 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
11079 break;
11080 case MSM_VIDC_MATRIX_601_6_625:
11081 case MSM_VIDC_MATRIX_601_6_525:
11082 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11083 break;
11084 case MSM_VIDC_MATRIX_SMPTE_240M:
11085 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
11086 break;
11087 case MSM_VIDC_MATRIX_BT_2020:
11088 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
11089 break;
11090 case MSM_VIDC_MATRIX_BT_2020_CONST:
11091 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
11092 break;
11093 default:
11094 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
11095 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
11096 break;
11097 }
11098 }
11099
print_debug_color_aspects(ColorAspects * a,const char * prefix)11100 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) {
11101 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)",
11102 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange),
11103 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs));
11104 }
11105
prepare_color_aspects_metadata(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorMetaData * color_mdata)11106 void omx_vdec::prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range,
11107 OMX_U32 transfer, OMX_U32 matrix,
11108 ColorMetaData *color_mdata)
11109 {
11110
11111 /* ColorAspects in qdMetaData */
11112 color_mdata->colorPrimaries = (enum ColorPrimaries) primaries;
11113 color_mdata->range = (enum ColorRange)range;
11114 color_mdata->transfer = (enum GammaTransfer)transfer;
11115 color_mdata->matrixCoefficients = (enum MatrixCoEfficients)matrix;
11116 }
11117
handle_color_space_info(void * data,ColorSpace_t * color_space,ColorMetaData * color_mdata,bool & set_color_aspects_only)11118 bool omx_vdec::handle_color_space_info(void *data,
11119 ColorSpace_t *color_space,
11120 ColorMetaData *color_mdata,
11121 bool& set_color_aspects_only)
11122 {
11123 ColorAspects tempAspects;
11124 memset(&tempAspects, 0x0, sizeof(ColorAspects));
11125 ColorAspects *aspects = &tempAspects;
11126
11127 /* Set default ColorAspects */
11128 prepare_color_aspects_metadata(ColorPrimaries_BT601_6_625, Range_Full,
11129 Transfer_SMPTE_170M, MatrixCoEff_BT601_6_625,
11130 color_mdata);
11131
11132 switch(output_capability) {
11133 case V4L2_PIX_FMT_MPEG2:
11134 {
11135 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
11136 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
11137
11138 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
11139 * understand this code */
11140
11141 if (seqdisp_payload && seqdisp_payload->color_descp) {
11142
11143 convert_color_space_info(seqdisp_payload->color_primaries, 1,
11144 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
11145 color_space,aspects);
11146 m_disp_hor_size = seqdisp_payload->disp_width;
11147 m_disp_vert_size = seqdisp_payload->disp_height;
11148 set_color_aspects_only = true;
11149 prepare_color_aspects_metadata(seqdisp_payload->color_primaries, 1,
11150 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
11151 color_mdata);
11152 }
11153 }
11154 break;
11155 case V4L2_PIX_FMT_H264:
11156 case V4L2_PIX_FMT_HEVC:
11157 {
11158 struct msm_vidc_vui_display_info_payload *display_info_payload;
11159 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
11160
11161 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
11162
11163 if (display_info_payload->video_signal_present_flag &&
11164 display_info_payload->color_description_present_flag) {
11165 convert_color_space_info(display_info_payload->color_primaries,
11166 display_info_payload->video_full_range_flag,
11167 display_info_payload->transfer_characteristics,
11168 display_info_payload->matrix_coefficients,
11169 color_space,aspects);
11170 set_color_aspects_only = true;
11171 prepare_color_aspects_metadata(display_info_payload->color_primaries,
11172 display_info_payload->video_full_range_flag,
11173 display_info_payload->transfer_characteristics,
11174 display_info_payload->matrix_coefficients,
11175 color_mdata);
11176 }
11177 }
11178 break;
11179 case V4L2_PIX_FMT_VC1_ANNEX_G:
11180 case V4L2_PIX_FMT_VC1_ANNEX_L:
11181 {
11182 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
11183 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
11184
11185 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
11186 * SMPTE 421M to understand this code */
11187
11188 if (m_enable_android_native_buffers &&
11189 vc1_seq_disp_payload->color_primaries) {
11190
11191 convert_color_space_info(vc1_seq_disp_payload->color_primaries,
11192 1,
11193 vc1_seq_disp_payload->transfer_char,
11194 vc1_seq_disp_payload->matrix_coeffs,
11195 color_space,aspects);
11196 set_color_aspects_only = true;
11197 prepare_color_aspects_metadata(vc1_seq_disp_payload->color_primaries,
11198 1,
11199 vc1_seq_disp_payload->transfer_char,
11200 vc1_seq_disp_payload->matrix_coeffs,
11201 color_mdata);
11202 }
11203 }
11204 break;
11205 case V4L2_PIX_FMT_VP8:
11206 {
11207 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
11208 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
11209 set_color_aspects_only = false;
11210 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
11211 * to understand this code */
11212
11213 if (vpx_color_space_payload->color_space == 0) {
11214 *color_space = ITU_R_601;
11215 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
11216 aspects->mRange = ColorAspects::RangeLimited;
11217 } else {
11218 DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
11219 break;
11220 }
11221 }
11222 break;
11223 case V4L2_PIX_FMT_VP9:
11224 {
11225 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
11226 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
11227 set_color_aspects_only = false;
11228 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
11229 * to understand this code */
11230
11231 switch(vpx_color_space_payload->color_space) {
11232 case MSM_VIDC_CS_BT_601:
11233 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11234 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11235 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
11236 aspects->mRange = m_client_color_space.sAspects.mRange;
11237 break;
11238 case MSM_VIDC_CS_BT_709:
11239 *color_space = ITU_R_709;
11240 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11241 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11242 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
11243 aspects->mRange = m_client_color_space.sAspects.mRange;
11244 break;
11245 case MSM_VIDC_CS_SMPTE_170:
11246 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11247 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11248 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11249 aspects->mRange = m_client_color_space.sAspects.mRange;
11250 break;
11251 case MSM_VIDC_CS_SMPTE_240:
11252 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
11253 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
11254 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
11255 aspects->mRange = m_client_color_space.sAspects.mRange;
11256 break;
11257 case MSM_VIDC_CS_BT_2020:
11258 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
11259 aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
11260 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
11261 aspects->mRange = m_client_color_space.sAspects.mRange;
11262 break;
11263 case MSM_VIDC_CS_RESERVED:
11264 aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
11265 aspects->mTransfer = ColorAspects::TransferOther;
11266 aspects->mPrimaries = ColorAspects::PrimariesOther;
11267 aspects->mRange = m_client_color_space.sAspects.mRange;
11268 break;
11269 case MSM_VIDC_CS_RGB:
11270 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11271 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11272 aspects->mPrimaries = ColorAspects::PrimariesOther;
11273 aspects->mRange = m_client_color_space.sAspects.mRange;
11274 break;
11275 default:
11276 break;
11277 }
11278 }
11279 break;
11280 default:
11281 break;
11282 }
11283
11284 print_debug_color_aspects(aspects, "Bitstream");
11285
11286 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
11287 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
11288 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
11289 m_internal_color_space.sAspects.mRange != aspects->mRange) {
11290 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
11291
11292 m_color_mdata.colorPrimaries = color_mdata->colorPrimaries;
11293 m_color_mdata.range = color_mdata->range;
11294 m_color_mdata.transfer = color_mdata->transfer;
11295 m_color_mdata.matrixCoefficients = color_mdata->matrixCoefficients;
11296
11297 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
11298 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
11299 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
11300
11301 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11302 OMX_QTIIndexConfigDescribeColorAspects,
11303 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11304 return true;
11305 }
11306 return false;
11307 }
11308
set_colorspace_in_handle(ColorSpace_t color_space,unsigned int buf_index)11309 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
11310 private_handle_t *private_handle = NULL;
11311 if (buf_index < drv_ctx.op_buf.actualcount &&
11312 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11313 native_buffer[buf_index].privatehandle) {
11314 private_handle = native_buffer[buf_index].privatehandle;
11315 }
11316 if (private_handle) {
11317 setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
11318 }
11319 }
11320
print_debug_hdr_color_info(HDRStaticInfo * hdr_info,const char * prefix)11321 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
11322 {
11323 if (!hdr_info->mID) {
11324 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
11325 hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
11326 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
11327 hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
11328 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
11329 hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
11330 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
11331 hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
11332 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
11333 hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
11334 DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
11335 hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
11336 }
11337
11338 }
11339
print_debug_hdr_color_info_mdata(ColorMetaData * color_mdata)11340 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
11341 {
11342 DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
11343 color_mdata->colorPrimaries, color_mdata->range,
11344 color_mdata->transfer, color_mdata->matrixCoefficients);
11345
11346 for(uint8_t i = 0; i < 3; i++) {
11347 for(uint8_t j = 0; j < 2; j++) {
11348 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
11349 }
11350 }
11351
11352 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
11353 color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
11354 color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
11355
11356 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
11357 color_mdata->masteringDisplayInfo.maxDisplayLuminance,
11358 color_mdata->masteringDisplayInfo.minDisplayLuminance);
11359
11360 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
11361 color_mdata->contentLightLevel.maxContentLightLevel,
11362 color_mdata->contentLightLevel.minPicAverageLightLevel);
11363
11364
11365 }
11366
handle_content_light_level_info(void * data,ContentLightLevel * light_level_mdata)11367 bool omx_vdec::handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata)
11368 {
11369 struct msm_vidc_content_light_level_sei_payload *light_level_payload =
11370 (msm_vidc_content_light_level_sei_payload*)(data);
11371
11372 light_level_mdata->lightLevelSEIEnabled = true;
11373 light_level_mdata->maxContentLightLevel = light_level_payload->nMaxContentLight;
11374 light_level_mdata->minPicAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11375
11376 if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
11377 (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
11378 m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
11379 m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11380 return true;
11381 }
11382 return false;
11383 }
11384
handle_mastering_display_color_info(void * data,MasteringDisplay * mastering_display_mdata)11385 bool omx_vdec::handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata)
11386 {
11387 struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
11388 (msm_vidc_mastering_display_colour_sei_payload*)(data);
11389 HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
11390 bool internal_disp_changed_flag = false;
11391
11392 mastering_display_mdata->colorVolumeSEIEnabled = true;
11393 for (uint8_t i = 0; i < 3; i++) {
11394 mastering_display_mdata->primaries.rgbPrimaries[i][0] = mastering_display_payload->nDisplayPrimariesX[i];
11395 mastering_display_mdata->primaries.rgbPrimaries[i][1] = mastering_display_payload->nDisplayPrimariesY[i];
11396 }
11397 mastering_display_mdata->primaries.whitePoint[0] = mastering_display_payload->nWhitePointX;
11398 mastering_display_mdata->primaries.whitePoint[1] = mastering_display_payload->nWhitePointY;
11399 mastering_display_mdata->maxDisplayLuminance = mastering_display_payload->nMaxDisplayMasteringLuminance;
11400 mastering_display_mdata->minDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11401
11402 internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
11403 (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[0]);
11404 internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
11405 (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[1]);
11406 internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
11407 (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[2]);
11408
11409 internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
11410 (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
11411
11412 /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
11413 requires it in cd/m2, so dividing by 10000 and rounding the value after division
11414 */
11415 uint16_t max_display_luminance_cd_m2 =
11416 static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
11417 internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
11418 (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
11419
11420 if (internal_disp_changed_flag) {
11421 hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[0];
11422 hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[0];
11423 hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[1];
11424 hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[1];
11425 hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[2];
11426 hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[2];
11427 hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
11428 hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
11429
11430 hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
11431 hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11432 }
11433
11434 return internal_disp_changed_flag;
11435 }
11436
set_colormetadata_in_handle(ColorMetaData * color_mdata,unsigned int buf_index)11437 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
11438 {
11439 private_handle_t *private_handle = NULL;
11440 if (buf_index < drv_ctx.op_buf.actualcount &&
11441 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11442 native_buffer[buf_index].privatehandle) {
11443 private_handle = native_buffer[buf_index].privatehandle;
11444 }
11445 if (private_handle) {
11446 setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
11447 }
11448 }
11449
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)11450 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11451 {
11452 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
11453 OMX_U8 *pBuffer = NULL;
11454 OMX_U32 num_conceal_MB = 0;
11455 OMX_TICKS time_stamp = 0;
11456 OMX_U32 frame_rate = 0;
11457 unsigned long consumed_len = 0;
11458 OMX_U32 num_MB_in_frame;
11459 OMX_U32 recovery_sei_flags = 1;
11460 int enable = OMX_InterlaceFrameProgressive;
11461 bool internal_hdr_info_changed_flag = false;
11462 bool color_event = false;
11463 ColorMetaData color_mdata;
11464 memset(&color_mdata, 0x0, sizeof(ColorMetaData));
11465 bool set_disp_color_aspects_only = false;
11466 ColorSpace_t color_space = ITU_R_601;
11467
11468 int buf_index = p_buf_hdr - m_out_mem_ptr;
11469 if (buf_index >= drv_ctx.extradata_info.count) {
11470 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
11471 buf_index, drv_ctx.extradata_info.count);
11472 return;
11473 }
11474 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
11475
11476 if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
11477 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
11478 return;
11479 }
11480
11481 if (!drv_ctx.extradata_info.uaddr) {
11482 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
11483 return;
11484 }
11485 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
11486 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
11487 p_extra = NULL;
11488 return;
11489 }
11490 if (!secure_mode) {
11491 pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
11492 PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
11493 if (pBuffer == MAP_FAILED) {
11494 DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno);
11495 return;
11496 }
11497 p_extra = (OMX_OTHER_EXTRADATATYPE *)
11498 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
11499 } else
11500 p_extra = m_other_extradata;
11501
11502 AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
11503 if (m_client_output_extradata_mem_ptr &&
11504 m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
11505 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
11506 }
11507
11508 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
11509
11510 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11511 p_extra = NULL;
11512 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11513 return;
11514 }
11515 m_extradata_info.output_crop_updated = OMX_FALSE;
11516 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
11517 if (data && p_extra) {
11518 while ((consumed_len < drv_ctx.extradata_info.buffer_size)
11519 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
11520 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
11521 DEBUG_PRINT_LOW("Invalid extra data size");
11522 break;
11523 }
11524
11525 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
11526 p_extra = NULL;
11527 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
11528 return;
11529 }
11530
11531 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
11532 switch ((unsigned long)data->eType) {
11533 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
11534 struct msm_vidc_interlace_payload *payload;
11535 OMX_U32 interlace_color_format;
11536 payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
11537 if (payload) {
11538 enable = OMX_InterlaceFrameProgressive;
11539 switch (payload->format) {
11540 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
11541 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11542 break;
11543 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
11544 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11545 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
11546 break;
11547 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
11548 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11549 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11550 break;
11551 default:
11552 DEBUG_PRINT_LOW("default case - set to progressive");
11553 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11554 }
11555 switch (payload->color_format) {
11556 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
11557 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11558 break;
11559 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
11560 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11561 break;
11562 default:
11563 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11564 DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
11565 }
11566 }
11567
11568 if (m_enable_android_native_buffers) {
11569 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
11570 payload->format, interlace_color_format ,enable,
11571 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
11572
11573 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11574 PP_PARAM_INTERLACED, (void*)&enable);
11575
11576 if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
11577 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11578 LINEAR_FORMAT, (void*)&interlace_color_format);
11579 } else if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11580 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11581 LINEAR_FORMAT, NULL);
11582 }
11583 }
11584 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
11585 append_interlace_extradata(p_extra, payload->format);
11586 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11587 if (p_client_extra) {
11588 append_interlace_extradata(p_client_extra, payload->format);
11589 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
11590 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11591 }
11592 }
11593 break;
11594 case MSM_VIDC_EXTRADATA_FRAME_RATE:
11595 struct msm_vidc_framerate_payload *frame_rate_payload;
11596 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
11597 frame_rate = frame_rate_payload->frame_rate;
11598 break;
11599 case MSM_VIDC_EXTRADATA_TIMESTAMP:
11600 struct msm_vidc_ts_payload *time_stamp_payload;
11601 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
11602 time_stamp = time_stamp_payload->timestamp_lo;
11603 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
11604 p_buf_hdr->nTimeStamp = time_stamp;
11605 break;
11606 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
11607 struct msm_vidc_concealmb_payload *conceal_mb_payload;
11608 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
11609 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11610 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11611 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
11612 break;
11613 case MSM_VIDC_EXTRADATA_INDEX:
11614 int *etype;
11615 etype = (int *)(void *)data->data;
11616 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
11617 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
11618 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
11619 if (aspect_ratio_payload) {
11620 ((struct vdec_output_frameinfo *)
11621 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
11622 ((struct vdec_output_frameinfo *)
11623 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
11624 }
11625 } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
11626 struct msm_vidc_output_crop_payload *output_crop_payload;
11627 output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
11628 if (output_crop_payload) {
11629 m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
11630 m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
11631 m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
11632 m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
11633 m_extradata_info.output_width = output_crop_payload->width;
11634 m_extradata_info.output_height = output_crop_payload->height;
11635 m_extradata_info.output_crop_updated = OMX_TRUE;
11636 }
11637 }
11638 break;
11639 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
11640 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
11641 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
11642 recovery_sei_flags = recovery_sei_payload->flags;
11643 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
11644 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
11645 DEBUG_PRINT_HIGH("***************************************************");
11646 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
11647 DEBUG_PRINT_HIGH("***************************************************");
11648 }
11649 break;
11650 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
11651 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
11652 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
11653 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
11654 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
11655 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
11656 return;
11657 }
11658 break;
11659 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
11660 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
11661 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
11662 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
11663 color_event = handle_color_space_info((void *)data->data, &color_space, &color_mdata, set_disp_color_aspects_only);
11664 break;
11665 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
11666 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
11667 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
11668 switch (s3d_frame_packing_payload->fpa_type) {
11669 case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
11670 if (s3d_frame_packing_payload->content_interprtation_type == 1)
11671 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
11672 else if (s3d_frame_packing_payload->content_interprtation_type == 2)
11673 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
11674 else {
11675 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
11676 stereo_output_mode = HAL_NO_3D;
11677 }
11678 break;
11679 case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
11680 stereo_output_mode = HAL_3D_TOP_BOTTOM;
11681 break;
11682 default:
11683 DEBUG_PRINT_ERROR("Unsupported framepacking type");
11684 stereo_output_mode = HAL_NO_3D;
11685 }
11686 DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
11687 s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
11688 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
11689 append_framepack_extradata(p_extra, s3d_frame_packing_payload);
11690 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11691 if (p_client_extra) {
11692 append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
11693 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11694 }
11695 }
11696 break;
11697 case MSM_VIDC_EXTRADATA_FRAME_QP:
11698 struct msm_vidc_frame_qp_payload *qp_payload;
11699 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
11700 if (client_extradata & OMX_QP_EXTRADATA) {
11701 append_qp_extradata(p_extra, qp_payload);
11702 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11703 if (p_client_extra) {
11704 append_qp_extradata(p_client_extra, qp_payload);
11705 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11706 }
11707 }
11708 break;
11709 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
11710 struct msm_vidc_frame_bits_info_payload *bits_info_payload;
11711 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
11712 if (client_extradata & OMX_BITSINFO_EXTRADATA) {
11713 append_bitsinfo_extradata(p_extra, bits_info_payload);
11714 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11715 if (p_client_extra) {
11716 append_bitsinfo_extradata(p_client_extra, bits_info_payload);
11717 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11718 }
11719 }
11720 break;
11721 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
11722 if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
11723 append_user_extradata(p_extra, data);
11724 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11725 if (p_client_extra) {
11726 append_user_extradata(p_client_extra, data);
11727 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11728 }
11729 }
11730 break;
11731 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
11732 struct msm_vidc_vqzip_sei_payload *vqzip_payload;
11733 vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
11734 if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
11735 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11736 append_vqzip_extradata(p_extra, vqzip_payload);
11737 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11738 if (p_client_extra) {
11739 append_vqzip_extradata(p_client_extra, vqzip_payload);
11740 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11741 }
11742 }
11743 break;
11744 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
11745
11746 internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data,
11747 &(color_mdata.contentLightLevel));
11748 break;
11749 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
11750 internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data,
11751 &(color_mdata.masteringDisplayInfo));
11752 break;
11753 default:
11754 DEBUG_PRINT_LOW("Unrecognized extradata");
11755 goto unrecognized_extradata;
11756 }
11757 consumed_len += data->nSize;
11758 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
11759 }
11760 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
11761 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11762 append_frame_info_extradata(p_extra,
11763 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11764 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11765 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11766 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11767 if (p_client_extra) {
11768 append_frame_info_extradata(p_client_extra,
11769 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11770 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11771 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11772 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11773 }
11774 }
11775 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
11776 append_frame_dimension_extradata(p_extra);
11777 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
11778 if (p_client_extra) {
11779 append_frame_dimension_extradata(p_client_extra);
11780 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11781 }
11782 }
11783
11784 if(internal_hdr_info_changed_flag) {
11785 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
11786 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
11787 memcpy(&m_color_mdata, &color_mdata, sizeof(ColorMetaData));
11788 auto_lock lock(m_hdr_info_client_lock);
11789 m_change_client_hdr_info = true;
11790 if(!color_event) {
11791 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
11792 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11793 OMX_QTIIndexConfigDescribeHDRColorInfo,
11794 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11795 }
11796 }
11797
11798 if (m_enable_android_native_buffers) {
11799 if (set_disp_color_aspects_only) {
11800 print_debug_hdr_color_info_mdata(&m_color_mdata);
11801 set_colormetadata_in_handle(&m_color_mdata, buf_index);
11802 } else {
11803 DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
11804 set_colorspace_in_handle(color_space, buf_index);
11805 }
11806 }
11807
11808 }
11809 unrecognized_extradata:
11810 if (client_extradata && p_extra) {
11811 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11812 append_terminator_extradata(p_extra);
11813 if (p_client_extra) {
11814 append_terminator_extradata(p_client_extra);
11815 }
11816 }
11817 if (secure_mode && p_extradata && m_other_extradata) {
11818 struct vdec_output_frameinfo *ptr_extradatabuff = NULL;
11819 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
11820 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
11821 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
11822 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
11823 ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd;
11824 ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size;
11825 ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size;
11826 }
11827 return;
11828 }
11829
enable_extradata(OMX_U64 requested_extradata,bool is_internal,bool enable)11830 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
11831 bool is_internal, bool enable)
11832 {
11833 OMX_ERRORTYPE ret = OMX_ErrorNone;
11834 struct v4l2_control control;
11835 if (m_state != OMX_StateLoaded) {
11836 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
11837 return OMX_ErrorIncorrectStateOperation;
11838 }
11839 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
11840 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
11841
11842 if (!is_internal) {
11843 if (enable)
11844 client_extradata |= requested_extradata;
11845 else
11846 client_extradata = client_extradata & ~requested_extradata;
11847 }
11848
11849 if (enable) {
11850 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
11851 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11852 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
11853 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11854 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
11855 " Quality of interlaced clips might be impacted.");
11856 }
11857 }
11858 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
11859 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11860 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
11861 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11862 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
11863 }
11864 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11865 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
11866 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11867 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
11868 }
11869 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11870 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
11871 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11872 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
11873 }
11874 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11875 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
11876 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11877 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11878 }
11879 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11880 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
11881 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11882 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11883 }
11884 if (output_capability == V4L2_PIX_FMT_MPEG2) {
11885 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11886 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11887 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11888 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11889 }
11890 }
11891 }
11892 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
11893 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11894 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
11895 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11896 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
11897 }
11898 }
11899 if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
11900 if (output_capability == V4L2_PIX_FMT_H264) {
11901 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
11902 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11903 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
11904 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11905 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
11906 }
11907 } else {
11908 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
11909 }
11910 }
11911 if (requested_extradata & OMX_QP_EXTRADATA) {
11912 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11913 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11914 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11915 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11916 }
11917 }
11918 if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
11919 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11920 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
11921 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11922 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
11923 }
11924 }
11925 if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
11926 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11927 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
11928 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11929 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
11930 }
11931 }
11932 if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
11933 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11934 control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
11935 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11936 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
11937 }
11938 client_extradata |= OMX_VQZIPSEI_EXTRADATA;
11939
11940 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11941 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11942 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11943 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11944 }
11945 client_extradata |= OMX_QP_EXTRADATA;
11946 }
11947 if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11948 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11949 control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
11950 DEBUG_PRINT_LOW("Enable output crop extra data");
11951 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11952 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11953 }
11954 }
11955 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
11956 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11957 switch(output_capability) {
11958 case V4L2_PIX_FMT_H264:
11959 case V4L2_PIX_FMT_HEVC:
11960 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
11961 break;
11962 case CODEC_TYPE_MPEG2:
11963 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11964 break;
11965 case V4L2_PIX_FMT_VP8:
11966 case V4L2_PIX_FMT_VP9:
11967 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
11968 break;
11969 case V4L2_PIX_FMT_VC1_ANNEX_G:
11970 case V4L2_PIX_FMT_VC1_ANNEX_L:
11971 control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
11972 break;
11973 default:
11974 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
11975 return ret;
11976 }
11977
11978 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11979 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
11980 }
11981 }
11982 if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
11983 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11984 if (output_capability == V4L2_PIX_FMT_H264 ||
11985 output_capability == V4L2_PIX_FMT_HEVC) {
11986 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
11987 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11988 DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
11989 }
11990 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
11991 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11992 DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
11993 }
11994 }
11995 }
11996 }
11997 ret = get_buffer_req(&drv_ctx.op_buf);
11998 return ret;
11999 }
12000
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)12001 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12002 {
12003 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
12004 OMX_U8 *data_ptr = extra->data, data = 0;
12005 while (byte_count < extra->nDataSize) {
12006 data = *data_ptr;
12007 while (data) {
12008 num_MB += (data&0x01);
12009 data >>= 1;
12010 }
12011 data_ptr++;
12012 byte_count++;
12013 }
12014 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
12015 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
12016 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
12017 }
12018
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)12019 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12020 {
12021 if (!m_debug_extradata || !extra)
12022 return;
12023
12024
12025 DEBUG_PRINT_HIGH(
12026 "============== Extra Data ==============\n"
12027 " Size: %u\n"
12028 " Version: %u\n"
12029 " PortIndex: %u\n"
12030 " Type: %x\n"
12031 " DataSize: %u",
12032 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
12033 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
12034
12035 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
12036 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
12037 DEBUG_PRINT_HIGH(
12038 "------ Interlace Format ------\n"
12039 " Size: %u\n"
12040 " Version: %u\n"
12041 " PortIndex: %u\n"
12042 " Is Interlace Format: %d\n"
12043 " Interlace Formats: %u\n"
12044 "=========== End of Interlace ===========",
12045 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
12046 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
12047 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
12048 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
12049
12050 DEBUG_PRINT_HIGH(
12051 "-------- Frame Format --------\n"
12052 " Picture Type: %d\n"
12053 " Interlace Type: %d\n"
12054 " Pan Scan Total Frame Num: %u\n"
12055 " Concealed Macro Blocks: %u\n"
12056 " Recovery SEI Flag: %u\n"
12057 " frame rate: %u\n"
12058 " Time Stamp: %llu\n"
12059 " Aspect Ratio X: %u\n"
12060 " Aspect Ratio Y: %u",
12061 fminfo->ePicType,
12062 fminfo->interlaceType,
12063 (unsigned int)fminfo->panScan.numWindows,
12064 (unsigned int)fminfo->nConcealedMacroblocks,
12065 (unsigned int)fminfo->nRecoverySeiFlag,
12066 (unsigned int)fminfo->nFrameRate,
12067 fminfo->nTimeStamp,
12068 (unsigned int)fminfo->aspectRatio.aspectRatioX,
12069 (unsigned int)fminfo->aspectRatio.aspectRatioY);
12070
12071 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
12072 DEBUG_PRINT_HIGH(
12073 "------------------------------"
12074 " Pan Scan Frame Num: %u\n"
12075 " Rectangle x: %d\n"
12076 " Rectangle y: %d\n"
12077 " Rectangle dx: %d\n"
12078 " Rectangle dy: %d",
12079 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
12080 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
12081 }
12082
12083 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
12084 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
12085 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12086 DEBUG_PRINT_HIGH(
12087 "------------------ Framepack Format ----------\n"
12088 " id: %u \n"
12089 " cancel_flag: %u \n"
12090 " type: %u \n"
12091 " quincunx_sampling_flagFormat: %u \n"
12092 " content_interpretation_type: %u \n"
12093 " spatial_flipping_flag: %u \n"
12094 " frame0_flipped_flag: %u \n"
12095 " field_views_flag: %u \n"
12096 " current_frame_is_frame0_flag: %u \n"
12097 " frame0_self_contained_flag: %u \n"
12098 " frame1_self_contained_flag: %u \n"
12099 " frame0_grid_position_x: %u \n"
12100 " frame0_grid_position_y: %u \n"
12101 " frame1_grid_position_x: %u \n"
12102 " frame1_grid_position_y: %u \n"
12103 " reserved_byte: %u \n"
12104 " repetition_period: %u \n"
12105 " extension_flag: %u \n"
12106 "================== End of Framepack ===========",
12107 (unsigned int)framepack->id,
12108 (unsigned int)framepack->cancel_flag,
12109 (unsigned int)framepack->type,
12110 (unsigned int)framepack->quincunx_sampling_flag,
12111 (unsigned int)framepack->content_interpretation_type,
12112 (unsigned int)framepack->spatial_flipping_flag,
12113 (unsigned int)framepack->frame0_flipped_flag,
12114 (unsigned int)framepack->field_views_flag,
12115 (unsigned int)framepack->current_frame_is_frame0_flag,
12116 (unsigned int)framepack->frame0_self_contained_flag,
12117 (unsigned int)framepack->frame1_self_contained_flag,
12118 (unsigned int)framepack->frame0_grid_position_x,
12119 (unsigned int)framepack->frame0_grid_position_y,
12120 (unsigned int)framepack->frame1_grid_position_x,
12121 (unsigned int)framepack->frame1_grid_position_y,
12122 (unsigned int)framepack->reserved_byte,
12123 (unsigned int)framepack->repetition_period,
12124 (unsigned int)framepack->extension_flag);
12125 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
12126 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12127 DEBUG_PRINT_HIGH(
12128 "---- QP (Frame quantization parameter) ----\n"
12129 " Frame QP: %u \n"
12130 "================ End of QP ================\n",
12131 (unsigned int)qp->nQP);
12132 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
12133 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
12134 DEBUG_PRINT_HIGH(
12135 "--------- Input bits information --------\n"
12136 " Header bits: %u \n"
12137 " Frame bits: %u \n"
12138 "===== End of Input bits information =====\n",
12139 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
12140 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
12141 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
12142 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
12143 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
12144 OMX_U32 i = 0;
12145 DEBUG_PRINT_HIGH(
12146 "-------------- Userdata -------------\n"
12147 " Stream userdata type: %u\n"
12148 " userdata size: %u\n"
12149 " STREAM_USERDATA:",
12150 (unsigned int)userdata->type, (unsigned int)userdata_size);
12151 for (i = 0; i < userdata_size; i+=4) {
12152 DEBUG_PRINT_HIGH(" %x %x %x %x",
12153 data_ptr[i], data_ptr[i+1],
12154 data_ptr[i+2], data_ptr[i+3]);
12155 }
12156 DEBUG_PRINT_HIGH(
12157 "=========== End of Userdata ===========");
12158 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
12159 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
12160 DEBUG_PRINT_HIGH(
12161 "-------------- VQZip -------------\n"
12162 " Size: %u\n",
12163 (unsigned int)vq->nSize);
12164 DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
12165 } else if (extra->eType == OMX_ExtraDataNone) {
12166 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
12167 } else {
12168 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
12169 }
12170 }
12171
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)12172 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12173 OMX_U32 interlaced_format_type)
12174 {
12175 OMX_STREAMINTERLACEFORMAT *interlace_format;
12176
12177 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
12178 return;
12179 }
12180 if (!extra) {
12181 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
12182 return;
12183 }
12184 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
12185 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12186 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12187 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
12188 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12189 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
12190 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12191 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
12192 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12193
12194 if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
12195 interlace_format->bInterlaceFormat = OMX_FALSE;
12196 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12197 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12198 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
12199 interlace_format->bInterlaceFormat = OMX_TRUE;
12200 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
12201 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
12202 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
12203 interlace_format->bInterlaceFormat = OMX_TRUE;
12204 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
12205 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
12206 } else {
12207 //default case - set to progressive
12208 interlace_format->bInterlaceFormat = OMX_FALSE;
12209 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12210 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12211 }
12212 print_debug_extradata(extra);
12213 }
12214
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)12215 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12216 {
12217 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
12218 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
12219 return;
12220 }
12221 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
12222 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12223 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12224 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
12225 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
12226 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
12227 frame_dimension->nDecWidth = rectangle.nLeft;
12228 frame_dimension->nDecHeight = rectangle.nTop;
12229 frame_dimension->nActualWidth = rectangle.nWidth;
12230 frame_dimension->nActualHeight = rectangle.nHeight;
12231 }
12232
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)12233 void omx_vdec::fill_aspect_ratio_info(
12234 struct vdec_aspectratioinfo *aspect_ratio_info,
12235 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
12236 {
12237 m_extradata = frame_info;
12238 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
12239 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
12240 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
12241 (unsigned int)m_extradata->aspectRatio.aspectRatioY);
12242 }
12243
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 recovery_sei_flag,OMX_U32 picture_type,OMX_U32 frame_rate,OMX_TICKS time_stamp,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)12244 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12245 OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
12246 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
12247 struct vdec_aspectratioinfo *aspect_ratio_info)
12248 {
12249 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
12250 struct msm_vidc_panscan_window *panscan_window;
12251 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
12252 return;
12253 }
12254 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
12255 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12256 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12257 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
12258 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
12259 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
12260 switch (picture_type) {
12261 case PICTURE_TYPE_I:
12262 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
12263 break;
12264 case PICTURE_TYPE_P:
12265 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
12266 break;
12267 case PICTURE_TYPE_B:
12268 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
12269 break;
12270 default:
12271 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
12272 }
12273 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
12274 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
12275 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
12276 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
12277 else
12278 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
12279 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
12280 frame_info->nConcealedMacroblocks = num_conceal_mb;
12281 frame_info->nRecoverySeiFlag = recovery_sei_flag;
12282 frame_info->nFrameRate = frame_rate;
12283 frame_info->nTimeStamp = time_stamp;
12284 frame_info->panScan.numWindows = 0;
12285 if (output_capability == V4L2_PIX_FMT_MPEG2) {
12286 if (m_disp_hor_size && m_disp_vert_size) {
12287 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
12288 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
12289 } else {
12290 frame_info->displayAspectRatio.displayHorizontalSize = 0;
12291 frame_info->displayAspectRatio.displayVerticalSize = 0;
12292 }
12293 }
12294
12295 if (panscan_payload) {
12296 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
12297 panscan_window = &panscan_payload->wnd[0];
12298 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
12299 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
12300 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
12301 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
12302 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
12303 panscan_window++;
12304 }
12305 }
12306 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
12307 print_debug_extradata(extra);
12308 }
12309
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)12310 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12311 {
12312 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
12313 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
12314 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12315 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12316 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
12317 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
12318 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
12319 *portDefn = m_port_def;
12320 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
12321 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
12322 (unsigned int)portDefn->format.video.nFrameWidth,
12323 (unsigned int)portDefn->format.video.nStride,
12324 (unsigned int)portDefn->format.video.nSliceHeight);
12325 }
12326
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)12327 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12328 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
12329 {
12330 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
12331 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
12332 DEBUG_PRINT_ERROR("frame packing size mismatch");
12333 return;
12334 }
12335 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
12336 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12337 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12338 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
12339 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12340 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12341 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12342 framepack->nVersion.nVersion = OMX_SPEC_VERSION;
12343 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12344 memcpy(&framepack->id, s3d_frame_packing_payload,
12345 sizeof(struct msm_vidc_s3d_frame_packing_payload));
12346 memcpy(&m_frame_pack_arrangement, framepack,
12347 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
12348 print_debug_extradata(extra);
12349 }
12350
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)12351 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12352 struct msm_vidc_frame_qp_payload *qp_payload)
12353 {
12354 OMX_QCOM_EXTRADATA_QP * qp = NULL;
12355 if (!qp_payload) {
12356 DEBUG_PRINT_ERROR("QP payload is NULL");
12357 return;
12358 }
12359 extra->nSize = OMX_QP_EXTRADATA_SIZE;
12360 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12361 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12362 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
12363 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
12364 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12365 qp->nQP = qp_payload->frame_qp;
12366 print_debug_extradata(extra);
12367 }
12368
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)12369 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12370 struct msm_vidc_frame_bits_info_payload *bits_payload)
12371 {
12372 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
12373 if (!bits_payload) {
12374 DEBUG_PRINT_ERROR("bits info payload is NULL");
12375 return;
12376 }
12377 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
12378 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12379 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12380 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
12381 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
12382 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
12383 bits->frame_bits = bits_payload->frame_bits;
12384 bits->header_bits = bits_payload->header_bits;
12385 print_debug_extradata(extra);
12386 }
12387
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)12388 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12389 OMX_OTHER_EXTRADATATYPE *p_user)
12390 {
12391 int userdata_size = 0;
12392 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
12393 userdata_payload =
12394 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
12395 userdata_size = p_user->nDataSize;
12396 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
12397 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12398 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12399 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
12400 extra->nDataSize = userdata_size;
12401 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
12402 memcpy(extra->data, p_user->data, extra->nDataSize);
12403 print_debug_extradata(extra);
12404 }
12405
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)12406 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12407 {
12408 if (!client_extradata) {
12409 return;
12410 }
12411 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
12412 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12413 extra->eType = OMX_ExtraDataNone;
12414 extra->nDataSize = 0;
12415 extra->data[0] = 0;
12416
12417 print_debug_extradata(extra);
12418 }
12419
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)12420 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12421 struct msm_vidc_vqzip_sei_payload *vqzip_payload)
12422 {
12423 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
12424
12425 extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
12426 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12427 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12428 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
12429 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
12430
12431 vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
12432 vq->nSize = vqzip_payload->size;
12433 memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
12434
12435 print_debug_extradata(extra);
12436 }
12437
allocate_desc_buffer(OMX_U32 index)12438 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
12439 {
12440 OMX_ERRORTYPE eRet = OMX_ErrorNone;
12441 if (index >= drv_ctx.ip_buf.actualcount) {
12442 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
12443 return OMX_ErrorInsufficientResources;
12444 }
12445 if (m_desc_buffer_ptr == NULL) {
12446 m_desc_buffer_ptr = (desc_buffer_hdr*) \
12447 calloc( (sizeof(desc_buffer_hdr)),
12448 drv_ctx.ip_buf.actualcount);
12449 if (m_desc_buffer_ptr == NULL) {
12450 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
12451 return OMX_ErrorInsufficientResources;
12452 }
12453 }
12454
12455 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
12456 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
12457 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
12458 return OMX_ErrorInsufficientResources;
12459 }
12460
12461 return eRet;
12462 }
12463
insert_demux_addr_offset(OMX_U32 address_offset)12464 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
12465 {
12466 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
12467 if (m_demux_entries < 8192) {
12468 m_demux_offsets[m_demux_entries++] = address_offset;
12469 }
12470 return;
12471 }
12472
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)12473 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
12474 {
12475 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
12476 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
12477 OMX_U32 index = 0;
12478
12479 m_demux_entries = 0;
12480
12481 while (index < bytes_to_parse) {
12482 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12483 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
12484 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12485 (buf[index+2] == 0x01)) ) {
12486 //Found start code, insert address offset
12487 insert_demux_addr_offset(index);
12488 if (buf[index+2] == 0x01) // 3 byte start code
12489 index += 3;
12490 else //4 byte start code
12491 index += 4;
12492 } else
12493 index++;
12494 }
12495 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
12496 return;
12497 }
12498
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)12499 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
12500 {
12501 //fix this, handle 3 byte start code, vc1 terminator entry
12502 OMX_U8 *p_demux_data = NULL;
12503 OMX_U32 desc_data = 0;
12504 OMX_U32 start_addr = 0;
12505 OMX_U32 nal_size = 0;
12506 OMX_U32 suffix_byte = 0;
12507 OMX_U32 demux_index = 0;
12508 OMX_U32 buffer_index = 0;
12509
12510 if (m_desc_buffer_ptr == NULL) {
12511 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
12512 return OMX_ErrorBadParameter;
12513 }
12514
12515 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
12516 if (buffer_index > drv_ctx.ip_buf.actualcount) {
12517 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
12518 return OMX_ErrorBadParameter;
12519 }
12520
12521 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
12522
12523 if ( ((OMX_U8*)p_demux_data == NULL) ||
12524 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
12525 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
12526 return OMX_ErrorBadParameter;
12527 } else {
12528 for (; demux_index < m_demux_entries; demux_index++) {
12529 desc_data = 0;
12530 start_addr = m_demux_offsets[demux_index];
12531 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
12532 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
12533 } else {
12534 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
12535 }
12536 if (demux_index < (m_demux_entries - 1)) {
12537 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
12538 } else {
12539 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
12540 }
12541 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
12542 (unsigned int)start_addr,
12543 (unsigned int)suffix_byte,
12544 (unsigned int)nal_size,
12545 (unsigned int)demux_index);
12546 desc_data = (start_addr >> 3) << 1;
12547 desc_data |= (start_addr & 7) << 21;
12548 desc_data |= suffix_byte << 24;
12549
12550 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12551 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
12552 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12553 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12554
12555 p_demux_data += 16;
12556 }
12557 if (codec_type_parse == CODEC_TYPE_VC1) {
12558 DEBUG_PRINT_LOW("VC1 terminator entry");
12559 desc_data = 0;
12560 desc_data = 0x82 << 24;
12561 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12562 memset(p_demux_data + 4, 0, sizeof(OMX_U32));
12563 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12564 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12565 p_demux_data += 16;
12566 m_demux_entries++;
12567 }
12568 //Add zero word to indicate end of descriptors
12569 memset(p_demux_data, 0, sizeof(OMX_U32));
12570
12571 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
12572 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
12573 }
12574 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
12575 m_demux_entries = 0;
12576 DEBUG_PRINT_LOW("Demux table complete!");
12577 return OMX_ErrorNone;
12578 }
12579
request_perf_level(enum vidc_perf_level perf_level)12580 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
12581 {
12582 struct v4l2_control control;
12583 char property_value[PROPERTY_VALUE_MAX] = {0};
12584
12585 property_get("vendor.vidc.debug.turbo", property_value, "0");
12586 memset(&control, 0, sizeof(v4l2_control));
12587 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
12588 switch (perf_level) {
12589 case VIDC_NOMINAL:
12590 if (atoi(property_value))
12591 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12592 else
12593 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
12594 break;
12595 case VIDC_TURBO:
12596 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
12597 break;
12598 default:
12599 DEBUG_PRINT_ERROR("Requested PERF level not supported");
12600 break;
12601 }
12602 if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
12603 return;
12604
12605 DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
12606 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
12607 current_perf_level = control.value;
12608 } else {
12609 DEBUG_PRINT_ERROR("Failed to set PERF level");
12610 }
12611 }
12612
allocate_color_convert_buf()12613 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
12614 {
12615 enabled = false;
12616 omx = NULL;
12617 init_members();
12618 ColorFormat = OMX_COLOR_FormatMax;
12619 dest_format = YCbCr420P;
12620 m_c2d_width = 0;
12621 m_c2d_height = 0;
12622 }
12623
set_vdec_client(void * client)12624 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
12625 {
12626 omx = reinterpret_cast<omx_vdec*>(client);
12627 }
12628
init_members()12629 void omx_vdec::allocate_color_convert_buf::init_members()
12630 {
12631 allocated_count = 0;
12632 buffer_size_req = 0;
12633 buffer_alignment_req = 0;
12634 m_c2d_width = m_c2d_height = 0;
12635 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
12636 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
12637 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
12638 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
12639 #ifdef USE_ION
12640 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
12641 #endif
12642 for (int i = 0; i < MAX_COUNT; i++)
12643 pmem_fd[i] = -1;
12644 }
12645
~allocate_color_convert_buf()12646 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
12647 {
12648 c2d.destroy();
12649 }
12650
update_buffer_req()12651 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
12652 {
12653 bool status = true;
12654 unsigned int src_size = 0, destination_size = 0;
12655 unsigned int height, width;
12656 struct v4l2_format fmt;
12657 OMX_COLOR_FORMATTYPE drv_color_format;
12658
12659 if (!omx) {
12660 DEBUG_PRINT_ERROR("Invalid client in color convert");
12661 return false;
12662 }
12663 if (!enabled) {
12664 DEBUG_PRINT_HIGH("No color conversion required");
12665 return status;
12666 }
12667 pthread_mutex_lock(&omx->c_lock);
12668
12669 memset(&fmt, 0x0, sizeof(struct v4l2_format));
12670 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
12671 fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
12672 ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
12673 width = fmt.fmt.pix_mp.width;
12674 height = fmt.fmt.pix_mp.height;
12675
12676 bool resolution_upgrade = (height > m_c2d_height ||
12677 width > m_c2d_width);
12678 if (resolution_upgrade) {
12679 // resolution upgraded ? ensure we are yet to allocate;
12680 // failing which, c2d buffers will never be reallocated and bad things will happen
12681 if (allocated_count > 0) {
12682 DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
12683 allocated_count);
12684 status = false;
12685 goto fail_update_buf_req;
12686 }
12687 }
12688
12689 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
12690 ColorFormat != OMX_COLOR_FormatYUV420Planar) {
12691 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
12692 status = false;
12693 goto fail_update_buf_req;
12694 }
12695 c2d.close();
12696 status = c2d.open(height,
12697 width,
12698 NV12_128m,dest_format);
12699 if (status) {
12700 status = c2d.get_buffer_size(C2D_INPUT,src_size);
12701 if (status)
12702 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
12703 }
12704 if (status) {
12705 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
12706 !destination_size) {
12707 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
12708 "driver size %u destination size %d",
12709 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
12710 destination_size);
12711 status = false;
12712 c2d.close();
12713 buffer_size_req = 0;
12714 // TODO: make this fatal. Driver is not supposed to quote size
12715 // smaller than what C2D needs !!
12716 } else {
12717 buffer_size_req = destination_size;
12718 m_c2d_height = height;
12719 m_c2d_width = width;
12720 }
12721 }
12722 fail_update_buf_req:
12723 pthread_mutex_unlock(&omx->c_lock);
12724 return status;
12725 }
12726
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)12727 bool omx_vdec::allocate_color_convert_buf::set_color_format(
12728 OMX_COLOR_FORMATTYPE dest_color_format)
12729 {
12730 bool status = true, drv_colorformat_c2d_enable = false;
12731 bool dest_color_format_c2d_enable = false;
12732 OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
12733 if (!omx) {
12734 DEBUG_PRINT_ERROR("Invalid client in color convert");
12735 return false;
12736 }
12737 pthread_mutex_lock(&omx->c_lock);
12738 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
12739 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
12740 drv_color_format = (OMX_COLOR_FORMATTYPE)
12741 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12742 else
12743 drv_color_format = (OMX_COLOR_FORMATTYPE)
12744 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12745 else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
12746 drv_color_format = (OMX_COLOR_FORMATTYPE)
12747 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12748 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
12749 drv_color_format = (OMX_COLOR_FORMATTYPE)
12750 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12751 } else {
12752 DEBUG_PRINT_ERROR("Incorrect color format");
12753 status = false;
12754 }
12755 drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
12756 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12757 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
12758 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12759 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12760 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12761 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12762
12763 dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
12764 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12765 (dest_color_format != (OMX_COLOR_FORMATTYPE)
12766 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12767
12768 if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
12769 DEBUG_PRINT_LOW("Enabling C2D");
12770 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
12771 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
12772 DEBUG_PRINT_ERROR("Unsupported color format for c2d");
12773 status = false;
12774 } else {
12775 ColorFormat = dest_color_format;
12776 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
12777 YCbCr420P : YCbCr420SP;
12778 if (enabled)
12779 c2d.destroy();
12780 enabled = false;
12781 if (!c2d.init()) {
12782 DEBUG_PRINT_ERROR("open failed for c2d");
12783 status = false;
12784 } else
12785 enabled = true;
12786 }
12787 } else {
12788 if (enabled)
12789 c2d.destroy();
12790 enabled = false;
12791 }
12792 pthread_mutex_unlock(&omx->c_lock);
12793 return status;
12794 }
12795
get_il_buf_hdr()12796 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
12797 {
12798 if (!omx) {
12799 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12800 return NULL;
12801 }
12802 if (!enabled)
12803 return omx->m_out_mem_ptr;
12804 return m_out_mem_ptr_client;
12805 }
12806
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12807 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
12808 (OMX_BUFFERHEADERTYPE *bufadd)
12809 {
12810 if (!omx) {
12811 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12812 return NULL;
12813 }
12814 if (!enabled)
12815 return bufadd;
12816
12817 unsigned index = 0;
12818 index = bufadd - omx->m_out_mem_ptr;
12819 if (index < omx->drv_ctx.op_buf.actualcount) {
12820 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12821 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
12822 bool status;
12823 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
12824 pthread_mutex_lock(&omx->c_lock);
12825 cache_clean_buffer(index);
12826 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
12827 omx->drv_ctx.op_buf_map_info[index].base_address, bufadd->pBuffer, pmem_fd[index],
12828 pmem_baseaddress[index], pmem_baseaddress[index]);
12829 if (!status) {
12830 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
12831 m_out_mem_ptr_client[index].nFilledLen = 0;
12832 pthread_mutex_unlock(&omx->c_lock);
12833 return &m_out_mem_ptr_client[index];
12834 } else {
12835 unsigned int filledLen = 0;
12836 c2d.get_output_filled_length(filledLen);
12837 m_out_mem_ptr_client[index].nFilledLen = filledLen;
12838 cache_clean_invalidate_buffer(index);
12839 }
12840 pthread_mutex_unlock(&omx->c_lock);
12841 } else
12842 m_out_mem_ptr_client[index].nFilledLen = 0;
12843 return &m_out_mem_ptr_client[index];
12844 }
12845 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
12846 return NULL;
12847 }
12848
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12849 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
12850 (OMX_BUFFERHEADERTYPE *bufadd)
12851 {
12852 if (!omx) {
12853 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12854 return NULL;
12855 }
12856 if (!enabled)
12857 return bufadd;
12858 unsigned index = 0;
12859 index = bufadd - m_out_mem_ptr_client;
12860 if (index < omx->drv_ctx.op_buf.actualcount) {
12861 return &omx->m_out_mem_ptr[index];
12862 }
12863 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
12864 return NULL;
12865 }
get_buffer_req(unsigned int & buffer_size)12866 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
12867 (unsigned int &buffer_size)
12868 {
12869 bool status = true;
12870 pthread_mutex_lock(&omx->c_lock);
12871 /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
12872 always uses VideoNativeMetadata and OMX receives buffer type as
12873 grallocsource via storeMetaDataInBuffers_l API. The buffer_size
12874 will be communicated to frameworks via IndexParamPortdefinition. */
12875 if (!enabled)
12876 buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
12877 omx->drv_ctx.op_buf.buffer_size;
12878 else {
12879 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
12880 DEBUG_PRINT_ERROR("Get buffer size failed");
12881 status = false;
12882 goto fail_get_buffer_size;
12883 }
12884 }
12885 fail_get_buffer_size:
12886 pthread_mutex_unlock(&omx->c_lock);
12887 return status;
12888 }
12889
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)12890 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
12891 OMX_U32 buffer_size, OMX_U32 actual_count)
12892 {
12893 OMX_U32 expectedSize = is_color_conversion_enabled() ? buffer_size_req : omx->dynamic_buf_mode ?
12894 sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
12895 if (buffer_size < expectedSize) {
12896 DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
12897 buffer_size, expectedSize);
12898 return OMX_ErrorBadParameter;
12899 }
12900 if (actual_count < omx->drv_ctx.op_buf.actualcount) {
12901 DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
12902 actual_count, omx->drv_ctx.op_buf.actualcount);
12903 return OMX_ErrorBadParameter;
12904 }
12905
12906 bool reqs_updated = false;
12907 if (enabled) {
12908 // disallow changing buffer size/count while we have active allocated buffers
12909 if (allocated_count > 0) {
12910 DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
12911 buffer_size_req, buffer_size, allocated_count);
12912 return OMX_ErrorInvalidState;
12913 }
12914
12915 buffer_size_req = buffer_size;
12916 } else {
12917 if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
12918 omx->drv_ctx.op_buf.buffer_size = buffer_size;
12919 reqs_updated = true;
12920 }
12921 }
12922
12923 if (actual_count > omx->drv_ctx.op_buf.actualcount) {
12924 omx->drv_ctx.op_buf.actualcount = actual_count;
12925 reqs_updated = true;
12926 }
12927
12928 if (reqs_updated) {
12929 omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
12930 omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
12931 omx->drv_ctx.extradata_info.buffer_size;
12932 return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
12933 }
12934 return OMX_ErrorNone;
12935 }
12936
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)12937 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
12938 OMX_BUFFERHEADERTYPE *bufhdr)
12939 {
12940 unsigned int index = 0;
12941
12942 if (!enabled)
12943 return omx->free_output_buffer(bufhdr);
12944 if (enabled && omx->is_component_secure())
12945 return OMX_ErrorNone;
12946 if (!allocated_count || !bufhdr) {
12947 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
12948 return OMX_ErrorBadParameter;
12949 }
12950 index = bufhdr - m_out_mem_ptr_client;
12951 if (index >= omx->drv_ctx.op_buf.actualcount) {
12952 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
12953 return OMX_ErrorBadParameter;
12954 }
12955 if (pmem_fd[index] >= 0) {
12956 munmap(pmem_baseaddress[index], buffer_size_req);
12957 close(pmem_fd[index]);
12958 }
12959 pmem_fd[index] = -1;
12960 #ifdef USE_ION
12961 omx->free_ion_memory(&op_buf_ion_info[index]);
12962 #endif
12963 if (allocated_count > 0)
12964 allocated_count--;
12965 else
12966 allocated_count = 0;
12967 if (!allocated_count) {
12968 pthread_mutex_lock(&omx->c_lock);
12969 c2d.close();
12970 init_members();
12971 pthread_mutex_unlock(&omx->c_lock);
12972 }
12973 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
12974 }
12975
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)12976 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
12977 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
12978 {
12979 OMX_ERRORTYPE eRet = OMX_ErrorNone;
12980 if (!enabled) {
12981 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
12982 return eRet;
12983 }
12984 if (enabled && omx->is_component_secure()) {
12985 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
12986 omx->is_component_secure());
12987 return OMX_ErrorUnsupportedSetting;
12988 }
12989 if (!bufferHdr || bytes > buffer_size_req) {
12990 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
12991 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
12992 (unsigned int)buffer_size_req, (unsigned int)bytes);
12993 return OMX_ErrorBadParameter;
12994 }
12995 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
12996 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
12997 return OMX_ErrorInsufficientResources;
12998 }
12999 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
13000 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
13001 port,appData,omx->drv_ctx.op_buf.buffer_size);
13002 if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
13003 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
13004 return eRet;
13005 }
13006 if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
13007 (int)omx->drv_ctx.op_buf.actualcount) {
13008 DEBUG_PRINT_ERROR("Invalid header index %ld",
13009 (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
13010 return OMX_ErrorUndefined;
13011 }
13012 unsigned int i = allocated_count;
13013 #ifdef USE_ION
13014 // Allocate color-conversion buffers as cached to improve software-reading
13015 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
13016 // cache invalidation.
13017 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
13018 buffer_size_req,buffer_alignment_req,
13019 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
13020 ION_FLAG_CACHED);
13021 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
13022 if (op_buf_ion_info[i].ion_device_fd < 0) {
13023 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
13024 return OMX_ErrorInsufficientResources;
13025 }
13026 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
13027 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
13028
13029 if (pmem_baseaddress[i] == MAP_FAILED) {
13030 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
13031 close(pmem_fd[i]);
13032 omx->free_ion_memory(&op_buf_ion_info[i]);
13033 return OMX_ErrorInsufficientResources;
13034 }
13035 #endif
13036 m_pmem_info_client[i].offset = 0;
13037 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
13038 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
13039 m_platform_list_client[i].nEntries = 1;
13040 m_platform_list_client[i].entryList = &m_platform_entry_client[i];
13041 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
13042 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
13043 m_out_mem_ptr_client[i].nFilledLen = 0;
13044 m_out_mem_ptr_client[i].nFlags = 0;
13045 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
13046 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
13047 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
13048 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
13049 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
13050 m_out_mem_ptr_client[i].pAppPrivate = appData;
13051 *bufferHdr = &m_out_mem_ptr_client[i];
13052 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
13053 allocated_count++;
13054 return eRet;
13055 }
13056
is_component_secure()13057 bool omx_vdec::is_component_secure()
13058 {
13059 return secure_mode;
13060 }
13061
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)13062 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
13063 {
13064 bool status = true;
13065 if (!enabled) {
13066 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
13067 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
13068 dest_color_format = (OMX_COLOR_FORMATTYPE)
13069 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
13070 else
13071 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
13072 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
13073 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
13074 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC){
13075 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
13076 } else
13077 status = false;
13078 } else {
13079 if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
13080 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
13081 dest_color_format = ColorFormat;
13082 } else
13083 status = false;
13084 }
13085 return status;
13086 }
13087
cache_ops(unsigned int index,unsigned int cmd)13088 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
13089 unsigned int index, unsigned int cmd)
13090 {
13091 if (!enabled) {
13092 return OMX_ErrorNone;
13093 }
13094
13095 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
13096 DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
13097 return OMX_ErrorBadParameter;
13098 }
13099
13100 struct ion_flush_data flush_data;
13101 struct ion_custom_data custom_data;
13102
13103 memset(&flush_data, 0x0, sizeof(flush_data));
13104 memset(&custom_data, 0x0, sizeof(custom_data));
13105
13106 flush_data.vaddr = pmem_baseaddress[index];
13107 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
13108 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
13109 flush_data.length = buffer_size_req;
13110 custom_data.cmd = cmd;
13111 custom_data.arg = (unsigned long)&flush_data;
13112
13113 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
13114 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
13115 flush_data.fd, flush_data.handle, flush_data.vaddr,
13116 flush_data.length);
13117 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
13118 if (ret < 0) {
13119 DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
13120 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
13121 strerror(errno));
13122 return OMX_ErrorUndefined;
13123 }
13124 return OMX_ErrorNone;
13125 }
13126
buf_ref_add(int nPortIndex)13127 void omx_vdec::buf_ref_add(int nPortIndex)
13128 {
13129 unsigned long i = 0;
13130 bool buf_present = false;
13131 long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
13132 OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
13133
13134 if (!dynamic_buf_mode || !out_dynamic_list) {
13135 return;
13136 }
13137
13138 pthread_mutex_lock(&m_lock);
13139 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13140 //check the buffer fd, offset, uv addr with list contents
13141 //If present increment reference.
13142 if ((out_dynamic_list[i].fd == fd) &&
13143 (out_dynamic_list[i].offset == offset)) {
13144 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
13145 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13146 if (!secure_mode) {
13147 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
13148 }
13149 buf_present = true;
13150 break;
13151 }
13152 }
13153 if (!buf_present) {
13154 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13155 //search for a entry to insert details of the new buffer
13156 if (out_dynamic_list[i].dup_fd < 0) {
13157 out_dynamic_list[i].fd = fd;
13158 out_dynamic_list[i].offset = offset;
13159 out_dynamic_list[i].dup_fd = dup(fd);
13160 out_dynamic_list[i].ref_count++;
13161 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
13162 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13163
13164 if (!secure_mode) {
13165 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
13166 (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
13167 PROT_READ|PROT_WRITE, MAP_SHARED,
13168 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
13169 //mmap returns (void *)-1 on failure and sets error code in errno.
13170 if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
13171 DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
13172 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
13173 break;
13174 }
13175 out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
13176 out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
13177 DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
13178 }
13179 break;
13180 }
13181 }
13182 }
13183 pthread_mutex_unlock(&m_lock);
13184 }
13185
buf_ref_remove()13186 void omx_vdec::buf_ref_remove()
13187 {
13188 unsigned long i = 0;
13189
13190 if (!dynamic_buf_mode || !out_dynamic_list) {
13191 return;
13192 }
13193
13194 pthread_mutex_lock(&m_lock);
13195 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
13196 if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
13197 DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
13198 munmap(out_dynamic_list[i].buffaddr,
13199 out_dynamic_list[i].mapped_size);
13200 }
13201
13202 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
13203 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
13204 close(out_dynamic_list[i].dup_fd);
13205 out_dynamic_list[i].dup_fd = -1;
13206 }
13207 pthread_mutex_unlock(&m_lock);
13208
13209 if (out_dynamic_list) {
13210 free(out_dynamic_list);
13211 out_dynamic_list = NULL;
13212 }
13213 }
13214
13215 #ifdef _MSM8974_
send_codec_config()13216 void omx_vdec::send_codec_config() {
13217 if (codec_config_flag) {
13218 unsigned long p1 = 0; // Parameter - 1
13219 unsigned long p2 = 0; // Parameter - 2
13220 unsigned long ident = 0;
13221 pthread_mutex_lock(&m_lock);
13222 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
13223 while (m_etb_q.m_size) {
13224 m_etb_q.pop_entry(&p1,&p2,&ident);
13225 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
13226 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
13227 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
13228 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
13229 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
13230 omx_report_error();
13231 }
13232 } else {
13233 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
13234 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
13235 }
13236 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
13237 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
13238 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
13239 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
13240 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
13241 omx_report_error ();
13242 }
13243 } else {
13244 pending_input_buffers++;
13245 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
13246 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
13247 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
13248 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
13249 }
13250 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
13251 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
13252 (OMX_BUFFERHEADERTYPE *)p1);
13253 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
13254 }
13255 }
13256 pthread_mutex_unlock(&m_lock);
13257 }
13258 }
13259 #endif
13260
perf_control()13261 omx_vdec::perf_control::perf_control()
13262 {
13263 m_perf_lib = NULL;
13264 m_perf_handle = 0;
13265 m_perf_lock_acquire = NULL;
13266 m_perf_lock_release = NULL;
13267 }
13268
~perf_control()13269 omx_vdec::perf_control::~perf_control()
13270 {
13271 if (m_perf_handle != 0 && m_perf_lock_release) {
13272 DEBUG_PRINT_LOW("NOTE2: release perf lock");
13273 m_perf_lock_release(m_perf_handle);
13274 }
13275 if (m_perf_lib) {
13276 dlclose(m_perf_lib);
13277 }
13278 }
13279
13280 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
13281
13282 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
13283
send_hint_to_mpctl(bool state)13284 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
13285 {
13286 if (load_lib() == false) {
13287 return;
13288 }
13289 m_perf_lock.lock();
13290 /* 0x4401 maps to video decode playback hint
13291 * in perflock, enum number is 44 and state
13292 * being sent on perflock acquire is 01 (true)
13293 */
13294 int arg = 0x4401;
13295
13296 if (state == true) {
13297 mpctl_obj.vid_inst_count++;
13298 } else if (state == false) {
13299 mpctl_obj.vid_inst_count--;
13300 }
13301
13302 if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
13303 mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
13304 mpctl_obj.vid_acquired = true;
13305 DEBUG_PRINT_INFO("Video slvp perflock acquired");
13306 } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
13307 m_perf_lock_release(mpctl_obj.vid_disp_handle);
13308 mpctl_obj.vid_acquired = false;
13309 DEBUG_PRINT_INFO("Video slvp perflock released");
13310 }
13311 m_perf_lock.unlock();
13312 }
13313
request_cores(int frame_duration_us)13314 void omx_vdec::perf_control::request_cores(int frame_duration_us)
13315 {
13316 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
13317 return;
13318 }
13319 bool retVal = load_lib();
13320 if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
13321 int arg = 0x700 /*base value*/ + 2 /*cores*/;
13322 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
13323 if (m_perf_handle) {
13324 DEBUG_PRINT_HIGH("perf lock acquired");
13325 }
13326 }
13327 }
13328
load_lib()13329 bool omx_vdec::perf_control::load_lib()
13330 {
13331 char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
13332 if (m_perf_lib)
13333 return true;
13334
13335 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
13336 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
13337 goto handle_err;
13338 }
13339
13340 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
13341 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
13342 goto handle_err;
13343 } else {
13344 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
13345 if (m_perf_lock_acquire == NULL) {
13346 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
13347 goto handle_err;
13348 }
13349 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
13350 if (m_perf_lock_release == NULL) {
13351 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
13352 goto handle_err;
13353 }
13354 }
13355 return true;
13356
13357 handle_err:
13358 if (m_perf_lib) {
13359 dlclose(m_perf_lib);
13360 }
13361 m_perf_lib = NULL;
13362 return false;
13363 }
13364
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)13365 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
13366 unsigned long nMaxFrameHeight)
13367 {
13368
13369 OMX_ERRORTYPE eRet = OMX_ErrorNone;
13370 int ret = 0;
13371 unsigned long min_res_buf_count = 0;
13372
13373 eRet = enable_smoothstreaming();
13374 if (eRet != OMX_ErrorNone) {
13375 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
13376 return eRet;
13377 }
13378
13379 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
13380 nMaxFrameWidth,
13381 nMaxFrameHeight);
13382 m_smoothstreaming_mode = true;
13383 m_smoothstreaming_width = nMaxFrameWidth;
13384 m_smoothstreaming_height = nMaxFrameHeight;
13385
13386 //Get upper limit buffer count for min supported resolution
13387 struct v4l2_format fmt;
13388 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13389 fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
13390 fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
13391 fmt.fmt.pix_mp.pixelformat = output_capability;
13392
13393 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13394 if (ret) {
13395 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
13396 m_decoder_capability.min_height,
13397 m_decoder_capability.min_width);
13398 return OMX_ErrorUnsupportedSetting;
13399 }
13400
13401 eRet = get_buffer_req(&drv_ctx.op_buf);
13402 if (eRet != OMX_ErrorNone) {
13403 DEBUG_PRINT_ERROR("failed to get_buffer_req");
13404 return eRet;
13405 }
13406
13407 min_res_buf_count = drv_ctx.op_buf.mincount;
13408 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
13409 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
13410
13411 m_extradata_info.output_crop_rect.nLeft = 0;
13412 m_extradata_info.output_crop_rect.nTop = 0;
13413 m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
13414 m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
13415
13416 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
13417 m_smoothstreaming_width, m_smoothstreaming_height);
13418 eRet = is_video_session_supported();
13419 if (eRet != OMX_ErrorNone) {
13420 DEBUG_PRINT_ERROR("video session is not supported");
13421 return eRet;
13422 }
13423
13424 //Get upper limit buffer size for max smooth streaming resolution set
13425 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13426 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
13427 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
13428 fmt.fmt.pix_mp.pixelformat = output_capability;
13429 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13430 if (ret) {
13431 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
13432 return OMX_ErrorUnsupportedSetting;
13433 }
13434
13435 eRet = get_buffer_req(&drv_ctx.op_buf);
13436 if (eRet != OMX_ErrorNone) {
13437 DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
13438 return eRet;
13439 }
13440 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
13441 (unsigned int)drv_ctx.op_buf.buffer_size);
13442
13443 drv_ctx.op_buf.mincount = min_res_buf_count;
13444 drv_ctx.op_buf.actualcount = min_res_buf_count;
13445 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
13446 eRet = set_buffer_req(&drv_ctx.op_buf);
13447 if (eRet != OMX_ErrorNone) {
13448 DEBUG_PRINT_ERROR("failed to set_buffer_req");
13449 return eRet;
13450 }
13451
13452 eRet = get_buffer_req(&drv_ctx.op_buf);
13453 if (eRet != OMX_ErrorNone) {
13454 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
13455 return eRet;
13456 }
13457 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
13458 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
13459 return eRet;
13460 }
13461
13462 //static
describeColorFormat(OMX_PTR pParam)13463 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
13464
13465 #ifndef FLEXYUV_SUPPORTED
13466 return OMX_ErrorUndefined;
13467 #else
13468
13469 if (pParam == NULL) {
13470 DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
13471 return OMX_ErrorBadParameter;
13472 }
13473
13474 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
13475
13476 MediaImage *img = &(params->sMediaImage);
13477 switch(params->eColorFormat) {
13478 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
13479 {
13480 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
13481 img->mNumPlanes = 3;
13482 // mWidth and mHeight represent the W x H of the largest plane
13483 // In our case, this happens to be the Stride x Scanlines of Y plane
13484 img->mWidth = params->nFrameWidth;
13485 img->mHeight = params->nFrameHeight;
13486 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13487 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
13488 img->mBitDepth = 8;
13489 //Plane 0 (Y)
13490 img->mPlane[MediaImage::Y].mOffset = 0;
13491 img->mPlane[MediaImage::Y].mColInc = 1;
13492 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
13493 img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
13494 img->mPlane[MediaImage::Y].mVertSubsampling = 1;
13495 //Plane 1 (U)
13496 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
13497 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
13498 img->mPlane[MediaImage::U].mRowInc =
13499 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13500 img->mPlane[MediaImage::U].mHorizSubsampling = 2;
13501 img->mPlane[MediaImage::U].mVertSubsampling = 2;
13502 //Plane 2 (V)
13503 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
13504 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
13505 img->mPlane[MediaImage::V].mRowInc =
13506 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13507 img->mPlane[MediaImage::V].mHorizSubsampling = 2;
13508 img->mPlane[MediaImage::V].mVertSubsampling = 2;
13509 break;
13510 }
13511
13512 case OMX_COLOR_FormatYUV420Planar:
13513 case OMX_COLOR_FormatYUV420SemiPlanar:
13514 // We need not describe the standard OMX linear formats as these are
13515 // understood by client. Fail this deliberately to let client fill-in
13516 return OMX_ErrorUnsupportedSetting;
13517
13518 default:
13519 // Rest all formats which are non-linear cannot be described
13520 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
13521 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
13522 return OMX_ErrorNone;
13523 };
13524
13525 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
13526 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
13527 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
13528 for (size_t i = 0; i < img->mNumPlanes; ++i) {
13529 DEBUG_PRINT_LOW(" Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
13530 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
13531 }
13532 return OMX_ErrorNone;
13533 #endif //FLEXYUV_SUPPORTED
13534 }
13535
prefetchNewBuffers()13536 void omx_vdec::prefetchNewBuffers() {
13537
13538 struct v4l2_decoder_cmd dec;
13539 uint32_t prefetch_count;
13540 uint32_t prefetch_size;
13541 uint32_t want_size;
13542 uint32_t have_size;
13543 int color_fmt, rc;
13544 uint32_t new_calculated_size;
13545 uint32_t new_buffer_size;
13546 uint32_t new_buffer_count;
13547 uint32_t old_buffer_size;
13548 uint32_t old_buffer_count;
13549
13550 memset((void *)&dec, 0 , sizeof(dec));
13551 DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n",
13552 drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
13553 drv_ctx.video_resolution.frame_width,
13554 drv_ctx.video_resolution.frame_height);
13555 dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
13556 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
13557 DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
13558 } else {
13559 DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
13560 dec.raw.data[0], dec.raw.data[1]);
13561 }
13562
13563 switch ((int)drv_ctx.output_format) {
13564 case VDEC_YUV_FORMAT_NV12:
13565 color_fmt = COLOR_FMT_NV12;
13566 break;
13567 case VDEC_YUV_FORMAT_NV12_UBWC:
13568 color_fmt = COLOR_FMT_NV12_UBWC;
13569 break;
13570 case VDEC_YUV_FORMAT_NV12_TP10_UBWC:
13571 color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
13572 break;
13573 default:
13574 color_fmt = -1;
13575 DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format);
13576 return;
13577 }
13578
13579 new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
13580 DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
13581 m_reconfig_width, m_reconfig_height, new_calculated_size);
13582 new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
13583 new_buffer_count = dec.raw.data[1];
13584 old_buffer_size = drv_ctx.op_buf.buffer_size;
13585 old_buffer_count = drv_ctx.op_buf.actualcount;
13586
13587 new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
13588
13589 prefetch_count = new_buffer_count;
13590 prefetch_size = new_buffer_size - old_buffer_size;
13591 want_size = new_buffer_size * new_buffer_count;
13592 have_size = old_buffer_size * old_buffer_count;
13593
13594 if (want_size > have_size) {
13595 DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
13596 DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
13597
13598 int ion_fd = open(MEM_DEVICE, O_RDONLY);
13599 if (ion_fd < 0) {
13600 DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
13601 return;
13602 }
13603
13604 struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
13605 struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
13606 struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
13607 size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
13608
13609 if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
13610 DEBUG_PRINT_ERROR("prefetch data allocation failed");
13611 goto prefetch_exit;
13612 }
13613
13614 for (uint32_t i = 0; i < prefetch_count; i++) {
13615 sizes[i] = prefetch_size;
13616 }
13617
13618 regions[0].nr_sizes = prefetch_count;
13619 regions[0].sizes = sizes;
13620 regions[0].vmid = ION_FLAG_CP_PIXEL;
13621
13622 prefetch_data->nr_regions = 1;
13623 prefetch_data->regions = regions;
13624 prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
13625
13626 custom_data->cmd = ION_IOC_PREFETCH;
13627 custom_data->arg = (unsigned long )prefetch_data;
13628
13629 rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
13630 if (rc) {
13631 DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
13632 }
13633
13634 prefetch_exit:
13635 close(ion_fd);
13636 free(sizes);
13637 free(regions);
13638 free(prefetch_data);
13639 free(custom_data);
13640 }
13641 }
13642
13643
13644 // No code beyond this !
13645
13646 // inline import of vendor-extensions implementation
13647 #include "omx_vdec_extensions.hpp"
13648