1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2019, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 /*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33 This module contains the implementation of the OpenMAX core & component.
34
35 *//*========================================================================*/
36
37 //////////////////////////////////////////////////////////////////////////////
38 // Include Files
39 //////////////////////////////////////////////////////////////////////////////
40
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include "vidc_common.h"
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <stdlib.h>
55 #include <media/hardware/HardwareAPI.h>
56 #include <sys/eventfd.h>
57 #include "PlatformConfig.h"
58 #include <nativebase/nativebase.h>
59
60 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
61 #include <sys/ioctl.h>
62 #include <sys/mman.h>
63 #endif
64
65 #ifdef _ANDROID_
66 #include <cutils/properties.h>
67
68 #ifdef _QUERY_DISP_RES_
69 #include "display_config.h"
70 #endif
71 #endif
72
73 #ifdef _USE_GLIB_
74 #include <glib.h>
75 #define strlcpy g_strlcpy
76 #endif
77
78 #include <qdMetaData.h>
79 #include <gralloc_priv.h>
80
81 #ifdef ANDROID_JELLYBEAN_MR2
82 #include "QComOMXMetadata.h"
83 #endif
84
85 #define BUFFER_LOG_LOC "/data/vendor/media"
86
87 #ifdef OUTPUT_EXTRADATA_LOG
88 FILE *outputExtradataFile;
89 char output_extradata_filename [] = "/data/vendor/media/extradata";
90 #endif
91
92 #define DEFAULT_FPS 30
93 #define MAX_SUPPORTED_FPS 240
94 #define DEFAULT_WIDTH_ALIGNMENT 128
95 #define DEFAULT_HEIGHT_ALIGNMENT 32
96
97 #define POLL_TIMEOUT 0x7fffffff
98
99 #define MEM_DEVICE "/dev/ion"
100
101 #ifdef _ANDROID_
102 extern "C" {
103 #include<utils/Log.h>
104 }
105 #endif//_ANDROID_
106
107 #define SZ_4K 0x1000
108 #define SZ_1M 0x100000
109
110 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
111 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
112 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
113 #undef ALIGN
114 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
115
116 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
117 | OMX_DISPLAY_INFO_EXTRADATA | OMX_HDR_COLOR_INFO_EXTRADATA \
118 | OMX_UBWC_CR_STATS_INFO_EXTRADATA)
119
120 // Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default
121 #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
122
123 #ifndef ION_FLAG_CP_BITSTREAM
124 #define ION_FLAG_CP_BITSTREAM 0
125 #endif
126
127 #ifndef ION_FLAG_CP_PIXEL
128 #define ION_FLAG_CP_PIXEL 0
129 #endif
130
131 #ifdef MASTER_SIDE_CP
132 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
133 #define SECURE_ALIGN SZ_4K
134 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
135 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
136 #else //SLAVE_SIDE_CP
137 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
138 #define SECURE_ALIGN SZ_1M
139 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
140 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
141 #endif
142
143 #define LUMINANCE_DIV_FACTOR 10000.0
144
145 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
146 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
147
148 using namespace android;
149
150 static OMX_U32 maxSmoothStreamingWidth = 1920;
151 static OMX_U32 maxSmoothStreamingHeight = 1088;
152
print_omx_buffer(const char * str,OMX_BUFFERHEADERTYPE * pHeader)153 void print_omx_buffer(const char *str, OMX_BUFFERHEADERTYPE *pHeader)
154 {
155 if (!pHeader)
156 return;
157
158 DEBUG_PRINT_HIGH("%s: Header %p buffer %p alloclen %d offset %d filledlen %d timestamp %lld flags %#x",
159 str, pHeader, pHeader->pBuffer, pHeader->nAllocLen,
160 pHeader->nOffset, pHeader->nFilledLen,
161 pHeader->nTimeStamp, pHeader->nFlags);
162 }
163
print_v4l2_buffer(const char * str,struct v4l2_buffer * v4l2)164 void print_v4l2_buffer(const char *str, struct v4l2_buffer *v4l2)
165 {
166 if (!v4l2)
167 return;
168
169 if (v4l2->length == 1)
170 DEBUG_PRINT_HIGH(
171 "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x\n",
172 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
173 "OUTPUT" : "CAPTURE", v4l2->index,
174 v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
175 v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
176 v4l2->m.planes[0].bytesused, v4l2->flags);
177 else
178 DEBUG_PRINT_HIGH(
179 "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x, extradata: fd %d off %d size %d filled %d\n",
180 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
181 "OUTPUT" : "CAPTURE", v4l2->index,
182 v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
183 v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
184 v4l2->m.planes[0].bytesused, v4l2->m.planes[1].reserved[0],
185 v4l2->flags, v4l2->m.planes[1].reserved[1],
186 v4l2->m.planes[1].length, v4l2->m.planes[1].bytesused);
187 }
188
async_message_thread(void * input)189 void* async_message_thread (void *input)
190 {
191 OMX_BUFFERHEADERTYPE *buffer;
192 struct v4l2_plane plane[VIDEO_MAX_PLANES];
193 struct pollfd pfds[2];
194 struct v4l2_buffer v4l2_buf;
195 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
196 struct v4l2_event dqevent;
197 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
198 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
199 pfds[1].events = POLLIN | POLLERR;
200 pfds[0].fd = omx->drv_ctx.video_driver_fd;
201 pfds[1].fd = omx->m_poll_efd;
202 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
203 DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
204 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
205 while (!omx->async_thread_force_stop) {
206 rc = poll(pfds, 2, POLL_TIMEOUT);
207 if (!rc) {
208 DEBUG_PRINT_ERROR("Poll timedout");
209 break;
210 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
211 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
212 break;
213 }
214 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
215 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
216 break;
217 }
218 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
219 struct vdec_msginfo vdec_msg;
220 memset(&vdec_msg, 0, sizeof(vdec_msg));
221 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
222 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
223 v4l2_buf.length = omx->drv_ctx.num_planes;
224 v4l2_buf.m.planes = plane;
225 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
226 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
227 vdec_msg.status_code=VDEC_S_SUCCESS;
228 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
229 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
230 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
231 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
232 (uint64_t)v4l2_buf.timestamp.tv_usec;
233
234 if (omx->async_message_process(input,&vdec_msg) < 0) {
235 DEBUG_PRINT_HIGH("async_message_thread Exited");
236 break;
237 }
238 }
239 }
240 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
241 struct vdec_msginfo vdec_msg;
242 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
243 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
244 v4l2_buf.length = 1;
245 v4l2_buf.m.planes = plane;
246 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
247 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
248 vdec_msg.status_code=VDEC_S_SUCCESS;
249 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
250 if (omx->async_message_process(input,&vdec_msg) < 0) {
251 DEBUG_PRINT_HIGH("async_message_thread Exited");
252 break;
253 }
254 }
255 }
256 if (pfds[0].revents & POLLPRI) {
257 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
258 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
259 struct vdec_msginfo vdec_msg;
260 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
261
262 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
263 vdec_msg.status_code=VDEC_S_SUCCESS;
264 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
265 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
266 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
267 omx->dpb_bit_depth = ptr[2];
268 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth - %d", ptr[3]);
269 omx->m_progressive = ptr[3];
270 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct - %d", ptr[4]);
271 omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
272 (omx_vdec:: EXCEPT_BT2020));
273 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace - %d", omx->m_color_space);
274 if (omx->async_message_process(input,&vdec_msg) < 0) {
275 DEBUG_PRINT_HIGH("async_message_thread Exited");
276 break;
277 }
278 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT) {
279
280 bool event_fields_changed = false;
281 bool send_msg = false;
282 omx_vdec::color_space_type tmp_color_space;
283 struct vdec_msginfo vdec_msg;
284 DEBUG_PRINT_HIGH("VIDC Port Reconfig received sufficient");
285 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
286 int tmp_profile = 0;
287 int tmp_level = 0;
288 int codec = omx->get_session_codec_type();
289 event_fields_changed |= (omx->dpb_bit_depth != (int)ptr[2]);
290 event_fields_changed |= (omx->m_progressive != (int)ptr[3]);
291 tmp_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
292 (omx_vdec:: EXCEPT_BT2020));
293 event_fields_changed |= (omx->m_color_space != tmp_color_space);
294
295 /*
296 * If the resolution is different due to 16\32 pixel alignment,
297 * let's handle as Sufficient. Ex : 1080 & 1088 or 2160 & 2176.
298 * When FBD comes, component updates the clients with actual
299 * resolution through set_buffer_geometry.
300 */
301
302 event_fields_changed |= (omx->drv_ctx.video_resolution.frame_height != ptr[7]);
303 event_fields_changed |= (omx->drv_ctx.video_resolution.frame_width != ptr[8]);
304
305 if ((codec == V4L2_PIX_FMT_H264) ||
306 (codec == V4L2_PIX_FMT_HEVC)) {
307 if (profile_level_converter::convert_v4l2_profile_to_omx(
308 codec, ptr[9], &tmp_profile) &&
309 profile_level_converter::convert_v4l2_level_to_omx(
310 codec, ptr[10], &tmp_level)) {
311 event_fields_changed |= (omx->mClientSessionForSufficiency &&
312 ((tmp_profile != (int)omx->mClientSetProfile) ||
313 (tmp_level > (int)omx->mClientSetLevel)));
314 }
315 }
316
317 if (!omx->is_down_scalar_enabled && omx->m_is_split_mode &&
318 (omx->drv_ctx.video_resolution.frame_height != ptr[0] ||
319 omx->drv_ctx.video_resolution.frame_width != ptr[1])) {
320 event_fields_changed = true;
321 }
322
323 if (event_fields_changed) {
324 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old Resolution(H,W) = (%d,%d) New Resolution(H,W) = (%d,%d))",
325 omx->drv_ctx.video_resolution.frame_height,
326 omx->drv_ctx.video_resolution.frame_width,
327 ptr[0], ptr[1]);
328 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old bitdepth = %d New bitdepth = %d",
329 omx->dpb_bit_depth, ptr[2]);
330 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old picstruct = %d New picstruct = %d",
331 omx->m_progressive, ptr[3]);
332 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old colorSpace = %s New colorspace = %s",
333 (omx->m_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"),
334 (tmp_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"));
335 DEBUG_PRINT_HIGH("Client Session for sufficiency feature is %s", omx->mClientSessionForSufficiency ? "enabled": "disabled");
336 DEBUG_PRINT_HIGH("VIDC Port Reconfig Client (Profile,Level) = (%d,%d) bitstream(Profile,Level) = (%d,%d))",
337 omx->mClientSetProfile,
338 omx->mClientSetLevel,
339 tmp_profile, tmp_level);
340 omx->dpb_bit_depth = ptr[2];
341 omx->m_progressive = ptr[3];
342 omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
343 (omx_vdec:: EXCEPT_BT2020));
344 send_msg = true;
345 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
346 vdec_msg.status_code=VDEC_S_SUCCESS;
347 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
348 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
349
350 } else {
351 struct v4l2_decoder_cmd dec;
352 memset(&dec, 0, sizeof(dec));
353 dec.cmd = V4L2_QCOM_CMD_SESSION_CONTINUE;
354 rc = ioctl(pfds[0].fd, VIDIOC_DECODER_CMD, &dec);
355 if (rc < 0) {
356 DEBUG_PRINT_ERROR("Session continue failed");
357 send_msg = true;
358 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
359 vdec_msg.status_code=VDEC_S_SUCCESS;
360 } else {
361 DEBUG_PRINT_HIGH("Sent Session continue");
362 }
363 }
364
365 if (send_msg) {
366 if (omx->async_message_process(input,&vdec_msg) < 0) {
367 DEBUG_PRINT_HIGH("async_message_thread Exited");
368 break;
369 }
370 }
371
372 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
373 struct vdec_msginfo vdec_msg;
374 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
375 // Old driver doesn't send flushType information.
376 // To make this backward compatible fallback to old approach
377 // if the flush_type is not present.
378 vdec_msg.status_code=VDEC_S_SUCCESS;
379 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
380 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
381 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
382 if (omx->async_message_process(input,&vdec_msg) < 0) {
383 DEBUG_PRINT_HIGH("async_message_thread Exited");
384 break;
385 }
386 }
387
388 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
389 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
390 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
391 if (omx->async_message_process(input,&vdec_msg) < 0) {
392 DEBUG_PRINT_HIGH("async_message_thread Exited");
393 break;
394 }
395 }
396 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
397 struct vdec_msginfo vdec_msg;
398 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
399 vdec_msg.status_code=VDEC_S_SUCCESS;
400 DEBUG_PRINT_ERROR("HW Overload received");
401 if (omx->async_message_process(input,&vdec_msg) < 0) {
402 DEBUG_PRINT_HIGH("async_message_thread Exited");
403 break;
404 }
405 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
406 struct vdec_msginfo vdec_msg;
407 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
408 vdec_msg.status_code=VDEC_S_SUCCESS;
409 DEBUG_PRINT_ERROR("HW Unsupported received");
410 if (omx->async_message_process(input,&vdec_msg) < 0) {
411 DEBUG_PRINT_HIGH("async_message_thread Exited");
412 break;
413 }
414 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
415 struct vdec_msginfo vdec_msg;
416 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
417 vdec_msg.status_code = VDEC_S_SUCCESS;
418 DEBUG_PRINT_HIGH("SYS Error Recieved");
419 if (omx->async_message_process(input,&vdec_msg) < 0) {
420 DEBUG_PRINT_HIGH("async_message_thread Exited");
421 break;
422 }
423 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
424 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
425
426 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
427 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
428 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
429 struct vdec_msginfo vdec_msg;
430
431 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
432
433 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
434 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
435 v4l2_buf.length = omx->drv_ctx.num_planes;
436 v4l2_buf.m.planes = plane;
437 v4l2_buf.index = ptr[5];
438 v4l2_buf.flags = 0;
439
440 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
441 vdec_msg.status_code = VDEC_S_SUCCESS;
442 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
443 vdec_msg.msgdata.output_frame.len = 0;
444 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
445 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
446 (uint64_t)ptr[4];
447 if (omx->async_message_process(input,&vdec_msg) < 0) {
448 DEBUG_PRINT_HIGH("async_message_thread Exitedn");
449 break;
450 }
451 } else {
452 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
453 continue;
454 }
455 }
456 }
457 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
458 return NULL;
459 }
460
message_thread_dec(void * input)461 void* message_thread_dec(void *input)
462 {
463 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
464 int res = 0;
465
466 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
467 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
468 while (!omx->message_thread_stop) {
469 res = omx->signal.wait(2 * 1000000000);
470 if (res == ETIMEDOUT || omx->message_thread_stop) {
471 continue;
472 } else if (res) {
473 DEBUG_PRINT_ERROR("omx_vdec: message_thread_dec wait on condition failed, exiting");
474 break;
475 }
476 omx->process_event_cb(omx);
477 }
478 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
479 return 0;
480 }
481
post_message(omx_vdec * omx,unsigned char id)482 void post_message(omx_vdec *omx, unsigned char id)
483 {
484 (void)id;
485 omx->signal.signal();
486 }
487
488 // omx_cmd_queue destructor
~omx_cmd_queue()489 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
490 {
491 // Nothing to do
492 }
493
494 // omx cmd queue constructor
omx_cmd_queue()495 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
496 {
497 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
498 }
499
500 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)501 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
502 {
503 bool ret = true;
504 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
505 m_q[m_write].id = id;
506 m_q[m_write].param1 = p1;
507 m_q[m_write].param2 = p2;
508 m_write++;
509 m_size ++;
510 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
511 m_write = 0;
512 }
513 } else {
514 ret = false;
515 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
516 }
517 return ret;
518 }
519
520 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)521 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
522 {
523 bool ret = true;
524 if (m_size > 0) {
525 *id = m_q[m_read].id;
526 *p1 = m_q[m_read].param1;
527 *p2 = m_q[m_read].param2;
528 // Move the read pointer ahead
529 ++m_read;
530 --m_size;
531 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
532 m_read = 0;
533 }
534 } else {
535 ret = false;
536 }
537 return ret;
538 }
539
540 // Retrieve the first mesg type in the queue
get_q_msg_type()541 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
542 {
543 return m_q[m_read].id;
544 }
545
546 #ifdef _ANDROID_
ts_arr_list()547 omx_vdec::ts_arr_list::ts_arr_list()
548 {
549 //initialize timestamps array
550 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
551 }
~ts_arr_list()552 omx_vdec::ts_arr_list::~ts_arr_list()
553 {
554 //free m_ts_arr_list?
555 }
556
insert_ts(OMX_TICKS ts)557 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
558 {
559 bool ret = true;
560 bool duplicate_ts = false;
561 int idx = 0;
562
563 //insert at the first available empty location
564 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
565 if (!m_ts_arr_list[idx].valid) {
566 //found invalid or empty entry, save timestamp
567 m_ts_arr_list[idx].valid = true;
568 m_ts_arr_list[idx].timestamp = ts;
569 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
570 ts, idx);
571 break;
572 }
573 }
574
575 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
576 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
577 ret = false;
578 }
579 return ret;
580 }
581
pop_min_ts(OMX_TICKS & ts)582 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
583 {
584 bool ret = true;
585 int min_idx = -1;
586 OMX_TICKS min_ts = 0;
587 int idx = 0;
588
589 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
590
591 if (m_ts_arr_list[idx].valid) {
592 //found valid entry, save index
593 if (min_idx < 0) {
594 //first valid entry
595 min_ts = m_ts_arr_list[idx].timestamp;
596 min_idx = idx;
597 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
598 min_ts = m_ts_arr_list[idx].timestamp;
599 min_idx = idx;
600 }
601 }
602
603 }
604
605 if (min_idx < 0) {
606 //no valid entries found
607 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
608 ts = 0;
609 ret = false;
610 } else {
611 ts = m_ts_arr_list[min_idx].timestamp;
612 m_ts_arr_list[min_idx].valid = false;
613 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
614 ts, min_idx);
615 }
616
617 return ret;
618
619 }
620
621
reset_ts_list()622 bool omx_vdec::ts_arr_list::reset_ts_list()
623 {
624 bool ret = true;
625 int idx = 0;
626
627 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
628 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
629 m_ts_arr_list[idx].valid = false;
630 }
631 return ret;
632 }
633 #endif
634
635 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)636 void *get_omx_component_factory_fn(void)
637 {
638 return (new omx_vdec);
639 }
640
is_platform_tp10capture_supported()641 bool is_platform_tp10capture_supported()
642 {
643 DEBUG_PRINT_HIGH("TP10 on capture port is supported");
644 return true;
645 }
646
get_session_codec_type()647 inline int omx_vdec::get_session_codec_type()
648 {
649 return output_capability;
650 }
651 /* ======================================================================
652 FUNCTION
653 omx_vdec::omx_vdec
654
655 DESCRIPTION
656 Constructor
657
658 PARAMETERS
659 None
660
661 RETURN VALUE
662 None.
663 ========================================================================== */
omx_vdec()664 omx_vdec::omx_vdec(): m_error_propogated(false),
665 m_state(OMX_StateInvalid),
666 m_app_data(NULL),
667 m_inp_mem_ptr(NULL),
668 m_out_mem_ptr(NULL),
669 m_client_output_extradata_mem_ptr(NULL),
670 input_flush_progress (false),
671 output_flush_progress (false),
672 input_use_buffer (false),
673 output_use_buffer (false),
674 ouput_egl_buffers(false),
675 m_use_output_pmem(OMX_FALSE),
676 pending_input_buffers(0),
677 pending_output_buffers(0),
678 m_out_bm_count(0),
679 m_inp_bm_count(0),
680 m_out_extradata_bm_count(0),
681 m_inp_bPopulated(OMX_FALSE),
682 m_out_bPopulated(OMX_FALSE),
683 m_flags(0),
684 m_inp_bEnabled(OMX_TRUE),
685 m_out_bEnabled(OMX_TRUE),
686 m_in_alloc_cnt(0),
687 m_platform_list(NULL),
688 m_platform_entry(NULL),
689 m_pmem_info(NULL),
690 psource_frame (NULL),
691 pdest_frame (NULL),
692 m_inp_heap_ptr (NULL),
693 m_phdr_pmem_ptr(NULL),
694 m_heap_inp_bm_count (0),
695 first_frame_meta (true),
696 frame_count (0),
697 nal_count (0),
698 nal_length(0),
699 first_frame(0),
700 first_buffer(NULL),
701 first_frame_size (0),
702 m_device_file_ptr(NULL),
703 m_disp_hor_size(0),
704 m_disp_vert_size(0),
705 prev_ts(LLONG_MAX),
706 prev_ts_actual(LLONG_MAX),
707 rst_prev_ts(true),
708 frm_int(0),
709 m_fps_received(0),
710 m_fps_prev(0),
711 m_drc_enable(0),
712 in_reconfig(false),
713 m_display_id(NULL),
714 client_extradata(0),
715 #ifdef _ANDROID_
716 m_enable_android_native_buffers(OMX_FALSE),
717 m_use_android_native_buffers(OMX_FALSE),
718 #endif
719 m_disable_dynamic_buf_mode(0),
720 m_desc_buffer_ptr(NULL),
721 secure_mode(false),
722 allocate_native_handle(false),
723 m_other_extradata(NULL),
724 m_profile(0),
725 client_set_fps(false),
726 stereo_output_mode(HAL_NO_3D),
727 m_last_rendered_TS(-1),
728 m_dec_hfr_fps(0),
729 m_queued_codec_config_count(0),
730 secure_scaling_to_non_secure_opb(false),
731 m_force_compressed_for_dpb(true),
732 m_is_display_session(false),
733 m_is_split_mode(false),
734 m_buffer_error(false)
735 {
736 m_poll_efd = -1;
737 drv_ctx.video_driver_fd = -1;
738 drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
739 /* Assumption is that , to begin with , we have all the frames with decoder */
740 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
741 memset(&m_debug,0,sizeof(m_debug));
742 #ifdef _ANDROID_
743
744 char property_value[PROPERTY_VALUE_MAX] = {0};
745 property_get("vendor.vidc.debug.level", property_value, "1");
746 debug_level = strtoul(property_value, NULL, 16);
747 property_value[0] = '\0';
748
749 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
750
751 // TODO: Support in XML
752 perf_flag = 0;
753 if (perf_flag) {
754 DEBUG_PRINT_HIGH("perf flag is %d", perf_flag);
755 dec_time.start();
756 }
757 proc_frms = latency = 0;
758 prev_n_filled_len = 0;
759
760 Platform::Config::getInt32(Platform::vidc_dec_log_in,
761 (int32_t *)&m_debug.in_buffer_log, 0);
762 Platform::Config::getInt32(Platform::vidc_dec_log_out,
763 (int32_t *)&m_debug.out_buffer_log, 0);
764
765 Platform::Config::getInt32(Platform::vidc_dec_hfr_fps,
766 (int32_t *)&m_dec_hfr_fps, 0);
767
768 DEBUG_PRINT_HIGH("HFR fps value = %d", m_dec_hfr_fps);
769
770 if (m_dec_hfr_fps) {
771 m_last_rendered_TS = 0;
772 }
773
774 property_value[0] = '\0';
775 property_get("vendor.vidc.dec.log.in", property_value, "0");
776 m_debug.in_buffer_log |= atoi(property_value);
777
778 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.in value is %d", m_debug.in_buffer_log);
779
780 property_value[0] = '\0';
781 property_get("vendor.vidc.dec.log.out", property_value, "0");
782 m_debug.out_buffer_log |= atoi(property_value);
783
784 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.out value is %d", m_debug.out_buffer_log);
785
786 property_value[0] = '\0';
787 property_get("vendor.vidc.dec.log.cc.out", property_value, "0");
788 m_debug.out_cc_buffer_log |= atoi(property_value);
789
790 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.cc.out value is %d", m_debug.out_buffer_log);
791
792 property_value[0] = '\0';
793 property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
794 m_debug.out_meta_buffer_log = atoi(property_value);
795
796 property_value[0] = '\0';
797 property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
798 if (*property_value)
799 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
800
801 struct timeval te;
802 gettimeofday(&te, NULL);
803 m_debug.session_id = te.tv_sec*1000LL + te.tv_usec/1000;
804 m_debug.seq_count = 0;
805
806 #ifdef _UBWC_
807 property_value[0] = '\0';
808 property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
809 m_disable_ubwc_mode = atoi(property_value);
810 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
811 #else
812 m_disable_ubwc_mode = true;
813 #endif
814 #endif
815 memset(&m_cmp,0,sizeof(m_cmp));
816 memset(&m_cb,0,sizeof(m_cb));
817 memset (&drv_ctx,0,sizeof(drv_ctx));
818 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
819 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
820 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
821 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
822 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
823 memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
824 memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
825 m_demux_entries = 0;
826 msg_thread_id = 0;
827 async_thread_id = 0;
828 msg_thread_created = false;
829 async_thread_created = false;
830 async_thread_force_stop = false;
831 message_thread_stop = false;
832 #ifdef _ANDROID_ICS_
833 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
834 #endif
835 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
836
837 /* invalidate m_frame_pack_arrangement */
838 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
839 m_frame_pack_arrangement.cancel_flag = 1;
840
841 drv_ctx.timestamp_adjust = false;
842 m_vendor_config.pData = NULL;
843 pthread_mutex_init(&m_lock, NULL);
844 pthread_mutex_init(&c_lock, NULL);
845 pthread_mutex_init(&buf_lock, NULL);
846 sem_init(&m_cmd_lock,0,0);
847 sem_init(&m_safe_flush, 0, 0);
848 streaming[CAPTURE_PORT] =
849 streaming[OUTPUT_PORT] = false;
850 #ifdef _ANDROID_
851 // TODO: Support in XML
852 m_debug_extradata = 0;
853 #endif
854 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
855 client_buffers.set_vdec_client(this);
856 dynamic_buf_mode = false;
857 is_down_scalar_enabled = false;
858 m_downscalar_width = 0;
859 m_downscalar_height = 0;
860 m_force_down_scalar = 0;
861 m_reconfig_height = 0;
862 m_reconfig_width = 0;
863 m_smoothstreaming_mode = false;
864 m_smoothstreaming_width = 0;
865 m_smoothstreaming_height = 0;
866 m_decode_order_mode = false;
867 m_client_req_turbo_mode = false;
868 is_q6_platform = false;
869 m_input_pass_buffer_fd = false;
870 memset(&m_extradata_info, 0, sizeof(m_extradata_info));
871 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
872 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
873 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
874 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
875 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
876
877 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
878 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
879 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
880 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
881 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
882 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
883
884 m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
885 m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
886
887 m_dither_config = DITHER_DISABLE;
888
889 DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
890 m_color_space = EXCEPT_BT2020;
891
892 init_color_aspects_map();
893
894 profile_level_converter::init();
895 mClientSessionForSufficiency = false;
896 mClientSetProfile = 0;
897 mClientSetLevel = 0;
898 }
899
900 static const int event_type[] = {
901 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
902 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
903 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
904 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
905 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
906 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
907 V4L2_EVENT_MSM_VIDC_SYS_ERROR,
908 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
909 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
910 };
911
subscribe_to_events(int fd)912 static OMX_ERRORTYPE subscribe_to_events(int fd)
913 {
914 OMX_ERRORTYPE eRet = OMX_ErrorNone;
915 struct v4l2_event_subscription sub;
916 int array_sz = sizeof(event_type)/sizeof(int);
917 int i,rc;
918 if (fd < 0) {
919 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
920 return OMX_ErrorBadParameter;
921 }
922
923 for (i = 0; i < array_sz; ++i) {
924 memset(&sub, 0, sizeof(sub));
925 sub.type = event_type[i];
926 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
927 if (rc) {
928 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
929 break;
930 }
931 }
932 if (i < array_sz) {
933 for (--i; i >=0 ; i--) {
934 memset(&sub, 0, sizeof(sub));
935 sub.type = event_type[i];
936 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
937 if (rc)
938 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
939 }
940 eRet = OMX_ErrorNotImplemented;
941 }
942 return eRet;
943 }
944
945
unsubscribe_to_events(int fd)946 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
947 {
948 OMX_ERRORTYPE eRet = OMX_ErrorNone;
949 struct v4l2_event_subscription sub;
950 int array_sz = sizeof(event_type)/sizeof(int);
951 int i,rc;
952 if (fd < 0) {
953 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
954 return OMX_ErrorBadParameter;
955 }
956
957 for (i = 0; i < array_sz; ++i) {
958 memset(&sub, 0, sizeof(sub));
959 sub.type = event_type[i];
960 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
961 if (rc) {
962 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
963 break;
964 }
965 }
966 return eRet;
967 }
968
969 /* ======================================================================
970 FUNCTION
971 omx_vdec::~omx_vdec
972
973 DESCRIPTION
974 Destructor
975
976 PARAMETERS
977 None
978
979 RETURN VALUE
980 None.
981 ========================================================================== */
~omx_vdec()982 omx_vdec::~omx_vdec()
983 {
984 m_pmem_info = NULL;
985 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
986 if (msg_thread_created) {
987 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
988 message_thread_stop = true;
989 post_message(this, OMX_COMPONENT_CLOSE_MSG);
990 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
991 pthread_join(msg_thread_id,NULL);
992 }
993 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
994 if(eventfd_write(m_poll_efd, 1)) {
995 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
996 async_thread_force_stop = true;
997 }
998
999 if (async_thread_created)
1000 pthread_join(async_thread_id,NULL);
1001 unsubscribe_to_events(drv_ctx.video_driver_fd);
1002 close(m_poll_efd);
1003 close(drv_ctx.video_driver_fd);
1004 pthread_mutex_destroy(&m_lock);
1005 pthread_mutex_destroy(&c_lock);
1006 pthread_mutex_destroy(&buf_lock);
1007 sem_destroy(&m_cmd_lock);
1008 if (perf_flag) {
1009 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
1010 dec_time.end();
1011 }
1012 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
1013 }
1014
set_dpb(bool is_split_mode,int dpb_color_format)1015 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
1016 {
1017 int rc = 0;
1018 struct v4l2_ext_control ctrl[2];
1019 struct v4l2_ext_controls controls;
1020
1021 DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
1022 is_split_mode ? "split" : "combined",
1023 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
1024 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
1025 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
1026 "unknown",
1027 capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
1028 capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
1029 capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC ? "nv12_10bit_ubwc":
1030 capture_capability == V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010 ? "P010":
1031 "unknown");
1032
1033 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1034 if (is_split_mode) {
1035 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1036 } else {
1037 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1038 }
1039
1040 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
1041 ctrl[1].value = dpb_color_format;
1042
1043 controls.count = 2;
1044 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1045 controls.controls = ctrl;
1046
1047 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1048 if (rc) {
1049 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1050 return OMX_ErrorUnsupportedSetting;
1051 }
1052 m_is_split_mode = is_split_mode;
1053 return OMX_ErrorNone;
1054 }
1055
decide_dpb_buffer_mode(bool is_downscalar_enabled)1056 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool is_downscalar_enabled)
1057 {
1058 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1059 struct v4l2_format fmt;
1060 int rc = 0;
1061
1062 // Default is Combined Mode
1063 bool enable_split = false;
1064 int dpb_color_format = V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE;
1065
1066 bool is_client_dest_format_non_ubwc = (
1067 capture_capability != V4L2_PIX_FMT_NV12_UBWC &&
1068 capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC);
1069 bool dither_enable = false;
1070 bool capability_changed = false;
1071
1072 // Downscalar is not supported
1073 is_downscalar_enabled = false;
1074
1075 switch (m_dither_config) {
1076 case DITHER_DISABLE:
1077 dither_enable = false;
1078 break;
1079 case DITHER_COLORSPACE_EXCEPTBT2020:
1080 dither_enable = (m_color_space == EXCEPT_BT2020);
1081 break;
1082 case DITHER_ALL_COLORSPACE:
1083 dither_enable = true;
1084 break;
1085 default:
1086 DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1087 }
1088
1089 // Reset v4l2_foramt struct object
1090 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1091
1092 if (is_client_dest_format_non_ubwc){
1093 // Assuming all the else blocks are for 8 bit depth
1094 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1095 enable_split = true;
1096 dpb_color_format = V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC;
1097 if(is_flexible_format){ // if flexible formats are expected, P010 is set for 10bit cases here
1098 drv_ctx.output_format = VDEC_YUV_FORMAT_P010_VENUS;
1099 capture_capability = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010;
1100 capability_changed = true;
1101 }
1102 } else if (m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE) {
1103 enable_split = true;
1104 dpb_color_format = V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC;
1105 } else {
1106 // Hardware does not support NV12+interlace clips.
1107 // Request NV12_UBWC and convert it to NV12+interlace using C2D
1108 // in combined mode
1109 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
1110 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
1111 capability_changed = true;
1112 }
1113 } else {
1114 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1115 enable_split = dither_enable;
1116
1117 if (dither_enable) {
1118 dpb_color_format = V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC;
1119 capture_capability = m_disable_ubwc_mode ?
1120 V4L2_PIX_FMT_NV12 : V4L2_PIX_FMT_NV12_UBWC;
1121 capability_changed = true;
1122 } else {
1123 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1124 capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1125 capability_changed = true;
1126 }
1127 }
1128 // 8 bit depth uses the default.
1129 // Combined mode
1130 // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE
1131 }
1132
1133 if (capability_changed == true) {
1134 // Get format for CAPTURE port
1135 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1136 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1137 if (rc) {
1138 DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1139 return OMX_ErrorUnsupportedSetting;
1140 }
1141
1142 // Set Capability for CAPTURE port if there is a change
1143 fmt.fmt.pix_mp.pixelformat = capture_capability;
1144 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1145 if (rc) {
1146 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1147 return OMX_ErrorUnsupportedSetting;
1148 }
1149 }
1150 // Check the component for its valid current state
1151 if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1152 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1153 DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1154 return OMX_ErrorNone;
1155 }
1156 eRet = set_dpb(enable_split, dpb_color_format);
1157 if (eRet) {
1158 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1159 }
1160
1161 return eRet;
1162 }
1163
check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)1164 bool omx_vdec::check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)
1165 {
1166 if(required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
1167 required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus) {
1168 //for now, the flexible formats should be NV12 by default for 8bit cases
1169 //it will change to P010 after 10bit port-reconfig accordingly
1170 return TRUE;
1171 }
1172 else {
1173 return FALSE;
1174 }
1175 }
1176
enable_downscalar()1177 int omx_vdec::enable_downscalar()
1178 {
1179 int rc = 0;
1180 struct v4l2_control control;
1181 struct v4l2_format fmt;
1182
1183 if (is_down_scalar_enabled) {
1184 DEBUG_PRINT_LOW("%s: already enabled", __func__);
1185 return 0;
1186 }
1187
1188 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1189 rc = decide_dpb_buffer_mode(true);
1190 if (rc) {
1191 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1192 return rc;
1193 }
1194 is_down_scalar_enabled = true;
1195
1196 return 0;
1197 }
1198
disable_downscalar()1199 int omx_vdec::disable_downscalar()
1200 {
1201 int rc = 0;
1202 struct v4l2_control control;
1203
1204 if (!is_down_scalar_enabled) {
1205 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1206 return 0;
1207 }
1208
1209 rc = decide_dpb_buffer_mode(false);
1210 if (rc < 0) {
1211 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1212 return rc;
1213 }
1214 is_down_scalar_enabled = false;
1215
1216 return rc;
1217 }
1218
decide_downscalar()1219 int omx_vdec::decide_downscalar()
1220 {
1221 int rc = 0;
1222 struct v4l2_format fmt;
1223 enum color_fmts color_format;
1224 OMX_U32 width, height;
1225 OMX_BOOL isPortraitVideo = OMX_FALSE;
1226
1227 if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1228 rc = disable_downscalar();
1229 if (rc) {
1230 DEBUG_PRINT_ERROR("Disable downscalar failed!");
1231 return rc;
1232 }
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)1397 void omx_vdec::process_event_cb(void *ctxt)
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 switch (ident) {
1438 case OMX_COMPONENT_GENERATE_EVENT:
1439 if (pThis->m_cb.EventHandler) {
1440 switch (p1) {
1441 case OMX_CommandStateSet:
1442 pThis->m_state = (OMX_STATETYPE) p2;
1443 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1444 pThis->m_state);
1445 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1446 OMX_EventCmdComplete, p1, p2, NULL);
1447 break;
1448
1449 case OMX_EventError:
1450 if (p2 == OMX_StateInvalid) {
1451 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1452 pThis->m_state = (OMX_STATETYPE) p2;
1453 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1454 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1455 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1456 pThis->omx_report_error();
1457 } else {
1458 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1459 OMX_EventError, p2, (OMX_U32)NULL, NULL );
1460 }
1461 break;
1462
1463 case OMX_CommandPortDisable:
1464 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1465 if (BITMASK_PRESENT(&pThis->m_flags,
1466 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1467 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1468 break;
1469 }
1470 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1471 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1472 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1473 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1474 pThis->in_reconfig = false;
1475 if (eRet != OMX_ErrorNone) {
1476 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1477 pThis->omx_report_error();
1478 break;
1479 }
1480 }
1481 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1482 OMX_EventCmdComplete, p1, p2, NULL );
1483 break;
1484 case OMX_CommandPortEnable:
1485 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1486 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1487 OMX_EventCmdComplete, p1, p2, NULL );
1488 break;
1489
1490 default:
1491 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1492 OMX_EventCmdComplete, p1, p2, NULL );
1493 break;
1494
1495 }
1496 } else {
1497 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1498 }
1499 break;
1500 case OMX_COMPONENT_GENERATE_ETB: {
1501 OMX_ERRORTYPE iret;
1502 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1503 if (iret == OMX_ErrorInsufficientResources) {
1504 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1505 pThis->omx_report_hw_overload ();
1506 } else if (iret != OMX_ErrorNone) {
1507 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1508 pThis->omx_report_error ();
1509 }
1510 }
1511 break;
1512
1513 case OMX_COMPONENT_GENERATE_FTB:
1514 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1515 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1516 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1517 pThis->omx_report_error ();
1518 }
1519 break;
1520
1521 case OMX_COMPONENT_GENERATE_COMMAND:
1522 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1523 (OMX_U32)p2,(OMX_PTR)NULL);
1524 break;
1525
1526 case OMX_COMPONENT_GENERATE_EBD:
1527
1528 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1529 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1530 pThis->omx_report_error ();
1531 } else {
1532 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1533 pThis->time_stamp_dts.remove_time_stamp(
1534 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1535 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1536 ?true:false);
1537 }
1538
1539 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1540 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1541 DEBUG_PRINT_ERROR("empty_buffer_done failure");
1542 pThis->omx_report_error ();
1543 }
1544 }
1545 break;
1546 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1547 int64_t *timestamp = (int64_t *)(intptr_t)p1;
1548 if (p1) {
1549 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1550 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1551 ?true:false);
1552 free(timestamp);
1553 }
1554 }
1555 break;
1556 case OMX_COMPONENT_GENERATE_FBD:
1557 if (p2 != VDEC_S_SUCCESS) {
1558 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1559 pThis->omx_report_error ();
1560 } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1561 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1562 DEBUG_PRINT_ERROR("fill_buffer_done failure");
1563 pThis->omx_report_error ();
1564 }
1565 break;
1566
1567 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1568 DEBUG_PRINT_HIGH("Driver flush i/p Port complete, flags %#llx",
1569 (unsigned long long)pThis->m_flags);
1570 if (!pThis->input_flush_progress) {
1571 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1572 } else {
1573 pThis->execute_input_flush();
1574 if (pThis->m_cb.EventHandler) {
1575 if (p2 != VDEC_S_SUCCESS) {
1576 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1577 pThis->omx_report_error ();
1578 } else {
1579 /*Check if we need generate event for Flush done*/
1580 pThis->notify_flush_done(ctxt);
1581
1582 if (BITMASK_PRESENT(&pThis->m_flags,
1583 OMX_COMPONENT_IDLE_PENDING)) {
1584 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1585 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1586 pThis->omx_report_error ();
1587 } else {
1588 pThis->streaming[OUTPUT_PORT] = false;
1589 }
1590 if (!pThis->output_flush_progress) {
1591 DEBUG_PRINT_LOW("Input flush done hence issue stop");
1592 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1593 OMX_COMPONENT_GENERATE_STOP_DONE);
1594 }
1595 }
1596 }
1597 } else {
1598 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1599 }
1600 }
1601 break;
1602
1603 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1604 DEBUG_PRINT_HIGH("Driver flush o/p Port complete, flags %#llx",
1605 (unsigned long long)pThis->m_flags);
1606 if (!pThis->output_flush_progress) {
1607 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1608 } else {
1609 pThis->execute_output_flush();
1610 if (pThis->m_cb.EventHandler) {
1611 if (p2 != VDEC_S_SUCCESS) {
1612 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1613 pThis->omx_report_error ();
1614 } else {
1615 /*Check if we need generate event for Flush done*/
1616 pThis->notify_flush_done(ctxt);
1617
1618 if (BITMASK_PRESENT(&pThis->m_flags,
1619 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1620 DEBUG_PRINT_LOW("Internal flush complete");
1621 BITMASK_CLEAR (&pThis->m_flags,
1622 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1623 if (BITMASK_PRESENT(&pThis->m_flags,
1624 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1625 pThis->post_event(OMX_CommandPortDisable,
1626 OMX_CORE_OUTPUT_PORT_INDEX,
1627 OMX_COMPONENT_GENERATE_EVENT);
1628 BITMASK_CLEAR (&pThis->m_flags,
1629 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1630 BITMASK_CLEAR (&pThis->m_flags,
1631 OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1632
1633 }
1634 }
1635
1636 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1637 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1638 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1639 pThis->omx_report_error ();
1640 break;
1641 }
1642 pThis->streaming[CAPTURE_PORT] = false;
1643 if (!pThis->input_flush_progress) {
1644 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1645 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1646 OMX_COMPONENT_GENERATE_STOP_DONE);
1647 }
1648 }
1649 }
1650 } else {
1651 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1652 }
1653 }
1654 break;
1655
1656 case OMX_COMPONENT_GENERATE_START_DONE:
1657 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE, flags %#llx",
1658 (unsigned long long)pThis->m_flags);
1659 if (pThis->m_cb.EventHandler) {
1660 if (p2 != VDEC_S_SUCCESS) {
1661 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1662 pThis->omx_report_error ();
1663 } else {
1664 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1665 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1666 DEBUG_PRINT_LOW("Move to executing");
1667 // Send the callback now
1668 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1669 pThis->m_state = OMX_StateExecuting;
1670 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1671 OMX_EventCmdComplete,OMX_CommandStateSet,
1672 OMX_StateExecuting, NULL);
1673 } else if (BITMASK_PRESENT(&pThis->m_flags,
1674 OMX_COMPONENT_PAUSE_PENDING)) {
1675 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1676 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1677 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1678 pThis->omx_report_error ();
1679 }
1680 }
1681 }
1682 } else {
1683 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1684 }
1685 break;
1686
1687 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1688 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1689 if (pThis->m_cb.EventHandler) {
1690 if (p2 != VDEC_S_SUCCESS) {
1691 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1692 pThis->omx_report_error ();
1693 } else {
1694 pThis->complete_pending_buffer_done_cbs();
1695 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1696 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1697 //Send the callback now
1698 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1699 pThis->m_state = OMX_StatePause;
1700 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1701 OMX_EventCmdComplete,OMX_CommandStateSet,
1702 OMX_StatePause, NULL);
1703 }
1704 }
1705 } else {
1706 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1707 }
1708
1709 break;
1710
1711 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1712 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1713 if (pThis->m_cb.EventHandler) {
1714 if (p2 != VDEC_S_SUCCESS) {
1715 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1716 pThis->omx_report_error ();
1717 } else {
1718 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1719 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1720 // Send the callback now
1721 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1722 pThis->m_state = OMX_StateExecuting;
1723 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1724 OMX_EventCmdComplete,OMX_CommandStateSet,
1725 OMX_StateExecuting,NULL);
1726 }
1727 }
1728 } else {
1729 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1730 }
1731
1732 break;
1733
1734 case OMX_COMPONENT_GENERATE_STOP_DONE:
1735 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1736 if (pThis->m_cb.EventHandler) {
1737 if (p2 != VDEC_S_SUCCESS) {
1738 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1739 pThis->omx_report_error ();
1740 } else {
1741 pThis->complete_pending_buffer_done_cbs();
1742 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1743 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1744 // Send the callback now
1745 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1746 pThis->m_state = OMX_StateIdle;
1747 DEBUG_PRINT_LOW("Move to Idle State");
1748 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1749 OMX_EventCmdComplete,OMX_CommandStateSet,
1750 OMX_StateIdle,NULL);
1751 }
1752 }
1753 } else {
1754 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1755 }
1756
1757 break;
1758
1759 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1760 if (p2 == OMX_IndexParamPortDefinition) {
1761 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1762 pThis->in_reconfig = true;
1763 } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1764 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1765
1766 /* Check if resolution is changed in smooth streaming mode */
1767 if (pThis->m_smoothstreaming_mode &&
1768 (pThis->framesize.nWidth !=
1769 pThis->drv_ctx.video_resolution.frame_width) ||
1770 (pThis->framesize.nHeight !=
1771 pThis->drv_ctx.video_resolution.frame_height)) {
1772
1773 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1774 pThis->framesize.nWidth,
1775 pThis->framesize.nHeight,
1776 pThis->drv_ctx.video_resolution.frame_width,
1777 pThis->drv_ctx.video_resolution.frame_height);
1778
1779 /* Update new resolution */
1780 pThis->framesize.nWidth =
1781 pThis->drv_ctx.video_resolution.frame_width;
1782 pThis->framesize.nHeight =
1783 pThis->drv_ctx.video_resolution.frame_height;
1784
1785 /* Update C2D with new resolution */
1786 if (!pThis->client_buffers.update_buffer_req()) {
1787 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1788 }
1789 }
1790
1791 /* Update new crop information */
1792 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1793 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1794 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1795 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1796
1797 /* Validate the new crop information */
1798 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1799 pThis->drv_ctx.video_resolution.frame_width) {
1800
1801 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1802 pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1803 pThis->drv_ctx.video_resolution.frame_width);
1804 pThis->rectangle.nLeft = 0;
1805
1806 if (pThis->rectangle.nWidth >
1807 pThis->drv_ctx.video_resolution.frame_width) {
1808
1809 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1810 pThis->rectangle.nWidth,
1811 pThis->drv_ctx.video_resolution.frame_width);
1812 pThis->rectangle.nWidth =
1813 pThis->drv_ctx.video_resolution.frame_width;
1814 }
1815 }
1816 if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1817 pThis->drv_ctx.video_resolution.frame_height) {
1818
1819 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1820 pThis->rectangle.nTop, pThis->rectangle.nHeight,
1821 pThis->drv_ctx.video_resolution.frame_height);
1822 pThis->rectangle.nTop = 0;
1823
1824 if (pThis->rectangle.nHeight >
1825 pThis->drv_ctx.video_resolution.frame_height) {
1826
1827 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1828 pThis->rectangle.nHeight,
1829 pThis->drv_ctx.video_resolution.frame_height);
1830 pThis->rectangle.nHeight =
1831 pThis->drv_ctx.video_resolution.frame_height;
1832 }
1833 }
1834 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1835 pThis->rectangle.nLeft, pThis->rectangle.nTop,
1836 pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1837 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1838 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1839 } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1840 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1841 } else {
1842 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1843 break;
1844 }
1845 if (pThis->m_debug.outfile) {
1846 fclose(pThis->m_debug.outfile);
1847 pThis->m_debug.outfile = NULL;
1848 }
1849 if (pThis->m_debug.ccoutfile) {
1850 fclose(pThis->m_debug.ccoutfile);
1851 pThis->m_debug.ccoutfile = NULL;
1852 }
1853 if (pThis->m_debug.out_ymeta_file) {
1854 fclose(pThis->m_debug.out_ymeta_file);
1855 pThis->m_debug.out_ymeta_file = NULL;
1856 }
1857 if (pThis->m_debug.out_uvmeta_file) {
1858 fclose(pThis->m_debug.out_uvmeta_file);
1859 pThis->m_debug.out_uvmeta_file = NULL;
1860 }
1861 pThis->m_debug.seq_count++;
1862
1863 if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1864 pThis->prefetchNewBuffers();
1865 }
1866
1867 if (pThis->m_cb.EventHandler) {
1868 uint32_t frame_data[4];
1869 frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1870 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1871 frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1872 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1873
1874 frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ?
1875 frame_data[0] : pThis->drv_ctx.video_resolution.frame_height;
1876
1877 frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ?
1878 frame_data[1] : pThis->drv_ctx.video_resolution.frame_width;
1879
1880 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1881 OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1882 } else {
1883 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1884 }
1885 break;
1886
1887 case OMX_COMPONENT_GENERATE_EOS_DONE:
1888 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1889 if (pThis->m_cb.EventHandler) {
1890 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1891 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1892 } else {
1893 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1894 }
1895 pThis->prev_ts = LLONG_MAX;
1896 pThis->rst_prev_ts = true;
1897 break;
1898
1899 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1900 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1901 pThis->omx_report_error();
1902 break;
1903
1904 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1905 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1906 pThis->omx_report_unsupported_setting();
1907 break;
1908
1909 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1910 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1911 pThis->omx_report_hw_overload();
1912 break;
1913
1914 default:
1915 break;
1916 }
1917 }
1918 pthread_mutex_lock(&pThis->m_lock);
1919 qsize = pThis->m_cmd_q.m_size;
1920 if (pThis->m_state != OMX_StatePause)
1921 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1922 pthread_mutex_unlock(&pThis->m_lock);
1923 } while (qsize>0);
1924
1925 }
1926
update_resolution(int width,int height,int stride,int scan_lines)1927 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1928 {
1929 int format_changed = 0;
1930 if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1931 (width != (int)drv_ctx.video_resolution.frame_width)) {
1932 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1933 width, drv_ctx.video_resolution.frame_width,
1934 height,drv_ctx.video_resolution.frame_height);
1935 format_changed = 1;
1936 }
1937 drv_ctx.video_resolution.frame_height = height;
1938 drv_ctx.video_resolution.frame_width = width;
1939 drv_ctx.video_resolution.scan_lines = scan_lines;
1940 drv_ctx.video_resolution.stride = stride;
1941
1942 if (!is_down_scalar_enabled) {
1943 rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
1944 rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
1945 rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
1946 rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
1947 }
1948 return format_changed;
1949 }
1950
log_input_buffers(const char * buffer_addr,int buffer_len,uint64_t timeStamp)1951 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len, uint64_t timeStamp)
1952 {
1953 if (m_debug.in_buffer_log && !m_debug.infile) {
1954 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1955 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p_%" PRId64 ".mpg", m_debug.log_loc,
1956 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this, m_debug.session_id);
1957 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1958 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1959 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
1960 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1961 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1962 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1963 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1964 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1965 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1966 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1967 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1968 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1969 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1970 } else {
1971 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.bin",
1972 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1973 }
1974 m_debug.infile = fopen (m_debug.infile_name, "ab");
1975 if (!m_debug.infile) {
1976 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging (%d:%s)",
1977 m_debug.infile_name, errno, strerror(errno));
1978 m_debug.infile_name[0] = '\0';
1979 return -1;
1980 }
1981 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1982 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1983 bool isVp9 = drv_ctx.decoder_format == VDEC_CODECTYPE_VP9;
1984 int width = drv_ctx.video_resolution.frame_width;
1985 int height = drv_ctx.video_resolution.frame_height;
1986 int fps = drv_ctx.frame_rate.fps_numerator;
1987 IvfFileHeader ivfHeader(isVp9, width, height, 1, fps, 0);
1988 fwrite((const char *)&ivfHeader,
1989 sizeof(ivfHeader),1,m_debug.infile);
1990 }
1991 }
1992 if (m_debug.infile && buffer_addr && buffer_len) {
1993 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1994 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1995 IvfFrameHeader ivfFrameHeader(buffer_len, timeStamp);
1996 fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.infile);
1997 }
1998 fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1999 }
2000 return 0;
2001 }
2002
log_cc_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2003 int omx_vdec::log_cc_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2004 if (!client_buffers.is_color_conversion_enabled() ||
2005 !m_debug.out_cc_buffer_log || !buffer || !buffer->nFilledLen)
2006 return 0;
2007
2008 if (m_debug.out_cc_buffer_log && !m_debug.ccoutfile) {
2009 snprintf(m_debug.ccoutfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_cc_%d_%d_%p_%" PRId64 "_%d.yuv",
2010 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2011 m_debug.session_id, m_debug.seq_count);
2012 m_debug.ccoutfile = fopen (m_debug.ccoutfile_name, "ab");
2013 if (!m_debug.ccoutfile) {
2014 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2015 m_debug.ccoutfile_name[0] = '\0';
2016 return -1;
2017 }
2018 DEBUG_PRINT_HIGH("Opened CC output file: %s for logging", m_debug.ccoutfile_name);
2019 }
2020
2021 fwrite(buffer->pBuffer, buffer->nFilledLen, 1, m_debug.ccoutfile);
2022 return 0;
2023 }
2024
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2025 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2026 int buf_index = 0;
2027 char *temp = NULL;
2028 char *bufaddr = NULL;
2029
2030 if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2031 return 0;
2032
2033 if (m_debug.out_buffer_log && !m_debug.outfile) {
2034 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p_%" PRId64 "_%d.yuv",
2035 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2036 m_debug.session_id, m_debug.seq_count);
2037 m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2038 if (!m_debug.outfile) {
2039 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2040 m_debug.outfile_name[0] = '\0';
2041 return -1;
2042 }
2043 DEBUG_PRINT_HIGH("Opened output file: %s for logging", m_debug.outfile_name);
2044 }
2045
2046 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2047 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2048 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2049 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2050 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2051 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2052 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2053 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2054 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2055 m_debug.out_ymetafile_name[0] = '\0';
2056 m_debug.out_uvmetafile_name[0] = '\0';
2057 return -1;
2058 }
2059 }
2060
2061 buf_index = buffer - m_out_mem_ptr;
2062 bufaddr = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2063 if (dynamic_buf_mode && !secure_mode) {
2064 bufaddr = (char*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
2065 PROT_READ|PROT_WRITE, MAP_SHARED,
2066 drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
2067 //mmap returns (void *)-1 on failure and sets error code in errno.
2068 if (bufaddr == MAP_FAILED) {
2069 DEBUG_PRINT_ERROR("mmap failed - errno: %d", errno);
2070 return -1;
2071 }
2072 }
2073 temp = bufaddr;
2074
2075 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2076 drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2077 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2078 drv_ctx.video_resolution.frame_width,
2079 drv_ctx.video_resolution.frame_height);
2080
2081 if (m_debug.outfile)
2082 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2083
2084 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2085 unsigned int width = 0, height = 0;
2086 unsigned int y_plane, y_meta_plane;
2087 int y_stride = 0, y_sclines = 0;
2088 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2089 int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2090 int i;
2091 int bytes_written = 0;
2092
2093 width = drv_ctx.video_resolution.frame_width;
2094 height = drv_ctx.video_resolution.frame_height;
2095 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2096 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2097 y_stride = VENUS_Y_STRIDE(color_fmt, width);
2098 y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2099 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2100 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2101
2102 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2103 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2104
2105 for (i = 0; i < y_meta_scanlines; i++) {
2106 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2107 temp += y_meta_stride;
2108 }
2109
2110 temp = bufaddr + y_meta_plane + y_plane;
2111 for(i = 0; i < uv_meta_scanlines; i++) {
2112 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2113 temp += uv_meta_stride;
2114 }
2115 }
2116 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2117 int stride = drv_ctx.video_resolution.stride;
2118 int scanlines = drv_ctx.video_resolution.scan_lines;
2119 if (m_smoothstreaming_mode) {
2120 stride = drv_ctx.video_resolution.frame_width;
2121 scanlines = drv_ctx.video_resolution.frame_height;
2122 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2123 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2124 }
2125 unsigned i;
2126 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2127 drv_ctx.video_resolution.frame_width,
2128 drv_ctx.video_resolution.frame_height, stride, scanlines);
2129 int bytes_written = 0;
2130 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2131 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2132 temp += stride;
2133 }
2134 temp = bufaddr + stride * scanlines;
2135 int stride_c = stride;
2136 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2137 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2138 temp += stride_c;
2139 }
2140 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
2141 int stride = drv_ctx.video_resolution.stride;
2142 int scanlines = drv_ctx.video_resolution.scan_lines;
2143 if (m_smoothstreaming_mode) {
2144 stride = drv_ctx.video_resolution.frame_width * 2;
2145 scanlines = drv_ctx.video_resolution.frame_height;
2146 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2147 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2148 }
2149 unsigned i;
2150 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2151 drv_ctx.video_resolution.frame_width,
2152 drv_ctx.video_resolution.frame_height, stride, scanlines);
2153 int bytes_written = 0;
2154 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2155 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2156 temp += stride;
2157 }
2158 temp = bufaddr + stride * scanlines;
2159 int stride_c = stride;
2160 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2161 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2162 temp += stride_c;
2163 }
2164 }
2165
2166 if (dynamic_buf_mode && !secure_mode) {
2167 munmap(bufaddr, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
2168 }
2169 return 0;
2170 }
2171
init_color_aspects_map()2172 void omx_vdec::init_color_aspects_map()
2173 {
2174 mPrimariesMap.insert({
2175 {ColorAspects::PrimariesUnspecified, (ColorPrimaries)(2)},
2176 {ColorAspects::PrimariesBT709_5, ColorPrimaries_BT709_5},
2177 {ColorAspects::PrimariesBT470_6M, ColorPrimaries_BT470_6M},
2178 {ColorAspects::PrimariesBT601_6_625, ColorPrimaries_BT601_6_625},
2179 {ColorAspects::PrimariesBT601_6_525, ColorPrimaries_BT601_6_525},
2180 {ColorAspects::PrimariesGenericFilm, ColorPrimaries_GenericFilm},
2181 {ColorAspects::PrimariesBT2020, ColorPrimaries_BT2020},
2182 });
2183 mTransferMap.insert({
2184 {ColorAspects::TransferUnspecified, (GammaTransfer)(2)},
2185 {ColorAspects::TransferLinear, Transfer_Linear},
2186 {ColorAspects::TransferSRGB, Transfer_sRGB},
2187 {ColorAspects::TransferSMPTE170M, Transfer_SMPTE_170M},
2188 {ColorAspects::TransferGamma22, Transfer_Gamma2_2},
2189 {ColorAspects::TransferGamma28, Transfer_Gamma2_8},
2190 {ColorAspects::TransferST2084, Transfer_SMPTE_ST2084},
2191 {ColorAspects::TransferHLG, Transfer_HLG},
2192 {ColorAspects::TransferSMPTE240M, Transfer_SMPTE_240M},
2193 {ColorAspects::TransferXvYCC, Transfer_XvYCC},
2194 {ColorAspects::TransferBT1361, Transfer_BT1361},
2195 {ColorAspects::TransferST428, Transfer_ST_428},
2196 });
2197 mMatrixCoeffMap.insert({
2198 {ColorAspects::MatrixUnspecified, (MatrixCoEfficients)(2)},
2199 {ColorAspects::MatrixBT709_5, MatrixCoEff_BT709_5},
2200 {ColorAspects::MatrixBT470_6M, MatrixCoeff_FCC_73_682},
2201 {ColorAspects::MatrixBT601_6, MatrixCoEff_BT601_6_625},
2202 {ColorAspects::MatrixSMPTE240M, MatrixCoEff_SMPTE240M},
2203 {ColorAspects::MatrixBT2020, MatrixCoEff_BT2020},
2204 {ColorAspects::MatrixBT2020Constant, MatrixCoEff_BT2020Constant},
2205 });
2206 mColorRangeMap.insert({
2207 {ColorAspects::RangeUnspecified, (ColorRange)(2)},
2208 {ColorAspects::RangeFull, Range_Full},
2209 {ColorAspects::RangeLimited, Range_Limited},
2210 });
2211 }
2212 /* ======================================================================
2213 FUNCTION
2214 omx_vdec::ComponentInit
2215
2216 DESCRIPTION
2217 Initialize the component.
2218
2219 PARAMETERS
2220 ctxt -- Context information related to the self.
2221 id -- Event identifier. This could be any of the following:
2222 1. Command completion event
2223 2. Buffer done callback event
2224 3. Frame done callback event
2225
2226 RETURN VALUE
2227 None.
2228
2229 ========================================================================== */
component_init(OMX_STRING role)2230 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2231 {
2232
2233 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2234 struct v4l2_fmtdesc fdesc;
2235 struct v4l2_format fmt;
2236 struct v4l2_requestbuffers bufreq;
2237 struct v4l2_control control;
2238 struct v4l2_frmsizeenum frmsize;
2239 struct v4l2_queryctrl query;
2240 unsigned int alignment = 0,buffer_size = 0, nBufCount = 0;
2241 int fds[2];
2242 int r,ret=0;
2243 bool codec_ambiguous = false;
2244 OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2245 char property_value[PROPERTY_VALUE_MAX] = {0};
2246 FILE *soc_file = NULL;
2247 char buffer[10];
2248 struct v4l2_ext_control ctrl[2];
2249 struct v4l2_ext_controls controls;
2250 int conceal_color_8bit = 0, conceal_color_10bit = 0;
2251
2252 #ifdef _ANDROID_
2253 char platform_name[PROPERTY_VALUE_MAX];
2254 property_get("ro.board.platform", platform_name, "0");
2255 if (!strncmp(platform_name, "msm8610", 7)) {
2256 device_name = (OMX_STRING)"/dev/video/q6_dec";
2257 is_q6_platform = true;
2258 maxSmoothStreamingWidth = 1280;
2259 maxSmoothStreamingHeight = 720;
2260 }
2261 #endif
2262
2263 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2264 OMX_MAX_STRINGNAME_SIZE)) {
2265 secure_mode = true;
2266 role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2267 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2268 OMX_MAX_STRINGNAME_SIZE)) {
2269 secure_mode = true;
2270 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2271 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2272 OMX_MAX_STRINGNAME_SIZE)) {
2273 secure_mode = true;
2274 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2275 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2276 OMX_MAX_STRINGNAME_SIZE)) {
2277 secure_mode = true;
2278 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2279 }
2280 else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure",
2281 OMX_MAX_STRINGNAME_SIZE)) {
2282 secure_mode = true;
2283 role = (OMX_STRING)"OMX.qcom.video.decoder.vp8";
2284 }
2285
2286 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2287
2288 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2289
2290 if (drv_ctx.video_driver_fd < 0) {
2291 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2292 return OMX_ErrorInsufficientResources;
2293 }
2294 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2295 drv_ctx.frame_rate.fps_denominator = 1;
2296 operating_frame_rate = DEFAULT_FPS;
2297 m_poll_efd = eventfd(0, 0);
2298 if (m_poll_efd < 0) {
2299 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2300 return OMX_ErrorInsufficientResources;
2301 }
2302 ret = subscribe_to_events(drv_ctx.video_driver_fd);
2303 if (!ret) {
2304 async_thread_created = true;
2305 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2306 }
2307 if (ret) {
2308 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2309 async_thread_created = false;
2310 return OMX_ErrorInsufficientResources;
2311 }
2312
2313 #ifdef OUTPUT_EXTRADATA_LOG
2314 outputExtradataFile = fopen (output_extradata_filename, "ab");
2315 #endif
2316
2317 // Copy the role information which provides the decoder kind
2318 strlcpy(drv_ctx.kind,role,128);
2319
2320
2321 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2322 OMX_MAX_STRINGNAME_SIZE)) {
2323 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2324 OMX_MAX_STRINGNAME_SIZE);
2325 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2326 output_capability = V4L2_PIX_FMT_MPEG2;
2327 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2328 nBufCount = 6;
2329 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2330 OMX_MAX_STRINGNAME_SIZE)) {
2331 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2332 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2333 output_capability=V4L2_PIX_FMT_H264;
2334 eCompressionFormat = OMX_VIDEO_CodingAVC;
2335 nBufCount = 8;
2336 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2337 OMX_MAX_STRINGNAME_SIZE)) {
2338 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2339 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2340 output_capability = V4L2_PIX_FMT_H264_MVC;
2341 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2342 nBufCount = 8;
2343 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2344 OMX_MAX_STRINGNAME_SIZE)) {
2345 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2346 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2347 output_capability = V4L2_PIX_FMT_HEVC;
2348 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2349 nBufCount = 8;
2350 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
2351 OMX_MAX_STRINGNAME_SIZE)) {
2352 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2353 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2354 output_capability = V4L2_PIX_FMT_VP8;
2355 eCompressionFormat = OMX_VIDEO_CodingVP8;
2356 nBufCount = 6;
2357 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \
2358 OMX_MAX_STRINGNAME_SIZE)) {
2359 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2360 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2361 output_capability = V4L2_PIX_FMT_VP9;
2362 eCompressionFormat = OMX_VIDEO_CodingVP9;
2363 nBufCount = 11;
2364 } else {
2365 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2366 eRet = OMX_ErrorInvalidComponentName;
2367 }
2368
2369 if (eRet == OMX_ErrorNone) {
2370 OMX_COLOR_FORMATTYPE dest_color_format;
2371 if (m_disable_ubwc_mode) {
2372 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2373 } else {
2374 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2375 }
2376 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2377 dest_color_format = (OMX_COLOR_FORMATTYPE)
2378 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2379 else
2380 dest_color_format = (OMX_COLOR_FORMATTYPE)
2381 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2382 if (!client_buffers.set_color_format(dest_color_format)) {
2383 DEBUG_PRINT_ERROR("Setting color format failed");
2384 eRet = OMX_ErrorInsufficientResources;
2385 }
2386
2387 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2388 m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2389 is_flexible_format = FALSE;
2390
2391 if (m_disable_ubwc_mode) {
2392 capture_capability = V4L2_PIX_FMT_NV12;
2393 } else {
2394 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2395 }
2396
2397 struct v4l2_capability cap;
2398 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2399 if (ret) {
2400 DEBUG_PRINT_ERROR("Failed to query capabilities");
2401 /*TODO: How to handle this case */
2402 } else {
2403 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2404 " version = %d, capabilities = %x", cap.driver, cap.card,
2405 cap.bus_info, cap.version, cap.capabilities);
2406 }
2407 ret=0;
2408 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2409 fdesc.index=0;
2410 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2411 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2412 fdesc.pixelformat, fdesc.flags);
2413 fdesc.index++;
2414 }
2415 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2416 fdesc.index=0;
2417 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2418
2419 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2420 fdesc.pixelformat, fdesc.flags);
2421 fdesc.index++;
2422 }
2423 m_extradata_info.output_crop_rect.nLeft = 0;
2424 m_extradata_info.output_crop_rect.nTop = 0;
2425 m_extradata_info.output_crop_rect.nWidth = 320;
2426 m_extradata_info.output_crop_rect.nHeight = 240;
2427 update_resolution(320, 240, 320, 240);
2428
2429 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2430 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2431 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2432 fmt.fmt.pix_mp.pixelformat = output_capability;
2433 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2434 if (ret) {
2435 /*TODO: How to handle this case */
2436 DEBUG_PRINT_ERROR("Failed to set format on output port");
2437 return OMX_ErrorInsufficientResources;
2438 }
2439 DEBUG_PRINT_HIGH("Set Format was successful");
2440
2441 /*
2442 * refer macro DEFAULT_CONCEAL_COLOR to set conceal color values
2443 */
2444 Platform::Config::getInt32(Platform::vidc_dec_conceal_color_8bit, &conceal_color_8bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2445 Platform::Config::getInt32(Platform::vidc_dec_conceal_color_10bit, &conceal_color_10bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2446 memset(&controls, 0, sizeof(controls));
2447 memset(ctrl, 0, sizeof(ctrl));
2448 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT;
2449 ctrl[0].value = conceal_color_8bit;
2450 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT;
2451 ctrl[1].value = conceal_color_10bit;
2452
2453 controls.count = 2;
2454 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
2455 controls.controls = ctrl;
2456 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
2457 if (ret) {
2458 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2459 }
2460
2461 //Get the hardware capabilities
2462 memset((void *)&frmsize,0,sizeof(frmsize));
2463 frmsize.index = 0;
2464 frmsize.pixel_format = output_capability;
2465 ret = ioctl(drv_ctx.video_driver_fd,
2466 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2467 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2468 DEBUG_PRINT_ERROR("Failed to get framesizes");
2469 return OMX_ErrorHardware;
2470 }
2471
2472 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2473 m_decoder_capability.min_width = frmsize.stepwise.min_width;
2474 m_decoder_capability.max_width = frmsize.stepwise.max_width;
2475 m_decoder_capability.min_height = frmsize.stepwise.min_height;
2476 m_decoder_capability.max_height = frmsize.stepwise.max_height;
2477 }
2478
2479 /* Based on UBWC enable, decide split mode to driver before calling S_FMT */
2480 eRet = set_dpb(m_disable_ubwc_mode, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
2481
2482 memset(&fmt, 0x0, sizeof(struct v4l2_format));
2483 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2484 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2485 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2486 fmt.fmt.pix_mp.pixelformat = capture_capability;
2487 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2488 if (ret) {
2489 /*TODO: How to handle this case */
2490 DEBUG_PRINT_ERROR("Failed to set format on capture port");
2491 }
2492 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2493 framesize.nWidth = drv_ctx.video_resolution.frame_width;
2494 framesize.nHeight = drv_ctx.video_resolution.frame_height;
2495
2496 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2497 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2498 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2499
2500 DEBUG_PRINT_HIGH("Set Format was successful");
2501 if (secure_mode) {
2502 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2503 control.value = 1;
2504 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2505 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2506 if (ret) {
2507 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2508 return OMX_ErrorInsufficientResources;
2509 }
2510 }
2511
2512 /*Get the Buffer requirements for input and output ports*/
2513 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2514 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2515
2516 if (secure_mode) {
2517 drv_ctx.op_buf.alignment = SECURE_ALIGN;
2518 drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2519 } else {
2520 drv_ctx.op_buf.alignment = SZ_4K;
2521 drv_ctx.ip_buf.alignment = SZ_4K;
2522 }
2523
2524 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2525 drv_ctx.extradata = 0;
2526 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2527 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2528 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2529 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2530 drv_ctx.idr_only_decoding = 0;
2531
2532 #ifdef _ANDROID_
2533 ctrl[0].id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
2534 ctrl[0].value = nBufCount;
2535
2536 controls.count = 1;
2537 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
2538 controls.controls = ctrl;
2539
2540 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_EXT_CTRLS, &controls);
2541 if (ret < 0)
2542 DEBUG_PRINT_HIGH("Failed to set OUTPUT Buffer count Err = %d Count = %d",
2543 ret, nBufCount);
2544
2545 if (m_dec_hfr_fps) {
2546 memset(&query, 0, sizeof(struct v4l2_queryctrl));
2547
2548 query.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
2549 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &query);
2550 if (!ret)
2551 m_dec_hfr_fps = MIN(query.maximum, m_dec_hfr_fps);
2552
2553 DEBUG_PRINT_HIGH("Updated HFR fps value = %d", m_dec_hfr_fps);
2554 }
2555
2556 #endif
2557 m_state = OMX_StateLoaded;
2558 #ifdef DEFAULT_EXTRADATA
2559 enable_extradata(DEFAULT_EXTRADATA, true, true);
2560 #endif
2561 eRet = get_buffer_req(&drv_ctx.ip_buf);
2562 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2563 get_buffer_req(&drv_ctx.op_buf);
2564
2565 msg_thread_created = true;
2566 r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2567
2568 if (r < 0) {
2569 DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2570 msg_thread_created = false;
2571 eRet = OMX_ErrorInsufficientResources;
2572 }
2573 }
2574
2575 {
2576 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2577 init_vendor_extensions(*extStore);
2578 mVendorExtensionStore.dumpExtensions((const char *)role);
2579 }
2580
2581 if (eRet != OMX_ErrorNone) {
2582 DEBUG_PRINT_ERROR("Component Init Failed");
2583 } else {
2584 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2585 drv_ctx.video_driver_fd);
2586 }
2587 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2588
2589 OMX_INIT_STRUCT(&m_sParamLowLatency, QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE);
2590 m_sParamLowLatency.nNumFrames = 0;
2591
2592 return eRet;
2593 }
2594
2595 /* ======================================================================
2596 FUNCTION
2597 omx_vdec::GetComponentVersion
2598
2599 DESCRIPTION
2600 Returns the component version.
2601
2602 PARAMETERS
2603 TBD.
2604
2605 RETURN VALUE
2606 OMX_ErrorNone.
2607
2608 ========================================================================== */
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)2609 OMX_ERRORTYPE omx_vdec::get_component_version
2610 (
2611 OMX_IN OMX_HANDLETYPE hComp,
2612 OMX_OUT OMX_STRING componentName,
2613 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2614 OMX_OUT OMX_VERSIONTYPE* specVersion,
2615 OMX_OUT OMX_UUIDTYPE* componentUUID
2616 )
2617 {
2618 (void) hComp;
2619 (void) componentName;
2620 (void) componentVersion;
2621 (void) componentUUID;
2622 if (m_state == OMX_StateInvalid) {
2623 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2624 return OMX_ErrorInvalidState;
2625 }
2626 /* TBD -- Return the proper version */
2627 if (specVersion) {
2628 specVersion->nVersion = OMX_SPEC_VERSION;
2629 }
2630 return OMX_ErrorNone;
2631 }
2632 /* ======================================================================
2633 FUNCTION
2634 omx_vdec::SendCommand
2635
2636 DESCRIPTION
2637 Returns zero if all the buffers released..
2638
2639 PARAMETERS
2640 None.
2641
2642 RETURN VALUE
2643 true/false
2644
2645 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2646 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2647 OMX_IN OMX_COMMANDTYPE cmd,
2648 OMX_IN OMX_U32 param1,
2649 OMX_IN OMX_PTR cmdData
2650 )
2651 {
2652 (void) hComp;
2653 (void) cmdData;
2654 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2655 if (m_state == OMX_StateInvalid) {
2656 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2657 return OMX_ErrorInvalidState;
2658 }
2659 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2660 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2661 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2662 "to invalid port: %u", (unsigned int)param1);
2663 return OMX_ErrorBadPortIndex;
2664 }
2665
2666 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2667 sem_wait(&m_cmd_lock);
2668 DEBUG_PRINT_LOW("send_command: Command Processed");
2669 return OMX_ErrorNone;
2670 }
2671
2672 /* ======================================================================
2673 FUNCTION
2674 omx_vdec::SendCommand
2675
2676 DESCRIPTION
2677 Returns zero if all the buffers released..
2678
2679 PARAMETERS
2680 None.
2681
2682 RETURN VALUE
2683 true/false
2684
2685 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2686 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2687 OMX_IN OMX_COMMANDTYPE cmd,
2688 OMX_IN OMX_U32 param1,
2689 OMX_IN OMX_PTR cmdData
2690 )
2691 {
2692 (void) hComp;
2693 (void) cmdData;
2694 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2695 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2696 int bFlag = 1,sem_posted = 0,ret=0;
2697
2698 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2699 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2700 m_state, eState);
2701
2702 if (cmd == OMX_CommandStateSet) {
2703 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2704 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2705 /***************************/
2706 /* Current State is Loaded */
2707 /***************************/
2708 if (m_state == OMX_StateLoaded) {
2709 if (eState == OMX_StateIdle) {
2710 //if all buffers are allocated or all ports disabled
2711 if (allocate_done() ||
2712 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2713 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2714 } else {
2715 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2716 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2717 // Skip the event notification
2718 bFlag = 0;
2719 }
2720 }
2721 /* Requesting transition from Loaded to Loaded */
2722 else if (eState == OMX_StateLoaded) {
2723 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2724 post_event(OMX_EventError,OMX_ErrorSameState,\
2725 OMX_COMPONENT_GENERATE_EVENT);
2726 eRet = OMX_ErrorSameState;
2727 }
2728 /* Requesting transition from Loaded to WaitForResources */
2729 else if (eState == OMX_StateWaitForResources) {
2730 /* Since error is None , we will post an event
2731 at the end of this function definition */
2732 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2733 }
2734 /* Requesting transition from Loaded to Executing */
2735 else if (eState == OMX_StateExecuting) {
2736 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2737 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2738 OMX_COMPONENT_GENERATE_EVENT);
2739 eRet = OMX_ErrorIncorrectStateTransition;
2740 }
2741 /* Requesting transition from Loaded to Pause */
2742 else if (eState == OMX_StatePause) {
2743 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2744 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2745 OMX_COMPONENT_GENERATE_EVENT);
2746 eRet = OMX_ErrorIncorrectStateTransition;
2747 }
2748 /* Requesting transition from Loaded to Invalid */
2749 else if (eState == OMX_StateInvalid) {
2750 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2751 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2752 eRet = OMX_ErrorInvalidState;
2753 } else {
2754 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2755 eState);
2756 eRet = OMX_ErrorBadParameter;
2757 }
2758 }
2759
2760 /***************************/
2761 /* Current State is IDLE */
2762 /***************************/
2763 else if (m_state == OMX_StateIdle) {
2764 if (eState == OMX_StateLoaded) {
2765 if (release_done()) {
2766 /*
2767 * Since error is None , we will post an event at the end
2768 * of this function definition
2769 * Reset buffer requirements here to ensure setting buffer requirement
2770 * when component move to executing state from loaded state via Idle.
2771 */
2772 drv_ctx.op_buf.buffer_size = 0;
2773 drv_ctx.op_buf.actualcount = 0;
2774 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2775 } else {
2776 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2777 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2778 // Skip the event notification
2779 bFlag = 0;
2780 }
2781 }
2782 /* Requesting transition from Idle to Executing */
2783 else if (eState == OMX_StateExecuting) {
2784 bFlag = 1;
2785 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2786 m_state=OMX_StateExecuting;
2787 }
2788 /* Requesting transition from Idle to Idle */
2789 else if (eState == OMX_StateIdle) {
2790 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2791 post_event(OMX_EventError,OMX_ErrorSameState,\
2792 OMX_COMPONENT_GENERATE_EVENT);
2793 eRet = OMX_ErrorSameState;
2794 }
2795 /* Requesting transition from Idle to WaitForResources */
2796 else if (eState == OMX_StateWaitForResources) {
2797 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2798 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2799 OMX_COMPONENT_GENERATE_EVENT);
2800 eRet = OMX_ErrorIncorrectStateTransition;
2801 }
2802 /* Requesting transition from Idle to Pause */
2803 else if (eState == OMX_StatePause) {
2804 /*To pause the Video core we need to start the driver*/
2805 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2806 NULL) < */0) {
2807 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2808 omx_report_error ();
2809 eRet = OMX_ErrorHardware;
2810 } else {
2811 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2812 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2813 bFlag = 0;
2814 }
2815 }
2816 /* Requesting transition from Idle to Invalid */
2817 else if (eState == OMX_StateInvalid) {
2818 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2819 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2820 eRet = OMX_ErrorInvalidState;
2821 } else {
2822 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2823 eRet = OMX_ErrorBadParameter;
2824 }
2825 }
2826
2827 /******************************/
2828 /* Current State is Executing */
2829 /******************************/
2830 else if (m_state == OMX_StateExecuting) {
2831 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2832 /* Requesting transition from Executing to Idle */
2833 if (eState == OMX_StateIdle) {
2834 /* Since error is None , we will post an event
2835 at the end of this function definition
2836 */
2837 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2838 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2839 if (!sem_posted) {
2840 sem_posted = 1;
2841 sem_post (&m_cmd_lock);
2842 execute_omx_flush(OMX_ALL);
2843 }
2844 bFlag = 0;
2845 }
2846 /* Requesting transition from Executing to Paused */
2847 else if (eState == OMX_StatePause) {
2848 DEBUG_PRINT_LOW("PAUSE Command Issued");
2849 m_state = OMX_StatePause;
2850 bFlag = 1;
2851 }
2852 /* Requesting transition from Executing to Loaded */
2853 else if (eState == OMX_StateLoaded) {
2854 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2855 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2856 OMX_COMPONENT_GENERATE_EVENT);
2857 eRet = OMX_ErrorIncorrectStateTransition;
2858 }
2859 /* Requesting transition from Executing to WaitForResources */
2860 else if (eState == OMX_StateWaitForResources) {
2861 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2862 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2863 OMX_COMPONENT_GENERATE_EVENT);
2864 eRet = OMX_ErrorIncorrectStateTransition;
2865 }
2866 /* Requesting transition from Executing to Executing */
2867 else if (eState == OMX_StateExecuting) {
2868 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2869 post_event(OMX_EventError,OMX_ErrorSameState,\
2870 OMX_COMPONENT_GENERATE_EVENT);
2871 eRet = OMX_ErrorSameState;
2872 }
2873 /* Requesting transition from Executing to Invalid */
2874 else if (eState == OMX_StateInvalid) {
2875 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2876 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2877 eRet = OMX_ErrorInvalidState;
2878 } else {
2879 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2880 eRet = OMX_ErrorBadParameter;
2881 }
2882 }
2883 /***************************/
2884 /* Current State is Pause */
2885 /***************************/
2886 else if (m_state == OMX_StatePause) {
2887 /* Requesting transition from Pause to Executing */
2888 if (eState == OMX_StateExecuting) {
2889 DEBUG_PRINT_LOW("Pause --> Executing");
2890 m_state = OMX_StateExecuting;
2891 bFlag = 1;
2892 }
2893 /* Requesting transition from Pause to Idle */
2894 else if (eState == OMX_StateIdle) {
2895 /* Since error is None , we will post an event
2896 at the end of this function definition */
2897 DEBUG_PRINT_LOW("Pause --> Idle");
2898 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2899 if (!sem_posted) {
2900 sem_posted = 1;
2901 sem_post (&m_cmd_lock);
2902 execute_omx_flush(OMX_ALL);
2903 }
2904 bFlag = 0;
2905 }
2906 /* Requesting transition from Pause to loaded */
2907 else if (eState == OMX_StateLoaded) {
2908 DEBUG_PRINT_ERROR("Pause --> loaded");
2909 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2910 OMX_COMPONENT_GENERATE_EVENT);
2911 eRet = OMX_ErrorIncorrectStateTransition;
2912 }
2913 /* Requesting transition from Pause to WaitForResources */
2914 else if (eState == OMX_StateWaitForResources) {
2915 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2916 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2917 OMX_COMPONENT_GENERATE_EVENT);
2918 eRet = OMX_ErrorIncorrectStateTransition;
2919 }
2920 /* Requesting transition from Pause to Pause */
2921 else if (eState == OMX_StatePause) {
2922 DEBUG_PRINT_ERROR("Pause --> Pause");
2923 post_event(OMX_EventError,OMX_ErrorSameState,\
2924 OMX_COMPONENT_GENERATE_EVENT);
2925 eRet = OMX_ErrorSameState;
2926 }
2927 /* Requesting transition from Pause to Invalid */
2928 else if (eState == OMX_StateInvalid) {
2929 DEBUG_PRINT_ERROR("Pause --> Invalid");
2930 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2931 eRet = OMX_ErrorInvalidState;
2932 } else {
2933 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2934 eRet = OMX_ErrorBadParameter;
2935 }
2936 }
2937 /***************************/
2938 /* Current State is WaitForResources */
2939 /***************************/
2940 else if (m_state == OMX_StateWaitForResources) {
2941 /* Requesting transition from WaitForResources to Loaded */
2942 if (eState == OMX_StateLoaded) {
2943 /* Since error is None , we will post an event
2944 at the end of this function definition */
2945 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2946 }
2947 /* Requesting transition from WaitForResources to WaitForResources */
2948 else if (eState == OMX_StateWaitForResources) {
2949 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2950 post_event(OMX_EventError,OMX_ErrorSameState,
2951 OMX_COMPONENT_GENERATE_EVENT);
2952 eRet = OMX_ErrorSameState;
2953 }
2954 /* Requesting transition from WaitForResources to Executing */
2955 else if (eState == OMX_StateExecuting) {
2956 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2957 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2958 OMX_COMPONENT_GENERATE_EVENT);
2959 eRet = OMX_ErrorIncorrectStateTransition;
2960 }
2961 /* Requesting transition from WaitForResources to Pause */
2962 else if (eState == OMX_StatePause) {
2963 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2964 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2965 OMX_COMPONENT_GENERATE_EVENT);
2966 eRet = OMX_ErrorIncorrectStateTransition;
2967 }
2968 /* Requesting transition from WaitForResources to Invalid */
2969 else if (eState == OMX_StateInvalid) {
2970 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2971 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2972 eRet = OMX_ErrorInvalidState;
2973 }
2974 /* Requesting transition from WaitForResources to Loaded -
2975 is NOT tested by Khronos TS */
2976
2977 } else {
2978 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2979 eRet = OMX_ErrorBadParameter;
2980 }
2981 }
2982 /********************************/
2983 /* Current State is Invalid */
2984 /*******************************/
2985 else if (m_state == OMX_StateInvalid) {
2986 /* State Transition from Inavlid to any state */
2987 if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState
2988 || OMX_StateIdle == eState || OMX_StateExecuting == eState
2989 || OMX_StatePause == eState || OMX_StateInvalid == eState) {
2990 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2991 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2992 OMX_COMPONENT_GENERATE_EVENT);
2993 eRet = OMX_ErrorInvalidState;
2994 }
2995 } else if (cmd == OMX_CommandFlush) {
2996 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2997 "with param1: %u", (unsigned int)param1);
2998 send_codec_config();
2999 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3000 param1 == OMX_ALL)) {
3001 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3002 struct timespec ts;
3003
3004 clock_gettime(CLOCK_REALTIME, &ts);
3005 ts.tv_sec += 2;
3006 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3007 m_queued_codec_config_count);
3008 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3009 if (sem_timedwait(&m_safe_flush, &ts)) {
3010 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3011 }
3012 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3013 }
3014 }
3015
3016 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3017 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3018 }
3019 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3020 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3021 }
3022 if (!sem_posted) {
3023 sem_posted = 1;
3024 DEBUG_PRINT_LOW("Set the Semaphore");
3025 sem_post (&m_cmd_lock);
3026 execute_omx_flush(param1);
3027 }
3028 bFlag = 0;
3029 } else if ( cmd == OMX_CommandPortEnable) {
3030 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3031 "with param1: %u", (unsigned int)param1);
3032 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3033 m_inp_bEnabled = OMX_TRUE;
3034
3035 if ( (m_state == OMX_StateLoaded &&
3036 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3037 || allocate_input_done()) {
3038 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3039 OMX_COMPONENT_GENERATE_EVENT);
3040 } else {
3041 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3042 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3043 // Skip the event notification
3044 bFlag = 0;
3045 }
3046 }
3047 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3048 DEBUG_PRINT_LOW("Enable output Port command recieved");
3049 m_out_bEnabled = OMX_TRUE;
3050
3051 if ( (m_state == OMX_StateLoaded &&
3052 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3053 || (allocate_output_done())) {
3054 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3055 OMX_COMPONENT_GENERATE_EVENT);
3056
3057 } else {
3058 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3059 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3060 // Skip the event notification
3061 bFlag = 0;
3062 /* enable/disable downscaling if required */
3063 ret = decide_downscalar();
3064 if (ret) {
3065 DEBUG_PRINT_LOW("decide_downscalar failed\n");
3066 }
3067 }
3068 }
3069 } else if (cmd == OMX_CommandPortDisable) {
3070 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3071 "with param1: %u", (unsigned int)param1);
3072 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3073 codec_config_flag = false;
3074 m_inp_bEnabled = OMX_FALSE;
3075 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3076 && release_input_done()) {
3077 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3078 OMX_COMPONENT_GENERATE_EVENT);
3079 } else {
3080 DEBUG_PRINT_HIGH("Set input port disable pending");
3081 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3082 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3083 if (!sem_posted) {
3084 sem_posted = 1;
3085 sem_post (&m_cmd_lock);
3086 }
3087 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3088 }
3089
3090 // Skip the event notification
3091 bFlag = 0;
3092 }
3093 }
3094 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3095 m_out_bEnabled = OMX_FALSE;
3096 DEBUG_PRINT_LOW("Disable output Port command recieved");
3097 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3098 && release_output_done()) {
3099 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3100 OMX_COMPONENT_GENERATE_EVENT);
3101 } else {
3102 DEBUG_PRINT_HIGH("Set output port disable pending");
3103 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3104 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3105 if (!sem_posted) {
3106 sem_posted = 1;
3107 sem_post (&m_cmd_lock);
3108 }
3109 DEBUG_PRINT_HIGH("Set output port flush in disable pending");
3110 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3111 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3112 }
3113 // Skip the event notification
3114 bFlag = 0;
3115
3116 }
3117 }
3118 } else {
3119 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3120 eRet = OMX_ErrorNotImplemented;
3121 }
3122 if (eRet == OMX_ErrorNone && bFlag) {
3123 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3124 }
3125 if (!sem_posted) {
3126 sem_post(&m_cmd_lock);
3127 }
3128
3129 return eRet;
3130 }
3131
3132 /* ======================================================================
3133 FUNCTION
3134 omx_vdec::ExecuteOmxFlush
3135
3136 DESCRIPTION
3137 Executes the OMX flush.
3138
3139 PARAMETERS
3140 flushtype - input flush(1)/output flush(0)/ both.
3141
3142 RETURN VALUE
3143 true/false
3144
3145 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3146 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3147 {
3148 bool bRet = false;
3149 struct v4l2_plane plane;
3150 struct v4l2_buffer v4l2_buf;
3151 struct v4l2_decoder_cmd dec;
3152 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3153 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3154 dec.cmd = V4L2_QCOM_CMD_FLUSH;
3155
3156 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3157
3158 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3159 output_flush_progress = true;
3160 dec.flags = V4L2_QCOM_CMD_FLUSH_CAPTURE;
3161 } else {
3162 /* XXX: The driver/hardware does not support flushing of individual ports
3163 * in all states. So we pretty much need to flush both ports internally,
3164 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3165 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3166 * we automatically omit sending the FLUSH done for the "opposite" port. */
3167 input_flush_progress = true;
3168 output_flush_progress = true;
3169 dec.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT | V4L2_QCOM_CMD_FLUSH_CAPTURE;
3170 }
3171
3172 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3173 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3174 bRet = false;
3175 }
3176
3177 return bRet;
3178 }
3179 /*=========================================================================
3180 FUNCTION : execute_output_flush
3181
3182 DESCRIPTION
3183 Executes the OMX flush at OUTPUT PORT.
3184
3185 PARAMETERS
3186 None.
3187
3188 RETURN VALUE
3189 true/false
3190 ==========================================================================*/
execute_output_flush()3191 bool omx_vdec::execute_output_flush()
3192 {
3193 unsigned long p1 = 0; // Parameter - 1
3194 unsigned long p2 = 0; // Parameter - 2
3195 unsigned long ident = 0;
3196 bool bRet = true;
3197
3198 /*Generate FBD for all Buffers in the FTBq*/
3199 pthread_mutex_lock(&m_lock);
3200 DEBUG_PRINT_LOW("Initiate Output Flush");
3201
3202 //reset last render TS
3203 if(m_last_rendered_TS > 0) {
3204 m_last_rendered_TS = 0;
3205 }
3206
3207 while (m_ftb_q.m_size) {
3208 m_ftb_q.pop_entry(&p1,&p2,&ident);
3209 if (ident == m_fill_output_msg ) {
3210 print_omx_buffer("Flush FBD", (OMX_BUFFERHEADERTYPE *)p2);
3211 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3212 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3213 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3214 }
3215 }
3216 pthread_mutex_unlock(&m_lock);
3217 output_flush_progress = false;
3218
3219 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3220 return bRet;
3221 }
3222 /*=========================================================================
3223 FUNCTION : execute_input_flush
3224
3225 DESCRIPTION
3226 Executes the OMX flush at INPUT PORT.
3227
3228 PARAMETERS
3229 None.
3230
3231 RETURN VALUE
3232 true/false
3233 ==========================================================================*/
execute_input_flush()3234 bool omx_vdec::execute_input_flush()
3235 {
3236 unsigned i =0;
3237 unsigned long p1 = 0; // Parameter - 1
3238 unsigned long p2 = 0; // Parameter - 2
3239 unsigned long ident = 0;
3240 bool bRet = true;
3241
3242 /*Generate EBD for all Buffers in the ETBq*/
3243 DEBUG_PRINT_LOW("Initiate Input Flush");
3244
3245 pthread_mutex_lock(&m_lock);
3246 DEBUG_PRINT_LOW("Check if the Queue is empty");
3247 while (m_etb_q.m_size) {
3248 m_etb_q.pop_entry(&p1,&p2,&ident);
3249
3250 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3251 print_omx_buffer("Flush ETB_ARBITRARY", (OMX_BUFFERHEADERTYPE *)p2);
3252 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3253 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3254 pending_input_buffers++;
3255 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3256 print_omx_buffer("Flush ETB", (OMX_BUFFERHEADERTYPE *)p2);
3257 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3258 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3259 print_omx_buffer("Flush EBD", (OMX_BUFFERHEADERTYPE *)p1);
3260 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3261 }
3262 }
3263 time_stamp_dts.flush_timestamp();
3264 /*Check if Heap Buffers are to be flushed*/
3265 pthread_mutex_unlock(&m_lock);
3266 input_flush_progress = false;
3267 prev_ts = LLONG_MAX;
3268 rst_prev_ts = true;
3269
3270 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3271 return bRet;
3272 }
3273
3274 /*=========================================================================
3275 FUNCTION : notify_flush_done
3276
3277 DESCRIPTION
3278 Notifies flush done to the OMX Client.
3279
3280 PARAMETERS
3281 ctxt -- Context information related to the self..
3282
3283 RETURN VALUE
3284 NONE
3285 ==========================================================================*/
notify_flush_done(void * ctxt)3286 void omx_vdec::notify_flush_done(void *ctxt) {
3287
3288 omx_vdec *pThis = (omx_vdec *) ctxt;
3289
3290 if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3291 if (BITMASK_PRESENT(&pThis->m_flags,
3292 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3293 DEBUG_PRINT_LOW("Notify Output Flush done");
3294 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3295 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3296 OMX_EventCmdComplete,OMX_CommandFlush,
3297 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3298 }
3299
3300 if (BITMASK_PRESENT(&pThis->m_flags,
3301 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3302 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3303 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3304 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3305 OMX_EventCmdComplete,OMX_CommandFlush,
3306 OMX_CORE_INPUT_PORT_INDEX,NULL );
3307 }
3308 }
3309 }
3310
3311 /* ======================================================================
3312 FUNCTION
3313 omx_vdec::SendCommandEvent
3314
3315 DESCRIPTION
3316 Send the event to decoder pipe. This is needed to generate the callbacks
3317 in decoder thread context.
3318
3319 PARAMETERS
3320 None.
3321
3322 RETURN VALUE
3323 true/false
3324
3325 ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3326 bool omx_vdec::post_event(unsigned long p1,
3327 unsigned long p2,
3328 unsigned long id)
3329 {
3330 bool bRet = false;
3331
3332 /* Just drop messages typically generated by hardware (w/o client request),
3333 * if we've reported an error to client. */
3334 if (m_error_propogated) {
3335 switch (id) {
3336 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3337 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3338 DEBUG_PRINT_ERROR("Dropping message %lx "
3339 "since client expected to be in error state", id);
3340 return false;
3341 default:
3342 /* whatever */
3343 break;
3344 }
3345 }
3346
3347 pthread_mutex_lock(&m_lock);
3348
3349 if (id == m_fill_output_msg ||
3350 id == OMX_COMPONENT_GENERATE_FBD ||
3351 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3352 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3353 m_ftb_q.insert_entry(p1,p2,id);
3354 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3355 id == OMX_COMPONENT_GENERATE_EBD ||
3356 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3357 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3358 m_etb_q.insert_entry(p1,p2,id);
3359 } else {
3360 DEBUG_PRINT_HIGH("post_event(%ld, %ld, %ld)", p1, p2, id);
3361 m_cmd_q.insert_entry(p1,p2,id);
3362 }
3363
3364 bRet = true;
3365 post_message(this, id);
3366
3367 pthread_mutex_unlock(&m_lock);
3368
3369 return bRet;
3370 }
3371
vdec_query_cap(struct v4l2_queryctrl & cap)3372 bool inline omx_vdec::vdec_query_cap(struct v4l2_queryctrl &cap) {
3373
3374 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &cap)) {
3375 DEBUG_PRINT_ERROR("Query caps for id = %u failed\n", cap.id);
3376 return false;
3377 }
3378 return true;
3379 }
3380
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3381 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3382 {
3383 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3384 struct v4l2_queryctrl profile_cap, level_cap;
3385 int v4l2_profile;
3386 int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
3387 QOMX_VIDEO_AVCProfileBaseline,
3388 QOMX_VIDEO_AVCProfileMain,
3389 QOMX_VIDEO_AVCProfileConstrainedHigh,
3390 QOMX_VIDEO_AVCProfileHigh };
3391 int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain,
3392 OMX_VIDEO_HEVCProfileMain10,
3393 OMX_VIDEO_HEVCProfileMain10HDR10 };
3394 int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple,
3395 OMX_VIDEO_MPEG2ProfileMain};
3396 int vp9_profiles[2] = { OMX_VIDEO_VP9Profile0,
3397 OMX_VIDEO_VP9Profile2HDR};
3398
3399 if (!profileLevelType)
3400 return OMX_ErrorBadParameter;
3401
3402 memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
3403 memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
3404
3405 if (output_capability == V4L2_PIX_FMT_H264) {
3406 level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3407 profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3408 } else if (output_capability == V4L2_PIX_FMT_VP8) {
3409 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
3410 } else if (output_capability == V4L2_PIX_FMT_VP9) {
3411 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL;
3412 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_PROFILE;
3413 } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3414 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
3415 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
3416 } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3417 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL;
3418 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE;
3419 } else {
3420 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
3421 return OMX_ErrorInvalidComponent;
3422 }
3423
3424 if (profile_cap.id) {
3425 if(!vdec_query_cap(profile_cap)) {
3426 DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
3427 return OMX_ErrorHardware;
3428 }
3429 }
3430
3431 if (level_cap.id) {
3432 if(!vdec_query_cap(level_cap)) {
3433 DEBUG_PRINT_ERROR("Getting capabilities for level failed");
3434 return OMX_ErrorHardware;
3435 }
3436 }
3437
3438 /* Get the corresponding omx level from v4l2 level */
3439 if (!profile_level_converter::convert_v4l2_level_to_omx(output_capability, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
3440 DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
3441 return OMX_ErrorHardware;
3442 }
3443
3444 /* For given profile index get corresponding profile that needs to be supported */
3445 if (profileLevelType->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
3446 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex);
3447 return OMX_ErrorBadPortIndex;
3448 }
3449
3450 if (output_capability == V4L2_PIX_FMT_H264) {
3451 if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
3452 profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
3453 } else {
3454 DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3455 (unsigned int)profileLevelType->nProfileIndex);
3456 return OMX_ErrorNoMore;
3457 }
3458 } else if (output_capability == V4L2_PIX_FMT_VP8) {
3459 if (profileLevelType->nProfileIndex == 0) {
3460 profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
3461 } else {
3462 DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3463 (unsigned int)profileLevelType->nProfileIndex);
3464 return OMX_ErrorNoMore;
3465 }
3466 /* Driver has no notion of VP8 profile. Only one profile is supported. Return this */
3467 return OMX_ErrorNone;
3468 } else if (output_capability == V4L2_PIX_FMT_VP9) {
3469 if (profileLevelType->nProfileIndex < (sizeof(vp9_profiles)/sizeof(int))) {
3470 profileLevelType->eProfile = vp9_profiles[profileLevelType->nProfileIndex];
3471 } else {
3472 DEBUG_PRINT_LOW("VP9: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3473 (unsigned int)profileLevelType->nProfileIndex);
3474 return OMX_ErrorNoMore;
3475 }
3476 } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3477 if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
3478 profileLevelType->eProfile = hevc_profiles[profileLevelType->nProfileIndex];
3479 } else {
3480 DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3481 (unsigned int)profileLevelType->nProfileIndex);
3482 return OMX_ErrorNoMore;
3483 }
3484 } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3485 if (profileLevelType->nProfileIndex < (sizeof(mpeg2_profiles)/sizeof(int))) {
3486 profileLevelType->eProfile = mpeg2_profiles[profileLevelType->nProfileIndex];
3487 } else {
3488 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3489 (unsigned int)profileLevelType->nProfileIndex);
3490 return OMX_ErrorNoMore;
3491 }
3492 }
3493
3494 /* Check if the profile is supported by driver or not */
3495 /* During query caps of profile driver sends a mask of */
3496 /* of all v4l2 profiles supported(in the flags field) */
3497 if(output_capability != V4L2_PIX_FMT_HEVC) {
3498 if (!profile_level_converter::convert_omx_profile_to_v4l2(output_capability, profileLevelType->eProfile, &v4l2_profile)) {
3499 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3500 return OMX_ErrorHardware;
3501 }
3502 }else { //convert omx profile to v4l2 profile for HEVC Main10 and Main10HDR10 profiles,seperately
3503 switch (profileLevelType->eProfile) {
3504 case OMX_VIDEO_HEVCProfileMain:
3505 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
3506 break;
3507 case OMX_VIDEO_HEVCProfileMain10:
3508 case OMX_VIDEO_HEVCProfileMain10HDR10:
3509 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
3510 break;
3511 default:
3512 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3513 return OMX_ErrorHardware;
3514 }
3515 }
3516
3517 if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
3518 DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
3519 eRet = OMX_ErrorNoMore;
3520 }
3521
3522 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
3523 (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
3524 return eRet;
3525 }
3526
3527 /* ======================================================================
3528 FUNCTION
3529 omx_vdec::GetParameter
3530
3531 DESCRIPTION
3532 OMX Get Parameter method implementation
3533
3534 PARAMETERS
3535 <TBD>.
3536
3537 RETURN VALUE
3538 Error None if successful.
3539
3540 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3541 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
3542 OMX_IN OMX_INDEXTYPE paramIndex,
3543 OMX_INOUT OMX_PTR paramData)
3544 {
3545 (void) hComp;
3546 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3547
3548 DEBUG_PRINT_LOW("get_parameter:");
3549 if (m_state == OMX_StateInvalid) {
3550 DEBUG_PRINT_ERROR("Get Param in Invalid State");
3551 return OMX_ErrorInvalidState;
3552 }
3553 if (paramData == NULL) {
3554 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3555 return OMX_ErrorBadParameter;
3556 }
3557 switch ((unsigned long)paramIndex) {
3558 case OMX_IndexParamPortDefinition: {
3559 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3560 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3561 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3562 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3563 if (decide_dpb_buffer_mode(is_down_scalar_enabled)) {
3564 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
3565 return OMX_ErrorBadParameter;
3566 }
3567 eRet = update_portdef(portDefn);
3568 if (eRet == OMX_ErrorNone)
3569 m_port_def = *portDefn;
3570 break;
3571 }
3572 case OMX_IndexParamVideoInit: {
3573 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3574 OMX_PORT_PARAM_TYPE *portParamType =
3575 (OMX_PORT_PARAM_TYPE *) paramData;
3576 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3577
3578 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3579 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3580 portParamType->nPorts = 2;
3581 portParamType->nStartPortNumber = 0;
3582 break;
3583 }
3584 case OMX_IndexParamVideoPortFormat: {
3585 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3586 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3587 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3588 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3589
3590 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3591 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3592
3593 if (0 == portFmt->nPortIndex) {
3594 if (0 == portFmt->nIndex) {
3595 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
3596 portFmt->eCompressionFormat = eCompressionFormat;
3597 } else {
3598 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3599 " NoMore compression formats");
3600 eRet = OMX_ErrorNoMore;
3601 }
3602 } else if (1 == portFmt->nPortIndex) {
3603 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
3604
3605 // Distinguish non-surface mode from normal playback use-case based on
3606 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3607 // For non-android, use the default list
3608 // Also use default format-list if FLEXIBLE YUV is supported,
3609 // as the client negotiates the standard color-format if it needs to
3610 bool useNonSurfaceMode = false;
3611 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3612 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3613 #endif
3614 portFmt->eColorFormat = useNonSurfaceMode ?
3615 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3616 getPreferredColorFormatDefaultMode(portFmt->nIndex);
3617
3618 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3619 eRet = OMX_ErrorNoMore;
3620 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3621 " NoMore Color formats");
3622 }
3623 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3624 } else {
3625 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3626 (int)portFmt->nPortIndex);
3627 eRet = OMX_ErrorBadPortIndex;
3628 }
3629 break;
3630 }
3631 /*Component should support this port definition*/
3632 case OMX_IndexParamAudioInit: {
3633 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3634 OMX_PORT_PARAM_TYPE *audioPortParamType =
3635 (OMX_PORT_PARAM_TYPE *) paramData;
3636 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3637 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3638 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3639 audioPortParamType->nPorts = 0;
3640 audioPortParamType->nStartPortNumber = 0;
3641 break;
3642 }
3643 /*Component should support this port definition*/
3644 case OMX_IndexParamImageInit: {
3645 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3646 OMX_PORT_PARAM_TYPE *imagePortParamType =
3647 (OMX_PORT_PARAM_TYPE *) paramData;
3648 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3649 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3650 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3651 imagePortParamType->nPorts = 0;
3652 imagePortParamType->nStartPortNumber = 0;
3653 break;
3654
3655 }
3656 /*Component should support this port definition*/
3657 case OMX_IndexParamOtherInit: {
3658 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3659 paramIndex);
3660 eRet =OMX_ErrorUnsupportedIndex;
3661 break;
3662 }
3663 case OMX_IndexParamStandardComponentRole: {
3664 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3665 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3666 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3667 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3668 comp_role->nSize = sizeof(*comp_role);
3669
3670 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3671 paramIndex);
3672 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3673 OMX_MAX_STRINGNAME_SIZE);
3674 break;
3675 }
3676 /* Added for parameter test */
3677 case OMX_IndexParamPriorityMgmt: {
3678 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3679 OMX_PRIORITYMGMTTYPE *priorityMgmType =
3680 (OMX_PRIORITYMGMTTYPE *) paramData;
3681 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3682 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3683 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3684
3685 break;
3686 }
3687 /* Added for parameter test */
3688 case OMX_IndexParamCompBufferSupplier: {
3689 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3690 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3691 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3692 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3693
3694 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3695 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3696 if (0 == bufferSupplierType->nPortIndex)
3697 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3698 else if (1 == bufferSupplierType->nPortIndex)
3699 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3700 else
3701 eRet = OMX_ErrorBadPortIndex;
3702
3703
3704 break;
3705 }
3706 case OMX_IndexParamVideoAvc: {
3707 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3708 paramIndex);
3709 break;
3710 }
3711 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3712 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3713 paramIndex);
3714 break;
3715 }
3716 case OMX_IndexParamVideoMpeg2: {
3717 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3718 paramIndex);
3719 break;
3720 }
3721 case OMX_IndexParamVideoProfileLevelQuerySupported: {
3722 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3723 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3724 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3725 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3726 eRet = get_supported_profile_level(profileLevelType);
3727 break;
3728 }
3729 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3730 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3731 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3732 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3733 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3734 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3735
3736 if (secure_mode && !secure_scaling_to_non_secure_opb) {
3737 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3738 GRALLOC_USAGE_PRIVATE_UNCACHED);
3739 } else {
3740 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3741 }
3742 } else {
3743 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3744 eRet = OMX_ErrorBadParameter;
3745 }
3746 }
3747 break;
3748 #endif
3749
3750 #ifdef FLEXYUV_SUPPORTED
3751 case OMX_QcomIndexFlexibleYUVDescription: {
3752 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3753 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3754 eRet = describeColorFormat(paramData);
3755 break;
3756 }
3757 #endif
3758 case OMX_IndexParamVideoProfileLevelCurrent: {
3759 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3760 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3761 struct v4l2_control profile_control, level_control;
3762
3763 switch (drv_ctx.decoder_format) {
3764 case VDEC_CODECTYPE_H264:
3765 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3766 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3767 break;
3768 default:
3769 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3770 eRet = OMX_ErrorNotImplemented;
3771 break;
3772 }
3773
3774 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3775 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3776 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3777 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3778 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3779 break;
3780 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3781 pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3782 break;
3783 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3784 pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3785 break;
3786 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3787 pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3788 break;
3789 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3790 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3791 break;
3792 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3793 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3794 break;
3795 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3796 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3797 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3798 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3799 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3800 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3801 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3802 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3803 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3804 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3805 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3806 eRet = OMX_ErrorUnsupportedIndex;
3807 break;
3808 }
3809 } else {
3810 eRet = OMX_ErrorUnsupportedIndex;
3811 }
3812
3813
3814 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3815 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3816 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3817 pParam->eLevel = OMX_VIDEO_AVCLevel1;
3818 break;
3819 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3820 pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3821 break;
3822 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3823 pParam->eLevel = OMX_VIDEO_AVCLevel11;
3824 break;
3825 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3826 pParam->eLevel = OMX_VIDEO_AVCLevel12;
3827 break;
3828 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3829 pParam->eLevel = OMX_VIDEO_AVCLevel13;
3830 break;
3831 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3832 pParam->eLevel = OMX_VIDEO_AVCLevel2;
3833 break;
3834 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3835 pParam->eLevel = OMX_VIDEO_AVCLevel21;
3836 break;
3837 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3838 pParam->eLevel = OMX_VIDEO_AVCLevel22;
3839 break;
3840 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
3841 pParam->eLevel = OMX_VIDEO_AVCLevel3;
3842 break;
3843 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
3844 pParam->eLevel = OMX_VIDEO_AVCLevel31;
3845 break;
3846 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
3847 pParam->eLevel = OMX_VIDEO_AVCLevel32;
3848 break;
3849 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
3850 pParam->eLevel = OMX_VIDEO_AVCLevel4;
3851 break;
3852 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
3853 pParam->eLevel = OMX_VIDEO_AVCLevel41;
3854 break;
3855 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
3856 pParam->eLevel = OMX_VIDEO_AVCLevel42;
3857 break;
3858 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
3859 pParam->eLevel = OMX_VIDEO_AVCLevel5;
3860 break;
3861 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
3862 pParam->eLevel = OMX_VIDEO_AVCLevel51;
3863 break;
3864 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
3865 pParam->eLevel = OMX_VIDEO_AVCLevel52;
3866 break;
3867 default:
3868 eRet = OMX_ErrorUnsupportedIndex;
3869 break;
3870 }
3871 } else {
3872 eRet = OMX_ErrorUnsupportedIndex;
3873 }
3874
3875 break;
3876
3877 }
3878 case OMX_QTIIndexParamVideoClientExtradata:
3879 {
3880 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
3881 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
3882 QOMX_EXTRADATA_ENABLE *pParam =
3883 (QOMX_EXTRADATA_ENABLE *)paramData;
3884 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
3885 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE;
3886 eRet = OMX_ErrorNone;
3887 } else {
3888 eRet = OMX_ErrorUnsupportedIndex;
3889 }
3890 break;
3891 }
3892 case OMX_QTIIndexParamDitherControl:
3893 {
3894 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
3895 DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
3896 QOMX_VIDEO_DITHER_CONTROL *pParam =
3897 (QOMX_VIDEO_DITHER_CONTROL *) paramData;
3898 pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
3899 eRet = OMX_ErrorNone;
3900 break;
3901 }
3902 case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
3903 {
3904 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3905 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
3906 OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam =
3907 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) paramData;
3908 pParam->eProfile = mClientSetProfile;
3909 pParam->eLevel = mClientSetLevel;
3910 eRet = OMX_ErrorNone;
3911 break;
3912 }
3913 default: {
3914 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3915 eRet =OMX_ErrorUnsupportedIndex;
3916 }
3917
3918 }
3919
3920 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3921 drv_ctx.video_resolution.frame_width,
3922 drv_ctx.video_resolution.frame_height,
3923 drv_ctx.video_resolution.stride,
3924 drv_ctx.video_resolution.scan_lines);
3925
3926 return eRet;
3927 }
3928
3929 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3930 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3931 {
3932 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3933 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3934 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3935
3936 if ((params == NULL) ||
3937 (params->nativeBuffer == NULL) ||
3938 (params->nativeBuffer->handle == NULL) ||
3939 !m_enable_android_native_buffers)
3940 return OMX_ErrorBadParameter;
3941 m_use_android_native_buffers = OMX_TRUE;
3942 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3943 private_handle_t *handle = (private_handle_t *)nBuf->handle;
3944 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3945 OMX_U8 *buffer = NULL;
3946 if (!secure_mode) {
3947 buffer = (OMX_U8*)mmap(0, handle->size,
3948 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3949 if (buffer == MAP_FAILED) {
3950 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3951 return OMX_ErrorInsufficientResources;
3952 }
3953 }
3954 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3955 } else {
3956 eRet = OMX_ErrorBadParameter;
3957 }
3958 return eRet;
3959 }
3960 #endif
3961
enable_smoothstreaming()3962 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3963 struct v4l2_control control;
3964 struct v4l2_format fmt;
3965 /*control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3966 control.value = 1;
3967 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3968 if (rc < 0) {
3969 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3970 return OMX_ErrorHardware;
3971 }*/
3972 m_smoothstreaming_mode = true;
3973 return OMX_ErrorNone;
3974 }
3975
3976 /* ======================================================================
3977 FUNCTION
3978 omx_vdec::Setparameter
3979
3980 DESCRIPTION
3981 OMX Set Parameter method implementation.
3982
3983 PARAMETERS
3984 <TBD>.
3985
3986 RETURN VALUE
3987 OMX Error None if successful.
3988
3989 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3990 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
3991 OMX_IN OMX_INDEXTYPE paramIndex,
3992 OMX_IN OMX_PTR paramData)
3993 {
3994 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3995 int ret=0;
3996 struct v4l2_format fmt;
3997 #ifdef _ANDROID_
3998 char property_value[PROPERTY_VALUE_MAX] = {0};
3999 #endif
4000 if (m_state == OMX_StateInvalid) {
4001 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4002 return OMX_ErrorInvalidState;
4003 }
4004 if (paramData == NULL) {
4005 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4006 return OMX_ErrorBadParameter;
4007 }
4008 if ((m_state != OMX_StateLoaded) &&
4009 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4010 (m_out_bEnabled == OMX_TRUE) &&
4011 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4012 (m_inp_bEnabled == OMX_TRUE)) {
4013 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4014 return OMX_ErrorIncorrectStateOperation;
4015 }
4016 switch ((unsigned long)paramIndex) {
4017 case OMX_IndexParamPortDefinition: {
4018 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4019 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4020 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4021 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4022 //been called.
4023 DEBUG_PRINT_LOW(
4024 "set_parameter: OMX_IndexParamPortDefinition: dir %d port %d wxh %dx%d count: min %d actual %d size %d",
4025 (int)portDefn->eDir, (int)portDefn->nPortIndex,
4026 (int)portDefn->format.video.nFrameWidth,
4027 (int)portDefn->format.video.nFrameHeight,
4028 (int)portDefn->nBufferCountMin,
4029 (int)portDefn->nBufferCountActual,
4030 (int)portDefn->nBufferSize);
4031
4032 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4033 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4034 portDefn->nBufferCountActual);
4035 eRet = OMX_ErrorBadParameter;
4036 break;
4037 }
4038 if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
4039 if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS ||
4040 portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
4041 DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
4042 portDefn->nBufferCountActual, portDefn->nBufferSize);
4043 eRet = OMX_ErrorBadParameter;
4044 break;
4045 }
4046 m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
4047 portDefn->nBufferCountActual);
4048 break;
4049 }
4050
4051 if (OMX_DirOutput == portDefn->eDir) {
4052 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4053 bool port_format_changed = false;
4054 m_display_id = portDefn->format.video.pNativeWindow;
4055 unsigned int buffer_size;
4056 /* update output port resolution with client supplied dimensions
4057 in case scaling is enabled, else it follows input resolution set
4058 */
4059 if (decide_dpb_buffer_mode(is_down_scalar_enabled)) {
4060 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
4061 return OMX_ErrorBadParameter;
4062 }
4063 if (is_down_scalar_enabled) {
4064 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4065 (unsigned int)portDefn->format.video.nFrameWidth,
4066 (unsigned int)portDefn->format.video.nFrameHeight);
4067 if (portDefn->format.video.nFrameHeight != 0x0 &&
4068 portDefn->format.video.nFrameWidth != 0x0) {
4069 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4070 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4071 fmt.fmt.pix_mp.pixelformat = capture_capability;
4072 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4073 if (ret) {
4074 DEBUG_PRINT_ERROR("Get Resolution failed");
4075 eRet = OMX_ErrorHardware;
4076 break;
4077 }
4078 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4079 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4080 port_format_changed = true;
4081 }
4082
4083 /* set crop info */
4084 rectangle.nLeft = 0;
4085 rectangle.nTop = 0;
4086 rectangle.nWidth = portDefn->format.video.nFrameWidth;
4087 rectangle.nHeight = portDefn->format.video.nFrameHeight;
4088
4089 m_extradata_info.output_crop_rect.nLeft = 0;
4090 m_extradata_info.output_crop_rect.nTop = 0;
4091 m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4092 m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4093
4094 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4095 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4096 fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4097 fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4098 fmt.fmt.pix_mp.pixelformat = capture_capability;
4099 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4100 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4101 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4102 if (ret) {
4103 DEBUG_PRINT_ERROR("Set Resolution failed");
4104 eRet = OMX_ErrorUnsupportedSetting;
4105 } else
4106 eRet = get_buffer_req(&drv_ctx.op_buf);
4107 }
4108
4109 if (eRet) {
4110 break;
4111 }
4112 }
4113
4114 if (eRet) {
4115 break;
4116 }
4117
4118 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4119 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4120 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4121 eRet = OMX_ErrorBadParameter;
4122 } else if (!client_buffers.get_buffer_req(buffer_size)) {
4123 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4124 eRet = OMX_ErrorBadParameter;
4125 } else if (!port_format_changed) {
4126
4127 // Buffer count can change only when port is unallocated
4128 if (m_out_mem_ptr &&
4129 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4130 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4131
4132 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4133 eRet = OMX_ErrorInvalidState;
4134 break;
4135 }
4136
4137 // route updating of buffer requirements via c2d proxy.
4138 // Based on whether c2d is enabled, requirements will be handed
4139 // to the vidc driver appropriately
4140 eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4141 portDefn->nBufferCountActual);
4142 if (eRet == OMX_ErrorNone) {
4143 m_port_def = *portDefn;
4144 } else {
4145 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4146 drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4147 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4148 eRet = OMX_ErrorBadParameter;
4149 }
4150 }
4151 } else if (OMX_DirInput == portDefn->eDir) {
4152 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4153 bool port_format_changed = false;
4154 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4155 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4156 // Frame rate only should be set if this is a "known value" or to
4157 // activate ts prediction logic (arbitrary mode only) sending input
4158 // timestamps with max value (LLONG_MAX).
4159 m_fps_received = portDefn->format.video.xFramerate;
4160 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4161 (unsigned int)portDefn->format.video.xFramerate >> 16);
4162 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4163 drv_ctx.frame_rate.fps_denominator);
4164 if (!drv_ctx.frame_rate.fps_numerator) {
4165 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4166 drv_ctx.frame_rate.fps_numerator = 30;
4167 }
4168 if (drv_ctx.frame_rate.fps_denominator)
4169 drv_ctx.frame_rate.fps_numerator = (int)
4170 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4171 drv_ctx.frame_rate.fps_denominator = 1;
4172 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4173 drv_ctx.frame_rate.fps_numerator;
4174 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4175 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4176 (float)drv_ctx.frame_rate.fps_denominator);
4177
4178 struct v4l2_outputparm oparm;
4179 /*XXX: we're providing timing info as seconds per frame rather than frames
4180 * per second.*/
4181 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4182 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4183
4184 struct v4l2_streamparm sparm;
4185 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4186 sparm.parm.output = oparm;
4187 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4188 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4189 eRet = OMX_ErrorHardware;
4190 break;
4191 }
4192 }
4193
4194 if (drv_ctx.video_resolution.frame_height !=
4195 portDefn->format.video.nFrameHeight ||
4196 drv_ctx.video_resolution.frame_width !=
4197 portDefn->format.video.nFrameWidth) {
4198 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4199 (unsigned int)portDefn->format.video.nFrameWidth,
4200 (unsigned int)portDefn->format.video.nFrameHeight);
4201 port_format_changed = true;
4202 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4203 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4204 if (frameHeight != 0x0 && frameWidth != 0x0) {
4205 if (m_smoothstreaming_mode &&
4206 ((frameWidth * frameHeight) <
4207 (m_smoothstreaming_width * m_smoothstreaming_height))) {
4208 frameWidth = m_smoothstreaming_width;
4209 frameHeight = m_smoothstreaming_height;
4210 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4211 "for adaptive-playback/smooth-streaming",
4212 (unsigned int)frameWidth, (unsigned int)frameHeight);
4213 }
4214
4215 m_extradata_info.output_crop_rect.nLeft = 0;
4216 m_extradata_info.output_crop_rect.nTop = 0;
4217 m_extradata_info.output_crop_rect.nWidth = frameWidth;
4218 m_extradata_info.output_crop_rect.nHeight = frameHeight;
4219
4220 update_resolution(frameWidth, frameHeight,
4221 frameWidth, frameHeight);
4222 if (is_down_scalar_enabled) {
4223 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4224 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4225 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4226 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4227 fmt.fmt.pix_mp.pixelformat = output_capability;
4228 DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4229 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4230 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4231 } else {
4232 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4233 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4234 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4235 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4236 fmt.fmt.pix_mp.pixelformat = output_capability;
4237 DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4238 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4239 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4240 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4241 fmt.fmt.pix_mp.pixelformat = capture_capability;
4242 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4243 }
4244 if (ret) {
4245 DEBUG_PRINT_ERROR("Set Resolution failed");
4246 eRet = OMX_ErrorUnsupportedSetting;
4247 } else {
4248 if (!is_down_scalar_enabled)
4249 eRet = get_buffer_req(&drv_ctx.op_buf);
4250 }
4251 if (eRet)
4252 break;
4253 }
4254 }
4255 if (m_custom_buffersize.input_buffersize
4256 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4257 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4258 m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4259 eRet = OMX_ErrorBadParameter;
4260 break;
4261 }
4262 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4263 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4264 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4265 eRet = OMX_ErrorBadParameter;
4266 break;
4267 }
4268 // Buffer count can change only when port is unallocated
4269 if (m_inp_mem_ptr &&
4270 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4271 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4272 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4273 eRet = OMX_ErrorInvalidState;
4274 break;
4275 }
4276
4277 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4278 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4279 port_format_changed = true;
4280 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4281 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4282 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4283 (~(buffer_prop->alignment - 1));
4284 eRet = set_buffer_req(buffer_prop);
4285 }
4286 if (false == port_format_changed) {
4287 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4288 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4289 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4290 eRet = OMX_ErrorBadParameter;
4291 }
4292 } else if (portDefn->eDir == OMX_DirMax) {
4293 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4294 (int)portDefn->nPortIndex);
4295 eRet = OMX_ErrorBadPortIndex;
4296 }
4297 }
4298 break;
4299 case OMX_IndexParamVideoPortFormat: {
4300 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4301 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4302 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4303 int ret=0;
4304 struct v4l2_format fmt;
4305 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4306 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4307
4308 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4309 if (1 == portFmt->nPortIndex) {
4310 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4311 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4312 if (ret < 0) {
4313 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4314 return OMX_ErrorBadParameter;
4315 }
4316 enum vdec_output_format op_format;
4317 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4318 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4319 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4320 op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12;
4321 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4322 //check if the required color format is a supported flexible format
4323 is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4324 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4325 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed ||
4326 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar) {
4327 op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12_UBWC;
4328 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4329 //check if the required color format is a supported flexible format
4330 is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4331 } else {
4332 eRet = OMX_ErrorBadParameter;
4333 }
4334
4335 if (eRet == OMX_ErrorNone) {
4336 drv_ctx.output_format = op_format;
4337 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4338 if (ret) {
4339 DEBUG_PRINT_ERROR("Set output format failed");
4340 eRet = OMX_ErrorUnsupportedSetting;
4341 /*TODO: How to handle this case */
4342 } else {
4343 eRet = get_buffer_req(&drv_ctx.op_buf);
4344 }
4345 }
4346 if (eRet == OMX_ErrorNone) {
4347 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4348 DEBUG_PRINT_ERROR("Set color format failed");
4349 eRet = OMX_ErrorBadParameter;
4350 }
4351 }
4352 }
4353 }
4354 break;
4355 case OMX_QTIIndexParamVideoClientExtradata: {
4356 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4357 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
4358 QOMX_EXTRADATA_ENABLE *pParam =
4359 (QOMX_EXTRADATA_ENABLE *)paramData;
4360
4361 if (m_state != OMX_StateLoaded) {
4362 DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
4363 return OMX_ErrorIncorrectStateOperation;
4364 }
4365
4366 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4367 m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
4368 } else {
4369 DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
4370 eRet = OMX_ErrorUnsupportedIndex;
4371 }
4372 break;
4373 }
4374 case OMX_IndexParamStandardComponentRole: {
4375 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4376 OMX_PARAM_COMPONENTROLETYPE *comp_role;
4377 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4378 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4379 comp_role->cRole);
4380
4381 if ((m_state == OMX_StateLoaded)&&
4382 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4383 DEBUG_PRINT_LOW("Set Parameter called in valid state");
4384 } else {
4385 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4386 return OMX_ErrorIncorrectStateOperation;
4387 }
4388
4389 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4390 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4391 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4392 } else {
4393 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4394 eRet =OMX_ErrorUnsupportedSetting;
4395 }
4396 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4397 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4398 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4399 } else {
4400 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4401 eRet = OMX_ErrorUnsupportedSetting;
4402 }
4403 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4404 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4405 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4406 } else {
4407 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4408 eRet = OMX_ErrorUnsupportedSetting;
4409 }
4410 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4411 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4412 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4413 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4414 } else {
4415 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4416 eRet = OMX_ErrorUnsupportedSetting;
4417 }
4418 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4419 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4420 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4421 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4422 } else {
4423 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4424 eRet = OMX_ErrorUnsupportedSetting;
4425 }
4426 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4427 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4428 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4429 } else {
4430 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4431 eRet = OMX_ErrorUnsupportedSetting;
4432 }
4433 } else {
4434 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4435 eRet = OMX_ErrorInvalidComponentName;
4436 }
4437 break;
4438 }
4439
4440 case OMX_IndexParamPriorityMgmt: {
4441 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4442 if (m_state != OMX_StateLoaded) {
4443 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4444 return OMX_ErrorIncorrectStateOperation;
4445 }
4446 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4447 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4448 (unsigned int)priorityMgmtype->nGroupID);
4449
4450 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4451 (unsigned int)priorityMgmtype->nGroupPriority);
4452
4453 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4454 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4455
4456 break;
4457 }
4458
4459 case OMX_IndexParamCompBufferSupplier: {
4460 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4461 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4462 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4463 bufferSupplierType->eBufferSupplier);
4464 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4465 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4466
4467 else
4468
4469 eRet = OMX_ErrorBadPortIndex;
4470
4471 break;
4472
4473 }
4474 case OMX_IndexParamVideoAvc: {
4475 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4476 paramIndex);
4477 break;
4478 }
4479 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4480 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4481 paramIndex);
4482 break;
4483 }
4484 case OMX_IndexParamVideoMpeg2: {
4485 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4486 paramIndex);
4487 break;
4488 }
4489 case OMX_QTIIndexParamLowLatencyMode: {
4490 struct v4l2_control control;
4491 int rc = 0;
4492 QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE* pParam =
4493 (QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
4494 control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
4495 if (pParam->bEnableLowLatencyMode)
4496 control.value = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_ENABLE;
4497 else
4498 control.value = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_DISABLE;
4499
4500 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4501 if (rc) {
4502 DEBUG_PRINT_ERROR("Set low latency failed");
4503 eRet = OMX_ErrorUnsupportedSetting;
4504 }
4505 break;
4506 }
4507 case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4508 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4509 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4510 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4511 struct v4l2_control control;
4512 int pic_order,rc=0;
4513 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4514 pictureOrder->eOutputPictureOrder);
4515 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4516 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4517 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4518 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4519 time_stamp_dts.set_timestamp_reorder_mode(false);
4520 } else
4521 eRet = OMX_ErrorBadParameter;
4522 if (eRet == OMX_ErrorNone) {
4523 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4524 control.value = pic_order;
4525 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4526 if (rc) {
4527 DEBUG_PRINT_ERROR("Set picture order failed");
4528 eRet = OMX_ErrorUnsupportedSetting;
4529 }
4530 }
4531 m_decode_order_mode =
4532 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4533 break;
4534 }
4535 case OMX_QcomIndexParamConcealMBMapExtraData:
4536 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4537 eRet = enable_extradata(OMX_MB_ERROR_MAP_EXTRADATA, false,
4538 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4539 break;
4540 case OMX_QcomIndexParamFrameInfoExtraData:
4541 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4542 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4543 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4544 break;
4545 case OMX_ExtraDataFrameDimension:
4546 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4547 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4548 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4549 break;
4550 case OMX_QcomIndexParamInterlaceExtraData:
4551 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4552 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4553 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4554 break;
4555 case OMX_QcomIndexParamOutputCropExtraData:
4556 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4557 eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4558 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4559 break;
4560 case OMX_QcomIndexParamH264TimeInfo:
4561 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4562 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4563 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4564 break;
4565 case OMX_QcomIndexParamVideoFramePackingExtradata:
4566 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4567 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4568 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4569 break;
4570 case OMX_QcomIndexParamVideoQPExtraData:
4571 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4572 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4573 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4574 break;
4575 case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4576 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4577 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4578 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4579 break;
4580 case OMX_QcomIndexEnableExtnUserData:
4581 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4582 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4583 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4584 break;
4585 case OMX_QTIIndexParamVQZipSEIExtraData:
4586 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4587 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4588 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4589 break;
4590 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4591 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4592 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4593 struct v4l2_control control;
4594 int rc;
4595 drv_ctx.idr_only_decoding = 1;
4596 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4597 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4598 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4599 if (rc) {
4600 DEBUG_PRINT_ERROR("Set picture order failed");
4601 eRet = OMX_ErrorUnsupportedSetting;
4602 } else {
4603 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4604 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4605 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4606 if (rc) {
4607 DEBUG_PRINT_ERROR("Sync frame setting failed");
4608 eRet = OMX_ErrorUnsupportedSetting;
4609 }
4610 /*Setting sync frame decoding on driver might change buffer
4611 * requirements so update them here*/
4612 if (get_buffer_req(&drv_ctx.ip_buf)) {
4613 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4614 eRet = OMX_ErrorUnsupportedSetting;
4615 }
4616 if (get_buffer_req(&drv_ctx.op_buf)) {
4617 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4618 eRet = OMX_ErrorUnsupportedSetting;
4619 }
4620 }
4621 }
4622 break;
4623
4624 case OMX_QcomIndexParamIndexExtraDataType: {
4625 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4626 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4627 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4628 (extradataIndexType->bEnabled == OMX_TRUE) &&
4629 (extradataIndexType->nPortIndex == 1)) {
4630 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4631 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4632 } else if ((extradataIndexType->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataOutputCropInfo) &&
4633 (extradataIndexType->bEnabled == OMX_TRUE) &&
4634 (extradataIndexType->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX)) {
4635 eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4636 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4637 }
4638 }
4639 break;
4640 case OMX_QcomIndexParamEnableSmoothStreaming: {
4641 #ifndef SMOOTH_STREAMING_DISABLED
4642 eRet = enable_smoothstreaming();
4643 #else
4644 eRet = OMX_ErrorUnsupportedSetting;
4645 #endif
4646 }
4647 break;
4648 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4649 /* Need to allow following two set_parameters even in Idle
4650 * state. This is ANDROID architecture which is not in sync
4651 * with openmax standard. */
4652 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4653 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4654 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4655 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4656 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4657 eRet = OMX_ErrorUnsupportedSetting;
4658 break;
4659 } else if (m_out_mem_ptr) {
4660 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4661 eRet = OMX_ErrorInvalidState;
4662 break;
4663 }
4664 if (enableNativeBuffers) {
4665 m_enable_android_native_buffers = enableNativeBuffers->enable;
4666 }
4667 #if !defined(FLEXYUV_SUPPORTED)
4668 if (m_enable_android_native_buffers) {
4669 // Use the most-preferred-native-color-format as surface-mode is hinted here
4670 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4671 DEBUG_PRINT_ERROR("Failed to set native color format!");
4672 eRet = OMX_ErrorUnsupportedSetting;
4673 }
4674 }
4675 #endif
4676 }
4677 break;
4678 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4679 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4680 eRet = use_android_native_buffer(hComp, paramData);
4681 }
4682 break;
4683 #if ALLOCATE_OUTPUT_NATIVEHANDLE
4684 case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4685
4686 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4687 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4688
4689 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4690 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
4691 eRet = OMX_ErrorUnsupportedSetting;
4692 break;
4693 } else if (m_inp_mem_ptr) {
4694 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4695 eRet = OMX_ErrorInvalidState;
4696 break;
4697 }
4698
4699 if (allocateNativeHandleParams != NULL) {
4700 allocate_native_handle = allocateNativeHandleParams->enable;
4701 }
4702 }
4703 break;
4704 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
4705 #endif
4706 case OMX_QcomIndexParamEnableTimeStampReorder: {
4707 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4708 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4709 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4710 if (reorder->bEnable == OMX_TRUE) {
4711 frm_int =0;
4712 time_stamp_dts.set_timestamp_reorder_mode(true);
4713 } else
4714 time_stamp_dts.set_timestamp_reorder_mode(false);
4715 } else {
4716 time_stamp_dts.set_timestamp_reorder_mode(false);
4717 if (reorder->bEnable == OMX_TRUE) {
4718 eRet = OMX_ErrorUnsupportedSetting;
4719 }
4720 }
4721 }
4722 break;
4723 case OMX_IndexParamVideoProfileLevelCurrent: {
4724 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4725 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4726 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4727 if (pParam) {
4728 m_profile_lvl.eProfile = pParam->eProfile;
4729 m_profile_lvl.eLevel = pParam->eLevel;
4730 }
4731 break;
4732
4733 }
4734 case OMX_QcomIndexParamVideoMetaBufferMode:
4735 {
4736 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4737 StoreMetaDataInBuffersParams *metabuffer =
4738 (StoreMetaDataInBuffersParams *)paramData;
4739 if (!metabuffer) {
4740 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4741 eRet = OMX_ErrorBadParameter;
4742 break;
4743 }
4744 if (m_disable_dynamic_buf_mode) {
4745 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4746 eRet = OMX_ErrorUnsupportedSetting;
4747 break;
4748 }
4749 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4750
4751 if (m_out_mem_ptr) {
4752 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
4753 eRet = OMX_ErrorInvalidState;
4754 break;
4755 }
4756
4757 dynamic_buf_mode = metabuffer->bStoreMetaData;
4758 DEBUG_PRINT_HIGH("%s buffer mode",
4759 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4760
4761 } else {
4762 DEBUG_PRINT_ERROR(
4763 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4764 (unsigned int)metabuffer->nPortIndex);
4765 eRet = OMX_ErrorUnsupportedSetting;
4766 }
4767 break;
4768 }
4769 case OMX_QcomIndexParamVideoDownScalar:
4770 {
4771 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4772 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4773 struct v4l2_control control;
4774 int rc;
4775 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
4776
4777 if (pParam && pParam->bEnable) {
4778 rc = enable_downscalar();
4779 if (rc < 0) {
4780 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
4781 return OMX_ErrorUnsupportedSetting;
4782 }
4783 m_force_down_scalar = pParam->bEnable;
4784 } else {
4785 rc = disable_downscalar();
4786 if (rc < 0) {
4787 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
4788 return OMX_ErrorUnsupportedSetting;
4789 }
4790 m_force_down_scalar = pParam->bEnable;
4791 }
4792 break;
4793 }
4794 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4795 case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4796 {
4797 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4798 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4799 PrepareForAdaptivePlaybackParams* pParams =
4800 (PrepareForAdaptivePlaybackParams *) paramData;
4801 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4802 if (!pParams->bEnable) {
4803 return OMX_ErrorNone;
4804 }
4805 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4806 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4807 DEBUG_PRINT_ERROR(
4808 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4809 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4810 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4811 eRet = OMX_ErrorBadParameter;
4812 } else {
4813 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4814 }
4815 } else {
4816 DEBUG_PRINT_ERROR(
4817 "Prepare for adaptive playback supported only on output port");
4818 eRet = OMX_ErrorBadParameter;
4819 }
4820 break;
4821 }
4822
4823 case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
4824 {
4825 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4826 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
4827 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4828 if (m_disable_dynamic_buf_mode) {
4829 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
4830 }
4831 break;
4832 }
4833 #endif
4834 case OMX_QcomIndexParamVideoCustomBufferSize:
4835 {
4836 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4837 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4838 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4839 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4840 struct v4l2_control control;
4841 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4842 control.value = pParam->nBufferSize;
4843 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4844 DEBUG_PRINT_ERROR("Failed to set input buffer size");
4845 eRet = OMX_ErrorUnsupportedSetting;
4846 } else {
4847 eRet = get_buffer_req(&drv_ctx.ip_buf);
4848 if (eRet == OMX_ErrorNone) {
4849 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4850 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4851 m_custom_buffersize.input_buffersize);
4852 } else {
4853 DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4854 }
4855 }
4856 } else {
4857 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4858 eRet = OMX_ErrorBadParameter;
4859 }
4860 break;
4861 }
4862 case OMX_QTIIndexParamVQZIPSEIType:
4863 {
4864 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
4865 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
4866 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
4867 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
4868 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
4869
4870 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4871 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4872 if (eRet != OMX_ErrorNone) {
4873 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
4874 eRet = OMX_ErrorBadParameter;
4875 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4876 break;
4877 }
4878 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4879 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4880 if (eRet != OMX_ErrorNone) {
4881 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
4882 eRet = OMX_ErrorBadParameter;
4883 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4884 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4885 break;
4886 }
4887 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4888 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4889 if (eRet != OMX_ErrorNone) {
4890 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
4891 eRet = OMX_ErrorBadParameter;
4892 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4893 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4894 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
4895 }
4896 break;
4897 }
4898 case OMX_QTIIndexParamPassInputBufferFd:
4899 {
4900 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4901 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4902 if (m_input_pass_buffer_fd)
4903 DEBUG_PRINT_LOW("Enable passing input buffer FD");
4904 break;
4905 }
4906 case OMX_QTIIndexParamForceCompressedForDPB:
4907 {
4908 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
4909 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
4910 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
4911 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
4912 if (m_disable_ubwc_mode) {
4913 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
4914 eRet = OMX_ErrorUnsupportedSetting;
4915 break;
4916 }
4917 if (!paramData) {
4918 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
4919 eRet = OMX_ErrorBadParameter;
4920 break;
4921 }
4922
4923 m_force_compressed_for_dpb = pParam->bEnable;
4924 break;
4925 }
4926 case OMX_QTIIndexParamForceUnCompressedForOPB:
4927 {
4928 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
4929 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
4930 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
4931 if (!paramData) {
4932 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
4933 eRet = OMX_ErrorBadParameter;
4934 break;
4935 }
4936 m_disable_ubwc_mode = pParam->bEnable;
4937 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
4938 break;
4939 }
4940 case OMX_QTIIndexParamDitherControl:
4941 {
4942 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4943 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
4944 QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
4945 DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
4946 if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
4947 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
4948 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
4949 eRet = OMX_ErrorBadParameter;
4950 break;
4951 }
4952 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
4953 DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
4954 break;
4955 }
4956 case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
4957 {
4958 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4959 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
4960 OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4961
4962 if ((output_capability != V4L2_PIX_FMT_H264) ||
4963 (output_capability != V4L2_PIX_FMT_HEVC)) {
4964 DEBUG_PRINT_ERROR("set_parameter: Unsupported codec for client configured profile and level");
4965 eRet = OMX_ErrorBadParameter;
4966 }
4967
4968 DEBUG_PRINT_LOW("set_parameter: Client set profile is: %d", pParam->eProfile);
4969 DEBUG_PRINT_LOW("set_parameter: Client set level is: %d", pParam->eLevel);
4970 mClientSessionForSufficiency = true;
4971 mClientSetProfile = pParam->eProfile;
4972 mClientSetLevel = pParam->eLevel;
4973 break;
4974 }
4975 default: {
4976 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4977 eRet = OMX_ErrorUnsupportedIndex;
4978 }
4979 }
4980 if (eRet != OMX_ErrorNone)
4981 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4982 return eRet;
4983 }
4984
4985 /* ======================================================================
4986 FUNCTION
4987 omx_vdec::GetConfig
4988
4989 DESCRIPTION
4990 OMX Get Config Method implementation.
4991
4992 PARAMETERS
4993 <TBD>.
4994
4995 RETURN VALUE
4996 OMX Error None if successful.
4997
4998 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4999 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
5000 OMX_IN OMX_INDEXTYPE configIndex,
5001 OMX_INOUT OMX_PTR configData)
5002 {
5003 (void) hComp;
5004 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5005
5006 if (m_state == OMX_StateInvalid) {
5007 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5008 return OMX_ErrorInvalidState;
5009 }
5010
5011 switch ((unsigned long)configIndex) {
5012 case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5013 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5014 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5015 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5016 decoderinstances->nNumOfInstances = 16;
5017 /*TODO: How to handle this case */
5018 break;
5019 }
5020 case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5021 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5022 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5023 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5024 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5025 memcpy(configFmt, &m_frame_pack_arrangement,
5026 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5027 } else {
5028 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5029 }
5030 break;
5031 }
5032 case OMX_IndexConfigCommonOutputCrop: {
5033 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5034 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5035 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5036 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5037 rectangle.nLeft, rectangle.nTop,
5038 rectangle.nWidth, rectangle.nHeight);
5039 break;
5040 }
5041 case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5042 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5043 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5044 struct v4l2_control control;
5045
5046 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5047 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5048 eRet = OMX_ErrorNotImplemented;
5049 break;
5050 }
5051
5052 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5053 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5054 coding->bCabac = (OMX_BOOL)
5055 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5056 /* We can't query driver at the moment for the cabac mode, so
5057 * just use 0xff...f as a place holder for future improvement */
5058 coding->nCabacInitIdc = ~0;
5059 } else {
5060 eRet = OMX_ErrorUnsupportedIndex;
5061 }
5062
5063 break;
5064 }
5065 case OMX_QTIIndexConfigDescribeColorAspects:
5066 {
5067 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5068 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5069
5070 if (params->bRequestingDataSpace) {
5071 DEBUG_PRINT_ERROR("Does not handle dataspace request");
5072 return OMX_ErrorUnsupportedSetting;
5073 }
5074
5075 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5076 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5077 get_preferred_color_aspects(params->sAspects);
5078 print_debug_color_aspects(&(params->sAspects), "GetConfig");
5079
5080 break;
5081 }
5082 case OMX_QTIIndexConfigDescribeHDRColorInfo:
5083 {
5084 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5085 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5086 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5087 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5088 get_preferred_hdr_info(params->sInfo);
5089 print_debug_hdr_color_info(&(params->sInfo), "GetConfig HDR");
5090
5091 break;
5092 }
5093 case OMX_IndexConfigAndroidVendorExtension:
5094 {
5095 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5096
5097 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5098 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5099 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5100 return get_vendor_extension_config(ext);
5101 }
5102 default:
5103 {
5104 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5105 eRet = OMX_ErrorBadParameter;
5106 }
5107
5108 }
5109
5110 return eRet;
5111 }
5112
5113 /* ======================================================================
5114 FUNCTION
5115 omx_vdec::SetConfig
5116
5117 DESCRIPTION
5118 OMX Set Config method implementation
5119
5120 PARAMETERS
5121 <TBD>.
5122
5123 RETURN VALUE
5124 OMX Error None if successful.
5125 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5126 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
5127 OMX_IN OMX_INDEXTYPE configIndex,
5128 OMX_IN OMX_PTR configData)
5129 {
5130 (void) hComp;
5131 if (m_state == OMX_StateInvalid) {
5132 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5133 return OMX_ErrorInvalidState;
5134 }
5135
5136 OMX_ERRORTYPE ret = OMX_ErrorNone;
5137 OMX_VIDEO_CONFIG_NALSIZE *pNal;
5138
5139 DEBUG_PRINT_LOW("Set Config Called");
5140
5141 if (configIndex == OMX_IndexConfigVideoNalSize) {
5142 struct v4l2_control temp;
5143 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5144
5145 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5146 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5147 switch (pNal->nNaluBytes) {
5148 case 0:
5149 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5150 break;
5151 case 2:
5152 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5153 break;
5154 case 4:
5155 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5156 break;
5157 default:
5158 return OMX_ErrorUnsupportedSetting;
5159 }
5160
5161 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5162 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5163 return OMX_ErrorHardware;
5164 }
5165
5166 nal_length = pNal->nNaluBytes;
5167
5168 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5169 return ret;
5170 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5171 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5172 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5173
5174 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5175 if (config->bEnabled) {
5176 if ((config->nFps >> 16) > 0 &&
5177 (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5178 m_fps_received = config->nFps;
5179 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5180 (unsigned int)config->nFps >> 16);
5181 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5182 drv_ctx.frame_rate.fps_denominator);
5183
5184 if (!drv_ctx.frame_rate.fps_numerator) {
5185 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5186 drv_ctx.frame_rate.fps_numerator = 30;
5187 }
5188
5189 if (drv_ctx.frame_rate.fps_denominator) {
5190 drv_ctx.frame_rate.fps_numerator = (int)
5191 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5192 }
5193
5194 drv_ctx.frame_rate.fps_denominator = 1;
5195 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5196 drv_ctx.frame_rate.fps_numerator;
5197
5198 struct v4l2_outputparm oparm;
5199 /*XXX: we're providing timing info as seconds per frame rather than frames
5200 * per second.*/
5201 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5202 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5203
5204 struct v4l2_streamparm sparm;
5205 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5206 sparm.parm.output = oparm;
5207 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5208 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5209 performance might be affected");
5210 ret = OMX_ErrorHardware;
5211 }
5212 client_set_fps = true;
5213 } else {
5214 DEBUG_PRINT_ERROR("Frame rate not supported.");
5215 ret = OMX_ErrorUnsupportedSetting;
5216 }
5217 } else {
5218 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5219 client_set_fps = false;
5220 }
5221 } else {
5222 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5223 (int)config->nPortIndex);
5224 ret = OMX_ErrorBadPortIndex;
5225 }
5226
5227 return ret;
5228 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5229 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5230 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5231 struct v4l2_control control;
5232 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5233 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5234
5235 switch (config->eDecodeType) {
5236 case OMX_QCOM_PictypeDecode_I:
5237 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5238 break;
5239 case OMX_QCOM_PictypeDecode_IPB:
5240 default:
5241 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5242 break;
5243 }
5244
5245 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5246 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5247 if (ret)
5248 DEBUG_PRINT_ERROR("Failed to set picture type decode");
5249
5250 return ret;
5251 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5252 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5253 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5254
5255 struct v4l2_control control;
5256
5257 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5258 if (priority->nU32 == 0)
5259 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5260 else
5261 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5262
5263 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5264 DEBUG_PRINT_ERROR("Failed to set Priority");
5265 ret = OMX_ErrorUnsupportedSetting;
5266 }
5267 return ret;
5268 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5269 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5270 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5271
5272 struct v4l2_control control;
5273
5274 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5275 control.value = rate->nU32;
5276
5277 if (rate->nU32 == QOMX_VIDEO_HIGH_PERF_OPERATING_MODE) {
5278 DEBUG_PRINT_LOW("Turbo mode requested");
5279 m_client_req_turbo_mode = true;
5280 } else {
5281 operating_frame_rate = rate->nU32 >> 16;
5282 m_client_req_turbo_mode = false;
5283 DEBUG_PRINT_LOW("Operating Rate Set = %d fps", operating_frame_rate);
5284 }
5285
5286 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5287 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5288 OMX_ErrorUnsupportedSetting;
5289 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5290 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5291 }
5292 return ret;
5293
5294 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5295 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5296 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5297 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5298 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5299 }
5300
5301 print_debug_color_aspects(&(params->sAspects), "Set Config");
5302 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5303 return ret;
5304 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5305 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5306 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5307 if (!DEFAULT_EXTRADATA & OMX_HDR_COLOR_INFO_EXTRADATA) {
5308 ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, true, true);
5309 if (ret != OMX_ErrorNone) {
5310 DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5311 return ret;
5312 }
5313 }
5314
5315 print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5316 memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5317 return ret;
5318
5319 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5320 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5321
5322 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5323 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5324 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5325
5326 return set_vendor_extension_config(ext);
5327 }
5328
5329 return OMX_ErrorNotImplemented;
5330 }
5331
5332 #define extn_equals(param, extn) (!strcmp(param, extn))
5333
5334 /* ======================================================================
5335 FUNCTION
5336 omx_vdec::GetExtensionIndex
5337
5338 DESCRIPTION
5339 OMX GetExtensionIndex method implementaion. <TBD>
5340
5341 PARAMETERS
5342 <TBD>.
5343
5344 RETURN VALUE
5345 OMX Error None if everything successful.
5346
5347 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5348 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
5349 OMX_IN OMX_STRING paramName,
5350 OMX_OUT OMX_INDEXTYPE* indexType)
5351 {
5352 (void) hComp;
5353 if (m_state == OMX_StateInvalid) {
5354 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5355 return OMX_ErrorInvalidState;
5356 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5357 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5358 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5359 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5360 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5361 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5362 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5363 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5364 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5365 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5366 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5367 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5368 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5369 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5370 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNOUTPUTCROP_EXTRADATA)) {
5371 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamOutputCropExtraData;
5372 }
5373 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5374 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5375 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5376 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5377 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5378 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5379 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5380 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5381 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5382 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5383 }
5384 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5385 else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5386 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5387 }
5388 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5389 #endif
5390 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5391 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5392 }
5393 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5394 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5395 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5396 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5397 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5398 }
5399 #endif
5400 #ifdef FLEXYUV_SUPPORTED
5401 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5402 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5403 }
5404 #endif
5405 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5406 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5407 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5408 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5409 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5410 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5411 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5412 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5413 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5414 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5415 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5416 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5417 } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5418 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5419 } else if (extn_equals(paramName, "OMX.QTI.index.param.ClientConfiguredProfileLevel")) {
5420 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency;
5421 }else {
5422 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5423 return OMX_ErrorNotImplemented;
5424 }
5425 return OMX_ErrorNone;
5426 }
5427
5428 /* ======================================================================
5429 FUNCTION
5430 omx_vdec::GetState
5431
5432 DESCRIPTION
5433 Returns the state information back to the caller.<TBD>
5434
5435 PARAMETERS
5436 <TBD>.
5437
5438 RETURN VALUE
5439 Error None if everything is successful.
5440 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5441 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
5442 OMX_OUT OMX_STATETYPE* state)
5443 {
5444 (void) hComp;
5445 *state = m_state;
5446 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5447 return OMX_ErrorNone;
5448 }
5449
5450 /* ======================================================================
5451 FUNCTION
5452 omx_vdec::ComponentTunnelRequest
5453
5454 DESCRIPTION
5455 OMX Component Tunnel Request method implementation. <TBD>
5456
5457 PARAMETERS
5458 None.
5459
5460 RETURN VALUE
5461 OMX Error None if everything successful.
5462
5463 ========================================================================== */
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)5464 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
5465 OMX_IN OMX_U32 port,
5466 OMX_IN OMX_HANDLETYPE peerComponent,
5467 OMX_IN OMX_U32 peerPort,
5468 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5469 {
5470 (void) hComp;
5471 (void) port;
5472 (void) peerComponent;
5473 (void) peerPort;
5474 (void) tunnelSetup;
5475 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5476 return OMX_ErrorNotImplemented;
5477 }
5478
5479 /* ======================================================================
5480 FUNCTION
5481 omx_vdec::UseOutputBuffer
5482
5483 DESCRIPTION
5484 Helper function for Use buffer in the input pin
5485
5486 PARAMETERS
5487 None.
5488
5489 RETURN VALUE
5490 true/false
5491
5492 ========================================================================== */
allocate_extradata()5493 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5494 {
5495 #ifdef USE_ION
5496 if (drv_ctx.extradata_info.buffer_size) {
5497 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5498 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5499 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5500 free_ion_memory(&drv_ctx.extradata_info.ion);
5501 }
5502 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5503 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5504 drv_ctx.extradata_info.size, 4096,
5505 &drv_ctx.extradata_info.ion.ion_alloc_data,
5506 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5507 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5508 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5509 return OMX_ErrorInsufficientResources;
5510 }
5511 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5512 drv_ctx.extradata_info.size,
5513 PROT_READ|PROT_WRITE, MAP_SHARED,
5514 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5515 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5516 DEBUG_PRINT_ERROR("Failed to map extradata memory");
5517 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5518 free_ion_memory(&drv_ctx.extradata_info.ion);
5519 return OMX_ErrorInsufficientResources;
5520 }
5521 }
5522 #endif
5523 if (drv_ctx.extradata_info.buffer_size && !m_other_extradata) {
5524 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5525 if (!m_other_extradata) {
5526 DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5527 return OMX_ErrorInsufficientResources;
5528 }
5529 }
5530 return OMX_ErrorNone;
5531 }
5532
free_extradata()5533 void omx_vdec::free_extradata()
5534 {
5535 #ifdef USE_ION
5536 if (drv_ctx.extradata_info.uaddr) {
5537 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5538 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5539 free_ion_memory(&drv_ctx.extradata_info.ion);
5540 }
5541 #endif
5542 if (m_other_extradata) {
5543 free(m_other_extradata);
5544 m_other_extradata = NULL;
5545 }
5546 }
5547
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)5548 OMX_ERRORTYPE omx_vdec::use_output_buffer(
5549 OMX_IN OMX_HANDLETYPE hComp,
5550 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5551 OMX_IN OMX_U32 port,
5552 OMX_IN OMX_PTR appData,
5553 OMX_IN OMX_U32 bytes,
5554 OMX_IN OMX_U8* buffer)
5555 {
5556 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5557 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
5558 unsigned i= 0; // Temporary counter
5559 OMX_PTR privateAppData = NULL;
5560 private_handle_t *handle = NULL;
5561 OMX_U8 *buff = buffer;
5562 (void) hComp;
5563 (void) port;
5564
5565 if (!m_out_mem_ptr) {
5566 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5567 eRet = allocate_output_headers();
5568 if (eRet == OMX_ErrorNone)
5569 eRet = allocate_extradata();
5570 output_use_buffer = true;
5571 }
5572
5573 if (eRet == OMX_ErrorNone) {
5574 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5575 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5576 break;
5577 }
5578 }
5579 }
5580
5581 if (i >= drv_ctx.op_buf.actualcount) {
5582 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5583 eRet = OMX_ErrorInsufficientResources;
5584 }
5585
5586 if (eRet != OMX_ErrorNone)
5587 return eRet;
5588
5589 if (dynamic_buf_mode) {
5590 *bufferHdr = (m_out_mem_ptr + i );
5591 (*bufferHdr)->pBuffer = NULL;
5592 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5593 enum v4l2_buf_type buf_type;
5594 int rr = 0;
5595
5596 set_buffer_req(&drv_ctx.op_buf);
5597 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5598 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5599 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5600 return OMX_ErrorInsufficientResources;
5601 } else {
5602 streaming[CAPTURE_PORT] = true;
5603 DEBUG_PRINT_LOW("STREAMON Successful");
5604 }
5605 }
5606 BITMASK_SET(&m_out_bm_count,i);
5607 (*bufferHdr)->pAppPrivate = appData;
5608 (*bufferHdr)->pBuffer = buffer;
5609 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5610 return eRet;
5611 }
5612
5613 if (eRet == OMX_ErrorNone) {
5614 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5615 if (m_enable_android_native_buffers) {
5616 if (m_use_android_native_buffers) {
5617 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5618 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5619 handle = (private_handle_t *)nBuf->handle;
5620 privateAppData = params->pAppPrivate;
5621 } else {
5622 handle = (private_handle_t *)buff;
5623 privateAppData = appData;
5624 }
5625 if (!handle) {
5626 DEBUG_PRINT_ERROR("handle is invalid");
5627 return OMX_ErrorBadParameter;
5628 }
5629
5630 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5631 if (secure_mode && secure_scaling_to_non_secure_opb) {
5632 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5633 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5634 } else {
5635 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5636 " expected %u, got %u",
5637 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5638 return OMX_ErrorBadParameter;
5639 }
5640 }
5641
5642 drv_ctx.op_buf.buffer_size = handle->size;
5643
5644 if (!m_use_android_native_buffers) {
5645 if (!secure_mode) {
5646 buff = (OMX_U8*)mmap(0, handle->size,
5647 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
5648 if (buff == MAP_FAILED) {
5649 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5650 return OMX_ErrorInsufficientResources;
5651 }
5652 }
5653 }
5654 #if defined(_ANDROID_ICS_)
5655 native_buffer[i].nativehandle = handle;
5656 native_buffer[i].privatehandle = handle;
5657 #endif
5658 if (!handle) {
5659 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5660 return OMX_ErrorBadParameter;
5661 }
5662 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5663 drv_ctx.ptr_outputbuffer[i].offset = 0;
5664 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5665 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5666 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5667 } else
5668 #endif
5669
5670 if (!ouput_egl_buffers && !m_use_output_pmem) {
5671 #ifdef USE_ION
5672 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5673 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
5674 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
5675 &drv_ctx.op_buf_ion_info[i].fd_ion_data,
5676 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5677 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
5678 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
5679 return OMX_ErrorInsufficientResources;
5680 }
5681 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5682 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5683 #else
5684 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5685 open (MEM_DEVICE,O_RDWR);
5686
5687 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5688 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5689 return OMX_ErrorInsufficientResources;
5690 }
5691
5692 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
5693 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
5694 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5695 open (MEM_DEVICE,O_RDWR);
5696 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5697 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5698 return OMX_ErrorInsufficientResources;
5699 }
5700 }
5701
5702 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5703 drv_ctx.op_buf.buffer_size,
5704 drv_ctx.op_buf.alignment)) {
5705 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5706 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5707 return OMX_ErrorInsufficientResources;
5708 }
5709 #endif
5710 if (!secure_mode) {
5711 drv_ctx.ptr_outputbuffer[i].bufferaddr =
5712 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
5713 PROT_READ|PROT_WRITE, MAP_SHARED,
5714 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
5715 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5716 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5717 #ifdef USE_ION
5718 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5719 #endif
5720 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5721 return OMX_ErrorInsufficientResources;
5722 }
5723 }
5724 drv_ctx.ptr_outputbuffer[i].offset = 0;
5725 privateAppData = appData;
5726 } else {
5727
5728 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5729 if (!appData || !bytes ) {
5730 if (!secure_mode && !buffer) {
5731 DEBUG_PRINT_ERROR("Bad parameters for use buffer");
5732 return OMX_ErrorBadParameter;
5733 }
5734 }
5735
5736 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
5737 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
5738 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
5739 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
5740 !pmem_list->nEntries ||
5741 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
5742 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
5743 return OMX_ErrorBadParameter;
5744 }
5745 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5746 pmem_list->entryList->entry;
5747 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
5748 pmem_info->pmem_fd);
5749 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
5750 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
5751 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5752 drv_ctx.ptr_outputbuffer[i].mmaped_size =
5753 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5754 privateAppData = appData;
5755 }
5756 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5757 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5758 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5759 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5760 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5761
5762 *bufferHdr = (m_out_mem_ptr + i );
5763 if (secure_mode)
5764 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5765
5766 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
5767 enum v4l2_buf_type buf_type;
5768 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5769 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
5770 return OMX_ErrorInsufficientResources;
5771 } else {
5772 streaming[CAPTURE_PORT] = true;
5773 DEBUG_PRINT_LOW("STREAMON Successful");
5774 }
5775 }
5776
5777 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
5778 if (m_enable_android_native_buffers) {
5779 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
5780 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
5781 } else {
5782 (*bufferHdr)->pBuffer = buff;
5783 }
5784 (*bufferHdr)->pAppPrivate = privateAppData;
5785 BITMASK_SET(&m_out_bm_count,i);
5786 }
5787 return eRet;
5788 }
5789
allocate_client_output_extradata_headers()5790 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() {
5791 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5792 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
5793 int i = 0;
5794
5795 if (!m_client_output_extradata_mem_ptr) {
5796 int nBufferCount = 0;
5797
5798 nBufferCount = m_client_out_extradata_info.getBufferCount();
5799 DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
5800
5801 m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
5802
5803 if (m_client_output_extradata_mem_ptr) {
5804 bufHdr = m_client_output_extradata_mem_ptr;
5805 for (i=0; i < nBufferCount; i++) {
5806 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
5807 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
5808 // Set the values when we determine the right HxW param
5809 bufHdr->nAllocLen = 0;
5810 bufHdr->nFilledLen = 0;
5811 bufHdr->pAppPrivate = NULL;
5812 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
5813 bufHdr->pBuffer = NULL;
5814 bufHdr->pOutputPortPrivate = NULL;
5815 bufHdr++;
5816 }
5817 } else {
5818 DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
5819 m_client_output_extradata_mem_ptr);
5820 eRet = OMX_ErrorInsufficientResources;
5821 }
5822 }
5823 return eRet;
5824 }
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)5825 OMX_ERRORTYPE omx_vdec::use_client_output_extradata_buffer(
5826 OMX_IN OMX_HANDLETYPE hComp,
5827 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5828 OMX_IN OMX_U32 port,
5829 OMX_IN OMX_PTR appData,
5830 OMX_IN OMX_U32 bytes,
5831 OMX_IN OMX_U8* buffer)
5832 {
5833 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5834 unsigned i = 0; // Temporary counter
5835 unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
5836 OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
5837 (void) hComp;
5838
5839 if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
5840 !client_extradata || bytes != buffer_size|| bufferHdr == NULL) {
5841 DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
5842 "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
5843 OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr);
5844 eRet = OMX_ErrorBadParameter;
5845 return eRet;
5846 }
5847
5848 if (!m_client_output_extradata_mem_ptr) {
5849 eRet = allocate_client_output_extradata_headers();
5850 }
5851
5852 if (eRet == OMX_ErrorNone) {
5853 for (i = 0; i < buffer_count; i++) {
5854 if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
5855 break;
5856 }
5857 }
5858 }
5859
5860 if (i >= buffer_count) {
5861 DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
5862 eRet = OMX_ErrorInsufficientResources;
5863 }
5864
5865 if (eRet == OMX_ErrorNone) {
5866 BITMASK_SET(&m_out_extradata_bm_count,i);
5867 *bufferHdr = (m_client_output_extradata_mem_ptr + i );
5868 (*bufferHdr)->pAppPrivate = appData;
5869 (*bufferHdr)->pBuffer = buffer;
5870 (*bufferHdr)->nAllocLen = bytes;
5871 }
5872
5873 return eRet;
5874 }
5875 /* ======================================================================
5876 FUNCTION
5877 omx_vdec::use_input_heap_buffers
5878
5879 DESCRIPTION
5880 OMX Use Buffer Heap allocation method implementation.
5881
5882 PARAMETERS
5883 <TBD>.
5884
5885 RETURN VALUE
5886 OMX Error None , if everything successful.
5887
5888 ========================================================================== */
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)5889 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
5890 OMX_IN OMX_HANDLETYPE hComp,
5891 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5892 OMX_IN OMX_U32 port,
5893 OMX_IN OMX_PTR appData,
5894 OMX_IN OMX_U32 bytes,
5895 OMX_IN OMX_U8* buffer)
5896 {
5897 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5898 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5899
5900 if (secure_mode) {
5901 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
5902 return OMX_ErrorUndefined;
5903 }
5904
5905 if (!m_inp_heap_ptr)
5906 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5907 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5908 drv_ctx.ip_buf.actualcount);
5909 if (!m_phdr_pmem_ptr)
5910 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5911 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5912 drv_ctx.ip_buf.actualcount);
5913 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5914 DEBUG_PRINT_ERROR("Insufficent memory");
5915 eRet = OMX_ErrorInsufficientResources;
5916 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5917 input_use_buffer = true;
5918 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5919 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5920 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5921 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5922 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5923 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5924 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5925 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5926 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5927 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5928 (unsigned)NULL, (unsigned)NULL)) {
5929 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5930 return OMX_ErrorInsufficientResources;
5931 }
5932 m_in_alloc_cnt++;
5933 } else {
5934 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5935 eRet = OMX_ErrorInsufficientResources;
5936 }
5937 return eRet;
5938 }
5939
5940 /* ======================================================================
5941 FUNCTION
5942 omx_vdec::UseBuffer
5943
5944 DESCRIPTION
5945 OMX Use Buffer method implementation.
5946
5947 PARAMETERS
5948 <TBD>.
5949
5950 RETURN VALUE
5951 OMX Error None , if everything successful.
5952
5953 ========================================================================== */
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)5954 OMX_ERRORTYPE omx_vdec::use_buffer(
5955 OMX_IN OMX_HANDLETYPE hComp,
5956 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5957 OMX_IN OMX_U32 port,
5958 OMX_IN OMX_PTR appData,
5959 OMX_IN OMX_U32 bytes,
5960 OMX_IN OMX_U8* buffer)
5961 {
5962 OMX_ERRORTYPE error = OMX_ErrorNone;
5963
5964 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5965 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5966 return OMX_ErrorBadParameter;
5967 }
5968 if (m_state == OMX_StateInvalid) {
5969 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5970 return OMX_ErrorInvalidState;
5971 }
5972 if (port == OMX_CORE_INPUT_PORT_INDEX) {
5973 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
5974 // ensure that use-buffer was called for previous allocation.
5975 // Mix-and-match of useBuffer and allocateBuffer is not allowed
5976 if (m_inp_mem_ptr && !input_use_buffer) {
5977 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
5978 return OMX_ErrorUndefined;
5979 }
5980 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5981 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
5982 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5983 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
5984 error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
5985 } else {
5986 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5987 error = OMX_ErrorBadPortIndex;
5988 }
5989 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5990 if (error == OMX_ErrorNone) {
5991 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5992 // Send the callback now
5993 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5994 post_event(OMX_CommandStateSet,OMX_StateIdle,
5995 OMX_COMPONENT_GENERATE_EVENT);
5996 }
5997 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5998 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5999 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6000 post_event(OMX_CommandPortEnable,
6001 OMX_CORE_INPUT_PORT_INDEX,
6002 OMX_COMPONENT_GENERATE_EVENT);
6003 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6004 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6005 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6006 post_event(OMX_CommandPortEnable,
6007 OMX_CORE_OUTPUT_PORT_INDEX,
6008 OMX_COMPONENT_GENERATE_EVENT);
6009 }
6010 }
6011 return error;
6012 }
6013
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)6014 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6015 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6016 {
6017 (void) bufferindex;
6018
6019 if (pmem_bufferHdr)
6020 free_input_buffer(pmem_bufferHdr);
6021 return OMX_ErrorNone;
6022 }
6023
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6024 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6025 {
6026 unsigned int index = 0;
6027 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6028 return OMX_ErrorBadParameter;
6029 }
6030 print_omx_buffer("free_input_buffer", bufferHdr);
6031
6032 index = bufferHdr - m_inp_mem_ptr;
6033 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6034
6035 bufferHdr->pInputPortPrivate = NULL;
6036
6037 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6038 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6039 if (!secure_mode) {
6040 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6041 drv_ctx.ptr_inputbuffer[index].mmaped_size);
6042 }
6043
6044 if (allocate_native_handle){
6045 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6046 native_handle_close(nh);
6047 native_handle_delete(nh);
6048 } else {
6049 // Close fd for non-secure and secure non-native-handle case
6050 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6051 }
6052 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6053
6054 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6055 free(m_desc_buffer_ptr[index].buf_addr);
6056 m_desc_buffer_ptr[index].buf_addr = NULL;
6057 m_desc_buffer_ptr[index].desc_data_size = 0;
6058 }
6059 #ifdef USE_ION
6060 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6061 #endif
6062 m_in_alloc_cnt--;
6063 } else {
6064 DEBUG_PRINT_ERROR("Invalid input buffer fd %d", drv_ctx.ptr_inputbuffer[index].pmem_fd);
6065 }
6066 } else {
6067 DEBUG_PRINT_ERROR("Invalid input buffer index %d, drv_ctx.ptr_inputbuffer %p",
6068 index, drv_ctx.ptr_inputbuffer);
6069 }
6070
6071 return OMX_ErrorNone;
6072 }
6073
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6074 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6075 {
6076 unsigned int index = 0;
6077
6078 if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6079 return OMX_ErrorBadParameter;
6080 }
6081 print_omx_buffer("free_output_buffer", bufferHdr);
6082
6083 index = bufferHdr - m_out_mem_ptr;
6084
6085 if (index < drv_ctx.op_buf.actualcount
6086 && drv_ctx.ptr_outputbuffer) {
6087 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6088 drv_ctx.ptr_outputbuffer[index].bufferaddr);
6089
6090 if (!dynamic_buf_mode) {
6091 if (streaming[CAPTURE_PORT] &&
6092 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6093 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6094 DEBUG_PRINT_ERROR("STREAMOFF(CAPTURE_MPLANE) Failed");
6095 } else {
6096 DEBUG_PRINT_LOW("STREAMOFF(CAPTURE_MPLANE) Successful");
6097 }
6098 }
6099 #ifdef _ANDROID_
6100 if (m_enable_android_native_buffers) {
6101 if (!secure_mode) {
6102 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6103 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6104 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6105 }
6106 }
6107 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6108 } else {
6109 #endif
6110 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
6111 if (!secure_mode) {
6112 munmap (drv_ctx.ptr_outputbuffer[index].bufferaddr,
6113 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6114 drv_ctx.ptr_outputbuffer[index].bufferaddr = NULL;
6115 drv_ctx.ptr_outputbuffer[index].mmaped_size = 0;
6116 }
6117 close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
6118 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6119 #ifdef USE_ION
6120 free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
6121 #endif
6122 }
6123 #ifdef _ANDROID_
6124 }
6125 #endif
6126 } //!dynamic_buf_mode
6127 if (release_output_done()) {
6128 DEBUG_PRINT_HIGH("All output buffers released, free extradata");
6129 free_extradata();
6130 }
6131 }
6132
6133 return OMX_ErrorNone;
6134
6135 }
6136
6137 /* ======================================================================
6138 FUNCTION
6139 omx_vdec::AllocateInputBuffer
6140
6141 DESCRIPTION
6142 Helper function for allocate buffer in the input pin
6143
6144 PARAMETERS
6145 None.
6146
6147 RETURN VALUE
6148 true/false
6149
6150 ========================================================================== */
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)6151 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
6152 OMX_IN OMX_HANDLETYPE hComp,
6153 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6154 OMX_IN OMX_U32 port,
6155 OMX_IN OMX_PTR appData,
6156 OMX_IN OMX_U32 bytes)
6157 {
6158 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6159 OMX_BUFFERHEADERTYPE *input = NULL;
6160 unsigned i = 0;
6161 unsigned char *buf_addr = NULL;
6162 int pmem_fd = -1, ret = 0;
6163 unsigned int align_size = 0;
6164
6165 (void) hComp;
6166 (void) port;
6167
6168
6169 if (bytes != drv_ctx.ip_buf.buffer_size) {
6170 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6171 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6172 return OMX_ErrorBadParameter;
6173 }
6174
6175 if (!m_inp_mem_ptr) {
6176 /* Currently buffer reqs is being set only in set port defn */
6177 /* Client need not do set port definition if he sees enough buffers in get port defn */
6178 /* In such cases we need to do a set buffer reqs to driver. Doing it here */
6179 struct v4l2_requestbuffers bufreq;
6180
6181 DEBUG_PRINT_HIGH("Calling REQBUFS in %s ",__FUNCTION__);
6182 bufreq.memory = V4L2_MEMORY_USERPTR;
6183 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6184 bufreq.count = drv_ctx.ip_buf.actualcount;
6185 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6186 if (ret) {
6187 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
6188 /*TODO: How to handle this case */
6189 eRet = OMX_ErrorInsufficientResources;
6190 } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6191 DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6192 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6193 eRet = OMX_ErrorInsufficientResources;
6194 }
6195
6196 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6197 drv_ctx.ip_buf.actualcount,
6198 (unsigned int)drv_ctx.ip_buf.buffer_size);
6199
6200 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6201 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6202
6203 if (m_inp_mem_ptr == NULL) {
6204 return OMX_ErrorInsufficientResources;
6205 }
6206
6207 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6208 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6209
6210 if (drv_ctx.ptr_inputbuffer == NULL) {
6211 return OMX_ErrorInsufficientResources;
6212 }
6213 #ifdef USE_ION
6214 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6215 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6216
6217 if (drv_ctx.ip_buf_ion_info == NULL) {
6218 return OMX_ErrorInsufficientResources;
6219 }
6220 #endif
6221
6222 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6223 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6224 #ifdef USE_ION
6225 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6226 #endif
6227 }
6228 }
6229
6230 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6231 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6232 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6233 break;
6234 }
6235 }
6236
6237 if (i < drv_ctx.ip_buf.actualcount) {
6238 int rc;
6239 DEBUG_PRINT_LOW("Allocate input Buffer");
6240 #ifdef USE_ION
6241 align_size = drv_ctx.ip_buf.buffer_size + 512;
6242 align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6243 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6244 align_size, drv_ctx.op_buf.alignment,
6245 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6246 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6247 SECURE_FLAGS_INPUT_BUFFER : 0);
6248 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6249 return OMX_ErrorInsufficientResources;
6250 }
6251 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6252 #else
6253 pmem_fd = open (MEM_DEVICE,O_RDWR);
6254
6255 if (pmem_fd < 0) {
6256 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6257 return OMX_ErrorInsufficientResources;
6258 }
6259
6260 if (pmem_fd == 0) {
6261 pmem_fd = open (MEM_DEVICE,O_RDWR);
6262
6263 if (pmem_fd < 0) {
6264 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6265 return OMX_ErrorInsufficientResources;
6266 }
6267 }
6268
6269 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6270 drv_ctx.ip_buf.alignment)) {
6271 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6272 close(pmem_fd);
6273 return OMX_ErrorInsufficientResources;
6274 }
6275 #endif
6276 if (!secure_mode) {
6277 buf_addr = (unsigned char *)mmap(NULL,
6278 drv_ctx.ip_buf.buffer_size,
6279 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6280
6281 if (buf_addr == MAP_FAILED) {
6282 close(pmem_fd);
6283 #ifdef USE_ION
6284 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6285 #endif
6286 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6287 return OMX_ErrorInsufficientResources;
6288 }
6289 }
6290 *bufferHdr = (m_inp_mem_ptr + i);
6291 if (secure_mode)
6292 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6293 else
6294 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6295 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6296 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6297 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6298 drv_ctx.ptr_inputbuffer [i].offset = 0;
6299
6300 input = *bufferHdr;
6301 BITMASK_SET(&m_inp_bm_count,i);
6302 if (allocate_native_handle) {
6303 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6304 if (!nh) {
6305 DEBUG_PRINT_ERROR("Native handle create failed");
6306 return OMX_ErrorInsufficientResources;
6307 }
6308 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6309 input->pBuffer = (OMX_U8 *)nh;
6310 } else if (secure_mode || m_input_pass_buffer_fd) {
6311 /*Legacy method, pass ion fd stashed directly in pBuffer*/
6312 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6313 } else {
6314 input->pBuffer = (OMX_U8 *)buf_addr;
6315 }
6316 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6317 input->nVersion.nVersion = OMX_SPEC_VERSION;
6318 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6319 input->pAppPrivate = appData;
6320 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6321 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6322
6323 if (drv_ctx.disable_dmx) {
6324 eRet = allocate_desc_buffer(i);
6325 }
6326 } else {
6327 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6328 eRet = OMX_ErrorInsufficientResources;
6329 }
6330
6331 if (eRet == OMX_ErrorNone)
6332 DEBUG_PRINT_HIGH("Allocate_input_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d",
6333 i, input, input->pBuffer, input->nAllocLen,
6334 input->nOffset, drv_ctx.ptr_inputbuffer[i].pmem_fd);
6335
6336 return eRet;
6337 }
6338
6339
6340 /* ======================================================================
6341 FUNCTION
6342 omx_vdec::AllocateOutputBuffer
6343
6344 DESCRIPTION
6345 Helper fn for AllocateBuffer in the output pin
6346
6347 PARAMETERS
6348 <TBD>.
6349
6350 RETURN VALUE
6351 OMX Error None if everything went well.
6352
6353 ========================================================================== */
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)6354 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
6355 OMX_IN OMX_HANDLETYPE hComp,
6356 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6357 OMX_IN OMX_U32 port,
6358 OMX_IN OMX_PTR appData,
6359 OMX_IN OMX_U32 bytes)
6360 {
6361 (void)hComp;
6362 (void)port;
6363 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6364 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
6365 unsigned i= 0; // Temporary counter
6366 #ifdef USE_ION
6367 int ion_device_fd =-1;
6368 struct ion_allocation_data ion_alloc_data;
6369 struct ion_fd_data fd_ion_data;
6370 #endif
6371 if (!m_out_mem_ptr) {
6372 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6373 drv_ctx.op_buf.actualcount,
6374 (unsigned int)drv_ctx.op_buf.buffer_size);
6375 int nBufHdrSize = 0;
6376 int nPlatformEntrySize = 0;
6377 int nPlatformListSize = 0;
6378 int nPMEMInfoSize = 0;
6379
6380 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
6381 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
6382 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6383
6384 nBufHdrSize = drv_ctx.op_buf.actualcount *
6385 sizeof(OMX_BUFFERHEADERTYPE);
6386 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
6387 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6388 nPlatformListSize = drv_ctx.op_buf.actualcount *
6389 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6390 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6391 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6392
6393 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
6394 // Alloc mem for platform specific info
6395 char *pPtr=NULL;
6396 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6397 nPMEMInfoSize,1);
6398 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6399 calloc (sizeof(struct vdec_bufferpayload),
6400 drv_ctx.op_buf.actualcount);
6401 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
6402 calloc (sizeof (struct vdec_output_frameinfo),
6403 drv_ctx.op_buf.actualcount);
6404 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6405 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6406 free(pPtr);
6407 return OMX_ErrorInsufficientResources;
6408 }
6409
6410 #ifdef USE_ION
6411 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6412 calloc (sizeof(struct vdec_ion),
6413 drv_ctx.op_buf.actualcount);
6414 if (!drv_ctx.op_buf_ion_info) {
6415 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6416 return OMX_ErrorInsufficientResources;
6417 }
6418 #endif
6419
6420 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6421 && drv_ctx.ptr_respbuffer) {
6422 bufHdr = m_out_mem_ptr;
6423 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6424 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6425 (((char *) m_platform_list) + nPlatformListSize);
6426 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6427 (((char *) m_platform_entry) + nPlatformEntrySize);
6428 pPlatformList = m_platform_list;
6429 pPlatformEntry = m_platform_entry;
6430 pPMEMInfo = m_pmem_info;
6431
6432 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6433
6434 // Settting the entire storage nicely
6435 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6436 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6437 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
6438 // Set the values when we determine the right HxW param
6439 bufHdr->nAllocLen = bytes;
6440 bufHdr->nFilledLen = 0;
6441 bufHdr->pAppPrivate = appData;
6442 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
6443 // Platform specific PMEM Information
6444 // Initialize the Platform Entry
6445 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6446 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6447 pPlatformEntry->entry = pPMEMInfo;
6448 // Initialize the Platform List
6449 pPlatformList->nEntries = 1;
6450 pPlatformList->entryList = pPlatformEntry;
6451 // Keep pBuffer NULL till vdec is opened
6452 bufHdr->pBuffer = NULL;
6453 bufHdr->nOffset = 0;
6454 pPMEMInfo->offset = 0;
6455 pPMEMInfo->pmem_fd = -1;
6456 bufHdr->pPlatformPrivate = pPlatformList;
6457 /*Create a mapping between buffers*/
6458 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
6459 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
6460 &drv_ctx.ptr_outputbuffer[i];
6461 // Move the buffer and buffer header pointers
6462 bufHdr++;
6463 pPMEMInfo++;
6464 pPlatformEntry++;
6465 pPlatformList++;
6466 }
6467 } else {
6468 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6469 m_out_mem_ptr, pPtr);
6470 if (m_out_mem_ptr) {
6471 free(m_out_mem_ptr);
6472 m_out_mem_ptr = NULL;
6473 }
6474 if (pPtr) {
6475 free(pPtr);
6476 pPtr = NULL;
6477 }
6478 if (drv_ctx.ptr_outputbuffer) {
6479 free(drv_ctx.ptr_outputbuffer);
6480 drv_ctx.ptr_outputbuffer = NULL;
6481 }
6482 if (drv_ctx.ptr_respbuffer) {
6483 free(drv_ctx.ptr_respbuffer);
6484 drv_ctx.ptr_respbuffer = NULL;
6485 }
6486 #ifdef USE_ION
6487 if (drv_ctx.op_buf_ion_info) {
6488 DEBUG_PRINT_LOW("Free o/p ion context");
6489 free(drv_ctx.op_buf_ion_info);
6490 drv_ctx.op_buf_ion_info = NULL;
6491 }
6492 #endif
6493 eRet = OMX_ErrorInsufficientResources;
6494 }
6495 if (eRet == OMX_ErrorNone)
6496 eRet = allocate_extradata();
6497 }
6498
6499 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6500 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6501 break;
6502 }
6503 }
6504
6505 if (eRet == OMX_ErrorNone) {
6506 if (i < drv_ctx.op_buf.actualcount) {
6507 int rc;
6508 int pmem_fd = -1;
6509 unsigned char *pmem_baseaddress = NULL;
6510
6511 #ifdef USE_ION
6512 // Allocate output buffers as cached to improve performance of software-reading
6513 // of the YUVs. Output buffers are cache-invalidated in driver.
6514 // If color-conversion is involved, Only the C2D output buffers are cached, no
6515 // need to cache the decoder's output buffers
6516 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6517 ion_device_fd = alloc_map_ion_memory(drv_ctx.op_buf.buffer_size,
6518 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6519 &ion_alloc_data, &fd_ion_data,
6520 (secure_mode && !secure_scaling_to_non_secure_opb) ?
6521 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6522 if (ion_device_fd < 0) {
6523 return OMX_ErrorInsufficientResources;
6524 }
6525 pmem_fd = fd_ion_data.fd;
6526 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
6527 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
6528 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
6529 #else
6530 pmem_fd = open (MEM_DEVICE,O_RDWR);
6531 if (pmem_fd < 0) {
6532 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6533 drv_ctx.op_buf.buffer_size);
6534 return OMX_ErrorInsufficientResources;
6535 }
6536 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size,
6537 drv_ctx.op_buf.alignment)) {
6538 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6539 close(pmem_fd);
6540 return OMX_ErrorInsufficientResources;
6541 }
6542 #endif
6543 if (!secure_mode) {
6544 pmem_baseaddress = (unsigned char *)mmap(NULL,
6545 drv_ctx.op_buf.buffer_size,
6546 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
6547 if (pmem_baseaddress == MAP_FAILED) {
6548 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6549 (unsigned int)drv_ctx.op_buf.buffer_size);
6550 close(pmem_fd);
6551 #ifdef USE_ION
6552 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6553 #endif
6554 return OMX_ErrorInsufficientResources;
6555 }
6556 }
6557 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
6558 drv_ctx.ptr_outputbuffer[i].offset = 0;
6559 drv_ctx.ptr_outputbuffer[i].bufferaddr = pmem_baseaddress;
6560 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6561 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6562 m_pmem_info[i].pmem_fd = pmem_fd;
6563 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6564 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6565 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6566 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6567
6568 *bufferHdr = (m_out_mem_ptr + i );
6569 if (secure_mode) {
6570 #ifdef USE_ION
6571 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6572 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6573 #else
6574 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6575 #endif
6576 }
6577 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6578 enum v4l2_buf_type buf_type;
6579
6580 set_buffer_req(&drv_ctx.op_buf);
6581 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6582 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6583 if (rc) {
6584 DEBUG_PRINT_ERROR("STREAMON(CAPTURE_MPLANE) Failed");
6585 return OMX_ErrorInsufficientResources;
6586 } else {
6587 streaming[CAPTURE_PORT] = true;
6588 DEBUG_PRINT_LOW("STREAMON(CAPTURE_MPLANE) Successful");
6589 }
6590 }
6591
6592 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
6593 (*bufferHdr)->pAppPrivate = appData;
6594 BITMASK_SET(&m_out_bm_count,i);
6595 } else {
6596 DEBUG_PRINT_ERROR("Faile to allocate output buffer (%d) maxcount %d",
6597 i, drv_ctx.op_buf.actualcount);
6598 eRet = OMX_ErrorInsufficientResources;
6599 }
6600 }
6601
6602 if (eRet == OMX_ErrorNone)
6603 DEBUG_PRINT_HIGH("Allocate_output_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d",
6604 i, (*bufferHdr), (*bufferHdr)->pBuffer, (*bufferHdr)->nAllocLen,
6605 (*bufferHdr)->nOffset, drv_ctx.ptr_outputbuffer[i].pmem_fd);
6606
6607 return eRet;
6608 }
6609
6610
6611 // AllocateBuffer -- API Call
6612 /* ======================================================================
6613 FUNCTION
6614 omx_vdec::AllocateBuffer
6615
6616 DESCRIPTION
6617 Returns zero if all the buffers released..
6618
6619 PARAMETERS
6620 None.
6621
6622 RETURN VALUE
6623 true/false
6624
6625 ========================================================================== */
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)6626 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
6627 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6628 OMX_IN OMX_U32 port,
6629 OMX_IN OMX_PTR appData,
6630 OMX_IN OMX_U32 bytes)
6631 {
6632 unsigned i = 0;
6633 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
6634
6635 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
6636 if (m_state == OMX_StateInvalid) {
6637 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
6638 return OMX_ErrorInvalidState;
6639 }
6640
6641 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6642 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6643 // ensure that use-buffer was never called.
6644 // Mix-and-match of useBuffer and allocateBuffer is not allowed
6645 if (m_inp_mem_ptr && input_use_buffer) {
6646 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
6647 return OMX_ErrorUndefined;
6648 }
6649 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
6650 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6651 if (output_use_buffer) {
6652 DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
6653 return OMX_ErrorBadParameter;
6654 }
6655 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
6656 appData,bytes);
6657 } else {
6658 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6659 eRet = OMX_ErrorBadPortIndex;
6660 }
6661 if (eRet == OMX_ErrorNone) {
6662 if (allocate_done()) {
6663 DEBUG_PRINT_HIGH("Allocated all buffers on port %d", port);
6664 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6665 // Send the callback now
6666 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6667 post_event(OMX_CommandStateSet,OMX_StateIdle,
6668 OMX_COMPONENT_GENERATE_EVENT);
6669 }
6670 }
6671 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
6672 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6673 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6674 post_event(OMX_CommandPortEnable,
6675 OMX_CORE_INPUT_PORT_INDEX,
6676 OMX_COMPONENT_GENERATE_EVENT);
6677 }
6678 }
6679 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
6680 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6681 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6682 post_event(OMX_CommandPortEnable,
6683 OMX_CORE_OUTPUT_PORT_INDEX,
6684 OMX_COMPONENT_GENERATE_EVENT);
6685 }
6686 }
6687 }
6688 return eRet;
6689 }
6690
6691 // Free Buffer - API call
6692 /* ======================================================================
6693 FUNCTION
6694 omx_vdec::FreeBuffer
6695
6696 DESCRIPTION
6697
6698 PARAMETERS
6699 None.
6700
6701 RETURN VALUE
6702 true/false
6703
6704 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6705 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
6706 OMX_IN OMX_U32 port,
6707 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6708 {
6709 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6710 unsigned int nPortIndex;
6711 (void) hComp;
6712
6713 auto_lock l(buf_lock);
6714 if (m_state == OMX_StateIdle &&
6715 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6716 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
6717 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
6718 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
6719 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
6720 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
6721 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
6722 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
6723 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
6724 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
6725 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
6726 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
6727 post_event(OMX_EventError,
6728 OMX_ErrorPortUnpopulated,
6729 OMX_COMPONENT_GENERATE_EVENT);
6730 m_buffer_error = true;
6731 return OMX_ErrorIncorrectStateOperation;
6732 } else if (m_state != OMX_StateInvalid) {
6733 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6734 post_event(OMX_EventError,
6735 OMX_ErrorPortUnpopulated,
6736 OMX_COMPONENT_GENERATE_EVENT);
6737 }
6738
6739 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6740 if (!input_use_buffer)
6741 nPortIndex = buffer - m_inp_mem_ptr;
6742 else
6743 nPortIndex = buffer - m_inp_heap_ptr;
6744
6745 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6746 if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6747 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6748 // Clear the bit associated with it.
6749 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6750 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6751 if (input_use_buffer == true) {
6752
6753 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6754 if (m_phdr_pmem_ptr)
6755 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6756 } else {
6757 free_input_buffer(buffer);
6758 }
6759 m_inp_bPopulated = OMX_FALSE;
6760 /*Free the Buffer Header*/
6761 if (release_input_done()) {
6762 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6763 free_input_buffer_header();
6764 }
6765 } else {
6766 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6767 eRet = OMX_ErrorBadPortIndex;
6768 }
6769
6770 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6771 && release_input_done()) {
6772 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6773 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6774 post_event(OMX_CommandPortDisable,
6775 OMX_CORE_INPUT_PORT_INDEX,
6776 OMX_COMPONENT_GENERATE_EVENT);
6777 }
6778 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6779 // check if the buffer is valid
6780 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6781 if (nPortIndex < drv_ctx.op_buf.actualcount &&
6782 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6783 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6784 // Clear the bit associated with it.
6785 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6786 m_out_bPopulated = OMX_FALSE;
6787 client_buffers.free_output_buffer (buffer);
6788
6789 if (release_output_done()) {
6790 DEBUG_PRINT_HIGH("All output buffers released.");
6791 free_output_buffer_header();
6792 }
6793 } else {
6794 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6795 eRet = OMX_ErrorBadPortIndex;
6796 }
6797 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6798 && release_output_done()) {
6799 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6800 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6801 #ifdef _ANDROID_ICS_
6802 if (m_enable_android_native_buffers) {
6803 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6804 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6805 }
6806 #endif
6807
6808 post_event(OMX_CommandPortDisable,
6809 OMX_CORE_OUTPUT_PORT_INDEX,
6810 OMX_COMPONENT_GENERATE_EVENT);
6811 }
6812 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
6813 nPortIndex = buffer - m_client_output_extradata_mem_ptr;
6814 DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
6815
6816 BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
6817
6818 if (release_output_extradata_done()) {
6819 free_output_extradata_buffer_header();
6820 }
6821 } else {
6822 eRet = OMX_ErrorBadPortIndex;
6823 }
6824 if ((eRet == OMX_ErrorNone) &&
6825 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6826 if (release_done()) {
6827 /*
6828 * Reset buffer requirements here to ensure setting buffer requirement
6829 * when component move to executing state from loaded state via idle.
6830 */
6831 drv_ctx.op_buf.buffer_size = 0;
6832 drv_ctx.op_buf.actualcount = 0;
6833
6834 // Send the callback now
6835 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6836 post_event(OMX_CommandStateSet, OMX_StateLoaded,
6837 OMX_COMPONENT_GENERATE_EVENT);
6838 m_buffer_error = false;
6839 }
6840 }
6841 return eRet;
6842 }
6843
6844
6845 /* ======================================================================
6846 FUNCTION
6847 omx_vdec::EmptyThisBuffer
6848
6849 DESCRIPTION
6850 This routine is used to push the encoded video frames to
6851 the video decoder.
6852
6853 PARAMETERS
6854 None.
6855
6856 RETURN VALUE
6857 OMX Error None if everything went successful.
6858
6859 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6860 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
6861 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6862 {
6863 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6864 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6865
6866 if (m_state != OMX_StateExecuting &&
6867 m_state != OMX_StatePause &&
6868 m_state != OMX_StateIdle) {
6869 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6870 return OMX_ErrorInvalidState;
6871 }
6872
6873 if (m_error_propogated) {
6874 DEBUG_PRINT_ERROR("Empty this buffer not allowed after error");
6875 return OMX_ErrorHardware;
6876 }
6877
6878 if (buffer == NULL) {
6879 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6880 return OMX_ErrorBadParameter;
6881 }
6882 print_omx_buffer("EmptyThisBuffer", buffer);
6883
6884 if (!m_inp_bEnabled) {
6885 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
6886 return OMX_ErrorIncorrectStateOperation;
6887 }
6888
6889 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
6890 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
6891 return OMX_ErrorBadPortIndex;
6892 }
6893
6894 if (perf_flag) {
6895 if (!latency) {
6896 dec_time.stop();
6897 latency = dec_time.processing_time_us();
6898 dec_time.start();
6899 }
6900 }
6901
6902 if (input_use_buffer == true) {
6903 nBufferIndex = buffer - m_inp_heap_ptr;
6904 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
6905 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
6906 return OMX_ErrorBadParameter;
6907 }
6908 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
6909 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
6910 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
6911 buffer = &m_inp_mem_ptr[nBufferIndex];
6912 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
6913 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
6914 } else {
6915 nBufferIndex = buffer - m_inp_mem_ptr;
6916 }
6917
6918 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
6919 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
6920 return OMX_ErrorBadParameter;
6921 }
6922
6923 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6924 codec_config_flag = true;
6925 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
6926 }
6927
6928 if (m_input_pass_buffer_fd) {
6929 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
6930 }
6931
6932 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
6933 time_stamp_dts.insert_timestamp(buffer);
6934 return OMX_ErrorNone;
6935 }
6936
6937 /* ======================================================================
6938 FUNCTION
6939 omx_vdec::empty_this_buffer_proxy
6940
6941 DESCRIPTION
6942 This routine is used to push the encoded video frames to
6943 the video decoder.
6944
6945 PARAMETERS
6946 None.
6947
6948 RETURN VALUE
6949 OMX Error None if everything went successful.
6950
6951 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6952 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
6953 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6954 {
6955 VIDC_TRACE_NAME_HIGH("ETB");
6956 (void) hComp;
6957 int push_cnt = 0,i=0;
6958 unsigned nPortIndex = 0;
6959 OMX_ERRORTYPE ret = OMX_ErrorNone;
6960 struct vdec_bufferpayload *temp_buffer;
6961 bool port_setting_changed = true;
6962
6963 /*Should we generate a Aync error event*/
6964 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
6965 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
6966 return OMX_ErrorBadParameter;
6967 }
6968
6969 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
6970
6971 if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
6972 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
6973 nPortIndex);
6974 return OMX_ErrorBadParameter;
6975 }
6976
6977 pending_input_buffers++;
6978 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
6979
6980 /* return zero length and not an EOS buffer */
6981 if ((buffer->nFilledLen == 0) && ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
6982 DEBUG_PRINT_HIGH("return zero legth buffer");
6983 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6984 OMX_COMPONENT_GENERATE_EBD);
6985 return OMX_ErrorNone;
6986 }
6987
6988 if (input_flush_progress == true) {
6989 DEBUG_PRINT_LOW("Flush in progress return buffer ");
6990 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6991 OMX_COMPONENT_GENERATE_EBD);
6992 return OMX_ErrorNone;
6993 }
6994
6995 if (m_error_propogated == true) {
6996 DEBUG_PRINT_LOW("Return buffer in error state");
6997 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6998 OMX_COMPONENT_GENERATE_EBD);
6999 return OMX_ErrorNone;
7000 }
7001
7002 auto_lock l(buf_lock);
7003 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7004
7005 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7006 return OMX_ErrorBadParameter;
7007 }
7008
7009 if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7010 DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7011 return OMX_ErrorBadParameter;
7012 }
7013
7014 VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7015 VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7016 /*for use buffer we need to memcpy the data*/
7017 temp_buffer->buffer_len = buffer->nFilledLen;
7018
7019 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7020 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7021 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7022 buffer->nFilledLen);
7023 } else {
7024 return OMX_ErrorBadParameter;
7025 }
7026
7027 }
7028
7029 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7030 DEBUG_PRINT_LOW("ETB: dmx enabled");
7031 if (m_demux_entries == 0) {
7032 extract_demux_addr_offsets(buffer);
7033 }
7034
7035 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7036 handle_demux_data(buffer);
7037 }
7038
7039 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len, buffer->nTimeStamp);
7040
7041 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7042 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7043 }
7044
7045 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7046 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7047 nal_count = 0;
7048 frame_count = 0;
7049 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7050 m_demux_entries = 0;
7051 }
7052 struct v4l2_buffer buf;
7053 struct v4l2_plane plane;
7054 memset( (void *)&buf, 0, sizeof(buf));
7055 memset( (void *)&plane, 0, sizeof(plane));
7056 int rc;
7057 unsigned long print_count;
7058 if (temp_buffer->buffer_len == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7059 struct v4l2_decoder_cmd dec;
7060
7061 if (!streaming[OUTPUT_PORT]) {
7062 enum v4l2_buf_type buf_type;
7063 int ret = 0;
7064
7065 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7066 DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
7067 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7068 if (!ret) {
7069 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7070 streaming[OUTPUT_PORT] = true;
7071 } else {
7072 DEBUG_PRINT_ERROR("Streamon failed before sending stop command");
7073 return OMX_ErrorHardware;
7074 }
7075 }
7076
7077 DEBUG_PRINT_HIGH("Input EOS reached. Converted to STOP command") ;
7078 memset(&dec, 0, sizeof(dec));
7079 dec.cmd = V4L2_DEC_CMD_STOP;
7080 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec);
7081 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7082 OMX_COMPONENT_GENERATE_EBD);
7083 if (rc < 0) {
7084 DEBUG_PRINT_ERROR("Decoder CMD failed");
7085 return OMX_ErrorHardware;
7086 }
7087 return OMX_ErrorNone;
7088 }
7089
7090 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7091 DEBUG_PRINT_HIGH("Input EOS reached") ;
7092 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7093 }
7094
7095
7096 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7097 buf.index = nPortIndex;
7098 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7099 buf.memory = V4L2_MEMORY_USERPTR;
7100 plane.bytesused = temp_buffer->buffer_len;
7101 plane.length = drv_ctx.ip_buf.buffer_size;
7102 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7103 (unsigned long)temp_buffer->offset;
7104 plane.reserved[0] = temp_buffer->pmem_fd;
7105 plane.reserved[1] = temp_buffer->offset;
7106 plane.reserved[3] = (unsigned long)buffer->pMarkData;
7107 plane.reserved[4] = (unsigned long)buffer->hMarkTargetComponent;
7108 plane.data_offset = 0;
7109 buf.m.planes = &plane;
7110 buf.length = 1;
7111 if (buffer->nTimeStamp >= LLONG_MAX) {
7112 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7113 }
7114 //assumption is that timestamp is in milliseconds
7115 buf.timestamp.tv_sec = buffer->nTimeStamp / 1000000;
7116 buf.timestamp.tv_usec = (buffer->nTimeStamp % 1000000);
7117 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7118 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7119
7120 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7121 DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7122 android_atomic_inc(&m_queued_codec_config_count);
7123 }
7124
7125 print_v4l2_buffer("QBUF-ETB", &buf);
7126 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7127 if (rc) {
7128 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7129 print_v4l2_buffer("QBUF failed", &buf);
7130 print_omx_buffer("EBD on qbuf failed", buffer);
7131 m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7132 return OMX_ErrorHardware;
7133 }
7134
7135 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7136 codec_config_flag = false;
7137 }
7138 if (!streaming[OUTPUT_PORT]) {
7139 enum v4l2_buf_type buf_type;
7140 int ret,r;
7141
7142 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7143 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7144 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7145 if (!ret) {
7146 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7147 streaming[OUTPUT_PORT] = true;
7148 } else if (errno == EBUSY) {
7149 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7150 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7151 OMX_COMPONENT_GENERATE_EBD);
7152 return OMX_ErrorInsufficientResources;
7153 } else {
7154 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7155 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7156 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7157 OMX_COMPONENT_GENERATE_EBD);
7158 return OMX_ErrorBadParameter;
7159 }
7160 }
7161
7162 return ret;
7163 }
7164
7165 /* ======================================================================
7166 FUNCTION
7167 omx_vdec::FillThisBuffer
7168
7169 DESCRIPTION
7170 IL client uses this method to release the frame buffer
7171 after displaying them.
7172
7173 PARAMETERS
7174 None.
7175
7176 RETURN VALUE
7177 true/false
7178
7179 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7180 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7181 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7182 {
7183 if (m_state != OMX_StateExecuting &&
7184 m_state != OMX_StatePause &&
7185 m_state != OMX_StateIdle) {
7186 DEBUG_PRINT_ERROR("FTB in Invalid State");
7187 return OMX_ErrorInvalidState;
7188 }
7189
7190 if (buffer == NULL || buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7191 DEBUG_PRINT_ERROR("ERROR:FTB invalid buffer %p or PortIndex - %d",
7192 buffer, buffer ? (int)buffer->nOutputPortIndex : -1);
7193 return OMX_ErrorBadPortIndex;
7194 }
7195 print_omx_buffer("FillThisBuffer", buffer);
7196
7197 if (m_error_propogated) {
7198 DEBUG_PRINT_ERROR("Fill this buffer not allowed after error");
7199 return OMX_ErrorHardware;
7200 }
7201
7202 if (!m_out_bEnabled) {
7203 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7204 return OMX_ErrorIncorrectStateOperation;
7205 }
7206
7207 unsigned nPortIndex = 0;
7208 if (dynamic_buf_mode) {
7209 private_handle_t *handle = NULL;
7210 struct VideoDecoderOutputMetaData *meta;
7211 unsigned int nPortIndex = 0;
7212
7213 if (!buffer || !buffer->pBuffer) {
7214 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7215 return OMX_ErrorBadParameter;
7216 }
7217
7218 //get the buffer type and fd info
7219 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7220 handle = (private_handle_t *)meta->pHandle;
7221 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7222
7223 if (!handle) {
7224 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7225 return OMX_ErrorBadParameter;
7226 }
7227 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7228 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7229 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7230 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7231 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7232 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7233
7234 //Store private handle from GraphicBuffer
7235 native_buffer[nPortIndex].privatehandle = handle;
7236 native_buffer[nPortIndex].nativehandle = handle;
7237 } else {
7238 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7239 return OMX_ErrorBadParameter;
7240 }
7241
7242 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7243 //this with a more sane size so that we don't compensate in rest of code
7244 //We'll restore this size later on, so that it's transparent to client
7245 buffer->nFilledLen = 0;
7246 buffer->nAllocLen = handle->size;
7247
7248 if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
7249 m_is_display_session = true;
7250 } else {
7251 m_is_display_session = false;
7252 }
7253 DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
7254
7255 drv_ctx.op_buf.buffer_size = handle->size;
7256 }
7257
7258 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7259 if (buffer == NULL ||
7260 (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7261 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7262 nPortIndex, drv_ctx.op_buf.actualcount);
7263 return OMX_ErrorBadParameter;
7264 }
7265
7266 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7267 return OMX_ErrorNone;
7268 }
7269 /* ======================================================================
7270 FUNCTION
7271 omx_vdec::fill_this_buffer_proxy
7272
7273 DESCRIPTION
7274 IL client uses this method to release the frame buffer
7275 after displaying them.
7276
7277 PARAMETERS
7278 None.
7279
7280 RETURN VALUE
7281 true/false
7282
7283 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7284 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
7285 OMX_IN OMX_HANDLETYPE hComp,
7286 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7287 {
7288 VIDC_TRACE_NAME_HIGH("FTB");
7289 OMX_ERRORTYPE nRet = OMX_ErrorNone;
7290 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7291 unsigned nPortIndex = 0;
7292 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
7293 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
7294
7295 auto_lock l(buf_lock);
7296 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7297
7298 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
7299 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7300 nPortIndex, drv_ctx.op_buf.actualcount);
7301 return OMX_ErrorBadParameter;
7302 }
7303
7304 if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
7305 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7306 return OMX_ErrorBadParameter;
7307 }
7308
7309 /*Return back the output buffer to client*/
7310 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
7311 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7312 buffer->nFilledLen = 0;
7313 print_omx_buffer("FBD in FTBProxy", buffer);
7314 m_cb.FillBufferDone (hComp,m_app_data,buffer);
7315 return OMX_ErrorNone;
7316 }
7317 if (m_error_propogated == true) {
7318 DEBUG_PRINT_LOW("Return buffers in error state");
7319 buffer->nFilledLen = 0;
7320 print_omx_buffer("FBD in FTBProxy", buffer);
7321 m_cb.FillBufferDone (hComp,m_app_data,buffer);
7322 return OMX_ErrorNone;
7323 }
7324
7325 if (dynamic_buf_mode) {
7326 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7327 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7328 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7329 }
7330
7331 pending_output_buffers++;
7332 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7333 buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7334 if (!buffer) {
7335 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7336 return OMX_ErrorBadParameter;
7337 }
7338 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7339 if (ptr_respbuffer) {
7340 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7341 }
7342
7343 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7344 DEBUG_PRINT_ERROR("Invalid ptr_respbuffer %p, ptr_outputbuffer %p",
7345 ptr_respbuffer, ptr_outputbuffer);
7346 buffer->nFilledLen = 0;
7347 print_omx_buffer("FBD in error", buffer);
7348 m_cb.FillBufferDone (hComp,m_app_data,buffer);
7349 pending_output_buffers--;
7350 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7351 return OMX_ErrorBadParameter;
7352 }
7353
7354 int rc = 0;
7355 struct v4l2_buffer buf;
7356 struct v4l2_plane plane[VIDEO_MAX_PLANES];
7357 memset( (void *)&buf, 0, sizeof(buf));
7358 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7359 unsigned int extra_idx = 0;
7360
7361 buf.index = nPortIndex;
7362 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7363 buf.memory = V4L2_MEMORY_USERPTR;
7364 plane[0].bytesused = buffer->nFilledLen;
7365 plane[0].length = buffer->nAllocLen;
7366 plane[0].m.userptr =
7367 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7368 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7369 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7370 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7371 plane[0].data_offset = 0;
7372 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7373 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7374 plane[extra_idx].bytesused = 0;
7375 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7376 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7377 #ifdef USE_ION
7378 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7379 #endif
7380 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7381 plane[extra_idx].data_offset = 0;
7382 } else if (extra_idx >= VIDEO_MAX_PLANES) {
7383 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7384 return OMX_ErrorBadParameter;
7385 }
7386 buf.m.planes = plane;
7387 buf.length = drv_ctx.num_planes;
7388 print_v4l2_buffer("QBUF-FTB", &buf);
7389 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7390 if (rc) {
7391 buffer->nFilledLen = 0;
7392 DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
7393 print_omx_buffer("FBD in error", buffer);
7394 m_cb.FillBufferDone(hComp, m_app_data, buffer);
7395 return OMX_ErrorHardware;
7396 }
7397
7398 return OMX_ErrorNone;
7399 }
7400
7401 /* ======================================================================
7402 FUNCTION
7403 omx_vdec::SetCallbacks
7404
7405 DESCRIPTION
7406 Set the callbacks.
7407
7408 PARAMETERS
7409 None.
7410
7411 RETURN VALUE
7412 OMX Error None if everything successful.
7413
7414 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7415 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
7416 OMX_IN OMX_CALLBACKTYPE* callbacks,
7417 OMX_IN OMX_PTR appData)
7418 {
7419 (void) hComp;
7420
7421 if (!callbacks)
7422 return OMX_ErrorBadParameter;
7423
7424 m_cb = *callbacks;
7425 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7426 m_cb.EventHandler,m_cb.FillBufferDone);
7427 m_app_data = appData;
7428 return OMX_ErrorNone;
7429 }
7430
7431 /* ======================================================================
7432 FUNCTION
7433 omx_vdec::ComponentDeInit
7434
7435 DESCRIPTION
7436 Destroys the component and release memory allocated to the heap.
7437
7438 PARAMETERS
7439 <TBD>.
7440
7441 RETURN VALUE
7442 OMX Error None if everything successful.
7443
7444 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7445 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7446 {
7447 (void) hComp;
7448 OMX_ERRORTYPE nRet = OMX_ErrorNone;
7449 OMX_BUFFERHEADERTYPE *buffer;
7450
7451 unsigned i = 0;
7452 if (OMX_StateLoaded != m_state) {
7453 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7454 m_state);
7455 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7456 } else {
7457 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7458 }
7459
7460 /*Check if the output buffers have to be cleaned up*/
7461 buffer = client_buffers.get_il_buf_hdr();
7462 if (buffer) {
7463 DEBUG_PRINT_LOW("Freeing the Output Memory");
7464 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7465 if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7466 BITMASK_CLEAR(&m_out_bm_count, i);
7467 nRet = client_buffers.free_output_buffer (buffer+i);
7468 if (OMX_ErrorNone != nRet)
7469 break;
7470 }
7471 if (release_output_done()) {
7472 DEBUG_PRINT_HIGH("All output buffers are released");
7473 break;
7474 }
7475 }
7476 #ifdef _ANDROID_ICS_
7477 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7478 #endif
7479 }
7480
7481 /*Check if the input buffers have to be cleaned up*/
7482 if (m_inp_mem_ptr || m_inp_heap_ptr) {
7483 DEBUG_PRINT_LOW("Freeing the Input Memory");
7484 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7485
7486 if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7487 BITMASK_CLEAR(&m_inp_bm_count, i);
7488 if (m_inp_mem_ptr)
7489 free_input_buffer (i,&m_inp_mem_ptr[i]);
7490 else
7491 free_input_buffer (i,NULL);
7492 }
7493
7494 if (release_input_done()) {
7495 DEBUG_PRINT_HIGH("All input buffers released");
7496 break;
7497 }
7498 }
7499 }
7500 free_input_buffer_header();
7501 free_output_buffer_header();
7502
7503 if (m_platform_list) {
7504 free(m_platform_list);
7505 m_platform_list = NULL;
7506 }
7507 if (m_vendor_config.pData) {
7508 free(m_vendor_config.pData);
7509 m_vendor_config.pData = NULL;
7510 }
7511
7512 // Reset counters in mesg queues
7513 m_ftb_q.m_size=0;
7514 m_cmd_q.m_size=0;
7515 m_etb_q.m_size=0;
7516 m_ftb_q.m_read = m_ftb_q.m_write =0;
7517 m_cmd_q.m_read = m_cmd_q.m_write =0;
7518 m_etb_q.m_read = m_etb_q.m_write =0;
7519
7520 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7521 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7522 // NULL);
7523 DEBUG_PRINT_HIGH("Close the driver instance");
7524
7525 if (m_debug.infile) {
7526 fclose(m_debug.infile);
7527 m_debug.infile = NULL;
7528 }
7529 if (m_debug.outfile) {
7530 fclose(m_debug.outfile);
7531 m_debug.outfile = NULL;
7532 }
7533 if (m_debug.ccoutfile) {
7534 fclose(m_debug.ccoutfile);
7535 m_debug.ccoutfile = NULL;
7536 }
7537 if (m_debug.out_ymeta_file) {
7538 fclose(m_debug.out_ymeta_file);
7539 m_debug.out_ymeta_file = NULL;
7540 }
7541 if (m_debug.out_uvmeta_file) {
7542 fclose(m_debug.out_uvmeta_file);
7543 m_debug.out_uvmeta_file = NULL;
7544 }
7545 #ifdef OUTPUT_EXTRADATA_LOG
7546 if (outputExtradataFile)
7547 fclose (outputExtradataFile);
7548 #endif
7549 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
7550 return OMX_ErrorNone;
7551 }
7552
7553 /* ======================================================================
7554 FUNCTION
7555 omx_vdec::UseEGLImage
7556
7557 DESCRIPTION
7558 OMX Use EGL Image method implementation <TBD>.
7559
7560 PARAMETERS
7561 <TBD>.
7562
7563 RETURN VALUE
7564 Not Implemented error.
7565
7566 ========================================================================== */
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)7567 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
7568 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7569 OMX_IN OMX_U32 port,
7570 OMX_IN OMX_PTR appData,
7571 OMX_IN void* eglImage)
7572 {
7573 (void) appData;
7574 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
7575 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
7576 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
7577
7578 #ifdef USE_EGL_IMAGE_GPU
7579 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
7580 EGLint fd = -1, offset = 0,pmemPtr = 0;
7581 #else
7582 int fd = -1, offset = 0;
7583 #endif
7584 DEBUG_PRINT_HIGH("use EGL image support for decoder");
7585 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
7586 DEBUG_PRINT_ERROR("Invalid EGL image");
7587 }
7588 #ifdef USE_EGL_IMAGE_GPU
7589 if (m_display_id == NULL) {
7590 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
7591 return OMX_ErrorInsufficientResources;
7592 }
7593 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
7594 eglGetProcAddress("eglQueryImageKHR");
7595 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
7596 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
7597 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
7598 #else //with OMX test app
7599 struct temp_egl {
7600 int pmem_fd;
7601 int offset;
7602 };
7603 struct temp_egl *temp_egl_id = NULL;
7604 void * pmemPtr = (void *) eglImage;
7605 temp_egl_id = (struct temp_egl *)eglImage;
7606 if (temp_egl_id != NULL) {
7607 fd = temp_egl_id->pmem_fd;
7608 offset = temp_egl_id->offset;
7609 }
7610 #endif
7611 if (fd < 0) {
7612 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
7613 return OMX_ErrorInsufficientResources;
7614 }
7615 pmem_info.pmem_fd = (OMX_U32) fd;
7616 pmem_info.offset = (OMX_U32) offset;
7617 pmem_entry.entry = (void *) &pmem_info;
7618 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7619 pmem_list.entryList = &pmem_entry;
7620 pmem_list.nEntries = 1;
7621 ouput_egl_buffers = true;
7622 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
7623 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
7624 (OMX_U8 *)pmemPtr)) {
7625 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
7626 return OMX_ErrorInsufficientResources;
7627 }
7628 return OMX_ErrorNone;
7629 }
7630
7631 /* ======================================================================
7632 FUNCTION
7633 omx_vdec::ComponentRoleEnum
7634
7635 DESCRIPTION
7636 OMX Component Role Enum method implementation.
7637
7638 PARAMETERS
7639 <TBD>.
7640
7641 RETURN VALUE
7642 OMX Error None if everything is successful.
7643 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)7644 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
7645 OMX_OUT OMX_U8* role,
7646 OMX_IN OMX_U32 index)
7647 {
7648 (void) hComp;
7649 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7650
7651 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
7652 if ((0 == index) && role) {
7653 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
7654 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7655 } else {
7656 eRet = OMX_ErrorNoMore;
7657 }
7658 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
7659 if ((0 == index) && role) {
7660 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
7661 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7662 } else {
7663 DEBUG_PRINT_LOW("No more roles");
7664 eRet = OMX_ErrorNoMore;
7665 }
7666 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
7667 if ((0 == index) && role) {
7668 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
7669 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7670 } else {
7671 DEBUG_PRINT_LOW("No more roles");
7672 eRet = OMX_ErrorNoMore;
7673 }
7674 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
7675 if ((0 == index) && role) {
7676 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
7677 DEBUG_PRINT_LOW("component_role_enum: role %s", role);
7678 } else {
7679 DEBUG_PRINT_LOW("No more roles");
7680 eRet = OMX_ErrorNoMore;
7681 }
7682 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7683 if ((0 == index) && role) {
7684 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7685 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7686 } else {
7687 DEBUG_PRINT_LOW("No more roles");
7688 eRet = OMX_ErrorNoMore;
7689 }
7690 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
7691 if ((0 == index) && role) {
7692 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
7693 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7694 } else {
7695 DEBUG_PRINT_LOW("No more roles");
7696 eRet = OMX_ErrorNoMore;
7697 }
7698 } else {
7699 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7700 eRet = OMX_ErrorInvalidComponentName;
7701 }
7702 return eRet;
7703 }
7704
7705
7706
7707
7708 /* ======================================================================
7709 FUNCTION
7710 omx_vdec::AllocateDone
7711
7712 DESCRIPTION
7713 Checks if entire buffer pool is allocated by IL Client or not.
7714 Need this to move to IDLE state.
7715
7716 PARAMETERS
7717 None.
7718
7719 RETURN VALUE
7720 true/false.
7721
7722 ========================================================================== */
allocate_done(void)7723 bool omx_vdec::allocate_done(void)
7724 {
7725 bool bRet = false;
7726 bool bRet_In = false;
7727 bool bRet_Out = false;
7728 bool bRet_Out_Extra = false;
7729
7730 bRet_In = allocate_input_done();
7731 bRet_Out = allocate_output_done();
7732 bRet_Out_Extra = allocate_output_extradata_done();
7733
7734 if (bRet_In && bRet_Out && bRet_Out_Extra) {
7735 DEBUG_PRINT_HIGH("All ports buffers are allocated");
7736 bRet = true;
7737 }
7738
7739 return bRet;
7740 }
7741 /* ======================================================================
7742 FUNCTION
7743 omx_vdec::AllocateInputDone
7744
7745 DESCRIPTION
7746 Checks if I/P buffer pool is allocated by IL Client or not.
7747
7748 PARAMETERS
7749 None.
7750
7751 RETURN VALUE
7752 true/false.
7753
7754 ========================================================================== */
allocate_input_done(void)7755 bool omx_vdec::allocate_input_done(void)
7756 {
7757 bool bRet = false;
7758 unsigned i=0;
7759
7760 if (m_inp_mem_ptr == NULL) {
7761 return bRet;
7762 }
7763 if (m_inp_mem_ptr ) {
7764 for (; i<drv_ctx.ip_buf.actualcount; i++) {
7765 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7766 break;
7767 }
7768 }
7769 }
7770 if (i == drv_ctx.ip_buf.actualcount) {
7771 bRet = true;
7772 }
7773 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7774 m_inp_bPopulated = OMX_TRUE;
7775 }
7776 return bRet;
7777 }
7778 /* ======================================================================
7779 FUNCTION
7780 omx_vdec::AllocateOutputDone
7781
7782 DESCRIPTION
7783 Checks if entire O/P buffer pool is allocated by IL Client or not.
7784
7785 PARAMETERS
7786 None.
7787
7788 RETURN VALUE
7789 true/false.
7790
7791 ========================================================================== */
allocate_output_done(void)7792 bool omx_vdec::allocate_output_done(void)
7793 {
7794 bool bRet = false;
7795 unsigned j=0;
7796
7797 if (m_out_mem_ptr == NULL) {
7798 return bRet;
7799 }
7800
7801 if (m_out_mem_ptr) {
7802 for (; j < drv_ctx.op_buf.actualcount; j++) {
7803 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7804 break;
7805 }
7806 }
7807 }
7808
7809 if (j == drv_ctx.op_buf.actualcount) {
7810 bRet = true;
7811 if (m_out_bEnabled)
7812 m_out_bPopulated = OMX_TRUE;
7813 }
7814
7815 return bRet;
7816 }
7817
allocate_output_extradata_done(void)7818 bool omx_vdec::allocate_output_extradata_done(void) {
7819 bool bRet = false;
7820 unsigned j=0;
7821 unsigned nBufferCount = 0;
7822
7823 nBufferCount = m_client_out_extradata_info.getBufferCount();
7824
7825 if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
7826 return true;
7827 }
7828
7829 if (m_client_output_extradata_mem_ptr) {
7830 for (; j < nBufferCount; j++) {
7831 if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
7832 break;
7833 }
7834 }
7835
7836 if (j == nBufferCount) {
7837 bRet = true;
7838 DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
7839 }
7840 }
7841
7842 return bRet;
7843 }
7844 /* ======================================================================
7845 FUNCTION
7846 omx_vdec::ReleaseDone
7847
7848 DESCRIPTION
7849 Checks if IL client has released all the buffers.
7850
7851 PARAMETERS
7852 None.
7853
7854 RETURN VALUE
7855 true/false
7856
7857 ========================================================================== */
release_done(void)7858 bool omx_vdec::release_done(void)
7859 {
7860 bool bRet = false;
7861
7862 if (release_input_done()) {
7863 if (release_output_done()) {
7864 if (release_output_extradata_done()) {
7865 DEBUG_PRINT_HIGH("All ports buffers are released");
7866 bRet = true;
7867 }
7868 }
7869 }
7870 return bRet;
7871 }
7872
7873
7874 /* ======================================================================
7875 FUNCTION
7876 omx_vdec::ReleaseOutputDone
7877
7878 DESCRIPTION
7879 Checks if IL client has released all the buffers.
7880
7881 PARAMETERS
7882 None.
7883
7884 RETURN VALUE
7885 true/false
7886
7887 ========================================================================== */
release_output_done(void)7888 bool omx_vdec::release_output_done(void)
7889 {
7890 bool bRet = false;
7891 unsigned i=0,j=0;
7892
7893 if (m_out_mem_ptr) {
7894 for (; j < drv_ctx.op_buf.actualcount ; j++) {
7895 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
7896 break;
7897 }
7898 }
7899 if (j == drv_ctx.op_buf.actualcount) {
7900 m_out_bm_count = 0;
7901 bRet = true;
7902 }
7903 } else {
7904 m_out_bm_count = 0;
7905 bRet = true;
7906 }
7907 return bRet;
7908 }
7909 /* ======================================================================
7910 FUNCTION
7911 omx_vdec::ReleaseInputDone
7912
7913 DESCRIPTION
7914 Checks if IL client has released all the buffers.
7915
7916 PARAMETERS
7917 None.
7918
7919 RETURN VALUE
7920 true/false
7921
7922 ========================================================================== */
release_input_done(void)7923 bool omx_vdec::release_input_done(void)
7924 {
7925 bool bRet = false;
7926 unsigned i=0,j=0;
7927
7928 if (m_inp_mem_ptr) {
7929 for (; j<drv_ctx.ip_buf.actualcount; j++) {
7930 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
7931 break;
7932 }
7933 }
7934 if (j==drv_ctx.ip_buf.actualcount) {
7935 bRet = true;
7936 }
7937 } else {
7938 bRet = true;
7939 }
7940 return bRet;
7941 }
7942
release_output_extradata_done(void)7943 bool omx_vdec::release_output_extradata_done(void) {
7944 bool bRet = false;
7945 unsigned i=0,j=0, buffer_count=0;
7946
7947 buffer_count = m_client_out_extradata_info.getBufferCount();
7948 DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
7949 m_client_output_extradata_mem_ptr, buffer_count);
7950
7951 if (m_client_output_extradata_mem_ptr) {
7952 for (; j<buffer_count; j++) {
7953 if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
7954 break;
7955 }
7956 }
7957 if (j == buffer_count) {
7958 bRet = true;
7959 }
7960 } else {
7961 bRet = true;
7962 }
7963 return bRet;
7964 }
7965
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7966 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
7967 OMX_BUFFERHEADERTYPE * buffer)
7968 {
7969 VIDC_TRACE_NAME_HIGH("FBD");
7970 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
7971 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
7972 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
7973 return OMX_ErrorBadParameter;
7974 } else if (output_flush_progress) {
7975 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
7976 buffer->nFilledLen = 0;
7977 buffer->nTimeStamp = 0;
7978 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
7979 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7980 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
7981 }
7982
7983 if (m_debug_extradata) {
7984 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7985 DEBUG_PRINT_HIGH("***************************************************");
7986 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
7987 DEBUG_PRINT_HIGH("***************************************************");
7988 }
7989
7990 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
7991 DEBUG_PRINT_HIGH("***************************************************");
7992 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
7993 DEBUG_PRINT_HIGH("***************************************************");
7994 }
7995 }
7996
7997 pending_output_buffers --;
7998 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7999
8000 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8001 DEBUG_PRINT_HIGH("Output EOS has been reached");
8002 if (!output_flush_progress)
8003 post_event((unsigned)NULL, (unsigned)NULL,
8004 OMX_COMPONENT_GENERATE_EOS_DONE);
8005
8006 if (psource_frame) {
8007 print_omx_buffer("EBD in FBD", psource_frame);
8008 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8009 psource_frame = NULL;
8010 }
8011 if (pdest_frame) {
8012 pdest_frame->nFilledLen = 0;
8013 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8014 (unsigned)NULL);
8015 pdest_frame = NULL;
8016 }
8017 }
8018
8019 #ifdef OUTPUT_EXTRADATA_LOG
8020 if (outputExtradataFile) {
8021 int buf_index = buffer - m_out_mem_ptr;
8022 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8023
8024 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8025 p_extra = (OMX_OTHER_EXTRADATATYPE *)
8026 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8027
8028 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8029 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8030 p_extra->nSize, p_extra->eType);
8031 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8032
8033 if (p_extra->eType == OMX_ExtraDataNone) {
8034 break;
8035 }
8036 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8037 }
8038 }
8039 #endif
8040
8041 /* For use buffer we need to copy the data */
8042 if (!output_flush_progress) {
8043 /* This is the error check for non-recoverable errros */
8044 bool is_duplicate_ts_valid = true;
8045 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8046
8047 if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8048 output_capability == V4L2_PIX_FMT_MPEG2)
8049 is_duplicate_ts_valid = false;
8050
8051 if (buffer->nFilledLen > 0) {
8052 time_stamp_dts.get_next_timestamp(buffer,
8053 is_interlaced && is_duplicate_ts_valid);
8054 }
8055 }
8056 VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8057
8058 if (m_cb.FillBufferDone) {
8059 if (buffer->nFilledLen > 0) {
8060 set_frame_rate(buffer->nTimeStamp);
8061
8062 proc_frms++;
8063 if (perf_flag) {
8064 if (1 == proc_frms) {
8065 dec_time.stop();
8066 latency = dec_time.processing_time_us() - latency;
8067 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8068 dec_time.start();
8069 fps_metrics.start();
8070 }
8071 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8072 OMX_U64 proc_time = 0;
8073 fps_metrics.stop();
8074 proc_time = fps_metrics.processing_time_us();
8075 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8076 (unsigned int)proc_frms, (float)proc_time / 1e6,
8077 (float)(1e6 * proc_frms) / proc_time);
8078 }
8079 }
8080 }
8081 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8082 prev_ts = LLONG_MAX;
8083 rst_prev_ts = true;
8084 proc_frms = 0;
8085 }
8086
8087 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8088 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8089 buffer->pPlatformPrivate)->entryList->entry;
8090 OMX_BUFFERHEADERTYPE *il_buffer;
8091 il_buffer = client_buffers.get_il_buf_hdr(buffer);
8092 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8093
8094 if (il_buffer && m_last_rendered_TS >= 0) {
8095 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8096 // Convert fps into ms value. 1 sec = 1000000 ms.
8097 OMX_U64 target_ts_delta = m_dec_hfr_fps ? 1000000 / m_dec_hfr_fps : ts_delta;
8098
8099 // Current frame can be send for rendering if
8100 // (a) current FPS is <= 60
8101 // (b) is the next frame after the frame with TS 0
8102 // (c) is the first frame after seek
8103 // (d) the delta TS b\w two consecutive frames is > 16 ms
8104 // (e) its TS is equal to previous frame TS
8105 // (f) if marked EOS
8106
8107 if(current_framerate <= (OMX_U32)m_dec_hfr_fps || m_last_rendered_TS == 0 ||
8108 il_buffer->nTimeStamp == 0 || ts_delta >= (OMX_TICKS)target_ts_delta||
8109 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8110 m_last_rendered_TS = il_buffer->nTimeStamp;
8111 } else {
8112 //mark for droping
8113 buffer->nFilledLen = 0;
8114 }
8115
8116 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8117 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8118 il_buffer->nTimeStamp,ts_delta);
8119
8120 //above code makes sure that delta b\w two consecutive frames is not
8121 //greater than 16ms, slow-mo feature, so cap fps to max 60
8122 if (current_framerate > (OMX_U32)m_dec_hfr_fps ) {
8123 current_framerate = m_dec_hfr_fps;
8124 }
8125 }
8126
8127 // add current framerate to gralloc meta data
8128 if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && m_out_mem_ptr) {
8129 // If valid fps was received, directly send it to display for the 1st fbd.
8130 // Otherwise, calculate fps using fbd timestamps
8131 float refresh_rate = m_fps_prev;
8132 if (m_fps_received) {
8133 if (1 == proc_frms) {
8134 refresh_rate = m_fps_received / (float)(1<<16);
8135 }
8136 } else {
8137 // calculate and set refresh rate for every frame from second frame onwards
8138 // display will assume the default refresh rate for first frame (which is 60 fps)
8139 if (m_fps_prev) {
8140 if (drv_ctx.frame_rate.fps_denominator) {
8141 refresh_rate = drv_ctx.frame_rate.fps_numerator /
8142 (float) drv_ctx.frame_rate.fps_denominator;
8143 }
8144 }
8145 }
8146 OMX_U32 fps_limit = m_dec_hfr_fps ? (OMX_U32)m_dec_hfr_fps : 60;
8147 if (refresh_rate > fps_limit) {
8148 refresh_rate = fps_limit;
8149 }
8150 DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8151 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8152 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8153 UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8154 m_fps_prev = refresh_rate;
8155 }
8156
8157 if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) {
8158 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8159 DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8160 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8161 S3D_FORMAT, (void*)&stereo_output_mode);
8162 }
8163
8164 if (il_buffer) {
8165 log_output_buffers(buffer);
8166 log_cc_output_buffers(il_buffer);
8167 if (dynamic_buf_mode) {
8168 unsigned int nPortIndex = 0;
8169 nPortIndex = buffer-m_out_mem_ptr;
8170
8171 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8172 // to size of the handle. Do it _after_ log_output_buffers which
8173 // requires the respective sizes to be accurate.
8174
8175 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8176 buffer->nFilledLen = buffer->nFilledLen ?
8177 sizeof(struct VideoDecoderOutputMetaData) : 0;
8178
8179 //Clear graphic buffer handles in dynamic mode
8180 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8181 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8182 native_buffer[nPortIndex].privatehandle = NULL;
8183 native_buffer[nPortIndex].nativehandle = NULL;
8184 } else {
8185 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8186 return OMX_ErrorBadParameter;
8187 }
8188 }
8189 print_omx_buffer("FillBufferDone", buffer);
8190 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8191 } else {
8192 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8193 return OMX_ErrorBadParameter;
8194 }
8195 } else {
8196 DEBUG_PRINT_ERROR("NULL m_cb.FillBufferDone");
8197 return OMX_ErrorBadParameter;
8198 }
8199
8200 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8201 if (m_smoothstreaming_mode && m_out_mem_ptr) {
8202 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8203 BufferDim_t dim;
8204 private_handle_t *private_handle = NULL;
8205 dim.sliceWidth = framesize.nWidth;
8206 dim.sliceHeight = framesize.nHeight;
8207 if (buf_index < drv_ctx.op_buf.actualcount &&
8208 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8209 native_buffer[buf_index].privatehandle)
8210 private_handle = native_buffer[buf_index].privatehandle;
8211 if (private_handle) {
8212 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8213 dim.sliceWidth, dim.sliceHeight);
8214 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8215 }
8216 }
8217 #endif
8218
8219 return OMX_ErrorNone;
8220 }
8221
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8222 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
8223 OMX_BUFFERHEADERTYPE* buffer)
8224 {
8225 VIDC_TRACE_NAME_HIGH("EBD");
8226 int nBufferIndex = buffer - m_inp_mem_ptr;
8227
8228 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8229 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8230 return OMX_ErrorBadParameter;
8231 }
8232
8233 pending_input_buffers--;
8234 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
8235
8236 if (m_cb.EmptyBufferDone) {
8237 buffer->nFilledLen = 0;
8238 if (input_use_buffer == true) {
8239 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8240 }
8241
8242 /* Restore the FD that we over-wrote in ETB */
8243 if (m_input_pass_buffer_fd) {
8244 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8245 }
8246
8247 print_omx_buffer("EmptyBufferDone", buffer);
8248 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8249 }
8250 return OMX_ErrorNone;
8251 }
8252
async_message_process(void * context,void * message)8253 int omx_vdec::async_message_process (void *context, void* message)
8254 {
8255 omx_vdec* omx = NULL;
8256 struct vdec_msginfo *vdec_msg = NULL;
8257 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8258 struct v4l2_buffer *v4l2_buf_ptr = NULL;
8259 struct v4l2_plane *plane = NULL;
8260 struct vdec_output_frameinfo *output_respbuf = NULL;
8261 int rc=1;
8262 bool reconfig_event_sent = false;
8263 if (context == NULL || message == NULL) {
8264 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8265 return -1;
8266 }
8267 vdec_msg = (struct vdec_msginfo *)message;
8268
8269 omx = reinterpret_cast<omx_vdec*>(context);
8270
8271 switch (vdec_msg->msgcode) {
8272
8273 case VDEC_MSG_EVT_HW_ERROR:
8274 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8275 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8276 break;
8277
8278 case VDEC_MSG_EVT_HW_OVERLOAD:
8279 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8280 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8281 break;
8282
8283 case VDEC_MSG_EVT_HW_UNSUPPORTED:
8284 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8285 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8286 break;
8287
8288 case VDEC_MSG_RESP_START_DONE:
8289 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8290 OMX_COMPONENT_GENERATE_START_DONE);
8291 break;
8292
8293 case VDEC_MSG_RESP_STOP_DONE:
8294 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8295 OMX_COMPONENT_GENERATE_STOP_DONE);
8296 break;
8297
8298 case VDEC_MSG_RESP_RESUME_DONE:
8299 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8300 OMX_COMPONENT_GENERATE_RESUME_DONE);
8301 break;
8302
8303 case VDEC_MSG_RESP_PAUSE_DONE:
8304 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8305 OMX_COMPONENT_GENERATE_PAUSE_DONE);
8306 break;
8307
8308 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8309 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8310 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8311 break;
8312 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8313 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8314 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8315 break;
8316 case VDEC_MSG_RESP_INPUT_FLUSHED:
8317 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8318
8319 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8320 vdec_msg->msgdata.input_frame_clientdata; */
8321
8322 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8323 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8324 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8325 omxhdr = NULL;
8326 vdec_msg->status_code = VDEC_S_EFATAL;
8327 break;
8328
8329 }
8330 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8331
8332 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8333 DEBUG_PRINT_HIGH("Unsupported input");
8334 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8335 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8336 }
8337 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8338 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8339 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8340 }
8341 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8342
8343 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8344 android_atomic_dec(&omx->m_queued_codec_config_count);
8345 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8346 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8347 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8348 sem_post(&omx->m_safe_flush);
8349 }
8350 }
8351 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8352 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8353 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8354 }
8355 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8356 OMX_COMPONENT_GENERATE_EBD);
8357 break;
8358 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8359 int64_t *timestamp;
8360 timestamp = (int64_t *) malloc(sizeof(int64_t));
8361 if (timestamp) {
8362 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8363 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8364 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8365 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8366 (long long)vdec_msg->msgdata.output_frame.time_stamp);
8367 }
8368 break;
8369 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8370 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8371 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8372 if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8373 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8374 omxhdr = NULL;
8375 vdec_msg->status_code = VDEC_S_EFATAL;
8376 break;
8377 }
8378 plane = v4l2_buf_ptr->m.planes;
8379 omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8380
8381 if (omxhdr && omxhdr->pOutputPortPrivate &&
8382 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8383 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8384 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8385
8386 omxhdr->pMarkData = (OMX_PTR)(unsigned long)plane[0].reserved[3];
8387 omxhdr->hMarkTargetComponent = (OMX_HANDLETYPE)(unsigned long)plane[0].reserved[4];
8388
8389 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
8390 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8391 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8392 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8393 omxhdr->nFlags = 0;
8394
8395 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8396 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8397 //rc = -1;
8398 }
8399 if (omxhdr->nFilledLen) {
8400 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8401 }
8402 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8403 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8404 } else {
8405 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8406 }
8407 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
8408 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8409 }
8410 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8411 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8412 }
8413 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8414 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8415 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8416 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8417 }
8418
8419 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8420 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8421 }
8422
8423 output_respbuf = (struct vdec_output_frameinfo *)\
8424 omxhdr->pOutputPortPrivate;
8425 if (!output_respbuf) {
8426 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8427 return -1;
8428 }
8429 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8430 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8431
8432 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8433 output_respbuf->pic_type = PICTURE_TYPE_I;
8434 }
8435 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8436 output_respbuf->pic_type = PICTURE_TYPE_P;
8437 }
8438 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8439 output_respbuf->pic_type = PICTURE_TYPE_B;
8440 }
8441
8442 if (vdec_msg->msgdata.output_frame.len) {
8443 DEBUG_PRINT_LOW("Processing extradata");
8444 reconfig_event_sent = omx->handle_extradata(omxhdr);
8445
8446 if (omx->m_extradata_info.output_crop_updated) {
8447 DEBUG_PRINT_LOW("Read FBD crop from output extra data");
8448 vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
8449 vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
8450 vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
8451 vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
8452 vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
8453 vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
8454 memcpy(vdec_msg->msgdata.output_frame.misrinfo,
8455 omx->m_extradata_info.misr_info, sizeof(vdec_misrinfo));
8456 } else {
8457 DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
8458 vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
8459 vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
8460 vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
8461 vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
8462 vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
8463 vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
8464
8465 /* Copy these values back to OMX internal variables to make both handlign same*/
8466
8467 omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
8468 omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
8469 omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
8470 omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
8471 omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8472 omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8473 }
8474 }
8475
8476 vdec_msg->msgdata.output_frame.bufferaddr =
8477 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8478
8479 DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
8480 " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8481 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
8482 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8483 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8484 (unsigned int)vdec_msg->msgdata.output_frame.len,
8485 vdec_msg->msgdata.output_frame.framesize.left,
8486 vdec_msg->msgdata.output_frame.framesize.top,
8487 vdec_msg->msgdata.output_frame.framesize.right,
8488 vdec_msg->msgdata.output_frame.framesize.bottom);
8489
8490 /* Post event if resolution OR crop changed */
8491 /* filled length will be changed if resolution changed */
8492 /* Crop parameters can be changed even without resolution change */
8493 if (omxhdr->nFilledLen
8494 && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8495 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8496 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8497 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8498 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
8499 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
8500 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
8501
8502 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",
8503 omx->prev_n_filled_len,
8504 omx->drv_ctx.video_resolution.frame_width,
8505 omx->drv_ctx.video_resolution.frame_height,
8506 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
8507 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
8508 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
8509 vdec_msg->msgdata.output_frame.picsize.frame_height,
8510 vdec_msg->msgdata.output_frame.framesize.left,
8511 vdec_msg->msgdata.output_frame.framesize.top,
8512 vdec_msg->msgdata.output_frame.framesize.right,
8513 vdec_msg->msgdata.output_frame.framesize.bottom);
8514
8515 memcpy(&omx->drv_ctx.frame_size,
8516 &vdec_msg->msgdata.output_frame.framesize,
8517 sizeof(struct vdec_framesize));
8518
8519 omx->drv_ctx.video_resolution.frame_width =
8520 vdec_msg->msgdata.output_frame.picsize.frame_width;
8521 omx->drv_ctx.video_resolution.frame_height =
8522 vdec_msg->msgdata.output_frame.picsize.frame_height;
8523 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
8524 omx->drv_ctx.video_resolution.stride =
8525 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
8526 omx->drv_ctx.video_resolution.scan_lines =
8527 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
8528 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
8529 omx->drv_ctx.video_resolution.stride =
8530 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
8531 omx->drv_ctx.video_resolution.scan_lines =
8532 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
8533 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
8534 omx->drv_ctx.video_resolution.stride =
8535 VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
8536 omx->drv_ctx.video_resolution.scan_lines =
8537 VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
8538 }
8539 else if(omx->drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
8540 omx->drv_ctx.video_resolution.stride =
8541 VENUS_Y_STRIDE(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_width);
8542 omx->drv_ctx.video_resolution.scan_lines =
8543 VENUS_Y_SCANLINES(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_height);
8544 }
8545
8546 if(!reconfig_event_sent) {
8547 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8548 OMX_IndexConfigCommonOutputCrop,
8549 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8550 reconfig_event_sent = true;
8551 } else {
8552 /* Update C2D with new resolution */
8553 if (!omx->client_buffers.update_buffer_req()) {
8554 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
8555 }
8556 }
8557 }
8558
8559 if (omxhdr->nFilledLen)
8560 omx->prev_n_filled_len = omxhdr->nFilledLen;
8561
8562 if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
8563 vdec_msg->msgdata.output_frame.bufferaddr)
8564 memcpy ( omxhdr->pBuffer, (void *)
8565 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
8566 (unsigned long)vdec_msg->msgdata.output_frame.offset),
8567 vdec_msg->msgdata.output_frame.len);
8568 } else {
8569 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
8570 (unsigned int)vdec_msg->msgdata.output_frame.len,
8571 omxhdr->nAllocLen, omx->prev_n_filled_len);
8572 omxhdr->nFilledLen = 0;
8573 }
8574
8575 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
8576 OMX_COMPONENT_GENERATE_FBD);
8577
8578 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
8579 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
8580 OMX_COMPONENT_GENERATE_EOS_DONE);
8581 } else {
8582 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
8583 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8584 }
8585 break;
8586 case VDEC_MSG_EVT_CONFIG_CHANGED:
8587 DEBUG_PRINT_HIGH("Port settings changed");
8588 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8589 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8590 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
8591 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8592 break;
8593 default:
8594 break;
8595 }
8596 return rc;
8597 }
8598
8599 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)8600 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
8601 OMX_U32 alignment)
8602 {
8603 struct pmem_allocation allocation;
8604 allocation.size = buffer_size;
8605 allocation.align = clip2(alignment);
8606 if (allocation.align < 4096) {
8607 allocation.align = 4096;
8608 }
8609 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
8610 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
8611 allocation.align, allocation.size);
8612 return false;
8613 }
8614 return true;
8615 }
8616 #endif
8617 #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)8618 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
8619 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
8620 struct ion_fd_data *fd_data, int flag)
8621 {
8622 int fd = -EINVAL;
8623 int rc = -EINVAL;
8624 int ion_dev_flag;
8625 struct vdec_ion ion_buf_info;
8626 if (!alloc_data || buffer_size <= 0 || !fd_data) {
8627 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
8628 return -EINVAL;
8629 }
8630 ion_dev_flag = O_RDONLY;
8631 fd = open (MEM_DEVICE, ion_dev_flag);
8632 if (fd < 0) {
8633 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
8634 return fd;
8635 }
8636
8637 alloc_data->flags = flag;
8638 alloc_data->len = buffer_size;
8639 alloc_data->align = clip2(alignment);
8640 if (alloc_data->align < 4096) {
8641 alloc_data->align = 4096;
8642 }
8643
8644 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
8645 if (secure_mode && (alloc_data->flags & ION_SECURE)) {
8646 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
8647 }
8648
8649 /* Use secure display cma heap for obvious reasons. */
8650 if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
8651 alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
8652 }
8653
8654 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
8655 if (rc || !alloc_data->handle) {
8656 DEBUG_PRINT_ERROR("ION ALLOC memory failed");
8657 alloc_data->handle = 0;
8658 close(fd);
8659 fd = -ENOMEM;
8660 return fd;
8661 }
8662 fd_data->handle = alloc_data->handle;
8663 rc = ioctl(fd,ION_IOC_MAP,fd_data);
8664 if (rc) {
8665 DEBUG_PRINT_ERROR("ION MAP failed ");
8666 ion_buf_info.ion_alloc_data = *alloc_data;
8667 ion_buf_info.ion_device_fd = fd;
8668 ion_buf_info.fd_ion_data = *fd_data;
8669 free_ion_memory(&ion_buf_info);
8670 fd_data->fd =-1;
8671 fd = -ENOMEM;
8672 return fd;
8673 }
8674 DEBUG_PRINT_HIGH("Alloc ion memory: fd %d len %d flags %#x mask %#x",
8675 fd_data->fd, (unsigned int)alloc_data->len,
8676 (unsigned int)alloc_data->flags, (unsigned int)alloc_data->heap_id_mask);
8677
8678 return fd;
8679 }
8680
free_ion_memory(struct vdec_ion * buf_ion_info)8681 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
8682 {
8683
8684 if (!buf_ion_info) {
8685 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
8686 return;
8687 }
8688 DEBUG_PRINT_HIGH("Free ion memory: fd %d len %d flags %#x mask %#x",
8689 buf_ion_info->fd_ion_data.fd,
8690 (unsigned int)buf_ion_info->ion_alloc_data.len,
8691 (unsigned int)buf_ion_info->ion_alloc_data.flags,
8692 (unsigned int)buf_ion_info->ion_alloc_data.heap_id_mask);
8693
8694 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
8695 &buf_ion_info->ion_alloc_data.handle)) {
8696 DEBUG_PRINT_ERROR("ION: free failed" );
8697 }
8698 close(buf_ion_info->ion_device_fd);
8699 buf_ion_info->ion_device_fd = -1;
8700 buf_ion_info->ion_alloc_data.handle = 0;
8701 buf_ion_info->fd_ion_data.fd = -1;
8702 }
8703 #endif
free_output_buffer_header()8704 void omx_vdec::free_output_buffer_header()
8705 {
8706 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
8707 output_use_buffer = false;
8708 ouput_egl_buffers = false;
8709
8710 if (m_out_mem_ptr) {
8711 free (m_out_mem_ptr);
8712 m_out_mem_ptr = NULL;
8713 }
8714
8715 if (m_platform_list) {
8716 free(m_platform_list);
8717 m_platform_list = NULL;
8718 }
8719
8720 if (drv_ctx.ptr_respbuffer) {
8721 free (drv_ctx.ptr_respbuffer);
8722 drv_ctx.ptr_respbuffer = NULL;
8723 }
8724 if (drv_ctx.ptr_outputbuffer) {
8725 free (drv_ctx.ptr_outputbuffer);
8726 drv_ctx.ptr_outputbuffer = NULL;
8727 }
8728 #ifdef USE_ION
8729 if (drv_ctx.op_buf_ion_info) {
8730 DEBUG_PRINT_LOW("Free o/p ion context");
8731 free(drv_ctx.op_buf_ion_info);
8732 drv_ctx.op_buf_ion_info = NULL;
8733 }
8734 #endif
8735 }
8736
free_input_buffer_header()8737 void omx_vdec::free_input_buffer_header()
8738 {
8739 input_use_buffer = false;
8740 if (m_inp_mem_ptr) {
8741 DEBUG_PRINT_LOW("Free input pmem Pointer area");
8742 free (m_inp_mem_ptr);
8743 m_inp_mem_ptr = NULL;
8744 }
8745 /* We just freed all the buffer headers, every thing in m_input_free_q,
8746 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
8747 while (m_input_free_q.m_size) {
8748 unsigned long address, p2, id;
8749 m_input_free_q.pop_entry(&address, &p2, &id);
8750 }
8751 while (m_input_pending_q.m_size) {
8752 unsigned long address, p2, id;
8753 m_input_pending_q.pop_entry(&address, &p2, &id);
8754 }
8755 pdest_frame = NULL;
8756 psource_frame = NULL;
8757 if (drv_ctx.ptr_inputbuffer) {
8758 DEBUG_PRINT_LOW("Free Driver Context pointer");
8759 free (drv_ctx.ptr_inputbuffer);
8760 drv_ctx.ptr_inputbuffer = NULL;
8761 }
8762 #ifdef USE_ION
8763 if (drv_ctx.ip_buf_ion_info) {
8764 DEBUG_PRINT_LOW("Free ion context");
8765 free(drv_ctx.ip_buf_ion_info);
8766 drv_ctx.ip_buf_ion_info = NULL;
8767 }
8768 #endif
8769 }
8770
free_output_extradata_buffer_header()8771 void omx_vdec::free_output_extradata_buffer_header() {
8772 client_extradata = false;
8773 if (m_client_output_extradata_mem_ptr) {
8774 DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
8775 free(m_client_output_extradata_mem_ptr);
8776 m_client_output_extradata_mem_ptr = NULL;
8777 }
8778 }
8779
stream_off(OMX_U32 port)8780 int omx_vdec::stream_off(OMX_U32 port)
8781 {
8782 enum v4l2_buf_type btype;
8783 int rc = 0;
8784 enum v4l2_ports v4l2_port = OUTPUT_PORT;
8785 struct v4l2_requestbuffers bufreq;
8786
8787 if (port == OMX_CORE_INPUT_PORT_INDEX) {
8788 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8789 v4l2_port = OUTPUT_PORT;
8790 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
8791 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8792 v4l2_port = CAPTURE_PORT;
8793 } else if (port == OMX_ALL) {
8794 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
8795 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
8796
8797 if (!rc_input)
8798 return rc_input;
8799 else
8800 return rc_output;
8801 }
8802
8803 if (!streaming[v4l2_port]) {
8804 // already streamed off, warn and move on
8805 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
8806 " which is already streamed off", v4l2_port);
8807 return 0;
8808 }
8809
8810 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
8811
8812 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
8813 if (rc) {
8814 /*TODO: How to handle this case */
8815 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
8816 } else {
8817 streaming[v4l2_port] = false;
8818 }
8819
8820 if (port == OMX_CORE_INPUT_PORT_INDEX) {
8821 bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8822 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
8823 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8824 }
8825
8826 bufreq.memory = V4L2_MEMORY_USERPTR;
8827 bufreq.count = 0;
8828 rc = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
8829 if (rc) {
8830 DEBUG_PRINT_ERROR("Failed to release buffers on %d Port", v4l2_port);
8831 }
8832 return rc;
8833 }
8834
get_buffer_req(vdec_allocatorproperty * buffer_prop)8835 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
8836 {
8837 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8838 struct v4l2_requestbuffers bufreq;
8839 struct v4l2_control control;
8840 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
8841 unsigned int final_extra_data_size = 0;
8842 struct v4l2_format fmt;
8843 int ret = 0;
8844 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
8845 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8846 bufreq.memory = V4L2_MEMORY_USERPTR;
8847 bufreq.count = 1;
8848 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8849 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8850 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8851 fmt.fmt.pix_mp.pixelformat = output_capability;
8852 control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
8853 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8854 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8855 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8856 fmt.fmt.pix_mp.pixelformat = capture_capability;
8857 control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
8858 } else {
8859 eRet = OMX_ErrorBadParameter;
8860 }
8861 control.value = buffer_prop->mincount;
8862 if (eRet == OMX_ErrorNone) {
8863 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control);
8864 }
8865 if (ret) {
8866 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
8867 /*TODO: How to handle this case */
8868 eRet = OMX_ErrorInsufficientResources;
8869 return eRet;
8870 }
8871 buffer_prop->actualcount = buffer_prop->mincount = control.value;
8872 DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
8873 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
8874 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8875
8876 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
8877
8878 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
8879 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
8880 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
8881
8882 if (ret) {
8883 /*TODO: How to handle this case */
8884 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
8885 eRet = OMX_ErrorInsufficientResources;
8886 } else {
8887 int extra_idx = 0;
8888
8889 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
8890 buf_size = buffer_prop->buffer_size;
8891 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
8892 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8893 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
8894 } else if (extra_idx >= VIDEO_MAX_PLANES) {
8895 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
8896 return OMX_ErrorBadParameter;
8897 }
8898
8899 default_extra_data_size = VENUS_EXTRADATA_SIZE(
8900 drv_ctx.video_resolution.frame_height,
8901 drv_ctx.video_resolution.frame_width);
8902 final_extra_data_size = extra_data_size > default_extra_data_size ?
8903 extra_data_size : default_extra_data_size;
8904
8905 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
8906 (~(buffer_prop->alignment - 1));
8907
8908 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
8909 drv_ctx.extradata_info.count = buffer_prop->actualcount;
8910 drv_ctx.extradata_info.buffer_size = final_extra_data_size;
8911 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
8912 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
8913 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
8914 if (extra_data_size)
8915 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
8916 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
8917
8918 if (in_reconfig) // BufReq will be set to driver when port is disabled
8919 buffer_prop->buffer_size = buf_size;
8920 else if (buf_size != buffer_prop->buffer_size) {
8921 buffer_prop->buffer_size = buf_size;
8922 eRet = set_buffer_req(buffer_prop);
8923 }
8924 }
8925 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
8926 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8927 return eRet;
8928 }
8929
set_buffer_req(vdec_allocatorproperty * buffer_prop)8930 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
8931 {
8932 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8933 unsigned buf_size = 0;
8934 struct v4l2_format fmt, c_fmt;
8935 struct v4l2_requestbuffers bufreq;
8936 int ret = 0;
8937 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
8938 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8939 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
8940 if (buf_size != buffer_prop->buffer_size) {
8941 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
8942 (unsigned int)buffer_prop->buffer_size, buf_size);
8943 eRet = OMX_ErrorBadParameter;
8944 } else {
8945 memset(&fmt, 0x0, sizeof(struct v4l2_format));
8946 memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
8947 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
8948 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
8949 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
8950
8951 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8952 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8953 fmt.fmt.pix_mp.pixelformat = output_capability;
8954 DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
8955 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
8956 fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.pixelformat);
8957 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
8958 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8959 c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8960 c_fmt.fmt.pix_mp.pixelformat = capture_capability;
8961 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
8962 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
8963 DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
8964 c_fmt.type, c_fmt.fmt.pix_mp.width, c_fmt.fmt.pix_mp.height,
8965 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage, c_fmt.fmt.pix_mp.pixelformat);
8966 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
8967 } else {
8968 eRet = OMX_ErrorBadParameter;
8969 }
8970 if (ret) {
8971 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
8972 eRet = OMX_ErrorInsufficientResources;
8973 }
8974
8975 bufreq.memory = V4L2_MEMORY_USERPTR;
8976 bufreq.count = buffer_prop->actualcount;
8977 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8978 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8979 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8980 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8981 } else {
8982 eRet = OMX_ErrorBadParameter;
8983 }
8984
8985 if (eRet == OMX_ErrorNone) {
8986 DEBUG_PRINT_LOW("REQBUFS: type %d count %d", bufreq.type, bufreq.count);
8987 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
8988 }
8989
8990 if (ret) {
8991 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
8992 /*TODO: How to handle this case */
8993 eRet = OMX_ErrorInsufficientResources;
8994 } else if (bufreq.count < buffer_prop->actualcount) {
8995 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
8996 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
8997 buffer_prop->actualcount, bufreq.count);
8998 eRet = OMX_ErrorInsufficientResources;
8999 } else {
9000 if (!client_buffers.update_buffer_req()) {
9001 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
9002 eRet = OMX_ErrorInsufficientResources;
9003 }
9004 }
9005 }
9006 return eRet;
9007 }
9008
update_picture_resolution()9009 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
9010 {
9011 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9012 return eRet;
9013 }
9014
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)9015 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
9016 {
9017 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9018 struct v4l2_format fmt;
9019 if (!portDefn) {
9020 DEBUG_PRINT_ERROR("update_portdef: invalid params");
9021 return OMX_ErrorBadParameter;
9022 }
9023 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
9024 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9025 portDefn->eDomain = OMX_PortDomainVideo;
9026 memset(&fmt, 0x0, sizeof(struct v4l2_format));
9027 if (0 == portDefn->nPortIndex) {
9028 portDefn->eDir = OMX_DirInput;
9029 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
9030 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
9031 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
9032 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9033 portDefn->format.video.eCompressionFormat = eCompressionFormat;
9034 //for input port, always report the fps value set by client,
9035 //to distinguish whether client got valid fps from parser.
9036 portDefn->format.video.xFramerate = m_fps_received;
9037 portDefn->bEnabled = m_inp_bEnabled;
9038 portDefn->bPopulated = m_inp_bPopulated;
9039
9040 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9041 fmt.fmt.pix_mp.pixelformat = output_capability;
9042 ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9043 } else if (1 == portDefn->nPortIndex) {
9044 unsigned int buf_size = 0;
9045 int ret = 0;
9046 if (!is_down_scalar_enabled) {
9047 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9048 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9049 fmt.fmt.pix_mp.pixelformat = capture_capability;
9050 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9051 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
9052 }
9053
9054 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9055 fmt.fmt.pix_mp.pixelformat = capture_capability;
9056 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9057 if (ret) {
9058 DEBUG_PRINT_ERROR("Get Resolution failed");
9059 return OMX_ErrorHardware;
9060 }
9061 drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
9062 if (!client_buffers.update_buffer_req()) {
9063 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
9064 return OMX_ErrorHardware;
9065 }
9066
9067 if (!client_buffers.get_buffer_req(buf_size)) {
9068 DEBUG_PRINT_ERROR("update buffer requirements");
9069 return OMX_ErrorHardware;
9070 }
9071 portDefn->nBufferSize = buf_size;
9072 portDefn->eDir = OMX_DirOutput;
9073 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
9074 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
9075 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9076 if (drv_ctx.frame_rate.fps_denominator > 0)
9077 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
9078 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
9079 else {
9080 DEBUG_PRINT_ERROR("Error: Divide by zero");
9081 return OMX_ErrorBadParameter;
9082 }
9083 portDefn->bEnabled = m_out_bEnabled;
9084 portDefn->bPopulated = m_out_bPopulated;
9085 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
9086 DEBUG_PRINT_ERROR("Error in getting color format");
9087 return OMX_ErrorHardware;
9088 }
9089 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9090 fmt.fmt.pix_mp.pixelformat = capture_capability;
9091 } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
9092 portDefn->nBufferSize = m_client_out_extradata_info.getSize();
9093 portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
9094 portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
9095 portDefn->eDir = OMX_DirOutput;
9096 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
9097 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
9098 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9099 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9100 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9101 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9102 DEBUG_PRINT_LOW(" get_parameter: Port idx %d nBufSize %u nBufCnt %u",
9103 (int)portDefn->nPortIndex,
9104 (unsigned int)portDefn->nBufferSize,
9105 (unsigned int)portDefn->nBufferCountActual);
9106 return eRet;
9107 } else {
9108 portDefn->eDir = OMX_DirMax;
9109 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
9110 (int)portDefn->nPortIndex);
9111 eRet = OMX_ErrorBadPortIndex;
9112 }
9113 if (in_reconfig) {
9114 m_extradata_info.output_crop_rect.nLeft = 0;
9115 m_extradata_info.output_crop_rect.nTop = 0;
9116 m_extradata_info.output_crop_rect.nWidth = fmt.fmt.pix_mp.width;
9117 m_extradata_info.output_crop_rect.nHeight = fmt.fmt.pix_mp.height;
9118 }
9119 update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
9120 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
9121
9122 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
9123 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
9124 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9125 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9126
9127 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
9128 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
9129 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
9130 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
9131 }
9132 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
9133 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
9134 (unsigned int)portDefn->nPortIndex,
9135 (unsigned int)portDefn->format.video.nFrameWidth,
9136 (unsigned int)portDefn->format.video.nFrameHeight,
9137 (int)portDefn->format.video.nStride,
9138 (unsigned int)portDefn->format.video.nSliceHeight,
9139 (unsigned int)portDefn->format.video.eColorFormat,
9140 (unsigned int)portDefn->nBufferSize,
9141 (unsigned int)portDefn->nBufferCountActual);
9142
9143 return eRet;
9144 }
9145
allocate_output_headers()9146 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
9147 {
9148 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9149 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
9150 unsigned i = 0;
9151
9152 if (!m_out_mem_ptr) {
9153 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation, Cnt %d Sz %d",
9154 drv_ctx.op_buf.actualcount, (unsigned int)drv_ctx.op_buf.buffer_size);
9155 int nBufHdrSize = 0;
9156 int nPlatformEntrySize = 0;
9157 int nPlatformListSize = 0;
9158 int nPMEMInfoSize = 0;
9159 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
9160 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
9161 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
9162
9163 nBufHdrSize = drv_ctx.op_buf.actualcount *
9164 sizeof(OMX_BUFFERHEADERTYPE);
9165 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
9166 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9167 nPlatformListSize = drv_ctx.op_buf.actualcount *
9168 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9169 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9170 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9171
9172 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
9173 // Alloc mem for platform specific info
9174 char *pPtr=NULL;
9175 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9176 nPMEMInfoSize,1);
9177 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9178 calloc (sizeof(struct vdec_bufferpayload),
9179 drv_ctx.op_buf.actualcount);
9180 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
9181 calloc (sizeof (struct vdec_output_frameinfo),
9182 drv_ctx.op_buf.actualcount);
9183 if (!pPtr || !drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9184 DEBUG_PRINT_ERROR("allocate_output_headers: allocation failed");
9185 free(pPtr); pPtr = NULL;
9186 free(drv_ctx.ptr_outputbuffer); drv_ctx.ptr_outputbuffer = NULL;
9187 free(drv_ctx.ptr_respbuffer); drv_ctx.ptr_respbuffer = NULL;
9188 return OMX_ErrorInsufficientResources;
9189 }
9190
9191 #ifdef USE_ION
9192 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9193 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9194 if (!drv_ctx.op_buf_ion_info) {
9195 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9196 free(pPtr); pPtr = NULL;
9197 free(drv_ctx.ptr_outputbuffer); drv_ctx.ptr_outputbuffer = NULL;
9198 free(drv_ctx.ptr_respbuffer); drv_ctx.ptr_respbuffer = NULL;
9199 return OMX_ErrorInsufficientResources;
9200 }
9201 #endif
9202
9203 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9204 && drv_ctx.ptr_respbuffer) {
9205 bufHdr = m_out_mem_ptr;
9206 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9207 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9208 (((char *) m_platform_list) + nPlatformListSize);
9209 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
9210 (((char *) m_platform_entry) + nPlatformEntrySize);
9211 pPlatformList = m_platform_list;
9212 pPlatformEntry = m_platform_entry;
9213 pPMEMInfo = m_pmem_info;
9214
9215 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
9216
9217 // Settting the entire storage nicely
9218 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
9219 m_out_mem_ptr,pPlatformEntry);
9220 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
9221 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
9222 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
9223 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
9224 // Set the values when we determine the right HxW param
9225 bufHdr->nAllocLen = 0;
9226 bufHdr->nFilledLen = 0;
9227 bufHdr->pAppPrivate = NULL;
9228 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9229 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
9230 pPlatformEntry->entry = pPMEMInfo;
9231 // Initialize the Platform List
9232 pPlatformList->nEntries = 1;
9233 pPlatformList->entryList = pPlatformEntry;
9234 // Keep pBuffer NULL till vdec is opened
9235 bufHdr->pBuffer = NULL;
9236 pPMEMInfo->offset = 0;
9237 pPMEMInfo->pmem_fd = -1;
9238 bufHdr->pPlatformPrivate = pPlatformList;
9239 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
9240 #ifdef USE_ION
9241 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
9242 #endif
9243 /*Create a mapping between buffers*/
9244 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
9245 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
9246 &drv_ctx.ptr_outputbuffer[i];
9247 // Move the buffer and buffer header pointers
9248 bufHdr++;
9249 pPMEMInfo++;
9250 pPlatformEntry++;
9251 pPlatformList++;
9252 }
9253 } else {
9254 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
9255 m_out_mem_ptr, pPtr);
9256 if (m_out_mem_ptr) {
9257 free(m_out_mem_ptr);
9258 m_out_mem_ptr = NULL;
9259 }
9260 if (pPtr) {
9261 free(pPtr);
9262 pPtr = NULL;
9263 }
9264 if (drv_ctx.ptr_outputbuffer) {
9265 free(drv_ctx.ptr_outputbuffer);
9266 drv_ctx.ptr_outputbuffer = NULL;
9267 }
9268 if (drv_ctx.ptr_respbuffer) {
9269 free(drv_ctx.ptr_respbuffer);
9270 drv_ctx.ptr_respbuffer = NULL;
9271 }
9272 #ifdef USE_ION
9273 if (drv_ctx.op_buf_ion_info) {
9274 DEBUG_PRINT_LOW("Free o/p ion context");
9275 free(drv_ctx.op_buf_ion_info);
9276 drv_ctx.op_buf_ion_info = NULL;
9277 }
9278 #endif
9279 eRet = OMX_ErrorInsufficientResources;
9280 }
9281 } else {
9282 eRet = OMX_ErrorInsufficientResources;
9283 }
9284 return eRet;
9285 }
9286
complete_pending_buffer_done_cbs()9287 void omx_vdec::complete_pending_buffer_done_cbs()
9288 {
9289 unsigned long p1, p2, ident;
9290 omx_cmd_queue tmp_q, pending_bd_q;
9291 pthread_mutex_lock(&m_lock);
9292 // pop all pending GENERATE FDB from ftb queue
9293 while (m_ftb_q.m_size) {
9294 m_ftb_q.pop_entry(&p1,&p2,&ident);
9295 if (ident == OMX_COMPONENT_GENERATE_FBD) {
9296 pending_bd_q.insert_entry(p1,p2,ident);
9297 } else {
9298 tmp_q.insert_entry(p1,p2,ident);
9299 }
9300 }
9301 //return all non GENERATE FDB to ftb queue
9302 while (tmp_q.m_size) {
9303 tmp_q.pop_entry(&p1,&p2,&ident);
9304 m_ftb_q.insert_entry(p1,p2,ident);
9305 }
9306 // pop all pending GENERATE EDB from etb queue
9307 while (m_etb_q.m_size) {
9308 m_etb_q.pop_entry(&p1,&p2,&ident);
9309 if (ident == OMX_COMPONENT_GENERATE_EBD) {
9310 pending_bd_q.insert_entry(p1,p2,ident);
9311 } else {
9312 tmp_q.insert_entry(p1,p2,ident);
9313 }
9314 }
9315 //return all non GENERATE FDB to etb queue
9316 while (tmp_q.m_size) {
9317 tmp_q.pop_entry(&p1,&p2,&ident);
9318 m_etb_q.insert_entry(p1,p2,ident);
9319 }
9320 pthread_mutex_unlock(&m_lock);
9321 // process all pending buffer dones
9322 while (pending_bd_q.m_size) {
9323 pending_bd_q.pop_entry(&p1,&p2,&ident);
9324 switch (ident) {
9325 case OMX_COMPONENT_GENERATE_EBD:
9326 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
9327 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
9328 omx_report_error ();
9329 }
9330 break;
9331
9332 case OMX_COMPONENT_GENERATE_FBD:
9333 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
9334 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
9335 omx_report_error ();
9336 }
9337 break;
9338 }
9339 }
9340 }
9341
set_frame_rate(OMX_S64 act_timestamp)9342 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
9343 {
9344 OMX_U32 new_frame_interval = 0;
9345 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
9346 && llabs(act_timestamp - prev_ts) > 2000) {
9347 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
9348 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
9349 if (new_frame_interval != frm_int || frm_int == 0) {
9350 frm_int = new_frame_interval;
9351 if (frm_int) {
9352 drv_ctx.frame_rate.fps_numerator = 1e6;
9353 drv_ctx.frame_rate.fps_denominator = frm_int;
9354 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
9355 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
9356 (float)drv_ctx.frame_rate.fps_denominator);
9357 /* We need to report the difference between this FBD and the previous FBD
9358 * back to the driver for clock scaling purposes. */
9359 struct v4l2_outputparm oparm;
9360 /*XXX: we're providing timing info as seconds per frame rather than frames
9361 * per second.*/
9362 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
9363 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
9364
9365 struct v4l2_streamparm sparm;
9366 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9367 sparm.parm.output = oparm;
9368 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
9369 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
9370 performance might be affected");
9371 }
9372
9373 }
9374 }
9375 }
9376 prev_ts = act_timestamp;
9377 }
9378
get_omx_output_buffer_header(int index)9379 OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index)
9380 {
9381 return m_out_mem_ptr + index;
9382 }
9383
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorAspects * aspects)9384 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
9385 OMX_U32 transfer, OMX_U32 matrix, ColorAspects *aspects)
9386 {
9387 switch (primaries) {
9388 case MSM_VIDC_BT709_5:
9389 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
9390 break;
9391 case MSM_VIDC_BT470_6_M:
9392 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
9393 break;
9394 case MSM_VIDC_BT601_6_625:
9395 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
9396 break;
9397 case MSM_VIDC_BT601_6_525:
9398 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
9399 break;
9400 case MSM_VIDC_GENERIC_FILM:
9401 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
9402 break;
9403 case MSM_VIDC_BT2020:
9404 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
9405 break;
9406 case MSM_VIDC_UNSPECIFIED:
9407 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
9408 default:
9409 //aspects->mPrimaries = ColorAspects::PrimariesOther;
9410 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
9411 break;
9412 }
9413
9414 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
9415
9416 switch (transfer) {
9417 case MSM_VIDC_TRANSFER_BT709_5:
9418 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
9419 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9420 break;
9421 case MSM_VIDC_TRANSFER_BT_470_6_M:
9422 aspects->mTransfer = ColorAspects::TransferGamma22;
9423 break;
9424 case MSM_VIDC_TRANSFER_BT_470_6_BG:
9425 aspects->mTransfer = ColorAspects::TransferGamma28;
9426 break;
9427 case MSM_VIDC_TRANSFER_SMPTE_240M:
9428 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
9429 break;
9430 case MSM_VIDC_TRANSFER_LINEAR:
9431 aspects->mTransfer = ColorAspects::TransferLinear;
9432 break;
9433 case MSM_VIDC_TRANSFER_IEC_61966:
9434 aspects->mTransfer = ColorAspects::TransferXvYCC;
9435 break;
9436 case MSM_VIDC_TRANSFER_BT_1361:
9437 aspects->mTransfer = ColorAspects::TransferBT1361;
9438 break;
9439 case MSM_VIDC_TRANSFER_SRGB:
9440 aspects->mTransfer = ColorAspects::TransferSRGB;
9441 break;
9442 case MSM_VIDC_TRANSFER_SMPTE_ST2084:
9443 aspects->mTransfer = ColorAspects::TransferST2084;
9444 break;
9445 case MSM_VIDC_TRANSFER_HLG:
9446 aspects->mTransfer = ColorAspects::TransferHLG;
9447 break;
9448 default:
9449 //aspects->mTransfer = ColorAspects::TransferOther;
9450 aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
9451 break;
9452 }
9453
9454 switch (matrix) {
9455 case MSM_VIDC_MATRIX_BT_709_5:
9456 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
9457 break;
9458 case MSM_VIDC_MATRIX_FCC_47:
9459 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
9460 break;
9461 case MSM_VIDC_MATRIX_601_6_625:
9462 case MSM_VIDC_MATRIX_601_6_525:
9463 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
9464 break;
9465 case MSM_VIDC_MATRIX_SMPTE_240M:
9466 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
9467 break;
9468 case MSM_VIDC_MATRIX_BT_2020:
9469 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
9470 break;
9471 case MSM_VIDC_MATRIX_BT_2020_CONST:
9472 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
9473 break;
9474 default:
9475 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
9476 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
9477 break;
9478 }
9479 }
9480
print_debug_color_aspects(ColorAspects * a,const char * prefix)9481 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) {
9482 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)",
9483 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange),
9484 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs));
9485
9486 }
9487
handle_color_space_info(void * data)9488 bool omx_vdec::handle_color_space_info(void *data)
9489 {
9490 ColorAspects tempAspects;
9491 memset(&tempAspects, 0x0, sizeof(ColorAspects));
9492 ColorAspects *aspects = &tempAspects;
9493
9494 switch(output_capability) {
9495 case V4L2_PIX_FMT_MPEG2:
9496 {
9497 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
9498 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
9499
9500 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
9501 * understand this code */
9502
9503 if (seqdisp_payload && seqdisp_payload->color_descp) {
9504
9505 convert_color_space_info(seqdisp_payload->color_primaries, 1,
9506 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
9507 aspects);
9508 m_disp_hor_size = seqdisp_payload->disp_width;
9509 m_disp_vert_size = seqdisp_payload->disp_height;
9510 }
9511 }
9512 break;
9513 case V4L2_PIX_FMT_H264:
9514 case V4L2_PIX_FMT_HEVC:
9515 {
9516 struct msm_vidc_vui_display_info_payload *display_info_payload;
9517 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
9518
9519 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
9520
9521 if (display_info_payload->video_signal_present_flag &&
9522 display_info_payload->color_description_present_flag) {
9523 convert_color_space_info(display_info_payload->color_primaries,
9524 display_info_payload->video_full_range_flag,
9525 display_info_payload->transfer_characteristics,
9526 display_info_payload->matrix_coefficients,
9527 aspects);
9528 }
9529 }
9530 break;
9531 case V4L2_PIX_FMT_VP8:
9532 {
9533 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
9534 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
9535 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
9536 * to understand this code */
9537
9538 if (vpx_color_space_payload->color_space == 0) {
9539 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
9540 aspects->mRange = ColorAspects::RangeLimited;
9541 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9542 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
9543 } else {
9544 DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
9545 break;
9546 }
9547 }
9548 break;
9549 case V4L2_PIX_FMT_VP9:
9550 {
9551 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
9552 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
9553 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
9554 * to understand this code */
9555
9556 switch(vpx_color_space_payload->color_space) {
9557 case MSM_VIDC_CS_BT_601:
9558 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
9559 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9560 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
9561 aspects->mRange = m_client_color_space.sAspects.mRange;
9562 break;
9563 case MSM_VIDC_CS_BT_709:
9564 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
9565 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9566 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
9567 aspects->mRange = m_client_color_space.sAspects.mRange;
9568 break;
9569 case MSM_VIDC_CS_SMPTE_170:
9570 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
9571 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9572 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
9573 aspects->mRange = m_client_color_space.sAspects.mRange;
9574 break;
9575 case MSM_VIDC_CS_SMPTE_240:
9576 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
9577 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
9578 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
9579 aspects->mRange = m_client_color_space.sAspects.mRange;
9580 break;
9581 case MSM_VIDC_CS_BT_2020:
9582 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
9583 aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
9584 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
9585 aspects->mRange = m_client_color_space.sAspects.mRange;
9586 break;
9587 case MSM_VIDC_CS_RESERVED:
9588 aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
9589 aspects->mTransfer = ColorAspects::TransferOther;
9590 aspects->mPrimaries = ColorAspects::PrimariesOther;
9591 aspects->mRange = m_client_color_space.sAspects.mRange;
9592 break;
9593 case MSM_VIDC_CS_RGB:
9594 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
9595 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
9596 aspects->mPrimaries = ColorAspects::PrimariesOther;
9597 aspects->mRange = m_client_color_space.sAspects.mRange;
9598 break;
9599 default:
9600 break;
9601 }
9602 }
9603 break;
9604 default:
9605 break;
9606 }
9607
9608 print_debug_color_aspects(aspects, "Bitstream");
9609
9610 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
9611 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
9612 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
9613 m_internal_color_space.sAspects.mRange != aspects->mRange) {
9614 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
9615
9616 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
9617 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
9618 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
9619
9620 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9621 OMX_QTIIndexConfigDescribeColorAspects,
9622 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9623 return true;
9624 }
9625 return false;
9626 }
9627
print_debug_hdr_color_info(HDRStaticInfo * hdr_info,const char * prefix)9628 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
9629 {
9630 if (!hdr_info->mID) {
9631 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
9632 hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
9633 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
9634 hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
9635 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
9636 hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
9637 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
9638 hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
9639 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
9640 hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
9641 DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
9642 hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
9643 }
9644
9645 }
9646
print_debug_hdr_color_info_mdata(ColorMetaData * color_mdata)9647 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
9648 {
9649 DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
9650 color_mdata->colorPrimaries, color_mdata->range,
9651 color_mdata->transfer, color_mdata->matrixCoefficients);
9652
9653 for(uint8_t i = 0; i < 3; i++) {
9654 for(uint8_t j = 0; j < 2; j++) {
9655 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
9656 }
9657 }
9658
9659 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
9660 color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
9661 color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
9662
9663 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
9664 color_mdata->masteringDisplayInfo.maxDisplayLuminance,
9665 color_mdata->masteringDisplayInfo.minDisplayLuminance);
9666
9667 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
9668 color_mdata->contentLightLevel.maxContentLightLevel,
9669 color_mdata->contentLightLevel.minPicAverageLightLevel);
9670
9671
9672 }
9673
handle_content_light_level_info(void * data)9674 bool omx_vdec::handle_content_light_level_info(void* data)
9675 {
9676 struct msm_vidc_content_light_level_sei_payload *light_level_payload =
9677 (msm_vidc_content_light_level_sei_payload*)(data);
9678
9679 if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
9680 (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
9681 m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
9682 m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
9683 return true;
9684 }
9685 return false;
9686 }
9687
handle_mastering_display_color_info(void * data)9688 bool omx_vdec::handle_mastering_display_color_info(void* data)
9689 {
9690 struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
9691 (msm_vidc_mastering_display_colour_sei_payload*)(data);
9692 HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
9693 bool internal_disp_changed_flag = false;
9694
9695 internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
9696 (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[0]);
9697 internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
9698 (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[1]);
9699 internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
9700 (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[2]);
9701
9702 internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
9703 (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
9704
9705 /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
9706 requires it in cd/m2, so dividing by 10000 and rounding the value after division
9707 */
9708 uint16_t max_display_luminance_cd_m2 =
9709 static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
9710 internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
9711 (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
9712
9713 if (internal_disp_changed_flag) {
9714 hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[0];
9715 hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[0];
9716 hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[1];
9717 hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[1];
9718 hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[2];
9719 hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[2];
9720 hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
9721 hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
9722
9723 hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
9724 hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
9725 }
9726
9727 return internal_disp_changed_flag;
9728 }
9729
set_colormetadata_in_handle(ColorMetaData * color_mdata,unsigned int buf_index)9730 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
9731 {
9732 private_handle_t *private_handle = NULL;
9733 if (buf_index < drv_ctx.op_buf.actualcount &&
9734 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
9735 native_buffer[buf_index].privatehandle) {
9736 private_handle = native_buffer[buf_index].privatehandle;
9737 }
9738 if (private_handle) {
9739 setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
9740 }
9741 }
9742
convert_color_aspects_to_metadata(ColorAspects & aspects,ColorMetaData & color_mdata)9743 void omx_vdec::convert_color_aspects_to_metadata(ColorAspects& aspects, ColorMetaData &color_mdata)
9744 {
9745 PrimariesMap::const_iterator primary_it = mPrimariesMap.find(aspects.mPrimaries);
9746 TransferMap::const_iterator transfer_it = mTransferMap.find(aspects.mTransfer);
9747 MatrixCoeffMap::const_iterator matrix_it = mMatrixCoeffMap.find(aspects.mMatrixCoeffs);
9748 RangeMap::const_iterator range_it = mColorRangeMap.find(aspects.mRange);
9749
9750 if (primary_it == mPrimariesMap.end()) {
9751 DEBUG_PRINT_LOW("No mapping for %d in PrimariesMap, defaulting to unspecified", aspects.mPrimaries);
9752 color_mdata.colorPrimaries = (ColorPrimaries)2;
9753 } else {
9754 color_mdata.colorPrimaries = primary_it->second;
9755 }
9756
9757 if (transfer_it == mTransferMap.end()) {
9758 DEBUG_PRINT_LOW("No mapping for %d in TransferMap, defaulting to unspecified", aspects.mTransfer);
9759 color_mdata.transfer = (GammaTransfer)2;
9760 } else {
9761 color_mdata.transfer = transfer_it->second;
9762 }
9763
9764 if (matrix_it == mMatrixCoeffMap.end()) {
9765 DEBUG_PRINT_LOW("No mapping for %d in MatrixCoeffMap, defaulting to unspecified", aspects.mMatrixCoeffs);
9766 color_mdata.matrixCoefficients = (MatrixCoEfficients)2;
9767 } else {
9768 color_mdata.matrixCoefficients = matrix_it->second;
9769 }
9770
9771 if (range_it == mColorRangeMap.end()) {
9772 DEBUG_PRINT_LOW("No mapping for %d in ColorRangeMap, defaulting to limited range", aspects.mRange);
9773 color_mdata.range = Range_Limited;
9774 } else {
9775 color_mdata.range = range_it->second;
9776 }
9777 }
9778
convert_hdr_info_to_metadata(HDRStaticInfo & hdr_info,ColorMetaData & color_mdata)9779 void omx_vdec::convert_hdr_info_to_metadata(HDRStaticInfo& hdr_info, ColorMetaData &color_mdata)
9780 {
9781 HDRStaticInfo::Type1 zero_hdr_info;
9782 MasteringDisplay& mastering_display = color_mdata.masteringDisplayInfo;
9783 ContentLightLevel& content_light = color_mdata.contentLightLevel;
9784 bool hdr_info_enabled = false;
9785 memset(&zero_hdr_info, 0, sizeof(HDRStaticInfo::Type1));
9786 hdr_info_enabled = (memcmp(&hdr_info, &zero_hdr_info, sizeof(HDRStaticInfo::Type1))!= 0);
9787
9788 if (hdr_info_enabled) {
9789 mastering_display.colorVolumeSEIEnabled = true;
9790 mastering_display.primaries.rgbPrimaries[0][0] = hdr_info.sType1.mR.x;
9791 mastering_display.primaries.rgbPrimaries[0][1] = hdr_info.sType1.mR.y;
9792 mastering_display.primaries.rgbPrimaries[1][0] = hdr_info.sType1.mG.x;
9793 mastering_display.primaries.rgbPrimaries[1][1] = hdr_info.sType1.mG.y;
9794 mastering_display.primaries.rgbPrimaries[2][0] = hdr_info.sType1.mB.x;
9795 mastering_display.primaries.rgbPrimaries[2][1] = hdr_info.sType1.mB.y;
9796 mastering_display.primaries.whitePoint[0] = hdr_info.sType1.mW.x;
9797 mastering_display.primaries.whitePoint[1] = hdr_info.sType1.mW.y;
9798 mastering_display.maxDisplayLuminance = hdr_info.sType1.mMaxDisplayLuminance * LUMINANCE_DIV_FACTOR;
9799 mastering_display.minDisplayLuminance = hdr_info.sType1.mMinDisplayLuminance;
9800 content_light.lightLevelSEIEnabled = true;
9801 content_light.maxContentLightLevel = hdr_info.sType1.mMaxContentLightLevel;
9802 content_light.minPicAverageLightLevel = hdr_info.sType1.mMaxFrameAverageLightLevel;
9803 }
9804
9805 }
9806
get_preferred_color_aspects(ColorAspects & preferredColorAspects)9807 void omx_vdec::get_preferred_color_aspects(ColorAspects& preferredColorAspects)
9808 {
9809 // For VPX, use client-color if specified.
9810 // For the rest, try to use the stream-color if present
9811 bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
9812 output_capability == V4L2_PIX_FMT_VP9);
9813
9814 const ColorAspects &preferredColor = preferClientColor ?
9815 m_client_color_space.sAspects : m_internal_color_space.sAspects;
9816 const ColorAspects &defaultColor = preferClientColor ?
9817 m_internal_color_space.sAspects : m_client_color_space.sAspects;
9818
9819 preferredColorAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
9820 preferredColor.mPrimaries : defaultColor.mPrimaries;
9821 preferredColorAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
9822 preferredColor.mTransfer : defaultColor.mTransfer;
9823 preferredColorAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
9824 preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
9825 preferredColorAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
9826 preferredColor.mRange : defaultColor.mRange;
9827
9828 }
9829
get_preferred_hdr_info(HDRStaticInfo & finalHDRInfo)9830 void omx_vdec::get_preferred_hdr_info(HDRStaticInfo& finalHDRInfo)
9831 {
9832 bool preferClientHDR = (output_capability == V4L2_PIX_FMT_VP9);
9833
9834 const HDRStaticInfo &preferredHDRInfo = preferClientHDR ?
9835 m_client_hdr_info.sInfo : m_internal_hdr_info.sInfo;
9836 const HDRStaticInfo &defaultHDRInfo = preferClientHDR ?
9837 m_internal_hdr_info.sInfo : m_client_hdr_info.sInfo;
9838 finalHDRInfo.sType1.mR = ((preferredHDRInfo.sType1.mR.x != 0) && (preferredHDRInfo.sType1.mR.y != 0)) ?
9839 preferredHDRInfo.sType1.mR : defaultHDRInfo.sType1.mR;
9840 finalHDRInfo.sType1.mG = ((preferredHDRInfo.sType1.mG.x != 0) && (preferredHDRInfo.sType1.mG.y != 0)) ?
9841 preferredHDRInfo.sType1.mG : defaultHDRInfo.sType1.mG;
9842 finalHDRInfo.sType1.mB = ((preferredHDRInfo.sType1.mB.x != 0) && (preferredHDRInfo.sType1.mB.y != 0)) ?
9843 preferredHDRInfo.sType1.mB : defaultHDRInfo.sType1.mB;
9844 finalHDRInfo.sType1.mW = ((preferredHDRInfo.sType1.mW.x != 0) && (preferredHDRInfo.sType1.mW.y != 0)) ?
9845 preferredHDRInfo.sType1.mW : defaultHDRInfo.sType1.mW;
9846 finalHDRInfo.sType1.mMaxDisplayLuminance = (preferredHDRInfo.sType1.mMaxDisplayLuminance != 0) ?
9847 preferredHDRInfo.sType1.mMaxDisplayLuminance : defaultHDRInfo.sType1.mMaxDisplayLuminance;
9848 finalHDRInfo.sType1.mMinDisplayLuminance = (preferredHDRInfo.sType1.mMinDisplayLuminance != 0) ?
9849 preferredHDRInfo.sType1.mMinDisplayLuminance : defaultHDRInfo.sType1.mMinDisplayLuminance;
9850 finalHDRInfo.sType1.mMaxContentLightLevel = (preferredHDRInfo.sType1.mMaxContentLightLevel != 0) ?
9851 preferredHDRInfo.sType1.mMaxContentLightLevel : defaultHDRInfo.sType1.mMaxContentLightLevel;
9852 finalHDRInfo.sType1.mMaxFrameAverageLightLevel = (preferredHDRInfo.sType1.mMaxFrameAverageLightLevel != 0) ?
9853 preferredHDRInfo.sType1.mMaxFrameAverageLightLevel : defaultHDRInfo.sType1.mMaxFrameAverageLightLevel;
9854 }
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)9855 bool omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
9856 {
9857 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
9858 OMX_U8 *pBuffer = NULL;
9859 OMX_U32 num_conceal_MB = 0;
9860 OMX_TICKS time_stamp = 0;
9861 OMX_U32 frame_rate = 0;
9862 unsigned long consumed_len = 0;
9863 OMX_U32 num_MB_in_frame;
9864 OMX_U32 recovery_sei_flags = 1;
9865 int enable = OMX_InterlaceFrameProgressive;
9866 bool internal_hdr_info_changed_flag = false;
9867 bool reconfig_event_sent = false;
9868
9869 int buf_index = p_buf_hdr - m_out_mem_ptr;
9870 if (buf_index >= drv_ctx.extradata_info.count) {
9871 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
9872 buf_index, drv_ctx.extradata_info.count);
9873 return reconfig_event_sent;
9874 }
9875 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
9876
9877 if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
9878 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
9879 return reconfig_event_sent;
9880 }
9881
9882 if (!drv_ctx.extradata_info.uaddr) {
9883 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
9884 return reconfig_event_sent;
9885 }
9886 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
9887 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
9888 p_extra = NULL;
9889 return reconfig_event_sent;
9890 }
9891 if (!secure_mode) {
9892 pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
9893 PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
9894 if (pBuffer == MAP_FAILED) {
9895 DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno);
9896 return reconfig_event_sent;
9897 }
9898 p_extra = (OMX_OTHER_EXTRADATATYPE *)
9899 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
9900 } else
9901 p_extra = m_other_extradata;
9902
9903 AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
9904 if (m_client_output_extradata_mem_ptr &&
9905 m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
9906 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
9907 }
9908
9909 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
9910
9911 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
9912 p_extra = NULL;
9913 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
9914 return reconfig_event_sent;
9915 }
9916 m_extradata_info.output_crop_updated = OMX_FALSE;
9917 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
9918 if (data && p_extra) {
9919 while ((consumed_len < drv_ctx.extradata_info.buffer_size)
9920 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
9921 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
9922 DEBUG_PRINT_LOW("Invalid extra data size");
9923 break;
9924 }
9925
9926 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
9927 p_extra = NULL;
9928 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
9929 return reconfig_event_sent;
9930 }
9931
9932 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
9933 switch ((unsigned long)data->eType) {
9934 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
9935 struct msm_vidc_interlace_payload *payload;
9936 payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
9937 if (payload) {
9938 DEBUG_PRINT_LOW("Interlace format %#x", payload->format);
9939 enable = OMX_InterlaceFrameProgressive;
9940 switch (payload->format & 0x1F) {
9941 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
9942 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9943 break;
9944 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
9945 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
9946 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
9947 break;
9948 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
9949 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
9950 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
9951 break;
9952 case MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST:
9953 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
9954 enable = OMX_InterlaceFrameTopFieldFirst;
9955 break;
9956 case MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST:
9957 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
9958 enable = OMX_InterlaceFrameBottomFieldFirst;
9959 break;
9960 default:
9961 DEBUG_PRINT_LOW("default case - set to progressive");
9962 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9963 }
9964 }
9965
9966 if (m_enable_android_native_buffers) {
9967 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d",
9968 payload->format, enable);
9969
9970 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
9971 PP_PARAM_INTERLACED, (void*)&enable);
9972
9973 }
9974 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
9975 append_interlace_extradata(p_extra, (payload->format & 0x1F));
9976 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
9977 if (p_client_extra) {
9978 append_interlace_extradata(p_client_extra, (payload->format & 0x1F));
9979 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
9980 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
9981 }
9982 }
9983 break;
9984 case MSM_VIDC_EXTRADATA_FRAME_RATE:
9985 struct msm_vidc_framerate_payload *frame_rate_payload;
9986 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
9987 frame_rate = frame_rate_payload->frame_rate;
9988 break;
9989 case MSM_VIDC_EXTRADATA_TIMESTAMP:
9990 struct msm_vidc_ts_payload *time_stamp_payload;
9991 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
9992 time_stamp = time_stamp_payload->timestamp_lo;
9993 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
9994 p_buf_hdr->nTimeStamp = time_stamp;
9995 break;
9996 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
9997 struct msm_vidc_concealmb_payload *conceal_mb_payload;
9998 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
9999 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10000 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10001 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
10002 break;
10003 case MSM_VIDC_EXTRADATA_INDEX:
10004 int *etype;
10005 etype = (int *)(void *)data->data;
10006 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
10007 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
10008 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
10009 if (aspect_ratio_payload) {
10010 ((struct vdec_output_frameinfo *)
10011 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
10012 ((struct vdec_output_frameinfo *)
10013 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
10014 }
10015 } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
10016 struct msm_vidc_output_crop_payload *output_crop_payload;
10017 output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
10018 if (output_crop_payload) {
10019 m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
10020 m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
10021 m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
10022 m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
10023 m_extradata_info.output_width = output_crop_payload->width;
10024 m_extradata_info.output_height = output_crop_payload->height;
10025 m_extradata_info.output_crop_updated = OMX_TRUE;
10026 DEBUG_PRINT_HIGH("MISR0: %x %x %x %x\n",
10027 output_crop_payload->misr_info[0].misr_dpb_luma,
10028 output_crop_payload->misr_info[0].misr_dpb_chroma,
10029 output_crop_payload->misr_info[0].misr_opb_luma,
10030 output_crop_payload->misr_info[0].misr_opb_chroma);
10031 DEBUG_PRINT_HIGH("MISR1: %x %x %x %x\n",
10032 output_crop_payload->misr_info[1].misr_dpb_luma,
10033 output_crop_payload->misr_info[1].misr_dpb_chroma,
10034 output_crop_payload->misr_info[1].misr_opb_luma,
10035 output_crop_payload->misr_info[1].misr_opb_chroma);
10036 memcpy(m_extradata_info.misr_info, output_crop_payload->misr_info, 2 * sizeof(msm_vidc_misr_info));
10037 if (client_extradata & OMX_OUTPUTCROP_EXTRADATA) {
10038 append_outputcrop_extradata(p_extra, output_crop_payload);
10039 p_extra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U8 *)p_extra) + ALIGN(p_extra->nSize, 4));
10040 if (p_client_extra) {
10041 append_outputcrop_extradata(p_client_extra, output_crop_payload);
10042 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10043 }
10044 }
10045 }
10046 }
10047 break;
10048 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
10049 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
10050 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
10051 recovery_sei_flags = recovery_sei_payload->flags;
10052 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
10053 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
10054 DEBUG_PRINT_HIGH("***************************************************");
10055 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
10056 DEBUG_PRINT_HIGH("***************************************************");
10057 }
10058 break;
10059 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
10060 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
10061 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
10062 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
10063 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
10064 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
10065 return reconfig_event_sent;
10066 }
10067 break;
10068 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
10069 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
10070 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
10071 reconfig_event_sent |= handle_color_space_info((void *)data->data);
10072 break;
10073 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
10074 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
10075 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
10076 switch (s3d_frame_packing_payload->fpa_type) {
10077 case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
10078 if (s3d_frame_packing_payload->content_interprtation_type == 1)
10079 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
10080 else if (s3d_frame_packing_payload->content_interprtation_type == 2)
10081 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
10082 else {
10083 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
10084 stereo_output_mode = HAL_NO_3D;
10085 }
10086 break;
10087 case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
10088 stereo_output_mode = HAL_3D_TOP_BOTTOM;
10089 break;
10090 default:
10091 DEBUG_PRINT_ERROR("Unsupported framepacking type");
10092 stereo_output_mode = HAL_NO_3D;
10093 }
10094 DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
10095 s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
10096 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
10097 append_framepack_extradata(p_extra, s3d_frame_packing_payload);
10098 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10099 if (p_client_extra) {
10100 append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
10101 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10102 }
10103 }
10104 break;
10105 case MSM_VIDC_EXTRADATA_FRAME_QP:
10106 struct msm_vidc_frame_qp_payload *qp_payload;
10107 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
10108 if (client_extradata & OMX_QP_EXTRADATA) {
10109 append_qp_extradata(p_extra, qp_payload);
10110 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10111 if (p_client_extra) {
10112 append_qp_extradata(p_client_extra, qp_payload);
10113 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10114 }
10115 }
10116 break;
10117 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
10118 struct msm_vidc_frame_bits_info_payload *bits_info_payload;
10119 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
10120 if (client_extradata & OMX_BITSINFO_EXTRADATA) {
10121 append_bitsinfo_extradata(p_extra, bits_info_payload);
10122 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10123 if (p_client_extra) {
10124 append_bitsinfo_extradata(p_client_extra, bits_info_payload);
10125 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10126 }
10127 }
10128 break;
10129 case MSM_VIDC_EXTRADATA_UBWC_CR_STAT_INFO:
10130 struct msm_vidc_ubwc_cr_stats_info *cr_stats_info;
10131 struct UBWCStats stats[2];
10132
10133 cr_stats_info = (struct msm_vidc_ubwc_cr_stats_info *)(void *)data->data;
10134 stats[0].version = UBWC_2_0;
10135 stats[0].bDataValid = (uint8_t)true;
10136 stats[0].ubwc_stats.nCRStatsTile32 = cr_stats_info->stats_tile_32;
10137 stats[0].ubwc_stats.nCRStatsTile64 = cr_stats_info->stats_tile_64;
10138 stats[0].ubwc_stats.nCRStatsTile96 = cr_stats_info->stats_tile_96;
10139 stats[0].ubwc_stats.nCRStatsTile128 = cr_stats_info->stats_tile_128;
10140 stats[0].ubwc_stats.nCRStatsTile160 = cr_stats_info->stats_tile_160;
10141 stats[0].ubwc_stats.nCRStatsTile192 = cr_stats_info->stats_tile_192;
10142 stats[0].ubwc_stats.nCRStatsTile256 = cr_stats_info->stats_tile_256;
10143 DEBUG_PRINT_HIGH("Field 0 : 32 Tile = %d 64 Tile = %d 96 Tile = %d 128 Tile = %d 160 Tile = %d 192 Tile = %d 256 Tile = %d\n",
10144 cr_stats_info->stats_tile_32, cr_stats_info->stats_tile_64,
10145 cr_stats_info->stats_tile_96, cr_stats_info->stats_tile_128,
10146 cr_stats_info->stats_tile_160, cr_stats_info->stats_tile_192,
10147 cr_stats_info->stats_tile_256);
10148 stats[1].bDataValid = (uint8_t)false;
10149 if (drv_ctx.interlace != VDEC_InterlaceFrameProgressive) {
10150
10151 cr_stats_info += sizeof(struct msm_vidc_ubwc_cr_stats_info);
10152 stats[1].version = UBWC_2_0;
10153 stats[1].bDataValid = (uint8_t)true;
10154 stats[1].ubwc_stats.nCRStatsTile32 = cr_stats_info->stats_tile_32;
10155 stats[1].ubwc_stats.nCRStatsTile64 = cr_stats_info->stats_tile_64;
10156 stats[1].ubwc_stats.nCRStatsTile96 = cr_stats_info->stats_tile_96;
10157 stats[1].ubwc_stats.nCRStatsTile128 = cr_stats_info->stats_tile_128;
10158 stats[1].ubwc_stats.nCRStatsTile160 = cr_stats_info->stats_tile_160;
10159 stats[1].ubwc_stats.nCRStatsTile192 = cr_stats_info->stats_tile_192;
10160 stats[1].ubwc_stats.nCRStatsTile256 = cr_stats_info->stats_tile_256;
10161 DEBUG_PRINT_HIGH("Field 1 : 32 Tile = %d 64 Tile = %d 96 Tile = %d 128 Tile = %d 160 Tile = %d 192 Tile = %d 256 Tile = %d\n",
10162 cr_stats_info->stats_tile_32, cr_stats_info->stats_tile_64,
10163 cr_stats_info->stats_tile_96, cr_stats_info->stats_tile_128,
10164 cr_stats_info->stats_tile_160, cr_stats_info->stats_tile_192,
10165 cr_stats_info->stats_tile_256);
10166 }
10167 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10168 SET_UBWC_CR_STATS_INFO, (void*)stats);
10169 break;
10170 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
10171 if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
10172 append_user_extradata(p_extra, data);
10173 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10174 if (p_client_extra) {
10175 append_user_extradata(p_client_extra, data);
10176 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10177 }
10178 }
10179 break;
10180 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
10181 struct msm_vidc_vqzip_sei_payload *vqzip_payload;
10182 vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
10183 if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
10184 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10185 append_vqzip_extradata(p_extra, vqzip_payload);
10186 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10187 if (p_client_extra) {
10188 append_vqzip_extradata(p_client_extra, vqzip_payload);
10189 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10190 }
10191 }
10192 break;
10193 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
10194
10195 internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data);
10196 break;
10197 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
10198 internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data);
10199 break;
10200 default:
10201 DEBUG_PRINT_LOW("Unrecognized extradata");
10202 goto unrecognized_extradata;
10203 }
10204 consumed_len += data->nSize;
10205 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
10206 }
10207 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
10208 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10209 append_frame_info_extradata(p_extra,
10210 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10211 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10212 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10213 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10214 if (p_client_extra) {
10215 append_frame_info_extradata(p_client_extra,
10216 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10217 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10218 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10219 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10220 }
10221 }
10222 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
10223 append_frame_dimension_extradata(p_extra);
10224 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
10225 if (p_client_extra) {
10226 append_frame_dimension_extradata(p_client_extra);
10227 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
10228 }
10229 }
10230
10231 if(internal_hdr_info_changed_flag) {
10232 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
10233 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
10234 if(!reconfig_event_sent) {
10235 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
10236 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
10237 OMX_QTIIndexConfigDescribeHDRColorInfo,
10238 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
10239 reconfig_event_sent = true;
10240 }
10241 }
10242
10243 if (m_enable_android_native_buffers) {
10244 ColorAspects final_color_aspects;
10245 HDRStaticInfo final_hdr_info;
10246 ColorMetaData color_mdata;
10247 memset(&final_color_aspects, 0, sizeof(final_color_aspects));
10248 memset(&final_hdr_info, 0, sizeof(final_hdr_info));
10249 memset(&color_mdata, 0, sizeof(color_mdata));
10250 get_preferred_color_aspects(final_color_aspects);
10251
10252 /* For VP8, always set the metadata on gralloc handle to 601-LR */
10253 if (output_capability == V4L2_PIX_FMT_VP8) {
10254 final_color_aspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
10255 final_color_aspects.mRange = ColorAspects::RangeLimited;
10256 final_color_aspects.mTransfer = ColorAspects::TransferSMPTE170M;
10257 final_color_aspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10258 }
10259 get_preferred_hdr_info(final_hdr_info);
10260 convert_color_aspects_to_metadata(final_color_aspects, color_mdata);
10261 convert_hdr_info_to_metadata(final_hdr_info, color_mdata);
10262 print_debug_hdr_color_info_mdata(&color_mdata);
10263 set_colormetadata_in_handle(&color_mdata, buf_index);
10264 }
10265
10266 }
10267 unrecognized_extradata:
10268 if (client_extradata && p_extra) {
10269 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10270 append_terminator_extradata(p_extra);
10271 if (p_client_extra) {
10272 append_terminator_extradata(p_client_extra);
10273 }
10274 }
10275 if (secure_mode && p_extradata && m_other_extradata) {
10276 struct vdec_output_frameinfo *ptr_extradatabuff = NULL;
10277 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
10278 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
10279 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
10280 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
10281 ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd;
10282 ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size;
10283 ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size;
10284 }
10285 return reconfig_event_sent;
10286 }
10287
enable_extradata(OMX_U64 requested_extradata,bool is_internal,bool enable)10288 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
10289 bool is_internal, bool enable)
10290 {
10291 OMX_ERRORTYPE ret = OMX_ErrorNone;
10292 struct v4l2_control control;
10293 if (m_state != OMX_StateLoaded) {
10294 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
10295 return OMX_ErrorIncorrectStateOperation;
10296 }
10297 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
10298 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
10299
10300 if (!is_internal) {
10301 if (enable)
10302 client_extradata |= requested_extradata;
10303 else
10304 client_extradata = client_extradata & ~requested_extradata;
10305 }
10306
10307 if (enable) {
10308 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
10309 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10310 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
10311 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10312 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
10313 " Quality of interlaced clips might be impacted.");
10314 }
10315 }
10316 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
10317 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10318 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
10319 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10320 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
10321 }
10322 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10323 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
10324 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10325 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
10326 }
10327 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10328 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
10329 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10330 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
10331 }
10332 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10333 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
10334 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10335 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10336 }
10337 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10338 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
10339 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10340 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10341 }
10342 if (output_capability == V4L2_PIX_FMT_MPEG2) {
10343 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10344 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10345 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10346 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10347 }
10348 }
10349 }
10350 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
10351 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10352 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
10353 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10354 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
10355 }
10356 }
10357 if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
10358 if (output_capability == V4L2_PIX_FMT_H264) {
10359 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
10360 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10361 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
10362 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10363 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
10364 }
10365 } else {
10366 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
10367 }
10368 }
10369 if (requested_extradata & OMX_QP_EXTRADATA) {
10370 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10371 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10372 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10373 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10374 }
10375 }
10376 if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
10377 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10378 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
10379 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10380 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
10381 }
10382 }
10383 if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
10384 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10385 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
10386 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10387 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
10388 }
10389 }
10390 if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
10391 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10392 control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
10393 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10394 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
10395 }
10396 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10397 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10398 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10399 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10400 }
10401 }
10402 if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
10403 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10404 control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
10405 DEBUG_PRINT_LOW("Enable output crop extra data");
10406 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10407 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
10408 }
10409 }
10410 if (requested_extradata & OMX_UBWC_CR_STATS_INFO_EXTRADATA) {
10411 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10412 control.value = V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO;
10413 DEBUG_PRINT_LOW("Enable UBWC stats extra data");
10414 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10415 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
10416 }
10417 }
10418 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
10419 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10420 switch(output_capability) {
10421 case V4L2_PIX_FMT_H264:
10422 case V4L2_PIX_FMT_HEVC:
10423 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
10424 break;
10425 case V4L2_PIX_FMT_VP8:
10426 case V4L2_PIX_FMT_VP9:
10427 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
10428 break;
10429 default:
10430 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
10431 return ret;
10432 }
10433
10434 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10435 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
10436 }
10437 }
10438 if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
10439 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10440 if (output_capability == V4L2_PIX_FMT_H264 ||
10441 output_capability == V4L2_PIX_FMT_HEVC) {
10442 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
10443 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10444 DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
10445 }
10446 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
10447 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10448 DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
10449 }
10450 }
10451 }
10452 }
10453 ret = get_buffer_req(&drv_ctx.op_buf);
10454 return ret;
10455 }
10456
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)10457 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10458 {
10459 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
10460 OMX_U8 *data_ptr = extra->data, data = 0;
10461 while (byte_count < extra->nDataSize) {
10462 data = *data_ptr;
10463 while (data) {
10464 num_MB += (data&0x01);
10465 data >>= 1;
10466 }
10467 data_ptr++;
10468 byte_count++;
10469 }
10470 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10471 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10472 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
10473 }
10474
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)10475 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10476 {
10477 if (!m_debug_extradata || !extra)
10478 return;
10479
10480
10481 DEBUG_PRINT_HIGH(
10482 "============== Extra Data ==============\n"
10483 " Size: %u\n"
10484 " Version: %u\n"
10485 " PortIndex: %u\n"
10486 " Type: %x\n"
10487 " DataSize: %u",
10488 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
10489 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
10490
10491 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
10492 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10493 DEBUG_PRINT_HIGH(
10494 "------ Interlace Format ------\n"
10495 " Size: %u\n"
10496 " Version: %u\n"
10497 " PortIndex: %u\n"
10498 " Is Interlace Format: %d\n"
10499 " Interlace Formats: %u\n"
10500 "=========== End of Interlace ===========",
10501 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
10502 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
10503 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
10504 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10505
10506 DEBUG_PRINT_HIGH(
10507 "-------- Frame Format --------\n"
10508 " Picture Type: %d\n"
10509 " Interlace Type: %d\n"
10510 " Pan Scan Total Frame Num: %u\n"
10511 " Concealed Macro Blocks: %u\n"
10512 " Recovery SEI Flag: %u\n"
10513 " frame rate: %u\n"
10514 " Time Stamp: %llu\n"
10515 " Aspect Ratio X: %u\n"
10516 " Aspect Ratio Y: %u",
10517 fminfo->ePicType,
10518 fminfo->interlaceType,
10519 (unsigned int)fminfo->panScan.numWindows,
10520 (unsigned int)fminfo->nConcealedMacroblocks,
10521 (unsigned int)fminfo->nRecoverySeiFlag,
10522 (unsigned int)fminfo->nFrameRate,
10523 fminfo->nTimeStamp,
10524 (unsigned int)fminfo->aspectRatio.aspectRatioX,
10525 (unsigned int)fminfo->aspectRatio.aspectRatioY);
10526
10527 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
10528 DEBUG_PRINT_HIGH(
10529 "------------------------------"
10530 " Pan Scan Frame Num: %u\n"
10531 " Rectangle x: %d\n"
10532 " Rectangle y: %d\n"
10533 " Rectangle dx: %d\n"
10534 " Rectangle dy: %d",
10535 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
10536 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
10537 }
10538
10539 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
10540 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
10541 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10542 DEBUG_PRINT_HIGH(
10543 "------------------ Framepack Format ----------\n"
10544 " id: %u \n"
10545 " cancel_flag: %u \n"
10546 " type: %u \n"
10547 " quincunx_sampling_flagFormat: %u \n"
10548 " content_interpretation_type: %u \n"
10549 " spatial_flipping_flag: %u \n"
10550 " frame0_flipped_flag: %u \n"
10551 " field_views_flag: %u \n"
10552 " current_frame_is_frame0_flag: %u \n"
10553 " frame0_self_contained_flag: %u \n"
10554 " frame1_self_contained_flag: %u \n"
10555 " frame0_grid_position_x: %u \n"
10556 " frame0_grid_position_y: %u \n"
10557 " frame1_grid_position_x: %u \n"
10558 " frame1_grid_position_y: %u \n"
10559 " reserved_byte: %u \n"
10560 " repetition_period: %u \n"
10561 " extension_flag: %u \n"
10562 "================== End of Framepack ===========",
10563 (unsigned int)framepack->id,
10564 (unsigned int)framepack->cancel_flag,
10565 (unsigned int)framepack->type,
10566 (unsigned int)framepack->quincunx_sampling_flag,
10567 (unsigned int)framepack->content_interpretation_type,
10568 (unsigned int)framepack->spatial_flipping_flag,
10569 (unsigned int)framepack->frame0_flipped_flag,
10570 (unsigned int)framepack->field_views_flag,
10571 (unsigned int)framepack->current_frame_is_frame0_flag,
10572 (unsigned int)framepack->frame0_self_contained_flag,
10573 (unsigned int)framepack->frame1_self_contained_flag,
10574 (unsigned int)framepack->frame0_grid_position_x,
10575 (unsigned int)framepack->frame0_grid_position_y,
10576 (unsigned int)framepack->frame1_grid_position_x,
10577 (unsigned int)framepack->frame1_grid_position_y,
10578 (unsigned int)framepack->reserved_byte,
10579 (unsigned int)framepack->repetition_period,
10580 (unsigned int)framepack->extension_flag);
10581 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
10582 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
10583 DEBUG_PRINT_HIGH(
10584 "---- QP (Frame quantization parameter) ----\n"
10585 " Frame QP: %u \n"
10586 " Sum of Frame QP: %u \n"
10587 " Sum of Skipped QP: %u \n"
10588 " Num Skipped Blocks: %u \n"
10589 " Total Blocks: %u \n"
10590 "================ End of QP ================\n",
10591 (unsigned int)qp->nQP,(unsigned int)qp->nQPSum,
10592 (unsigned int)qp->nSkipQPSum,(unsigned int)qp->nSkipNumBlocks,
10593 (unsigned int)qp->nTotalNumBlocks);
10594 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
10595 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
10596 DEBUG_PRINT_HIGH(
10597 "--------- Input bits information --------\n"
10598 " Header bits: %u \n"
10599 " Frame bits: %u \n"
10600 "===== End of Input bits information =====\n",
10601 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
10602 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
10603 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
10604 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
10605 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
10606 OMX_U32 i = 0;
10607 DEBUG_PRINT_HIGH(
10608 "-------------- Userdata -------------\n"
10609 " Stream userdata type: %u\n"
10610 " userdata size: %u\n"
10611 " STREAM_USERDATA:",
10612 (unsigned int)userdata->type, (unsigned int)userdata_size);
10613 for (i = 0; i < userdata_size; i+=4) {
10614 DEBUG_PRINT_HIGH(" %x %x %x %x",
10615 data_ptr[i], data_ptr[i+1],
10616 data_ptr[i+2], data_ptr[i+3]);
10617 }
10618 DEBUG_PRINT_HIGH(
10619 "=========== End of Userdata ===========");
10620 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
10621 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
10622 DEBUG_PRINT_HIGH(
10623 "-------------- VQZip -------------\n"
10624 " Size: %u\n",
10625 (unsigned int)vq->nSize);
10626 DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
10627 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo) {
10628 OMX_QCOM_OUTPUT_CROP *outputcrop_info = (OMX_QCOM_OUTPUT_CROP*)(void *)extra->data;
10629 DEBUG_PRINT_HIGH(
10630 "------------------ output crop ----------\n"
10631 " left: %u \n"
10632 " top: %u \n"
10633 " display_width: %u \n"
10634 " display_height: %u \n"
10635 " width: %u \n"
10636 " height: %u \n"
10637 " frame_num: %u \n"
10638 " bit_depth_y: %u \n"
10639 " bit_depth_c: %u \n"
10640 " top field: misr_dpb_luma: %u \n"
10641 " top field: misr_dpb_chroma: %u \n"
10642 " top field: misr_opb_luma: %u \n"
10643 " top field: misr_opb_chroma: %u \n"
10644 " bottom field: misr_dpb_luma: %u \n"
10645 "bottom field: misr_dpb_chroma: %u \n"
10646 " bottom field: misr_opb_luma: %u \n"
10647 "bottom field: misr_opb_chroma: %u \n"
10648 "================== End of output crop ===========",
10649 (unsigned int)outputcrop_info->left,
10650 (unsigned int)outputcrop_info->top,
10651 (unsigned int)outputcrop_info->display_width,
10652 (unsigned int)outputcrop_info->display_height,
10653 (unsigned int)outputcrop_info->width,
10654 (unsigned int)outputcrop_info->height,
10655 (unsigned int)outputcrop_info->frame_num,
10656 (unsigned int)outputcrop_info->bit_depth_y,
10657 (unsigned int)outputcrop_info->bit_depth_c,
10658 (unsigned int)outputcrop_info->misr_info[0].misr_dpb_luma,
10659 (unsigned int)outputcrop_info->misr_info[0].misr_dpb_chroma,
10660 (unsigned int)outputcrop_info->misr_info[0].misr_opb_luma,
10661 (unsigned int)outputcrop_info->misr_info[0].misr_opb_chroma,
10662 (unsigned int)outputcrop_info->misr_info[1].misr_dpb_luma,
10663 (unsigned int)outputcrop_info->misr_info[1].misr_dpb_chroma,
10664 (unsigned int)outputcrop_info->misr_info[1].misr_opb_luma,
10665 (unsigned int)outputcrop_info->misr_info[1].misr_opb_chroma);
10666 } else if (extra->eType == OMX_ExtraDataNone) {
10667 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
10668 } else {
10669 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
10670 }
10671 }
10672
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)10673 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10674 OMX_U32 interlaced_format_type)
10675 {
10676 OMX_STREAMINTERLACEFORMAT *interlace_format;
10677
10678 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
10679 return;
10680 }
10681 if (!extra) {
10682 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
10683 return;
10684 }
10685 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
10686 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10687 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10688 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
10689 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10690 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10691 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
10692 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
10693 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10694
10695 if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
10696 interlace_format->bInterlaceFormat = OMX_FALSE;
10697 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
10698 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10699 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
10700 interlace_format->bInterlaceFormat = OMX_TRUE;
10701 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
10702 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10703 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
10704 interlace_format->bInterlaceFormat = OMX_TRUE;
10705 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
10706 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
10707 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST) {
10708 interlace_format->bInterlaceFormat = OMX_TRUE;
10709 interlace_format->nInterlaceFormats = OMX_InterlaceFrameTopFieldFirst;
10710 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
10711 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST) {
10712 interlace_format->bInterlaceFormat = OMX_TRUE;
10713 interlace_format->nInterlaceFormats = OMX_InterlaceFrameBottomFieldFirst;
10714 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
10715 } else {
10716 //default case - set to progressive
10717 interlace_format->bInterlaceFormat = OMX_FALSE;
10718 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
10719 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10720 }
10721 print_debug_extradata(extra);
10722 }
10723
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)10724 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10725 {
10726 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
10727 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
10728 return;
10729 }
10730 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
10731 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10732 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10733 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
10734 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
10735 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
10736 frame_dimension->nDecWidth = rectangle.nLeft;
10737 frame_dimension->nDecHeight = rectangle.nTop;
10738 frame_dimension->nActualWidth = rectangle.nWidth;
10739 frame_dimension->nActualHeight = rectangle.nHeight;
10740 }
10741
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)10742 void omx_vdec::fill_aspect_ratio_info(
10743 struct vdec_aspectratioinfo *aspect_ratio_info,
10744 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
10745 {
10746 m_extradata = frame_info;
10747 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
10748 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
10749 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
10750 (unsigned int)m_extradata->aspectRatio.aspectRatioY);
10751 }
10752
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)10753 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10754 OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
10755 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
10756 struct vdec_aspectratioinfo *aspect_ratio_info)
10757 {
10758 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
10759 struct msm_vidc_panscan_window *panscan_window;
10760 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
10761 return;
10762 }
10763 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
10764 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10765 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10766 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
10767 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
10768 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10769 switch (picture_type) {
10770 case PICTURE_TYPE_I:
10771 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
10772 break;
10773 case PICTURE_TYPE_P:
10774 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
10775 break;
10776 case PICTURE_TYPE_B:
10777 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
10778 break;
10779 default:
10780 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
10781 }
10782 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
10783 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
10784 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
10785 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
10786 else if (drv_ctx.interlace == VDEC_InterlaceFrameTopFieldFirst)
10787 frame_info->interlaceType = OMX_QCOM_InterlaceFrameTopFieldFirst;
10788 else if (drv_ctx.interlace == VDEC_InterlaceFrameBottomFieldFirst)
10789 frame_info->interlaceType = OMX_QCOM_InterlaceFrameBottomFieldFirst;
10790 else
10791 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
10792 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
10793 frame_info->nConcealedMacroblocks = num_conceal_mb;
10794 frame_info->nRecoverySeiFlag = recovery_sei_flag;
10795 frame_info->nFrameRate = frame_rate;
10796 frame_info->nTimeStamp = time_stamp;
10797 frame_info->panScan.numWindows = 0;
10798 if (output_capability == V4L2_PIX_FMT_MPEG2) {
10799 if (m_disp_hor_size && m_disp_vert_size) {
10800 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
10801 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
10802 } else {
10803 frame_info->displayAspectRatio.displayHorizontalSize = 0;
10804 frame_info->displayAspectRatio.displayVerticalSize = 0;
10805 }
10806 }
10807
10808 if (panscan_payload) {
10809 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
10810 panscan_window = &panscan_payload->wnd[0];
10811 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
10812 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
10813 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
10814 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
10815 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
10816 panscan_window++;
10817 }
10818 }
10819 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
10820 print_debug_extradata(extra);
10821 }
10822
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)10823 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10824 {
10825 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
10826 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
10827 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10828 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10829 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
10830 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10831 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
10832 *portDefn = m_port_def;
10833 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
10834 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
10835 (unsigned int)portDefn->format.video.nFrameWidth,
10836 (unsigned int)portDefn->format.video.nStride,
10837 (unsigned int)portDefn->format.video.nSliceHeight);
10838 }
10839
append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_output_crop_payload * output_crop_payload)10840 void omx_vdec::append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10841 struct msm_vidc_output_crop_payload *output_crop_payload) {
10842 extra->nSize = OMX_OUTPUTCROP_EXTRADATA_SIZE;
10843 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10844 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10845 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo;
10846 extra->nDataSize = sizeof(OMX_QCOM_OUTPUT_CROP);
10847 memcpy(extra->data, output_crop_payload, extra->nDataSize);
10848
10849 print_debug_extradata(extra);
10850 }
10851
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)10852 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10853 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
10854 {
10855 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
10856 if (18 * sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
10857 DEBUG_PRINT_ERROR("frame packing size mismatch");
10858 return;
10859 }
10860 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
10861 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10862 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10863 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
10864 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
10865 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10866 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
10867 framepack->nVersion.nVersion = OMX_SPEC_VERSION;
10868 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10869 memcpy(&framepack->id, s3d_frame_packing_payload,
10870 sizeof(struct msm_vidc_s3d_frame_packing_payload));
10871 memcpy(&m_frame_pack_arrangement, framepack,
10872 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
10873 print_debug_extradata(extra);
10874 }
10875
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)10876 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10877 struct msm_vidc_frame_qp_payload *qp_payload)
10878 {
10879 OMX_QCOM_EXTRADATA_QP * qp = NULL;
10880 if (!qp_payload) {
10881 DEBUG_PRINT_ERROR("QP payload is NULL");
10882 return;
10883 }
10884 extra->nSize = OMX_QP_EXTRADATA_SIZE;
10885 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10886 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10887 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
10888 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
10889 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
10890 qp->nQP = qp_payload->frame_qp;
10891 qp->nQPSum = qp_payload->qp_sum;
10892 qp->nSkipQPSum = qp_payload->skip_qp_sum;
10893 qp->nSkipNumBlocks = qp_payload->skip_num_blocks;
10894 qp->nTotalNumBlocks = qp_payload->total_num_blocks;
10895 print_debug_extradata(extra);
10896 }
10897
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)10898 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10899 struct msm_vidc_frame_bits_info_payload *bits_payload)
10900 {
10901 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
10902 if (!bits_payload) {
10903 DEBUG_PRINT_ERROR("bits info payload is NULL");
10904 return;
10905 }
10906 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
10907 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10908 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10909 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
10910 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
10911 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
10912 bits->frame_bits = bits_payload->frame_bits;
10913 bits->header_bits = bits_payload->header_bits;
10914 print_debug_extradata(extra);
10915 }
10916
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)10917 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10918 OMX_OTHER_EXTRADATATYPE *p_user)
10919 {
10920 int userdata_size = 0;
10921 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
10922 userdata_payload =
10923 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
10924 userdata_size = p_user->nDataSize;
10925 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
10926 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10927 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10928 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
10929 extra->nDataSize = userdata_size;
10930 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
10931 memcpy(extra->data, p_user->data, extra->nDataSize);
10932 print_debug_extradata(extra);
10933 }
10934
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)10935 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10936 {
10937 if (!client_extradata) {
10938 return;
10939 }
10940 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
10941 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10942 extra->eType = OMX_ExtraDataNone;
10943 extra->nDataSize = 0;
10944 extra->data[0] = 0;
10945
10946 print_debug_extradata(extra);
10947 }
10948
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)10949 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10950 struct msm_vidc_vqzip_sei_payload *vqzip_payload)
10951 {
10952 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
10953
10954 extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
10955 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10956 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10957 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
10958 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
10959
10960 vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
10961 vq->nSize = vqzip_payload->size;
10962 memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
10963
10964 print_debug_extradata(extra);
10965 }
10966
allocate_desc_buffer(OMX_U32 index)10967 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
10968 {
10969 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10970 if (index >= drv_ctx.ip_buf.actualcount) {
10971 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
10972 return OMX_ErrorInsufficientResources;
10973 }
10974 if (m_desc_buffer_ptr == NULL) {
10975 m_desc_buffer_ptr = (desc_buffer_hdr*) \
10976 calloc( (sizeof(desc_buffer_hdr)),
10977 drv_ctx.ip_buf.actualcount);
10978 if (m_desc_buffer_ptr == NULL) {
10979 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
10980 return OMX_ErrorInsufficientResources;
10981 }
10982 }
10983
10984 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
10985 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
10986 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
10987 return OMX_ErrorInsufficientResources;
10988 }
10989
10990 return eRet;
10991 }
10992
insert_demux_addr_offset(OMX_U32 address_offset)10993 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
10994 {
10995 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
10996 if (m_demux_entries < 8192) {
10997 m_demux_offsets[m_demux_entries++] = address_offset;
10998 }
10999 return;
11000 }
11001
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)11002 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
11003 {
11004 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
11005 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
11006 OMX_U32 index = 0;
11007
11008 m_demux_entries = 0;
11009
11010 while (index < bytes_to_parse) {
11011 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11012 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
11013 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11014 (buf[index+2] == 0x01)) ) {
11015 //Found start code, insert address offset
11016 insert_demux_addr_offset(index);
11017 if (buf[index+2] == 0x01) // 3 byte start code
11018 index += 3;
11019 else //4 byte start code
11020 index += 4;
11021 } else
11022 index++;
11023 }
11024 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
11025 return;
11026 }
11027
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)11028 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11029 {
11030 //fix this, handle 3 byte start code, vc1 terminator entry
11031 OMX_U8 *p_demux_data = NULL;
11032 OMX_U32 desc_data = 0;
11033 OMX_U32 start_addr = 0;
11034 OMX_U32 nal_size = 0;
11035 OMX_U32 suffix_byte = 0;
11036 OMX_U32 demux_index = 0;
11037 OMX_U32 buffer_index = 0;
11038
11039 if (m_desc_buffer_ptr == NULL) {
11040 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
11041 return OMX_ErrorBadParameter;
11042 }
11043
11044 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
11045 if (buffer_index > drv_ctx.ip_buf.actualcount) {
11046 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
11047 return OMX_ErrorBadParameter;
11048 }
11049
11050 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
11051
11052 if ( ((OMX_U8*)p_demux_data == NULL) ||
11053 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
11054 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
11055 return OMX_ErrorBadParameter;
11056 } else {
11057 for (; demux_index < m_demux_entries; demux_index++) {
11058 desc_data = 0;
11059 start_addr = m_demux_offsets[demux_index];
11060 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
11061 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
11062 } else {
11063 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
11064 }
11065 if (demux_index < (m_demux_entries - 1)) {
11066 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
11067 } else {
11068 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
11069 }
11070 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
11071 (unsigned int)start_addr,
11072 (unsigned int)suffix_byte,
11073 (unsigned int)nal_size,
11074 (unsigned int)demux_index);
11075 desc_data = (start_addr >> 3) << 1;
11076 desc_data |= (start_addr & 7) << 21;
11077 desc_data |= suffix_byte << 24;
11078
11079 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11080 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
11081 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11082 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11083
11084 p_demux_data += 16;
11085 }
11086 //Add zero word to indicate end of descriptors
11087 memset(p_demux_data, 0, sizeof(OMX_U32));
11088
11089 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
11090 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
11091 }
11092 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
11093 m_demux_entries = 0;
11094 DEBUG_PRINT_LOW("Demux table complete!");
11095 return OMX_ErrorNone;
11096 }
11097
allocate_color_convert_buf()11098 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
11099 {
11100 enabled = false;
11101 omx = NULL;
11102 init_members();
11103 ColorFormat = OMX_COLOR_FormatMax;
11104 dest_format = YCbCr420P;
11105 m_c2d_width = 0;
11106 m_c2d_height = 0;
11107
11108 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][-1] =
11109 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11110 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][VDEC_CODECTYPE_MVC] =
11111 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11112 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_UBWC][-1] =
11113 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11114 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_TP10_UBWC][-1] =
11115 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
11116 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_P010_VENUS][-1] =
11117 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus;
11118
11119 mMapOutput2Convert.insert( {
11120 {VDEC_YUV_FORMAT_NV12, NV12_128m},
11121 {VDEC_YUV_FORMAT_NV12_UBWC, NV12_UBWC},
11122 {VDEC_YUV_FORMAT_NV12_TP10_UBWC, TP10_UBWC},
11123 {VDEC_YUV_FORMAT_P010_VENUS, YCbCr420_VENUS_P010},
11124 });
11125 }
11126
set_vdec_client(void * client)11127 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
11128 {
11129 omx = reinterpret_cast<omx_vdec*>(client);
11130 }
11131
init_members()11132 void omx_vdec::allocate_color_convert_buf::init_members()
11133 {
11134 allocated_count = 0;
11135 buffer_size_req = 0;
11136 buffer_alignment_req = 0;
11137 m_c2d_width = m_c2d_height = 0;
11138 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
11139 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
11140 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
11141 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
11142 #ifdef USE_ION
11143 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
11144 #endif
11145 for (int i = 0; i < MAX_COUNT; i++)
11146 pmem_fd[i] = -1;
11147 }
11148
update_buffer_req()11149 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
11150 {
11151 bool status = true;
11152 unsigned int src_size = 0, destination_size = 0;
11153 unsigned int height, width;
11154 struct v4l2_format fmt;
11155 OMX_COLOR_FORMATTYPE drv_color_format;
11156
11157 if (!omx) {
11158 DEBUG_PRINT_ERROR("Invalid client in color convert");
11159 return false;
11160 }
11161 if (!enabled) {
11162 DEBUG_PRINT_HIGH("No color conversion required");
11163 return true;
11164 }
11165 pthread_mutex_lock(&omx->c_lock);
11166
11167 ColorSubMapping::const_iterator
11168 found = mMapOutput2Convert.find(omx->drv_ctx.output_format);
11169 if (found == mMapOutput2Convert.end()) {
11170 DEBUG_PRINT_HIGH("%s: Could not find the color conversion "
11171 "mapping for %#X. Setting to default NV12",
11172 __func__, omx->drv_ctx.output_format);
11173 src_format = NV12_128m;
11174 } else {
11175 src_format = (ColorConvertFormat) found->second;;
11176 }
11177
11178 memset(&fmt, 0x0, sizeof(struct v4l2_format));
11179 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
11180 fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
11181 ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
11182 width = fmt.fmt.pix_mp.width;
11183 height = fmt.fmt.pix_mp.height;
11184
11185 bool resolution_upgrade = (height > m_c2d_height ||
11186 width > m_c2d_width);
11187 bool is_interlaced = omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive;
11188 if (resolution_upgrade) {
11189 // resolution upgraded ? ensure we are yet to allocate;
11190 // failing which, c2d buffers will never be reallocated and bad things will happen
11191 if (allocated_count > 0) {
11192 DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
11193 allocated_count);
11194 status = false;
11195 }
11196 }
11197
11198 if (status != false) {
11199 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
11200 (ColorFormat != OMX_COLOR_FormatYUV420Planar &&
11201 ColorFormat != OMX_COLOR_FormatYUV420SemiPlanar)) {
11202 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
11203 status = false;
11204 } else {
11205 ColorSubMapping::const_iterator
11206 found = mMapOutput2Convert.find(
11207 omx->drv_ctx.output_format);
11208 if (found == mMapOutput2Convert.end()) {
11209 src_format = NV12_128m;
11210 } else {
11211 src_format = (ColorConvertFormat) found->second;;
11212 }
11213
11214 DEBUG_PRINT_INFO("C2D: Set Resolution, Interlace(%s) Conversion(%#X -> %#X)"
11215 " src(%dX%d) dest(%dX%d)",
11216 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) ? "true": "false",
11217 src_format, dest_format, width,
11218 omx->drv_ctx.interlace !=
11219 VDEC_InterlaceFrameProgressive?(height+1)/2 : height,
11220 width, height);
11221 status = c2dcc.setResolution(width,
11222 omx->drv_ctx.interlace !=
11223 VDEC_InterlaceFrameProgressive?
11224 (height+1)/2 : height,
11225 width, height,
11226 src_format, dest_format,
11227 0,0);
11228 if (status) {
11229 src_size = c2dcc.getBuffSize(C2D_INPUT);
11230 destination_size = c2dcc.getBuffSize(C2D_OUTPUT);
11231
11232 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
11233 !destination_size) {
11234 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
11235 "driver size %u destination size %d",
11236 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
11237 destination_size);
11238 buffer_size_req = 0;
11239 // TODO: make this fatal. Driver is not supposed to quote size
11240 // smaller than what C2D needs !!
11241 } else {
11242 buffer_size_req = destination_size;
11243 m_c2d_height = height;
11244 m_c2d_width = width;
11245 }
11246 }
11247 }
11248 }
11249 pthread_mutex_unlock(&omx->c_lock);
11250 return status;
11251 }
11252
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)11253 bool omx_vdec::allocate_color_convert_buf::set_color_format(
11254 OMX_COLOR_FORMATTYPE dest_color_format)
11255 {
11256 bool status = true, drv_colorformat_c2d_enable = false;
11257 bool dest_color_format_c2d_enable = false;
11258 OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
11259 if (!omx) {
11260 DEBUG_PRINT_ERROR("Invalid client in color convert");
11261 return false;
11262 }
11263 pthread_mutex_lock(&omx->c_lock);
11264 status = get_color_format (drv_color_format);
11265
11266 drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
11267 (drv_color_format != (OMX_COLOR_FORMATTYPE)
11268 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
11269 (drv_color_format != (OMX_COLOR_FORMATTYPE)
11270 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed) &&
11271 (drv_color_format != (OMX_COLOR_FORMATTYPE)
11272 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
11273
11274 dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
11275 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
11276 (dest_color_format != (OMX_COLOR_FORMATTYPE)
11277 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
11278
11279 if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
11280 DEBUG_PRINT_LOW("Enabling C2D");
11281 if (dest_color_format == OMX_COLOR_FormatYUV420Planar ||
11282 dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar ) {
11283 ColorFormat = dest_color_format;
11284 dest_format = dest_color_format == OMX_COLOR_FormatYUV420Planar? YCbCr420P: YCbCr420SP;
11285 enabled = true;
11286 } else {
11287 DEBUG_PRINT_ERROR("Unsupported output color format for c2d (%d)",
11288 dest_color_format);
11289 status = false;
11290 enabled = false;
11291 }
11292 } else {
11293 enabled = false;
11294 }
11295 pthread_mutex_unlock(&omx->c_lock);
11296 return status;
11297 }
11298
get_il_buf_hdr()11299 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
11300 {
11301 if (!omx) {
11302 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11303 return NULL;
11304 }
11305 if (!enabled)
11306 return omx->m_out_mem_ptr;
11307 return m_out_mem_ptr_client;
11308 }
11309
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11310 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
11311 (OMX_BUFFERHEADERTYPE *bufadd)
11312 {
11313 if (!omx) {
11314 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11315 return NULL;
11316 }
11317 if (!enabled)
11318 return bufadd;
11319
11320 unsigned index = 0;
11321 index = bufadd - omx->m_out_mem_ptr;
11322 if (index < omx->drv_ctx.op_buf.actualcount) {
11323 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
11324 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
11325 bool status = false;
11326 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
11327 pthread_mutex_lock(&omx->c_lock);
11328 cache_clean_buffer(index);
11329
11330 DEBUG_PRINT_INFO("C2D: Start color convertion");
11331 status = c2dcc.convertC2D(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
11332 bufadd->pBuffer, bufadd->pBuffer,
11333 pmem_fd[index], pmem_baseaddress[index],
11334 pmem_baseaddress[index]);
11335
11336 if (!status) {
11337 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
11338 m_out_mem_ptr_client[index].nFilledLen = 0;
11339 pthread_mutex_unlock(&omx->c_lock);
11340 return &m_out_mem_ptr_client[index];
11341 } else {
11342 unsigned int filledLen = 0;
11343 c2dcc.getBuffFilledLen(C2D_OUTPUT, filledLen);
11344 m_out_mem_ptr_client[index].nFilledLen = filledLen;
11345 cache_clean_invalidate_buffer(index);
11346 }
11347 pthread_mutex_unlock(&omx->c_lock);
11348 } else
11349 m_out_mem_ptr_client[index].nFilledLen = 0;
11350 return &m_out_mem_ptr_client[index];
11351 }
11352 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
11353 return NULL;
11354 }
11355
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11356 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
11357 (OMX_BUFFERHEADERTYPE *bufadd)
11358 {
11359 if (!omx) {
11360 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11361 return NULL;
11362 }
11363 if (!enabled)
11364 return bufadd;
11365 unsigned index = 0;
11366 index = bufadd - m_out_mem_ptr_client;
11367 if (index < omx->drv_ctx.op_buf.actualcount) {
11368 return &omx->m_out_mem_ptr[index];
11369 }
11370 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
11371 return NULL;
11372 }
get_buffer_req(unsigned int & buffer_size)11373 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
11374 (unsigned int &buffer_size)
11375 {
11376 bool status = true;
11377 pthread_mutex_lock(&omx->c_lock);
11378 /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
11379 always uses VideoNativeMetadata and OMX receives buffer type as
11380 grallocsource via storeMetaDataInBuffers_l API. The buffer_size
11381 will be communicated to frameworks via IndexParamPortdefinition. */
11382 if (!enabled)
11383 buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
11384 omx->drv_ctx.op_buf.buffer_size;
11385 else {
11386 buffer_size = c2dcc.getBuffSize(C2D_OUTPUT);
11387 }
11388 pthread_mutex_unlock(&omx->c_lock);
11389 return status;
11390 }
11391
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)11392 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
11393 OMX_U32 buffer_size, OMX_U32 actual_count)
11394 {
11395 OMX_U32 expectedSize = is_color_conversion_enabled() ? buffer_size_req : omx->dynamic_buf_mode ?
11396 sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
11397 if (buffer_size < expectedSize) {
11398 DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
11399 buffer_size, expectedSize);
11400 return OMX_ErrorBadParameter;
11401 }
11402 if (actual_count < omx->drv_ctx.op_buf.mincount) {
11403 DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
11404 actual_count, omx->drv_ctx.op_buf.mincount);
11405 return OMX_ErrorBadParameter;
11406 }
11407
11408 if (enabled) {
11409 // disallow changing buffer size/count while we have active allocated buffers
11410 if (allocated_count > 0) {
11411 DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
11412 buffer_size_req, buffer_size, allocated_count);
11413 return OMX_ErrorInvalidState;
11414 }
11415
11416 buffer_size_req = buffer_size;
11417 } else {
11418 if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
11419 omx->drv_ctx.op_buf.buffer_size = buffer_size;
11420 }
11421 }
11422
11423 omx->drv_ctx.op_buf.actualcount = actual_count;
11424 omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
11425 omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
11426 omx->drv_ctx.extradata_info.buffer_size;
11427 return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
11428 }
11429
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)11430 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
11431 OMX_BUFFERHEADERTYPE *bufhdr)
11432 {
11433 unsigned int index = 0;
11434
11435 if (!enabled)
11436 return omx->free_output_buffer(bufhdr);
11437 if (enabled && omx->is_component_secure())
11438 return OMX_ErrorNone;
11439 if (!allocated_count || !bufhdr) {
11440 for (unsigned i = 0; i < omx->drv_ctx.op_buf.actualcount; i++)
11441 omx->free_output_buffer(&omx->m_out_mem_ptr[i]);
11442 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
11443 return OMX_ErrorBadParameter;
11444 }
11445 index = bufhdr - m_out_mem_ptr_client;
11446 if (index >= omx->drv_ctx.op_buf.actualcount) {
11447 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
11448 return OMX_ErrorBadParameter;
11449 }
11450 if (pmem_fd[index] >= 0) {
11451 munmap(pmem_baseaddress[index], buffer_size_req);
11452 close(pmem_fd[index]);
11453 }
11454 pmem_fd[index] = -1;
11455 #ifdef USE_ION
11456 omx->free_ion_memory(&op_buf_ion_info[index]);
11457 #endif
11458 if (allocated_count > 0)
11459 allocated_count--;
11460 else
11461 allocated_count = 0;
11462 if (!allocated_count) {
11463 pthread_mutex_lock(&omx->c_lock);
11464 init_members();
11465 pthread_mutex_unlock(&omx->c_lock);
11466 }
11467 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
11468 }
11469
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)11470 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
11471 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
11472 {
11473 OMX_ERRORTYPE eRet = OMX_ErrorNone;
11474 if (!enabled) {
11475 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
11476 return eRet;
11477 }
11478 if (enabled && omx->is_component_secure()) {
11479 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
11480 omx->is_component_secure());
11481 return OMX_ErrorUnsupportedSetting;
11482 }
11483 if (!bufferHdr || bytes > buffer_size_req) {
11484 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
11485 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
11486 (unsigned int)buffer_size_req, (unsigned int)bytes);
11487 return OMX_ErrorBadParameter;
11488 }
11489 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
11490 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
11491 return OMX_ErrorInsufficientResources;
11492 }
11493 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
11494 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
11495 port,appData,omx->drv_ctx.op_buf.buffer_size);
11496 if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
11497 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
11498 return eRet;
11499 }
11500 if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
11501 (int)omx->drv_ctx.op_buf.actualcount) {
11502 DEBUG_PRINT_ERROR("Invalid header index %ld",
11503 (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
11504 return OMX_ErrorUndefined;
11505 }
11506 unsigned int i = allocated_count;
11507 #ifdef USE_ION
11508 // Allocate color-conversion buffers as cached to improve software-reading
11509 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
11510 // cache invalidation.
11511 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
11512 buffer_size_req,buffer_alignment_req,
11513 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
11514 ION_FLAG_CACHED);
11515 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
11516 if (op_buf_ion_info[i].ion_device_fd < 0) {
11517 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
11518 return OMX_ErrorInsufficientResources;
11519 }
11520 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
11521 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
11522
11523 if (pmem_baseaddress[i] == MAP_FAILED) {
11524 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
11525 close(pmem_fd[i]);
11526 omx->free_ion_memory(&op_buf_ion_info[i]);
11527 return OMX_ErrorInsufficientResources;
11528 }
11529 #endif
11530 m_pmem_info_client[i].offset = 0;
11531 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
11532 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
11533 m_platform_list_client[i].nEntries = 1;
11534 m_platform_list_client[i].entryList = &m_platform_entry_client[i];
11535 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
11536 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
11537 m_out_mem_ptr_client[i].nFilledLen = 0;
11538 m_out_mem_ptr_client[i].nFlags = 0;
11539 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11540 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
11541 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
11542 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
11543 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
11544 m_out_mem_ptr_client[i].pAppPrivate = appData;
11545 *bufferHdr = &m_out_mem_ptr_client[i];
11546 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
11547 allocated_count++;
11548 return eRet;
11549 }
11550
is_component_secure()11551 bool omx_vdec::is_component_secure()
11552 {
11553 return secure_mode;
11554 }
11555
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)11556 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
11557 {
11558 bool status = true;
11559 if (!enabled) {
11560 for (auto& x: mMapOutput2DriverColorFormat) {
11561 DecColorMapping::const_iterator
11562 found = mMapOutput2DriverColorFormat.find(omx->drv_ctx.output_format);
11563 if (found == mMapOutput2DriverColorFormat.end()) {
11564 status = false;
11565 } else {
11566 ColorSubMapping::const_iterator
11567 subFound = found->second.find(omx->drv_ctx.decoder_format);
11568 if (subFound == found->second.end()) {
11569 dest_color_format = (OMX_COLOR_FORMATTYPE)
11570 found->second.find(-1)->second;
11571 } else {
11572 dest_color_format = (OMX_COLOR_FORMATTYPE) subFound->second;
11573 }
11574 }
11575 }
11576 } else {
11577 if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
11578 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
11579 dest_color_format = ColorFormat;
11580 } else
11581 status = false;
11582 }
11583 return status;
11584 }
11585
cache_ops(unsigned int index,unsigned int cmd)11586 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
11587 unsigned int index, unsigned int cmd)
11588 {
11589 if (!enabled) {
11590 return OMX_ErrorNone;
11591 }
11592
11593 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
11594 DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
11595 return OMX_ErrorBadParameter;
11596 }
11597
11598 struct ion_flush_data flush_data;
11599 struct ion_custom_data custom_data;
11600
11601 memset(&flush_data, 0x0, sizeof(flush_data));
11602 memset(&custom_data, 0x0, sizeof(custom_data));
11603
11604 flush_data.vaddr = pmem_baseaddress[index];
11605 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
11606 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
11607 flush_data.length = buffer_size_req;
11608 custom_data.cmd = cmd;
11609 custom_data.arg = (unsigned long)&flush_data;
11610
11611 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
11612 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11613 flush_data.fd, flush_data.handle, flush_data.vaddr,
11614 flush_data.length);
11615 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
11616 if (ret < 0) {
11617 DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
11618 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11619 strerror(errno));
11620 return OMX_ErrorUndefined;
11621 }
11622 return OMX_ErrorNone;
11623 }
11624
send_codec_config()11625 void omx_vdec::send_codec_config() {
11626 if (codec_config_flag) {
11627 unsigned long p1 = 0; // Parameter - 1
11628 unsigned long p2 = 0; // Parameter - 2
11629 unsigned long ident = 0;
11630 pthread_mutex_lock(&m_lock);
11631 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
11632 while (m_etb_q.m_size) {
11633 m_etb_q.pop_entry(&p1,&p2,&ident);
11634 if (ident == OMX_COMPONENT_GENERATE_ETB) {
11635 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
11636 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
11637 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
11638 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
11639 omx_report_error ();
11640 }
11641 } else {
11642 pending_input_buffers++;
11643 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
11644 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
11645 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
11646 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
11647 }
11648 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
11649 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
11650 (OMX_BUFFERHEADERTYPE *)p1);
11651 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
11652 }
11653 }
11654 pthread_mutex_unlock(&m_lock);
11655 }
11656 }
11657
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)11658 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
11659 unsigned long nMaxFrameHeight)
11660 {
11661
11662 OMX_ERRORTYPE eRet = OMX_ErrorNone;
11663 int ret = 0;
11664 unsigned long min_res_buf_count = 0;
11665
11666 eRet = enable_smoothstreaming();
11667 if (eRet != OMX_ErrorNone) {
11668 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
11669 return eRet;
11670 }
11671
11672 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
11673 nMaxFrameWidth,
11674 nMaxFrameHeight);
11675 m_smoothstreaming_mode = true;
11676 m_smoothstreaming_width = nMaxFrameWidth;
11677 m_smoothstreaming_height = nMaxFrameHeight;
11678
11679 //Get upper limit buffer count for min supported resolution
11680 struct v4l2_format fmt;
11681 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
11682 fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
11683 fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
11684 fmt.fmt.pix_mp.pixelformat = output_capability;
11685
11686 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
11687 if (ret) {
11688 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
11689 m_decoder_capability.min_height,
11690 m_decoder_capability.min_width);
11691 return OMX_ErrorUnsupportedSetting;
11692 }
11693
11694 eRet = get_buffer_req(&drv_ctx.op_buf);
11695 if (eRet != OMX_ErrorNone) {
11696 DEBUG_PRINT_ERROR("failed to get_buffer_req");
11697 return eRet;
11698 }
11699
11700 min_res_buf_count = drv_ctx.op_buf.mincount;
11701 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
11702 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
11703
11704 m_extradata_info.output_crop_rect.nLeft = 0;
11705 m_extradata_info.output_crop_rect.nTop = 0;
11706 m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
11707 m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
11708
11709 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
11710 m_smoothstreaming_width, m_smoothstreaming_height);
11711
11712 //Get upper limit buffer size for max smooth streaming resolution set
11713 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
11714 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
11715 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
11716 fmt.fmt.pix_mp.pixelformat = output_capability;
11717 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
11718 if (ret) {
11719 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
11720 return OMX_ErrorUnsupportedSetting;
11721 }
11722
11723 eRet = get_buffer_req(&drv_ctx.op_buf);
11724 if (eRet != OMX_ErrorNone) {
11725 DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
11726 return eRet;
11727 }
11728 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
11729 (unsigned int)drv_ctx.op_buf.buffer_size);
11730
11731 drv_ctx.op_buf.mincount = min_res_buf_count;
11732 drv_ctx.op_buf.actualcount = min_res_buf_count;
11733 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
11734 eRet = set_buffer_req(&drv_ctx.op_buf);
11735 if (eRet != OMX_ErrorNone) {
11736 DEBUG_PRINT_ERROR("failed to set_buffer_req");
11737 return eRet;
11738 }
11739
11740 eRet = get_buffer_req(&drv_ctx.op_buf);
11741 if (eRet != OMX_ErrorNone) {
11742 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
11743 return eRet;
11744 }
11745 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
11746 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
11747 return eRet;
11748 }
11749
11750 //static
describeColorFormat(OMX_PTR pParam)11751 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
11752
11753 #ifndef FLEXYUV_SUPPORTED
11754 return OMX_ErrorUndefined;
11755 #else
11756
11757 if (pParam == NULL) {
11758 DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
11759 return OMX_ErrorBadParameter;
11760 }
11761
11762 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
11763
11764 MediaImage *img = &(params->sMediaImage);
11765 switch(params->eColorFormat) {
11766 case static_cast <OMX_COLOR_FORMATTYPE> (QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m):
11767 {
11768 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
11769 img->mNumPlanes = 3;
11770 // mWidth and mHeight represent the W x H of the largest plane
11771 // In our case, this happens to be the Stride x Scanlines of Y plane
11772 img->mWidth = params->nFrameWidth;
11773 img->mHeight = params->nFrameHeight;
11774 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11775 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
11776 img->mBitDepth = 8;
11777 //Plane 0 (Y)
11778 img->mPlane[MediaImage::Y].mOffset = 0;
11779 img->mPlane[MediaImage::Y].mColInc = 1;
11780 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
11781 img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
11782 img->mPlane[MediaImage::Y].mVertSubsampling = 1;
11783 //Plane 1 (U)
11784 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
11785 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
11786 img->mPlane[MediaImage::U].mRowInc =
11787 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11788 img->mPlane[MediaImage::U].mHorizSubsampling = 2;
11789 img->mPlane[MediaImage::U].mVertSubsampling = 2;
11790 //Plane 2 (V)
11791 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
11792 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
11793 img->mPlane[MediaImage::V].mRowInc =
11794 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
11795 img->mPlane[MediaImage::V].mHorizSubsampling = 2;
11796 img->mPlane[MediaImage::V].mVertSubsampling = 2;
11797 break;
11798 }
11799
11800 case OMX_COLOR_FormatYUV420Planar:
11801 case OMX_COLOR_FormatYUV420SemiPlanar:
11802 // We need not describe the standard OMX linear formats as these are
11803 // understood by client. Fail this deliberately to let client fill-in
11804 return OMX_ErrorUnsupportedSetting;
11805
11806 default:
11807 // Rest all formats which are non-linear cannot be described
11808 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
11809 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
11810 return OMX_ErrorNone;
11811 };
11812
11813 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
11814 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
11815 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
11816 for (size_t i = 0; i < img->mNumPlanes; ++i) {
11817 DEBUG_PRINT_LOW(" Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
11818 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
11819 }
11820 return OMX_ErrorNone;
11821 #endif //FLEXYUV_SUPPORTED
11822 }
11823
prefetchNewBuffers()11824 void omx_vdec::prefetchNewBuffers() {
11825
11826 struct v4l2_decoder_cmd dec;
11827 uint32_t prefetch_count;
11828 uint32_t prefetch_size;
11829 uint32_t want_size;
11830 uint32_t have_size;
11831 int color_fmt, rc;
11832 uint32_t new_calculated_size;
11833 uint32_t new_buffer_size;
11834 uint32_t new_buffer_count;
11835 uint32_t old_buffer_size;
11836 uint32_t old_buffer_count;
11837
11838 memset((void *)&dec, 0 , sizeof(dec));
11839 DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n",
11840 drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
11841 drv_ctx.video_resolution.frame_width,
11842 drv_ctx.video_resolution.frame_height);
11843 dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
11844 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
11845 DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
11846 } else {
11847 DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
11848 dec.raw.data[0], dec.raw.data[1]);
11849 }
11850
11851 switch ((int)drv_ctx.output_format) {
11852 case VDEC_YUV_FORMAT_NV12:
11853 color_fmt = COLOR_FMT_NV12;
11854 break;
11855 case VDEC_YUV_FORMAT_NV12_UBWC:
11856 color_fmt = COLOR_FMT_NV12_UBWC;
11857 break;
11858 case VDEC_YUV_FORMAT_NV12_TP10_UBWC:
11859 color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
11860 break;
11861 case VDEC_YUV_FORMAT_P010_VENUS:
11862 color_fmt = COLOR_FMT_P010;
11863 break;
11864 default:
11865 color_fmt = -1;
11866 DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format);
11867 return;
11868 }
11869
11870 new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
11871 DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
11872 m_reconfig_width, m_reconfig_height, new_calculated_size);
11873 new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
11874 new_buffer_count = dec.raw.data[1];
11875 old_buffer_size = drv_ctx.op_buf.buffer_size;
11876 old_buffer_count = drv_ctx.op_buf.actualcount;
11877
11878 new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
11879
11880 prefetch_count = new_buffer_count;
11881 prefetch_size = new_buffer_size - old_buffer_size;
11882 want_size = new_buffer_size * new_buffer_count;
11883 have_size = old_buffer_size * old_buffer_count;
11884
11885 if (want_size > have_size) {
11886 DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
11887 DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
11888
11889 int ion_fd = open(MEM_DEVICE, O_RDONLY);
11890 if (ion_fd < 0) {
11891 DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
11892 return;
11893 }
11894
11895 struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
11896 struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
11897 struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
11898 size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
11899
11900 if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
11901 DEBUG_PRINT_ERROR("prefetch data allocation failed");
11902 goto prefetch_exit;
11903 }
11904
11905 for (uint32_t i = 0; i < prefetch_count; i++) {
11906 sizes[i] = prefetch_size;
11907 }
11908
11909 regions[0].nr_sizes = prefetch_count;
11910 regions[0].sizes = sizes;
11911 regions[0].vmid = ION_FLAG_CP_PIXEL;
11912
11913 prefetch_data->nr_regions = 1;
11914 prefetch_data->regions = regions;
11915 prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
11916
11917 custom_data->cmd = ION_IOC_PREFETCH;
11918 custom_data->arg = (unsigned long )prefetch_data;
11919
11920 rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
11921 if (rc) {
11922 DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
11923 }
11924
11925 prefetch_exit:
11926 close(ion_fd);
11927 free(sizes);
11928 free(regions);
11929 free(prefetch_data);
11930 free(custom_data);
11931 }
11932 }
11933
11934
start()11935 void perf_metrics::start()
11936 {
11937 if (!active) {
11938 start_time = get_act_time();
11939 active = true;
11940 }
11941 }
11942
stop()11943 void perf_metrics::stop()
11944 {
11945 OMX_U64 stop_time = get_act_time();
11946 if (active) {
11947 proc_time += (stop_time - start_time);
11948 active = false;
11949 }
11950 }
11951
end(OMX_U32 units_cntr)11952 void perf_metrics::end(OMX_U32 units_cntr)
11953 {
11954 stop();
11955 ALOGV("--> Processing time : [%.2f] Sec", (float)proc_time / 1e6);
11956 if (units_cntr) {
11957 ALOGV("--> Avrg proc time : [%.2f] mSec", proc_time / (float)(units_cntr * 1e3));
11958 }
11959 }
11960
reset()11961 void perf_metrics::reset()
11962 {
11963 start_time = 0;
11964 proc_time = 0;
11965 active = false;
11966 }
11967
get_act_time()11968 OMX_U64 perf_metrics::get_act_time()
11969 {
11970 struct timeval act_time = {0, 0};
11971 gettimeofday(&act_time, NULL);
11972 return (act_time.tv_usec + act_time.tv_sec * 1e6);
11973 }
11974
processing_time_us()11975 OMX_U64 perf_metrics::processing_time_us()
11976 {
11977 return proc_time;
11978 }
11979
11980
11981 // No code beyond this !
11982
11983 // inline import of vendor-extensions implementation
11984 #include "omx_vdec_extensions.hpp"
11985