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