1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010-2018, 2020, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 #include <string.h>
30 #include <sys/ioctl.h>
31 #include <sys/prctl.h>
32 #include <sys/eventfd.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include "video_encoder_device_v4l2.h"
36 #include "omx_video_encoder.h"
37 #include "media/msm_vidc_utils.h"
38 #ifdef HYPERVISOR
39 #include "hypv_intercept.h"
40 #endif
41 #ifdef USE_ION
42 #include <linux/msm_ion.h>
43 #endif
44 #include<linux/v4l2-controls.h>
45 
46 #include <math.h>
47 #include <media/msm_media_info.h>
48 #include <cutils/properties.h>
49 #include <media/hardware/HardwareAPI.h>
50 
51 #ifdef _ANDROID_
52 #include <media/hardware/HardwareAPI.h>
53 #include <gralloc_priv.h>
54 #endif
55 
56 #ifdef _USE_GLIB_
57 #include <glib.h>
58 #define strlcpy g_strlcpy
59 #endif
60 
61 #include <qdMetaData.h>
62 #include <color_metadata.h>
63 #include "PlatformConfig.h"
64 
65 #define ATRACE_TAG ATRACE_TAG_VIDEO
66 #include <utils/Trace.h>
67 
68 #define YUV_STATS_LIBRARY_NAME "libgpustats.so" // UBWC case: use GPU library
69 
70 #ifdef HYPERVISOR
71 #define ioctl(x, y, z) hypv_ioctl(x, y, z)
72 #define poll(x, y, z)  hypv_poll(x, y, z)
73 #endif
74 
75 #undef ALIGN
76 #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
77 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
78 #define MAXDPB 16
79 #ifndef MIN
80 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
81 #endif
82 #ifndef MAX
83 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
84 #endif
85 
86 #define ROUND(__sz, __align) (((__sz) + ((__align>>1))) & (~(__align-1)))
87 #define MAX_PROFILE_PARAMS 6
88 #define HEVC_MAIN_START 0
89 #define HEVC_MAIN10_START (HEVC_MAIN_START + 13)
90 #define POLL_TIMEOUT 1000
91 #define MAX_SUPPORTED_SLICES_PER_FRAME 28 /* Max supported slices with 32 output buffers */
92 
93 #define SZ_4K 0x1000
94 #define SZ_1M 0x100000
95 
96 
97 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
98 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
99 
100 #define BUFFER_LOG_LOC "/data/vendor/media"
101 
102 #define OMX_VIDEO_LEVEL_UNKNOWN 0
103 
104 #define VENC_BFRAME_MAX_COUNT       1
105 #define VENC_BFRAME_MAX_FPS         60
106 #define VENC_BFRAME_MAX_WIDTH       1920
107 #define VENC_BFRAME_MAX_HEIGHT      1088
108 #define VENC_INFINITE_GOP 0xFFFFFFF
109 
110 /* TODO: Use sanctioned vendor bits for HEIF
111  * once end to end 64-bit support is available.
112  */
113 #define GRALLOC_USAGE_PRIVATE_HEIF_VIDEO (UINT32_C(1) << 27)
114 #define GRALLOC_USAGE_PRIVATE_10BIT_VIDEO (UINT32_C(1) << 30)
115 
116 #define REQUEST_LINEAR_COLOR_8_BIT   0x1
117 #define REQUEST_LINEAR_COLOR_10_BIT  0x2
118 #define REQUEST_LINEAR_COLOR_ALL     (REQUEST_LINEAR_COLOR_8_BIT | REQUEST_LINEAR_COLOR_10_BIT)
119 
120 #undef LOG_TAG
121 #define LOG_TAG "OMX-VENC: venc_dev"
122 
123 #define LUMINANCE_MULTIPLICATION_FACTOR 10000
124 
125 //constructor
venc_dev(class omx_venc * venc_class)126 venc_dev::venc_dev(class omx_venc *venc_class)
127 {
128     //nothing to do
129     int i = 0;
130     venc_handle = venc_class;
131     etb = ebd = ftb = fbd = 0;
132     m_poll_efd = -1;
133 
134     struct v4l2_control control;
135     for (i = 0; i < MAX_PORT; i++)
136         streaming[i] = false;
137 
138     stopped = 1;
139     paused = false;
140     async_thread_created = false;
141     async_thread_force_stop = false;
142     color_format = 0;
143     hw_overload = false;
144     mBatchSize = 0;
145     deinterlace_enabled = false;
146     m_roi_enabled = false;
147     m_roi_type = 0;
148     low_latency_mode = false;
149     pthread_mutex_init(&m_roilock, NULL);
150     pthread_mutex_init(&pause_resume_mlock, NULL);
151     pthread_cond_init(&pause_resume_cond, NULL);
152     memset(&input_extradata_info, 0, sizeof(input_extradata_info));
153     input_extradata_info.ion.data_fd = -1;
154     memset(&output_extradata_info, 0, sizeof(output_extradata_info));
155     output_extradata_info.ion.data_fd = -1;
156     memset(&idrperiod, 0, sizeof(idrperiod));
157     memset(&multislice, 0, sizeof(multislice));
158     memset (&slice_mode, 0 , sizeof(slice_mode));
159     memset(&m_sVenc_cfg, 0, sizeof(m_sVenc_cfg));
160     memset(&rate_ctrl, 0, sizeof(rate_ctrl));
161     memset(&bitrate, 0, sizeof(bitrate));
162     memset(&intra_period, 0, sizeof(intra_period));
163     memset(&codec_profile, 0, sizeof(codec_profile));
164     memset(&set_param, 0, sizeof(set_param));
165     memset(&time_inc, 0, sizeof(time_inc));
166     memset(&m_sInput_buff_property, 0, sizeof(m_sInput_buff_property));
167     memset(&m_sOutput_buff_property, 0, sizeof(m_sOutput_buff_property));
168     memset(&session_qp, 0, sizeof(session_qp));
169     memset(&session_ipb_qp_values, 0, sizeof(session_ipb_qp_values));
170     memset(&entropy, 0, sizeof(entropy));
171     memset(&dbkfilter, 0, sizeof(dbkfilter));
172     memset(&intra_refresh, 0, sizeof(intra_refresh));
173     memset(&hec, 0, sizeof(hec));
174     memset(&voptimecfg, 0, sizeof(voptimecfg));
175     memset(&capability, 0, sizeof(capability));
176     memset(&m_debug,0,sizeof(m_debug));
177     is_searchrange_set = false;
178     enable_mv_narrow_searchrange = false;
179     supported_rc_modes = RC_ALL;
180     memset(&vqzip_sei_info, 0, sizeof(vqzip_sei_info));
181     memset(&ltrinfo, 0, sizeof(ltrinfo));
182     memset(&fd_list, 0, sizeof(fd_list));
183     sess_priority.priority = 1;
184     operating_rate = 30;
185     memset(&color_space, 0x0, sizeof(color_space));
186     memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
187     client_req_disable_bframe   = false;
188     bframe_implicitly_enabled = false;
189     client_req_disable_temporal_layers  = false;
190     client_req_turbo_mode  = false;
191     intra_period.num_pframes = 29;
192     intra_period.num_bframes = 0;
193     mIsNativeRecorder = false;
194     m_hdr10meta_enabled = false;
195     hdr10metadata_supported = false;
196 
197     Platform::Config::getInt32(Platform::vidc_enc_log_in,
198             (int32_t *)&m_debug.in_buffer_log, 0);
199     Platform::Config::getInt32(Platform::vidc_enc_log_out,
200             (int32_t *)&m_debug.out_buffer_log, 0);
201     Platform::Config::getInt32(Platform::vidc_enc_csc_custom_matrix,
202             (int32_t *)&is_csc_custom_matrix_enabled, 0);
203 
204     char property_value[PROPERTY_VALUE_MAX] = {0};
205 
206     property_get("vendor.vidc.enc.log.in", property_value, "0");
207     m_debug.in_buffer_log |= atoi(property_value);
208 
209     property_value[0] = '\0';
210     property_get("vendor.vidc.enc.log.out", property_value, "0");
211     m_debug.out_buffer_log |= atoi(property_value);
212 
213     property_get("vendor.vidc.enc.log.extradata", property_value, "0");
214     m_debug.extradata_log = atoi(property_value);
215 
216 #ifdef _UBWC_
217     property_get("vendor.gralloc.disable_ubwc", property_value, "0");
218     if(!(strncmp(property_value, "1", PROPERTY_VALUE_MAX)) ||
219         !(strncmp(property_value, "true", PROPERTY_VALUE_MAX))) {
220         is_gralloc_source_ubwc = 0;
221     } else {
222         is_gralloc_source_ubwc = 1;
223     }
224 #else
225     is_gralloc_source_ubwc = 0;
226 #endif
227 
228      property_value[0] = '\0';
229      property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
230      if (*property_value)
231          strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
232 
233     mUseAVTimerTimestamps = false;
234     mIsGridset = false;
235     Platform::Config::getInt32(Platform::vidc_enc_linear_color_format,
236             (int32_t *)&mUseLinearColorFormat, 0);
237     Platform::Config::getInt32(Platform::vidc_enc_bitrate_savings_enable,
238             (int32_t *)&mBitrateSavingsEnable, 0);
239 
240     profile_level_converter::init();
241 }
242 
~venc_dev()243 venc_dev::~venc_dev()
244 {
245     if (m_roi_enabled) {
246         std::list<roidata>::iterator iter;
247         pthread_mutex_lock(&m_roilock);
248         for (iter = m_roilist.begin(); iter != m_roilist.end(); iter++) {
249             DEBUG_PRINT_HIGH("roidata with timestamp (%lld) should have been removed already",
250                 iter->info.nTimeStamp);
251         }
252         m_roilist.clear();
253         mRoiRegionList.clear();
254         pthread_mutex_unlock(&m_roilock);
255     }
256     pthread_mutex_destroy(&m_roilock);
257 }
258 
async_venc_message_thread(void * input)259 void* venc_dev::async_venc_message_thread (void *input)
260 {
261     struct venc_msg venc_msg;
262     omx_video* omx_venc_base = NULL;
263     omx_venc *omx = reinterpret_cast<omx_venc*>(input);
264     omx_venc_base = reinterpret_cast<omx_video*>(input);
265     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
266 
267     prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0);
268     struct v4l2_plane plane[VIDEO_MAX_PLANES];
269     struct pollfd pfds[2];
270     struct v4l2_buffer v4l2_buf;
271     struct v4l2_event dqevent;
272     struct statistics stats;
273     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
274     pfds[1].events = POLLIN | POLLERR;
275     pfds[0].fd = omx->handle->m_nDriver_fd;
276     pfds[1].fd = omx->handle->m_poll_efd;
277     int error_code = 0,rc=0;
278 
279     memset(&stats, 0, sizeof(statistics));
280     memset(&v4l2_buf, 0, sizeof(v4l2_buf));
281 
282     while (!omx->handle->async_thread_force_stop) {
283         pthread_mutex_lock(&omx->handle->pause_resume_mlock);
284 
285         if (omx->handle->paused) {
286             venc_msg.msgcode = VEN_MSG_PAUSE;
287             venc_msg.statuscode = VEN_S_SUCCESS;
288 
289             if (omx->async_message_process(input, &venc_msg) < 0) {
290                 DEBUG_PRINT_ERROR("ERROR: Failed to process pause msg");
291                 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
292                 break;
293             }
294 
295             /* Block here until the IL client resumes us again */
296             pthread_cond_wait(&omx->handle->pause_resume_cond,
297                     &omx->handle->pause_resume_mlock);
298 
299             venc_msg.msgcode = VEN_MSG_RESUME;
300             venc_msg.statuscode = VEN_S_SUCCESS;
301 
302             if (omx->async_message_process(input, &venc_msg) < 0) {
303                 DEBUG_PRINT_ERROR("ERROR: Failed to process resume msg");
304                 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
305                 break;
306             }
307             memset(&stats, 0, sizeof(statistics));
308         }
309 
310         pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
311 
312         rc = poll(pfds, 2, POLL_TIMEOUT);
313 
314         if (!rc) {
315             DEBUG_PRINT_HIGH("Poll timedout, pipeline stalled due to client/firmware ETB: %d, EBD: %d, FTB: %d, FBD: %d",
316                     omx->handle->etb, omx->handle->ebd, omx->handle->ftb, omx->handle->fbd);
317             continue;
318         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
319             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
320             break;
321         }
322 
323         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
324             DEBUG_PRINT_ERROR("async_venc_message_thread interrupted to be exited");
325             break;
326         }
327 
328         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
329             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
330             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
331             v4l2_buf.length = omx->handle->num_output_planes;
332             v4l2_buf.m.planes = plane;
333 
334             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
335                 venc_msg.msgcode=VEN_MSG_OUTPUT_BUFFER_DONE;
336                 venc_msg.statuscode=VEN_S_SUCCESS;
337                 omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf.index;
338                 venc_msg.buf.len= v4l2_buf.m.planes->bytesused;
339                 venc_msg.buf.offset = v4l2_buf.m.planes->data_offset;
340                 venc_msg.buf.flags = 0;
341                 venc_msg.buf.ptrbuffer = (OMX_U8 *)omx_venc_base->m_pOutput_pmem[v4l2_buf.index].buffer;
342                 venc_msg.buf.clientdata=(void*)omxhdr;
343                 venc_msg.buf.timestamp = (uint64_t) v4l2_buf.timestamp.tv_sec * (uint64_t) 1000000 + (uint64_t) v4l2_buf.timestamp.tv_usec;
344 
345                 /* TODO: ideally report other types of frames as well
346                  * for now it doesn't look like IL client cares about
347                  * other types
348                  */
349                 if (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
350                     venc_msg.buf.flags |= QOMX_VIDEO_PictureTypeIDR;
351                     venc_msg.buf.flags |= OMX_BUFFERFLAG_SYNCFRAME;
352                 }
353                 if (v4l2_buf.flags & V4L2_BUF_FLAG_PFRAME) {
354                     venc_msg.buf.flags |= OMX_VIDEO_PictureTypeP;
355                 } else if (v4l2_buf.flags & V4L2_BUF_FLAG_BFRAME) {
356                     venc_msg.buf.flags |= OMX_VIDEO_PictureTypeB;
357                 }
358 
359                 if (v4l2_buf.flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
360                     venc_msg.buf.flags |= OMX_BUFFERFLAG_CODECCONFIG;
361 
362                 if (v4l2_buf.flags & V4L2_QCOM_BUF_FLAG_EOS)
363                     venc_msg.buf.flags |= OMX_BUFFERFLAG_EOS;
364 
365                 if (omx->handle->num_output_planes > 1 && v4l2_buf.m.planes->bytesused)
366                     venc_msg.buf.flags |= OMX_BUFFERFLAG_EXTRADATA;
367 
368                 if (omxhdr->nFilledLen)
369                     venc_msg.buf.flags |= OMX_BUFFERFLAG_ENDOFFRAME;
370 
371                 omx->handle->fbd++;
372                 stats.bytes_generated += venc_msg.buf.len;
373 
374                 if (omx->async_message_process(input,&venc_msg) < 0) {
375                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
376                     break;
377                 }
378             }
379         }
380 
381         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
382             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
383             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
384             v4l2_buf.m.planes = plane;
385             v4l2_buf.length = omx->handle->num_input_planes;
386 
387             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
388                 venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE;
389                 venc_msg.statuscode=VEN_S_SUCCESS;
390                 omx->handle->ebd++;
391 
392                 if (omx->handle->mBatchSize) {
393                     int bufIndex = omx->handle->mBatchInfo.retrieveBufferAt(v4l2_buf.index);
394                     if (bufIndex < 0) {
395                         DEBUG_PRINT_ERROR("Retrieved invalid buffer %d", v4l2_buf.index);
396                         break;
397                     }
398                     if (omx->handle->mBatchInfo.isPending(bufIndex)) {
399                         DEBUG_PRINT_LOW(" EBD for %d [v4l2-id=%d].. batch still pending",
400                                 bufIndex, v4l2_buf.index);
401                         //do not return to client yet
402                         continue;
403                     }
404                     v4l2_buf.index = bufIndex;
405                 }
406                 if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion)
407                     omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf.index];
408                 else
409                     omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index];
410 
411                 venc_msg.buf.clientdata=(void*)omxhdr;
412 
413                 DEBUG_PRINT_LOW("sending EBD %p [id=%d]", omxhdr, v4l2_buf.index);
414                 if (omx->async_message_process(input,&venc_msg) < 0) {
415                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
416                     break;
417                 }
418             }
419         }
420 
421         if (pfds[0].revents & POLLPRI) {
422             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
423 
424             if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
425                 venc_msg.msgcode = VEN_MSG_FLUSH_INPUT_DONE;
426                 venc_msg.statuscode = VEN_S_SUCCESS;
427 
428                 if (omx->async_message_process(input,&venc_msg) < 0) {
429                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
430                     break;
431                 }
432 
433                 venc_msg.msgcode = VEN_MSG_FLUSH_OUPUT_DONE;
434                 venc_msg.statuscode = VEN_S_SUCCESS;
435 
436                 if (omx->async_message_process(input,&venc_msg) < 0) {
437                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
438                     break;
439                 }
440             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
441                 DEBUG_PRINT_ERROR("HW Overload received");
442                 venc_msg.statuscode = VEN_S_EFAIL;
443                 venc_msg.msgcode = VEN_MSG_HW_OVERLOAD;
444 
445                 if (omx->async_message_process(input,&venc_msg) < 0) {
446                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
447                     break;
448                 }
449             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR){
450                 DEBUG_PRINT_ERROR("ERROR: Encoder is in bad state");
451                 venc_msg.msgcode = VEN_MSG_INDICATION;
452                 venc_msg.statuscode=VEN_S_EFAIL;
453 
454                 if (omx->async_message_process(input,&venc_msg) < 0) {
455                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
456                     break;
457                 }
458             }
459         }
460 
461         /* calc avg. fps, bitrate */
462         struct timeval tv;
463         gettimeofday(&tv,NULL);
464         OMX_U64 time_diff = (OMX_U32)((tv.tv_sec * 1000000 + tv.tv_usec) -
465                 (stats.prev_tv.tv_sec * 1000000 + stats.prev_tv.tv_usec));
466         if (time_diff >= 5000000) {
467             OMX_U32 num_fbd = omx->handle->fbd - stats.prev_fbd;
468             if (stats.prev_tv.tv_sec && num_fbd && time_diff) {
469                 float framerate = num_fbd * 1000000/(float)time_diff;
470                 OMX_U32 bitrate = (stats.bytes_generated * 8 / num_fbd) * framerate;
471                 DEBUG_PRINT_INFO("stats: avg. fps %0.2f, bitrate %d",
472                     framerate, bitrate);
473             }
474             stats.prev_tv = tv;
475             stats.bytes_generated = 0;
476             stats.prev_fbd = omx->handle->fbd;
477         }
478 
479     }
480 
481     DEBUG_PRINT_HIGH("omx_venc: Async Thread exit");
482     return NULL;
483 }
484 
485 static const int event_type[] = {
486     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
487     V4L2_EVENT_MSM_VIDC_SYS_ERROR
488 };
489 
subscribe_to_events(int fd)490 static OMX_ERRORTYPE subscribe_to_events(int fd)
491 {
492     OMX_ERRORTYPE eRet = OMX_ErrorNone;
493     struct v4l2_event_subscription sub;
494     int array_sz = sizeof(event_type)/sizeof(int);
495     int i,rc;
496     memset(&sub, 0, sizeof(sub));
497 
498     if (fd < 0) {
499        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
500         return OMX_ErrorBadParameter;
501     }
502 
503     for (i = 0; i < array_sz; ++i) {
504         memset(&sub, 0, sizeof(sub));
505         sub.type = event_type[i];
506         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
507 
508         if (rc) {
509            DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
510             break;
511         }
512     }
513 
514     if (i < array_sz) {
515         for (--i; i >=0 ; i--) {
516             memset(&sub, 0, sizeof(sub));
517             sub.type = event_type[i];
518             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
519 
520             if (rc)
521                DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
522         }
523 
524         eRet = OMX_ErrorNotImplemented;
525     }
526 
527     return eRet;
528 }
529 
venc_query_cap(struct v4l2_queryctrl & cap)530 bool venc_dev::venc_query_cap(struct v4l2_queryctrl &cap) {
531 
532     if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &cap)) {
533         DEBUG_PRINT_ERROR("Query caps for id = %u failed", cap.id);
534         return false;
535     }
536     return true;
537 }
538 
venc_validate_range(OMX_S32 id,OMX_S32 val)539 bool inline venc_dev::venc_validate_range(OMX_S32 id, OMX_S32 val) {
540 
541     struct v4l2_queryctrl cap;
542     memset(&cap, 0, sizeof(struct v4l2_queryctrl));
543 
544     cap.id = id;
545     if (venc_query_cap(cap)) {
546         if (val >= cap.minimum && val <= cap.maximum) {
547             return true;
548         } else {
549             DEBUG_PRINT_INFO("id = %u, value = %u, min = %u, max = %u",
550                 cap.id, val, cap.minimum, cap.maximum);
551         }
552     }
553     return false;
554 }
555 
get_roi_for_timestamp(struct roidata & roi,OMX_TICKS timestamp)556 void venc_dev::get_roi_for_timestamp(struct roidata &roi, OMX_TICKS timestamp)
557 {
558     std::list<roidata>::iterator iter;
559     bool found = false;
560 
561     memset(&roi, 0, sizeof(struct roidata));
562     roi.dirty = false;
563 
564     pthread_mutex_lock(&m_roilock);
565     iter = m_roilist.begin();
566     while (iter != m_roilist.end()) {
567         if (iter->info.nTimeStamp < timestamp) {
568             /* remove previous roi data */
569             iter = m_roilist.erase(iter);
570             /* iter++ is not required as erase would do it */
571             continue;
572         } else if (iter->info.nTimeStamp == timestamp){
573             found = true;
574             roi = *iter;
575             break;
576         }
577         iter++;
578     }
579     if (found) {
580         DEBUG_PRINT_LOW("found roidata with timestamp %lld us", roi.info.nTimeStamp);
581     }
582     pthread_mutex_unlock(&m_roilock);
583 }
584 
append_mbi_extradata(void * dst,struct msm_vidc_extradata_header * src)585 int venc_dev::append_mbi_extradata(void *dst, struct msm_vidc_extradata_header* src)
586 {
587     OMX_QCOM_EXTRADATA_MBINFO *mbi = (OMX_QCOM_EXTRADATA_MBINFO *)dst;
588 
589     if (!dst || !src)
590         return 0;
591 
592     /* TODO: Once Venus 3XX target names are known, nFormat should 2 for those
593      * targets, since the payload format will be different */
594     mbi->nFormat = 2;
595     mbi->nDataSize = src->data_size;
596     memcpy(&mbi->data, &src->data, src->data_size);
597 
598     return mbi->nDataSize + sizeof(*mbi);
599 }
600 
get_yuv_size(unsigned long fmt,int width,int height)601 inline int get_yuv_size(unsigned long fmt, int width, int height) {
602     unsigned int y_stride, uv_stride, y_sclines,
603                 uv_sclines, y_plane, uv_plane;
604     unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0;
605     unsigned size = 0;
606 
607     y_stride = VENUS_Y_STRIDE(fmt, width);
608     uv_stride = VENUS_UV_STRIDE(fmt, width);
609     y_sclines = VENUS_Y_SCANLINES(fmt, height);
610     uv_sclines = VENUS_UV_SCANLINES(fmt, height);
611 
612     switch (fmt) {
613         case COLOR_FMT_NV12:
614             y_plane = y_stride * y_sclines;
615             uv_plane = uv_stride * uv_sclines;
616             size = MSM_MEDIA_ALIGN(y_plane + uv_plane, 4096);
617             break;
618          default:
619             break;
620     }
621     return size;
622 }
623 
append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE * p_extra,struct msm_vidc_extradata_header * p_extradata)624 void venc_dev::append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE *p_extra,
625             struct msm_vidc_extradata_header *p_extradata)
626 {
627     OMX_U32 payloadSize = append_mbi_extradata(&p_extra->data, p_extradata);
628     p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + payloadSize - sizeof(unsigned int), 4);
629     p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
630     p_extra->nPortIndex = OMX_DirOutput;
631     p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoEncoderMBInfo;
632     p_extra->nDataSize = payloadSize;
633 
634 }
635 
append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE * p_extra,struct msm_vidc_extradata_header * p_extradata)636 void venc_dev::append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE *p_extra,
637             struct msm_vidc_extradata_header *p_extradata)
638 {
639     p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size  - sizeof(unsigned int), 4);
640     p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
641     p_extra->nPortIndex = OMX_DirOutput;
642     p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
643     p_extra->nDataSize = p_extradata->data_size;
644     memcpy(p_extra->data, p_extradata->data, p_extradata->data_size);
645 }
646 
append_extradata_none(OMX_OTHER_EXTRADATATYPE * p_extra)647 void venc_dev::append_extradata_none(OMX_OTHER_EXTRADATATYPE *p_extra)
648 {
649     p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4);
650     p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
651     p_extra->nPortIndex = OMX_DirOutput;
652     p_extra->eType = OMX_ExtraDataNone;
653     p_extra->nDataSize = 0;
654 }
655 
handle_input_extradata(struct v4l2_buffer buf)656 bool venc_dev::handle_input_extradata(struct v4l2_buffer buf)
657 {
658     OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
659     unsigned int consumed_len = 0, filled_len = 0;
660     unsigned int yuv_size = 0, index = 0;
661     int enable = 0, i = 0, size = 0;
662     unsigned char *pVirt = NULL;
663     int height = m_sVenc_cfg.input_height;
664     int width = m_sVenc_cfg.input_width;
665     OMX_TICKS nTimeStamp = buf.timestamp.tv_sec * 1000000 + buf.timestamp.tv_usec;
666     int fd = buf.m.planes[0].reserved[0];
667     bool vqzip_sei_found = false;
668     char *p_extradata = NULL;
669     OMX_OTHER_EXTRADATATYPE *data = NULL;
670     struct roidata roi;
671     bool status = true;
672     OMX_U32 packet_size = 0;
673     OMX_U32 payload_size = 0;
674 
675     if (!EXTRADATA_IDX(num_input_planes)) {
676         DEBUG_PRINT_LOW("Input extradata not enabled");
677         return true;
678     }
679 
680     if (!input_extradata_info.uaddr) {
681         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
682         return true;
683     }
684 
685     DEBUG_PRINT_HIGH("Processing Extradata for Buffer = %lld", nTimeStamp); // Useful for debugging
686 #ifdef USE_ION
687     venc_handle->do_cache_operations(input_extradata_info.ion.data_fd);
688 #endif
689     if (m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV12 || m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV21) {
690         size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
691         yuv_size = get_yuv_size(COLOR_FMT_NV12, width, height);
692         pVirt = (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
693         if (pVirt == MAP_FAILED) {
694             DEBUG_PRINT_ERROR("%s Failed to mmap",__func__);
695             status = false;
696             goto bailout;
697         }
698         p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + yuv_size + 3)&(~3));
699     }
700 
701     if (!venc_get_index_from_fd(fd, &index)) {
702         status = false;
703         goto bailout;
704     }
705     p_extradata = input_extradata_info.uaddr + index * input_extradata_info.buffer_size;
706     data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
707     memset((void *)(data), 0, (input_extradata_info.buffer_size)); // clear stale data in current buffer
708 
709     while (p_extra && (consumed_len + sizeof(OMX_OTHER_EXTRADATATYPE)) <= (size - yuv_size)
710         && (consumed_len + p_extra->nSize) <= (size - yuv_size)
711         && (filled_len + sizeof(OMX_OTHER_EXTRADATATYPE) <= input_extradata_info.buffer_size)
712         && (filled_len + p_extra->nSize <= input_extradata_info.buffer_size)
713         && (p_extra->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
714 
715         DEBUG_PRINT_LOW("Extradata Type = 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
716         switch ((OMX_QCOM_EXTRADATATYPE)p_extra->eType) {
717         case OMX_ExtraDataFrameDimension:
718         {
719             struct msm_vidc_extradata_index *payload;
720             OMX_QCOM_EXTRADATA_FRAMEDIMENSION *framedimension_format;
721             data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_extradata_index) + 3)&(~3);
722             data->nVersion.nVersion = OMX_SPEC_VERSION;
723             data->nPortIndex = 0;
724             data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_INDEX;
725             data->nDataSize = sizeof(struct msm_vidc_input_crop_payload);
726             framedimension_format = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)p_extra->data;
727             payload = (struct msm_vidc_extradata_index *)(data->data);
728             payload->type = MSM_VIDC_EXTRADATA_INPUT_CROP;
729             payload->input_crop.left = framedimension_format->nDecWidth;
730             payload->input_crop.top = framedimension_format->nDecHeight;
731             payload->input_crop.width = framedimension_format->nActualWidth;
732             payload->input_crop.height = framedimension_format->nActualHeight;
733             DEBUG_PRINT_LOW("Height = %d Width = %d Actual Height = %d Actual Width = %d",
734                 framedimension_format->nDecWidth, framedimension_format->nDecHeight,
735                 framedimension_format->nActualWidth, framedimension_format->nActualHeight);
736             filled_len += data->nSize;
737             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
738             break;
739         }
740         case OMX_ExtraDataQP:
741         {
742             OMX_QCOM_EXTRADATA_QP * qp_payload = NULL;
743             struct msm_vidc_frame_qp_payload *payload;
744             data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_frame_qp_payload) + 3)&(~3);
745             data->nVersion.nVersion = OMX_SPEC_VERSION;
746             data->nPortIndex = 0;
747             data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_FRAME_QP;
748             data->nDataSize = sizeof(struct  msm_vidc_frame_qp_payload);
749             qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data;
750             payload = (struct  msm_vidc_frame_qp_payload *)(data->data);
751             payload->frame_qp = qp_payload->nQP;
752             DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp);
753             filled_len += data->nSize;
754             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
755             break;
756         }
757         case OMX_ExtraDataVQZipSEI:
758             DEBUG_PRINT_LOW("VQZIP SEI Found ");
759             input_extradata_info.vqzip_sei_found = true;
760             break;
761         case OMX_ExtraDataFrameInfo:
762         {
763             OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
764             frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(p_extra->data);
765             if (frame_info->ePicType == OMX_VIDEO_PictureTypeI) {
766                 if (venc_set_intra_vop_refresh((OMX_BOOL)true) == false)
767                     DEBUG_PRINT_ERROR("%s Error in requesting I Frame ", __func__);
768             }
769             break;
770         }
771         default:
772             DEBUG_PRINT_HIGH("Unknown Extradata 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
773             break;
774         }
775 
776         consumed_len += p_extra->nSize;
777         p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
778     }
779 
780       /*
781        * Below code is based on these points.
782        * 1) As _PQ_ not defined in Napali :
783        *     a) Send data to Venus as ROI.
784        *     b) ROI enabled : Processed under unlocked context.
785        *     c) ROI disabled : Nothing to fill.
786        *     d) pq enabled : Not possible.
787        * 2) Normal ROI handling.
788        *     By this time if client sets next ROI, then we shouldn't process new ROI here.
789        */
790 
791     memset(&roi, 0, sizeof(struct roidata));
792     roi.dirty = false;
793     if (m_roi_enabled) {
794         get_roi_for_timestamp(roi, nTimeStamp);
795     }
796 
797     if (roi.dirty) {
798         OMX_U32 mbAlign = 16;
799         if (m_codec == OMX_VIDEO_CodingHEVC) {
800             mbAlign = 32;
801         }
802         OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
803         OMX_U32 mbRowAligned = ((mbRow + 7) >> 3) << 3;
804         OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
805         OMX_U32 numBytes = mbRowAligned * mbCol * 2;
806         OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
807 
808         data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload),256)
809                             + numBytesAligned;
810         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
811         if (data->nSize > input_extradata_info.buffer_size  - filled_len) {
812            DEBUG_PRINT_ERROR("Buffer size (%lu) is less than ROI extradata size (%u)",
813                              (input_extradata_info.buffer_size - filled_len) ,data->nSize);
814            status = false;
815            goto bailout;
816         }
817 
818         data->nVersion.nVersion = OMX_SPEC_VERSION;
819         data->nPortIndex = 0;
820         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
821         struct msm_vidc_roi_deltaqp_payload *roiData =
822                 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
823         roiData->b_roi_info = true;
824         roiData->mbi_info_size = numBytesAligned;
825         /* Video hardware expects ROI QP data to be aligned to 256,
826          * And its offset should be available in roiData->data[0].
827          *  -----------------
828          *  | unsigned int b_roi_info;   |
829          *  | int mbi_info_size;         |
830          *  ----------------------------
831          *  | data[0] = n                | => Contains Offset value to 256 aligned address
832          *  | .                          |
833          *  | .                          |
834          *  | .                          |
835          *  | data+n  <ROI data start>   | => 256 aligned address
836          *  ----------------------------
837          */
838         roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256) - (unsigned long)roiData->data);
839 
840         OMX_U8* tempBuf = (OMX_U8*)roi.info.pRoiMBInfo;
841         OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);;
842         OMX_U16* pBuf;
843         OMX_U8 clientROI;
844 
845         /* Convert input extradata format to HW compatible format
846          * Input        : 1byte per MB
847          * HW Format    : 2bytes per MB. (1 << 11) | ((clientROI & 0x3F)<< 4)
848          * MB Row must be aligned to 8
849          */
850         for (OMX_U32 j = 0;j < mbCol; j++)
851         {
852             pBuf = exDataBuf + j*mbRowAligned;
853             for (OMX_U32 i = 0;i < mbRow; i++)
854             {
855                 clientROI = *tempBuf++;
856                 *pBuf++ = (1 << 11) | ((clientROI & 0x3F)<< 4);
857             }
858         }
859         filled_len += data->nSize;
860         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
861     } else {
862         // m_roilist didn't contain any ROI info with OMX_IndexConfigVideoRoiInfo.
863         // then we can check mRoiRegionList which may contain the roi from vendor extension.
864         OMX_U32 freeSize = input_extradata_info.buffer_size - filled_len;
865         OMX_U32 appendSize = append_extradata_roi_region_qp_info(data, nTimeStamp, freeSize);
866         filled_len += appendSize;
867         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + appendSize);
868     }
869 
870     if (m_roi_enabled) {
871         if (roi.dirty) {
872             DEBUG_PRINT_LOW("free roidata with timestamp %lld us", roi.info.nTimeStamp);
873             roi.dirty = false;
874         }
875     }
876 
877     /* HDR10Plus MetaData information. Enabled by Default. */
878     payload_size = sizeof(struct msm_vidc_hdr10plus_metadata_payload) - sizeof(unsigned int)
879                                 + colorData.dynamicMetaDataLen;
880     packet_size = (sizeof(OMX_OTHER_EXTRADATATYPE) + payload_size + 3)&(~3);
881 
882     if (m_hdr10meta_enabled && (filled_len + packet_size <= input_extradata_info.buffer_size) && colorData.dynamicMetaDataLen > 0) {
883         struct msm_vidc_hdr10plus_metadata_payload *payload;
884 
885         data->nSize = packet_size;
886         data->nVersion.nVersion = OMX_SPEC_VERSION;
887         data->nPortIndex = 0;
888         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_HDR10PLUS_METADATA;
889         data->nDataSize = payload_size;
890 
891         payload = (struct  msm_vidc_hdr10plus_metadata_payload *)(data->data);
892         payload->size = colorData.dynamicMetaDataLen;
893         memcpy(payload->data, colorData.dynamicMetaDataPayload, colorData.dynamicMetaDataLen);
894 
895         filled_len += data->nSize;
896         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
897     } else if (colorData.dynamicMetaDataLen == 0) {
898         DEBUG_PRINT_HIGH("DynamicMetaDataLength == 0 Skip writing metadata.");
899     } else {
900         if (m_hdr10meta_enabled) {
901             DEBUG_PRINT_HIGH("Insufficient size for HDR10Metadata: Required %u Available %lu",
902                              packet_size, (input_extradata_info.buffer_size - filled_len));
903         }
904     }
905 
906 #ifdef _VQZIP_
907     if (vqzip_sei_info.enabled && !input_extradata_info.vqzip_sei_found) {
908         DEBUG_PRINT_ERROR("VQZIP is enabled, But no VQZIP SEI found. Rejecting the session");
909         if (pVirt)
910             munmap(pVirt, size);
911         status = false;
912         goto bailout; //This should be treated as fatal error
913     }
914     if (vqzip_sei_info.enabled && pVirt) {
915         data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) +  sizeof(struct VQZipStats) + 3)&(~3);
916         data->nVersion.nVersion = OMX_SPEC_VERSION;
917         data->nPortIndex = 0;
918         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_YUVSTATS_INFO;
919         data->nDataSize = sizeof(struct VQZipStats);
920         vqzip.fill_stats_data((void*)pVirt, (void*) data->data);
921         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
922     }
923 #endif
924         data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
925         data->nVersion.nVersion = OMX_SPEC_VERSION;
926         data->eType = OMX_ExtraDataNone;
927         data->nDataSize = 0;
928         data->data[0] = 0;
929 
930     if (pVirt)
931         munmap(pVirt, size);
932 
933 bailout:
934 #ifdef USE_ION
935     venc_handle->do_cache_operations(input_extradata_info.ion.data_fd);
936 #endif
937     return status;
938 }
939 
venc_handle_client_input_extradata(void * buffer)940 bool venc_dev::venc_handle_client_input_extradata(void *buffer)
941 {
942     OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
943     OMX_OTHER_EXTRADATATYPE *p_extra = (OMX_OTHER_EXTRADATATYPE*)p_bufhdr->pBuffer;
944     while(p_extra->eType != OMX_ExtraDataNone) {
945         switch((int)p_extra->eType) {
946             case OMX_ExtraDataInputROIInfo:
947             {
948                 OMX_QTI_VIDEO_CONFIG_ROIINFO* roiInfo = reinterpret_cast<OMX_QTI_VIDEO_CONFIG_ROIINFO*>(p_extra->data);
949                 struct roidata roi;
950                 if (!m_roi_enabled) {
951                     DEBUG_PRINT_ERROR("ROI info not enabled");
952                     return false;
953                 }
954 
955                 if (!roiInfo) {
956                     DEBUG_PRINT_ERROR("No ROI info present");
957                     return false;
958                 }
959                 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
960                 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
961                     DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
962                     return false;
963                 }
964 
965                 memset(&roi, 0, sizeof(struct roidata));
966 
967                 roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
968                 roi.info.nTimeStamp = roiInfo->nTimeStamp;
969                 memcpy(roi.info.pRoiMBInfo, &roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
970 
971                 roi.dirty = true;
972 
973                 pthread_mutex_lock(&m_roilock);
974                 DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
975                 m_roilist.push_back(roi);
976                 pthread_mutex_unlock(&m_roilock);
977                 break;
978             }
979         }
980         p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
981     }
982     return true;
983 }
984 
handle_output_extradata(void * buffer,int index)985 bool venc_dev::handle_output_extradata(void *buffer, int index)
986 {
987     OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer;
988     OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
989     OMX_OTHER_EXTRADATATYPE *p_clientextra = NULL;
990     OMX_U32 remaining_extradata_size = 0;
991     OMX_U32 remaining_client_extradata_size = 0;
992     OMX_U32 remaining_fw_extradata_size = 0;
993 
994     if(venc_handle->m_client_output_extradata_mem_ptr && venc_handle->m_sExtraData
995         && venc_handle->m_client_out_extradata_info.getSize() >=
996         output_extradata_info.buffer_size) {
997         p_clientextra = (OMX_OTHER_EXTRADATATYPE * )
998             ((venc_handle->m_client_output_extradata_mem_ptr + index) ->pBuffer);
999     }
1000     if (p_clientextra == NULL) {
1001         DEBUG_PRINT_ERROR("Client Extradata buffers not allocated\n");
1002     }
1003 
1004     if (!output_extradata_info.uaddr) {
1005         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
1006         return false;
1007     }
1008 
1009     p_extra = (OMX_OTHER_EXTRADATATYPE *)ALIGN(p_bufhdr->pBuffer +
1010                 p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4);
1011 
1012     if (output_extradata_info.buffer_size >
1013             p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4)) {
1014         DEBUG_PRINT_ERROR("Insufficient buffer size for extradata");
1015         p_extra = NULL;
1016         return false;
1017     } else if (sizeof(msm_vidc_extradata_header) != sizeof(OMX_OTHER_EXTRADATATYPE)) {
1018         /* A lot of the code below assumes this condition, so error out if it's not met */
1019         DEBUG_PRINT_ERROR("Extradata ABI mismatch");
1020         return false;
1021     }
1022     remaining_extradata_size = p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset +
1023                                                            p_bufhdr->nFilledLen, 4);
1024     if(p_clientextra){
1025        remaining_client_extradata_size = (venc_handle->m_client_output_extradata_mem_ptr +
1026                                           index)->nAllocLen;
1027     }
1028     remaining_fw_extradata_size = output_extradata_info.buffer_size;
1029 
1030     struct msm_vidc_extradata_header *p_extradata = NULL;
1031     do {
1032         DEBUG_PRINT_LOW("Remaining size for: extradata= %d client= %d fw= %d ",\
1033                         remaining_extradata_size,remaining_client_extradata_size,\
1034                         remaining_fw_extradata_size);
1035 
1036         if (remaining_fw_extradata_size < sizeof(OMX_OTHER_EXTRADATATYPE)) {
1037            DEBUG_PRINT_ERROR("Insufficient space for extradata");
1038            break;
1039         }
1040         p_extradata = (struct msm_vidc_extradata_header *) (p_extradata ?
1041             ((char *)p_extradata) + p_extradata->size :
1042             output_extradata_info.uaddr + index * output_extradata_info.buffer_size);
1043 
1044         if ((remaining_fw_extradata_size < p_extradata->size)) {
1045            DEBUG_PRINT_ERROR("Corrupt extradata");
1046            break;
1047         }
1048         remaining_fw_extradata_size -= p_extradata->size;
1049 
1050         if (remaining_extradata_size < p_extradata->size){
1051            DEBUG_PRINT_ERROR("insufficient size available in extradata port buffer");
1052            break;
1053         }
1054 
1055         if(p_clientextra){
1056            if (remaining_client_extradata_size < p_extradata->size) {
1057               DEBUG_PRINT_ERROR("insufficient size available in client buffer");
1058               break;
1059            }
1060         }
1061 
1062         switch (p_extradata->type) {
1063             case MSM_VIDC_EXTRADATA_METADATA_MBI:
1064             {
1065                 append_extradata_mbidata(p_extra, p_extradata);
1066                 if(p_clientextra) {
1067                      append_extradata_mbidata(p_clientextra, p_extradata);
1068                 }
1069                 DEBUG_PRINT_LOW("MBI Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
1070                 break;
1071             }
1072             case MSM_VIDC_EXTRADATA_METADATA_LTR:
1073             {
1074                 append_extradata_ltrinfo(p_extra, p_extradata);
1075                 if(p_clientextra) {
1076                     append_extradata_ltrinfo(p_clientextra, p_extradata);
1077                 }
1078                 DEBUG_PRINT_LOW("LTRInfo Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
1079                 break;
1080             }
1081             case MSM_VIDC_EXTRADATA_NONE:
1082                 append_extradata_none(p_extra);
1083                 if(p_clientextra) {
1084                     append_extradata_none(p_clientextra);
1085                 }
1086                 break;
1087             default:
1088                 /* No idea what this stuff is, just skip over it */
1089                 DEBUG_PRINT_HIGH("Found an unrecognised extradata (%x) ignoring it",
1090                         p_extradata->type);
1091                 continue;
1092         }
1093 
1094         remaining_extradata_size-= p_extra->nSize;
1095         if(p_clientextra) {
1096             remaining_client_extradata_size -= p_clientextra->nSize;
1097             DEBUG_PRINT_LOW("Client Extradata Size= %u",p_clientextra->nSize);
1098         }
1099 
1100         DEBUG_PRINT_LOW("Extradata Size= %u FW= %d",\
1101                         p_extra->nSize,p_extradata->size);
1102 
1103         p_extra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_extra) + p_extra->nSize);
1104         if(p_clientextra) {
1105             p_clientextra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_clientextra) + p_clientextra->nSize);
1106         }
1107     } while (p_extradata->type != MSM_VIDC_EXTRADATA_NONE);
1108 
1109     /* Just for debugging: Traverse the list of extra datas  and spit it out onto log */
1110     p_extra = (OMX_OTHER_EXTRADATATYPE *)ALIGN(p_bufhdr->pBuffer +
1111                 p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4);
1112     remaining_extradata_size = p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset +
1113                                                            p_bufhdr->nFilledLen, 4);
1114     while(p_extra->eType != OMX_ExtraDataNone)
1115     {
1116         DEBUG_PRINT_LOW("Remaining size for: extradata= %d",remaining_extradata_size);
1117         if (remaining_extradata_size < p_extra->nSize){
1118            DEBUG_PRINT_ERROR("insufficient size available in extradata port buffer");
1119            break;
1120         }
1121 
1122         DEBUG_PRINT_LOW("[%p/%u] found extradata type %x of size %u (%u) at %p",
1123                 p_bufhdr->pBuffer, (unsigned int)p_bufhdr->nFilledLen, p_extra->eType,
1124                 (unsigned int)p_extra->nSize, (unsigned int)p_extra->nDataSize, p_extra);
1125 
1126         remaining_extradata_size-= p_extra->nSize;
1127 
1128         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) +
1129                 p_extra->nSize);
1130     }
1131 
1132     return true;
1133 }
1134 
venc_set_format(int format)1135 int venc_dev::venc_set_format(int format)
1136 {
1137     int rc = true;
1138 
1139     if (format) {
1140         color_format = format;
1141 
1142         switch (color_format) {
1143         case NV12_128m:
1144         case NV12_512:
1145             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m);
1146         case NV12_UBWC:
1147             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed);
1148         case YCbCr420_VENUS_P010:
1149             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
1150         default:
1151             return false;
1152         }
1153 
1154     } else {
1155         color_format = 0;
1156         rc = false;
1157     }
1158 
1159     return rc;
1160 }
1161 
venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)1162 OMX_ERRORTYPE venc_dev::venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
1163 {
1164     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1165     struct v4l2_queryctrl profile_cap, level_cap;
1166     int v4l2_profile;
1167     int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
1168                             QOMX_VIDEO_AVCProfileBaseline,
1169                             QOMX_VIDEO_AVCProfileMain,
1170                             QOMX_VIDEO_AVCProfileConstrainedHigh,
1171                             QOMX_VIDEO_AVCProfileHigh };
1172     int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain,
1173                              OMX_VIDEO_HEVCProfileMain10HDR10,
1174                              OMX_VIDEO_HEVCProfileMainStill };
1175 
1176     if (!profileLevelType)
1177         return OMX_ErrorBadParameter;
1178 
1179     memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
1180     memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
1181 
1182     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1183         level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
1184         profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
1185     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1186         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
1187     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1188         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
1189         profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
1190     } else {
1191         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
1192         return OMX_ErrorInvalidComponent;
1193     }
1194 
1195     if (profile_cap.id) {
1196         if(!venc_query_cap(profile_cap)) {
1197             DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
1198             return OMX_ErrorHardware;
1199         }
1200     }
1201 
1202     if (level_cap.id) {
1203         if(!venc_query_cap(level_cap)) {
1204             DEBUG_PRINT_ERROR("Getting capabilities for level failed");
1205             return OMX_ErrorHardware;
1206         }
1207     }
1208 
1209     /* Get the corresponding omx level from v4l2 level */
1210     if (!profile_level_converter::convert_v4l2_level_to_omx(m_sVenc_cfg.codectype, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
1211         DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
1212         return OMX_ErrorHardware;
1213     }
1214 
1215     /* For given profile index get corresponding profile that needs to be supported */
1216     if (profileLevelType->nPortIndex != 1) {
1217         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on output port only %u",
1218                             (unsigned int)profileLevelType->nPortIndex);
1219         return OMX_ErrorBadPortIndex;
1220     }
1221 
1222     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1223         if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
1224             profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
1225         } else {
1226             DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1227                     (unsigned int)profileLevelType->nProfileIndex);
1228             return OMX_ErrorNoMore;
1229         }
1230     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1231         if (profileLevelType->nProfileIndex == 0) {
1232             profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
1233         } else {
1234             DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1235                     (unsigned int)profileLevelType->nProfileIndex);
1236             return OMX_ErrorNoMore;
1237         }
1238         /* Driver has no notion of VP8 profile and there is only one profile supported. Hence return here */
1239         return OMX_ErrorNone;
1240     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1241         if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
1242             profileLevelType->eProfile =  hevc_profiles[profileLevelType->nProfileIndex];
1243         } else {
1244             DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1245                     (unsigned int)profileLevelType->nProfileIndex);
1246             return OMX_ErrorNoMore;
1247         }
1248     }
1249 
1250     /* Check if the profile is supported by driver or not  */
1251     /* During query caps of profile driver sends a mask of */
1252     /* of all v4l2 profiles supported(in the flags field)  */
1253     if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, profileLevelType->eProfile, &v4l2_profile)) {
1254         DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
1255         return OMX_ErrorHardware;
1256     }
1257 
1258     DEBUG_PRINT_INFO("v4l2 profile : %d flags : %d ", v4l2_profile, profile_cap.flags);
1259     if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
1260         DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
1261         eRet = OMX_ErrorNoMore;
1262     }
1263 
1264     DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
1265             (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
1266     return eRet;
1267 }
1268 
venc_get_supported_color_format(unsigned index,OMX_U32 * colorFormat)1269 bool venc_dev::venc_get_supported_color_format(unsigned index, OMX_U32 *colorFormat) {
1270 #ifdef _UBWC_
1271     //we support following formats
1272     //index 0 - Compressed (UBWC) Venus flavour of YUV420SP
1273     //index 1 - Venus flavour of YUV420SP
1274     //index 2 - Compressed (UBWC) TP10 (10bit packed)
1275     //index 3 - Compressed (UBWC) Venus flavour of RGBA8888
1276     //index 4 - Venus flavour of RGBA8888
1277     //index 5 - opaque which internally maps to YUV420SP.
1278     //index 6 - vannilla YUV420SP
1279     //this can be extended in the future
1280     int supportedFormats[] = {
1281         [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed,
1282         [1] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1283         [2] = QOMX_COLOR_FormatYVU420SemiPlanar,
1284         [3] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed,
1285         [4] = QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus,
1286         [5] = QOMX_COLOR_Format32bitRGBA8888Compressed,
1287         [6] = QOMX_COLOR_Format32bitRGBA8888,
1288         [7] = QOMX_COLOR_FormatAndroidOpaque,
1289         [8] = OMX_COLOR_FormatYUV420SemiPlanar,
1290     };
1291 #else
1292     //we support two formats
1293     //index 0 - Venus flavour of YUV420SP
1294     //index 1 - opaque which internally maps to YUV420SP.
1295     //index 2 - vannilla YUV420SP
1296     //this can be extended in the future
1297     int supportedFormats[] = {
1298         [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1299         [1] = QOMX_COLOR_FormatYVU420SemiPlanar,
1300         [2] = QOMX_COLOR_FormatAndroidOpaque,
1301         [3] = OMX_COLOR_FormatYUV420SemiPlanar,
1302     };
1303 #endif
1304     if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1))
1305         return false;
1306     *colorFormat = supportedFormats[index];
1307     return true;
1308 }
1309 
allocate_extradata(struct extradata_buffer_info * extradata_info,int flags)1310 OMX_ERRORTYPE venc_dev::allocate_extradata(struct extradata_buffer_info *extradata_info, int flags)
1311 {
1312     if (extradata_info->allocated) {
1313         DEBUG_PRINT_HIGH("2nd allocation return for port = %d",extradata_info->port_index);
1314         return OMX_ErrorNone;
1315     }
1316 
1317 #ifdef USE_ION
1318 
1319     if (extradata_info->buffer_size) {
1320         if (extradata_info->ion.data_fd != -1) {
1321             venc_handle->ion_unmap(extradata_info->ion.data_fd, (void *)extradata_info->uaddr, extradata_info->size);
1322             venc_handle->free_ion_memory(&extradata_info->ion);
1323         }
1324         extradata_info->size = (extradata_info->size + 4095) & (~4095);
1325 
1326         // ION_IOC_MAP defined @ bionic/libc/kernel/uapi/linux/ion.h not in kernel,
1327         // and this ioctl uses "struct ion_fd_data" with handle member
1328         // Refer alloc_map_ion_memory definition @omx_video_base.cpp
1329         bool status = venc_handle->alloc_map_ion_memory(
1330                 extradata_info->size, &extradata_info->ion, flags);
1331 
1332         if (status == false) {
1333             DEBUG_PRINT_ERROR("Failed to alloc extradata memory\n");
1334             return OMX_ErrorInsufficientResources;
1335         }
1336 
1337         extradata_info->uaddr = (char *)venc_handle->ion_map(extradata_info->ion.data_fd,
1338                                                 extradata_info->size);
1339 
1340         if (extradata_info->uaddr == MAP_FAILED) {
1341             DEBUG_PRINT_ERROR("Failed to map extradata memory\n");
1342             venc_handle->free_ion_memory(&extradata_info->ion);
1343             return OMX_ErrorInsufficientResources;
1344         }
1345     }
1346 #else
1347     (void)flags;
1348 #endif
1349     extradata_info->allocated = OMX_TRUE;
1350     return OMX_ErrorNone;
1351 }
1352 
free_extradata(struct extradata_buffer_info * extradata_info)1353 void venc_dev::free_extradata(struct extradata_buffer_info *extradata_info)
1354 {
1355 #ifdef USE_ION
1356 
1357     if (extradata_info == NULL) {
1358         return;
1359     }
1360 
1361     if (extradata_info->uaddr) {
1362         venc_handle->ion_unmap(extradata_info->ion.data_fd, (void *)extradata_info->uaddr, extradata_info->size);
1363         extradata_info->uaddr = NULL;
1364         venc_handle->free_ion_memory(&extradata_info->ion);
1365     }
1366 
1367     memset(extradata_info, 0, sizeof(*extradata_info));
1368     extradata_info->ion.data_fd = -1;
1369     extradata_info->allocated = OMX_FALSE;
1370 #else
1371     (void)extradata_info;
1372 #endif // USE_ION
1373 }
1374 
free_extradata_all()1375 void venc_dev::free_extradata_all()
1376 {
1377     free_extradata(&output_extradata_info);
1378     free_extradata(&input_extradata_info);
1379 }
1380 
venc_get_output_log_flag()1381 bool venc_dev::venc_get_output_log_flag()
1382 {
1383     return (m_debug.out_buffer_log == 1);
1384 }
1385 
venc_output_log_buffers(const char * buffer_addr,int buffer_len,uint64_t timestamp)1386 int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len, uint64_t timestamp)
1387 {
1388     if (venc_handle->is_secure_session()) {
1389         DEBUG_PRINT_ERROR("logging secure output buffers is not allowed!");
1390         return -1;
1391     }
1392 
1393     if (!m_debug.outfile) {
1394         int size = 0;
1395         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1396            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.264",
1397                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1398         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1399            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%ld_%ld_%p.265",
1400                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1401         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1402            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.ivf",
1403                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1404         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
1405            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.tme",
1406                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1407         }
1408         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1409              DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1410                                 m_debug.outfile_name, size);
1411         }
1412         m_debug.outfile = fopen(m_debug.outfile_name, "ab");
1413         if (!m_debug.outfile) {
1414             DEBUG_PRINT_ERROR("Failed to open output file: %s for logging errno:%d",
1415                                m_debug.outfile_name, errno);
1416             m_debug.outfile_name[0] = '\0';
1417             return -1;
1418         }
1419         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1420             int fps = m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
1421             IvfFileHeader ivfFileHeader(false, m_sVenc_cfg.input_width,
1422                                         m_sVenc_cfg.input_height, fps, 1, 0);
1423             fwrite(&ivfFileHeader, sizeof(ivfFileHeader), 1, m_debug.outfile);
1424         }
1425     }
1426     if (m_debug.outfile && buffer_len) {
1427         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1428             IvfFrameHeader ivfFrameHeader(buffer_len, timestamp);
1429             fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.outfile);
1430         }
1431         DEBUG_PRINT_LOW("%s buffer_len:%d", __func__, buffer_len);
1432         fwrite(buffer_addr, buffer_len, 1, m_debug.outfile);
1433     }
1434     return 0;
1435 }
1436 
venc_extradata_log_buffers(char * buffer_addr,bool input)1437 int venc_dev::venc_extradata_log_buffers(char *buffer_addr, bool input)
1438 {
1439     int fd;
1440 
1441     if (input)
1442         fd = input_extradata_info.ion.data_fd;
1443     else
1444         fd = output_extradata_info.ion.data_fd;
1445 
1446 #ifdef USE_ION
1447     venc_handle->do_cache_operations(fd);
1448 #endif
1449     if (!m_debug.extradatafile && m_debug.extradata_log) {
1450         int size = 0;
1451 
1452         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1453            size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1454                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1455         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1456            size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1457                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1458         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1459            size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1460                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1461         }
1462         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1463              DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging size:%d",
1464                                 m_debug.extradatafile_name, size);
1465         }
1466 
1467         m_debug.extradatafile = fopen(m_debug.extradatafile_name, "ab");
1468         if (!m_debug.extradatafile) {
1469             DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging errno:%d",
1470                                m_debug.extradatafile_name, errno);
1471             m_debug.extradatafile_name[0] = '\0';
1472 #ifdef USE_ION
1473             venc_handle->do_cache_operations(fd);
1474 #endif
1475             return -1;
1476         }
1477     }
1478 
1479     if (m_debug.extradatafile && buffer_addr) {
1480         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
1481         do {
1482             p_extra = (OMX_OTHER_EXTRADATATYPE *)(!p_extra ? buffer_addr :
1483                     ((char *)p_extra) + p_extra->nSize);
1484             fwrite(p_extra, p_extra->nSize, 1, m_debug.extradatafile);
1485         } while (p_extra->eType != OMX_ExtraDataNone);
1486     }
1487 #ifdef USE_ION
1488     venc_handle->do_cache_operations(fd);
1489 #endif
1490     return 0;
1491 }
1492 
venc_input_log_buffers(OMX_BUFFERHEADERTYPE * pbuffer,int fd,int plane_offset,unsigned long inputformat,bool interlaced)1493 int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset,
1494         unsigned long inputformat, bool interlaced) {
1495     int status = 0;
1496     if (venc_handle->is_secure_session()) {
1497         DEBUG_PRINT_ERROR("logging secure input buffers is not allowed!");
1498         return -1;
1499     }
1500 
1501 #ifdef USE_ION
1502     venc_handle->do_cache_operations(fd);
1503 #endif
1504     if (!m_debug.infile) {
1505         int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%lu_%lu_%p.yuv",
1506                             m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1507         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1508              DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1509                                 m_debug.infile_name, size);
1510         }
1511         m_debug.infile = fopen (m_debug.infile_name, "ab");
1512         if (!m_debug.infile) {
1513             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1514             m_debug.infile_name[0] = '\0';
1515             status = -1;
1516             goto bailout;
1517         }
1518     }
1519 
1520     if (m_debug.infile && pbuffer && pbuffer->nFilledLen) {
1521         unsigned long stride, scanlines;
1522         unsigned long color_format;
1523         unsigned long i, msize;
1524         unsigned char *pvirt = NULL, *ptemp = NULL;
1525         unsigned char *temp = (unsigned char *)pbuffer->pBuffer;
1526 
1527         switch (inputformat) {
1528             case V4L2_PIX_FMT_NV12:
1529                 color_format = COLOR_FMT_NV12;
1530                 break;
1531             case V4L2_PIX_FMT_NV12_512:
1532                 color_format = COLOR_FMT_NV12_512;
1533                 break;
1534             case V4L2_PIX_FMT_NV12_UBWC:
1535                 color_format = COLOR_FMT_NV12_UBWC;
1536                 break;
1537             case V4L2_PIX_FMT_RGB32:
1538                 color_format = COLOR_FMT_RGBA8888;
1539                 break;
1540             case V4L2_PIX_FMT_RGBA8888_UBWC:
1541                 color_format = COLOR_FMT_RGBA8888_UBWC;
1542                 break;
1543             case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS:
1544                 color_format = COLOR_FMT_P010;
1545                 break;
1546             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1547                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1548                 break;
1549             default:
1550                 color_format = COLOR_FMT_NV12;
1551                 DEBUG_PRINT_LOW("Default format NV12 is set for logging [%lu]", inputformat);
1552                 break;
1553         }
1554 
1555         msize = VENUS_BUFFER_SIZE_USED(color_format, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,interlaced);
1556         const unsigned int extra_size = VENUS_EXTRADATA_SIZE(m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
1557 
1558         if (metadatamode == 1) {
1559             pvirt= (unsigned char *)mmap(NULL, msize, PROT_READ|PROT_WRITE,MAP_SHARED, fd, plane_offset);
1560             if (pvirt == MAP_FAILED) {
1561                 DEBUG_PRINT_ERROR("%s mmap failed", __func__);
1562                 status = -1;
1563                 goto bailout;
1564             }
1565             ptemp = pvirt;
1566         } else {
1567             ptemp = temp;
1568         }
1569 
1570         if (color_format == COLOR_FMT_NV12) {
1571             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1572             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1573 
1574             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1575                 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1576                 ptemp += stride;
1577             }
1578             if (metadatamode == 1) {
1579                 ptemp = pvirt + (stride * scanlines);
1580             } else {
1581                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1582             }
1583             for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1584                 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1585                 ptemp += stride;
1586             }
1587         } else if (color_format == COLOR_FMT_NV12_512) {
1588             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1589             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1590 
1591             for (i = 0; i < scanlines; i++) {
1592                 fwrite(ptemp, stride, 1, m_debug.infile);
1593                 ptemp += stride;
1594             }
1595             if (metadatamode == 1) {
1596                 ptemp = pvirt + (stride * scanlines);
1597             } else {
1598                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1599             }
1600             for (i = 0; i < scanlines/2; i++) {
1601                 fwrite(ptemp, stride, 1, m_debug.infile);
1602                 ptemp += stride;
1603             }
1604         } else if (color_format == COLOR_FMT_RGBA8888) {
1605             stride = VENUS_RGB_STRIDE(color_format, m_sVenc_cfg.input_width);
1606             scanlines = VENUS_RGB_SCANLINES(color_format, m_sVenc_cfg.input_height);
1607 
1608             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1609                 fwrite(ptemp, m_sVenc_cfg.input_width * 4, 1, m_debug.infile);
1610                 ptemp += stride;
1611             }
1612         } else if (color_format == COLOR_FMT_NV12_UBWC || color_format == COLOR_FMT_NV12_BPP10_UBWC || color_format == COLOR_FMT_RGBA8888_UBWC) {
1613             fwrite(ptemp, msize, 1, m_debug.infile);
1614         } else if(color_format == COLOR_FMT_P010) {
1615             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1616             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1617 
1618             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1619                 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1620                 ptemp += stride;
1621             }
1622             if (metadatamode == 1) {
1623                 ptemp = pvirt + (stride * scanlines);
1624             } else {
1625                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1626             }
1627             for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1628                 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1629                 ptemp += stride;
1630             }
1631         }
1632 
1633         if (metadatamode == 1 && pvirt) {
1634             munmap(pvirt, msize);
1635         }
1636     }
1637 bailout:
1638 #ifdef USE_ION
1639     venc_handle->do_cache_operations(fd);
1640 #endif
1641     return status;
1642 }
1643 
venc_open(OMX_U32 codec)1644 bool venc_dev::venc_open(OMX_U32 codec)
1645 {
1646     int r, minqp = 0, maxqp = 127;
1647     unsigned int alignment = 0,buffer_size = 0, temp =0;
1648     struct v4l2_control control;
1649     OMX_STRING device_name = (OMX_STRING)"/dev/video33";
1650     char property_value[PROPERTY_VALUE_MAX] = {0};
1651     FILE *soc_file = NULL;
1652     char buffer[10];
1653 
1654     property_get("ro.board.platform", m_platform_name, "0");
1655 
1656     if (!strncmp(m_platform_name, "msm8610", 7)) {
1657         device_name = (OMX_STRING)"/dev/video/q6_enc";
1658         supported_rc_modes = (RC_ALL & ~RC_CBR_CFR);
1659     }
1660 
1661     if (!strcmp(m_platform_name, "sm6150") || !strcmp(m_platform_name, "atoll") || !strcmp(m_platform_name, "trinket"))
1662     {
1663        hdr10metadata_supported = false;
1664     }
1665     else {
1666        hdr10metadata_supported = true;
1667     }
1668 
1669 #ifdef HYPERVISOR
1670     m_nDriver_fd = hypv_open(device_name, O_RDWR);
1671 #else
1672     m_nDriver_fd = open(device_name, O_RDWR);
1673 #endif
1674 
1675     if ((int)m_nDriver_fd < 0) {
1676         DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure");
1677         return false;
1678     }
1679     m_poll_efd = eventfd(0, 0);
1680     if (m_poll_efd < 0) {
1681         DEBUG_PRINT_ERROR("Failed to open event fd(%s)", strerror(errno));
1682         return false;
1683     }
1684     DEBUG_PRINT_LOW("m_nDriver_fd = %u", (unsigned int)m_nDriver_fd);
1685 
1686     // set the basic configuration of the video encoder driver
1687     m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH;
1688     m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT;
1689     m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH;
1690     m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT;
1691     m_sVenc_cfg.fps_num = 30;
1692     m_sVenc_cfg.fps_den = 1;
1693     m_sVenc_cfg.targetbitrate = 64000;
1694     m_sVenc_cfg.inputformat= V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1695     m_rotation.rotation = 0;
1696     m_codec = codec;
1697     downscalar_enabled = OMX_FALSE;
1698 
1699     if (codec == OMX_VIDEO_CodingAVC) {
1700         m_sVenc_cfg.codectype = V4L2_PIX_FMT_H264;
1701         codec_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1702         profile_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1703         idrperiod.idrperiod = 1;
1704         minqp = 0;
1705         maxqp = 51;
1706     } else if (codec == OMX_VIDEO_CodingVP8) {
1707         m_sVenc_cfg.codectype = V4L2_PIX_FMT_VP8;
1708         codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
1709         profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
1710         minqp = 0;
1711         maxqp = 127;
1712     } else if (codec == OMX_VIDEO_CodingHEVC || codec == OMX_VIDEO_CodingImageHEIC) {
1713         m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC;
1714         idrperiod.idrperiod = 1;
1715         minqp = 0;
1716         maxqp = 51;
1717         if (codec == OMX_VIDEO_CodingImageHEIC) {
1718             m_sVenc_cfg.input_width = DEFAULT_TILE_DIMENSION;
1719             m_sVenc_cfg.input_height = DEFAULT_TILE_DIMENSION;
1720             m_sVenc_cfg.dvs_width = DEFAULT_TILE_DIMENSION;
1721             m_sVenc_cfg.dvs_height = DEFAULT_TILE_DIMENSION;
1722             codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC;
1723         }
1724         else
1725             codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
1726         profile_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
1727     } else if (codec == QOMX_VIDEO_CodingTME) {
1728         m_sVenc_cfg.codectype = V4L2_PIX_FMT_TME;
1729     }
1730     session_ipb_qp_values.min_i_qp = minqp;
1731     session_ipb_qp_values.max_i_qp = maxqp;
1732     session_ipb_qp_values.min_p_qp = minqp;
1733     session_ipb_qp_values.max_p_qp = maxqp;
1734     session_ipb_qp_values.min_b_qp = minqp;
1735     session_ipb_qp_values.max_b_qp = maxqp;
1736 
1737     int ret;
1738     ret = subscribe_to_events(m_nDriver_fd);
1739 
1740     if (ret) {
1741         DEBUG_PRINT_ERROR("Subscribe Event Failed");
1742         return false;
1743     }
1744 
1745     struct v4l2_fmtdesc fdesc;
1746     struct v4l2_format fmt;
1747     struct v4l2_requestbuffers bufreq;
1748     struct v4l2_capability cap;
1749 
1750     ret = ioctl(m_nDriver_fd, VIDIOC_QUERYCAP, &cap);
1751 
1752     if (ret) {
1753         DEBUG_PRINT_ERROR("Failed to query capabilities");
1754     } else {
1755         DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1756                 " version = %d, capabilities = %x", cap.driver, cap.card,
1757                 cap.bus_info, cap.version, cap.capabilities);
1758     }
1759 
1760     ret=0;
1761     fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1762     fdesc.index=0;
1763 
1764     while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1765         DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1766                 fdesc.pixelformat, fdesc.flags);
1767         fdesc.index++;
1768     }
1769 
1770     fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1771     fdesc.index=0;
1772 
1773     while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1774         DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1775                 fdesc.pixelformat, fdesc.flags);
1776         fdesc.index++;
1777     }
1778 
1779     if (venc_handle->is_secure_session()) {
1780         m_sOutput_buff_property.alignment = SZ_1M;
1781         m_sInput_buff_property.alignment  = SZ_1M;
1782     } else {
1783         m_sOutput_buff_property.alignment = SZ_4K;
1784         m_sInput_buff_property.alignment  = SZ_4K;
1785     }
1786 
1787     memset(&fmt, 0, sizeof(fmt));
1788     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1789     fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
1790     fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
1791     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
1792 
1793     /*TODO: Return values not handled properly in this function anywhere.
1794      * Need to handle those.*/
1795     ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1796 
1797     if (ret) {
1798         DEBUG_PRINT_ERROR("Failed to set format on capture port");
1799         return false;
1800     }
1801 
1802     m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1803 
1804     memset(&fmt, 0, sizeof(fmt));
1805     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1806     fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
1807     fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
1808     fmt.fmt.pix_mp.pixelformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1809     fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
1810 
1811     ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1812     m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1813 
1814     if (m_codec == OMX_VIDEO_CodingImageHEIC) {
1815         if (!venc_set_grid_enable()) {
1816             DEBUG_PRINT_ERROR("Failed to enable grid");
1817             return false;
1818         }
1819 
1820         if (!venc_set_ratectrl_cfg(OMX_Video_ControlRateConstantQuality)) {
1821             DEBUG_PRINT_ERROR("Failed to set rate control:CQ");
1822             return false;
1823         }
1824     }
1825 
1826     bufreq.memory = V4L2_MEMORY_USERPTR;
1827     bufreq.count = 2;
1828 
1829     bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1830     ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1831     m_sInput_buff_property.mincount = m_sInput_buff_property.actualcount = bufreq.count;
1832 
1833     bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1834     bufreq.count = 2;
1835     ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1836     m_sOutput_buff_property.mincount = m_sOutput_buff_property.actualcount = bufreq.count;
1837 
1838     if(venc_handle->is_secure_session()) {
1839         control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1840         control.value = 1;
1841         DEBUG_PRINT_HIGH("ioctl: open secure device");
1842         ret=ioctl(m_nDriver_fd, VIDIOC_S_CTRL,&control);
1843         if (ret) {
1844             DEBUG_PRINT_ERROR("ioctl: open secure dev fail, rc %d", ret);
1845             return false;
1846         }
1847     }
1848 
1849     resume_in_stopped = 0;
1850     metadatamode = 0;
1851 
1852     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_TME) {
1853         control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
1854         control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
1855 
1856         DEBUG_PRINT_LOW("Calling IOCTL to disable seq_hdr in sync_frame id=%d, val=%d", control.id, control.value);
1857 
1858         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1859             DEBUG_PRINT_ERROR("Failed to set control");
1860     }
1861 
1862     struct v4l2_frmsizeenum frmsize;
1863 
1864     //Get the hardware capabilities
1865     memset((void *)&frmsize,0,sizeof(frmsize));
1866     frmsize.index = 0;
1867     frmsize.pixel_format = m_sVenc_cfg.codectype;
1868     ret = ioctl(m_nDriver_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize);
1869 
1870     if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
1871         DEBUG_PRINT_ERROR("Failed to get framesizes");
1872         return false;
1873     }
1874 
1875     if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1876         capability.min_width = frmsize.stepwise.min_width;
1877         capability.max_width = frmsize.stepwise.max_width;
1878         capability.min_height = frmsize.stepwise.min_height;
1879         capability.max_height = frmsize.stepwise.max_height;
1880     }
1881 
1882     //Initialize non-default parameters
1883     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1884         control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
1885         control.value = 0x7fffffff;
1886         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1887             DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAME\n");
1888     }
1889 
1890 
1891     /* Enable Low power mode by default for better power */
1892 
1893     input_extradata_info.port_index = OUTPUT_PORT;
1894     output_extradata_info.port_index = CAPTURE_PORT;
1895 
1896     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
1897         control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_PAYLOAD_VERSION;
1898         ret = ioctl(m_nDriver_fd, VIDIOC_G_CTRL,&control);
1899 
1900         if (ret) {
1901             DEBUG_PRINT_ERROR("Failed to read TME version");
1902             return false;
1903         }
1904         venc_handle->tme_payload_version = control.value;
1905         DEBUG_PRINT_HIGH("TME version is 0x%x", control.value);
1906     }
1907     return true;
1908 }
1909 
unsubscribe_to_events(int fd)1910 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
1911 {
1912     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1913     struct v4l2_event_subscription sub;
1914     int array_sz = sizeof(event_type)/sizeof(int);
1915     int i,rc;
1916 
1917     if (fd < 0) {
1918        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
1919         return OMX_ErrorBadParameter;
1920     }
1921 
1922     for (i = 0; i < array_sz; ++i) {
1923         memset(&sub, 0, sizeof(sub));
1924         sub.type = event_type[i];
1925         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1926 
1927         if (rc) {
1928            DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
1929             break;
1930         }
1931     }
1932 
1933     return eRet;
1934 }
1935 
venc_close()1936 void venc_dev::venc_close()
1937 {
1938     DEBUG_PRINT_LOW("venc_close: fd = %u", (unsigned int)m_nDriver_fd);
1939 
1940     if ((int)m_nDriver_fd >= 0) {
1941         DEBUG_PRINT_HIGH("venc_close E");
1942 
1943         if(eventfd_write(m_poll_efd, 1)) {
1944             DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
1945             async_thread_force_stop = true;
1946         }
1947 
1948         if (async_thread_created)
1949             pthread_join(m_tid,NULL);
1950 
1951         if (venc_handle->msg_thread_created) {
1952             venc_handle->msg_thread_created = false;
1953             venc_handle->msg_thread_stop = true;
1954             post_message(venc_handle, omx_video::OMX_COMPONENT_CLOSE_MSG);
1955             DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
1956             pthread_join(venc_handle->msg_thread_id, NULL);
1957         }
1958         DEBUG_PRINT_HIGH("venc_close X");
1959         unsubscribe_to_events(m_nDriver_fd);
1960         close(m_poll_efd);
1961 #ifdef HYPERVISOR
1962         hypv_close(m_nDriver_fd);
1963 #else
1964         close(m_nDriver_fd);
1965 #endif
1966         m_nDriver_fd = -1;
1967     }
1968 
1969 #ifdef _VQZIP_
1970     vqzip.deinit();
1971 #endif
1972 
1973     if (m_debug.infile) {
1974         fclose(m_debug.infile);
1975         m_debug.infile = NULL;
1976     }
1977 
1978     if (m_debug.outfile) {
1979         fclose(m_debug.outfile);
1980         m_debug.outfile = NULL;
1981     }
1982 
1983     if (m_debug.extradatafile) {
1984         fclose(m_debug.extradatafile);
1985         m_debug.extradatafile = NULL;
1986     }
1987 }
1988 
venc_set_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)1989 bool venc_dev::venc_set_buf_req(OMX_U32 *min_buff_count,
1990         OMX_U32 *actual_buff_count,
1991         OMX_U32 *buff_size,
1992         OMX_U32 port)
1993 {
1994     (void)min_buff_count, (void)buff_size;
1995     unsigned long temp_count = 0;
1996 
1997     if (port == 0) {
1998         if (*actual_buff_count > m_sInput_buff_property.mincount) {
1999             temp_count = m_sInput_buff_property.actualcount;
2000             m_sInput_buff_property.actualcount = *actual_buff_count;
2001             DEBUG_PRINT_LOW("I/P Count set to %u", (unsigned int)*actual_buff_count);
2002         }
2003     } else {
2004         if (*actual_buff_count > m_sOutput_buff_property.mincount) {
2005             temp_count = m_sOutput_buff_property.actualcount;
2006             m_sOutput_buff_property.actualcount = *actual_buff_count;
2007             DEBUG_PRINT_LOW("O/P Count set to %u", (unsigned int)*actual_buff_count);
2008         }
2009     }
2010 
2011     return true;
2012 
2013 }
2014 
venc_loaded_start()2015 bool venc_dev::venc_loaded_start()
2016 {
2017     return true;
2018 }
2019 
venc_loaded_stop()2020 bool venc_dev::venc_loaded_stop()
2021 {
2022     return true;
2023 }
2024 
venc_loaded_start_done()2025 bool venc_dev::venc_loaded_start_done()
2026 {
2027     return true;
2028 }
2029 
venc_loaded_stop_done()2030 bool venc_dev::venc_loaded_stop_done()
2031 {
2032     return true;
2033 }
2034 
venc_get_seq_hdr(void * buffer,unsigned buffer_size,unsigned * header_len)2035 bool venc_dev::venc_get_seq_hdr(void *buffer,
2036         unsigned buffer_size, unsigned *header_len)
2037 {
2038     (void) buffer, (void) buffer_size, (void) header_len;
2039     return true;
2040 }
2041 
venc_get_dimensions(OMX_U32 portIndex,OMX_U32 * w,OMX_U32 * h)2042 bool venc_dev::venc_get_dimensions(OMX_U32 portIndex, OMX_U32 *w, OMX_U32 *h) {
2043     struct v4l2_format fmt;
2044     memset(&fmt, 0, sizeof(fmt));
2045     fmt.type = portIndex == PORT_INDEX_OUT ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
2046             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2047 
2048     if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
2049         DEBUG_PRINT_ERROR("Failed to get format on %s port",
2050                 portIndex == PORT_INDEX_OUT ? "capture" : "output");
2051         return false;
2052     }
2053     *w = fmt.fmt.pix_mp.width;
2054     *h = fmt.fmt.pix_mp.height;
2055     return true;
2056 }
2057 
venc_get_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)2058 bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
2059         OMX_U32 *actual_buff_count,
2060         OMX_U32 *buff_size,
2061         OMX_U32 port)
2062 {
2063     struct v4l2_format fmt;
2064     unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
2065     int ret;
2066     int extra_idx = 0;
2067     struct v4l2_control control;
2068     unsigned int minCount = 0;
2069 
2070     memset(&control, 0, sizeof(control));
2071     memset(&fmt, 0, sizeof(fmt));
2072 
2073     if (port == 0) {
2074         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2075         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2076         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2077         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2078         fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
2079         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2080         if (ret) {
2081             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x, colorspace %d\n",
2082                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2083                 fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
2084             return false;
2085         }
2086         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2087 
2088         control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
2089         ret = ioctl(m_nDriver_fd,  VIDIOC_G_CTRL, &control);
2090         if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
2091             DEBUG_PRINT_ERROR("Driver returned invalid data, port = %d ret = %d Count = %d",
2092                 port, ret, (unsigned int)control.value);
2093             return false;
2094         }
2095 
2096         // Increase buffer-header count for metadata-mode on input port
2097         // to improve buffering and reduce bottlenecks in clients
2098         if (metadatamode) {
2099             DEBUG_PRINT_LOW("FW returned buffer count = %d , overwriting with 9",
2100                 control.value);
2101             minCount = 9;
2102         }
2103 
2104         if (m_sVenc_cfg.input_height * m_sVenc_cfg.input_width >= 3840*2160) {
2105             DEBUG_PRINT_LOW("Increasing buffer count = %d to 11", minCount);
2106             minCount = 11;
2107         }
2108 
2109         /* Need more buffers for HFR usecase */
2110         if (operating_rate >= 120 || (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) >= 120) {
2111             minCount = MAX(minCount, 16);
2112             DEBUG_PRINT_HIGH("fps %d, operating rate %d, input min count %d",
2113                    (int)(m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den), operating_rate, minCount);
2114         }
2115 
2116         // Request MAX_V4L2_BUFS from V4L2 in batch mode.
2117         // Keep the original count for the client
2118         if (metadatamode && mBatchSize) {
2119             minCount = MAX_V4L2_BUFS;
2120             DEBUG_PRINT_LOW("Set buffer count = %d as metadata mode and batchmode enabled", minCount);
2121         }
2122 
2123         // reset min count to 4 for HEIC cases
2124         if (mIsGridset) {
2125             minCount = 4;
2126             DEBUG_PRINT_LOW("Set buffer count = %d for HEIC", minCount);
2127         }
2128 
2129         minCount = MAX((unsigned int)control.value, minCount);
2130         m_sInput_buff_property.mincount = minCount;
2131 
2132         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2133         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2134         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2135         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2136         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2137         if (ret) {
2138             DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
2139                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2140                 fmt.fmt.pix_mp.pixelformat);
2141             return false;
2142         }
2143         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2144 
2145         if (m_sInput_buff_property.actualcount < m_sInput_buff_property.mincount)
2146             m_sInput_buff_property.actualcount = m_sInput_buff_property.mincount;
2147 
2148         *min_buff_count = m_sInput_buff_property.mincount;
2149         *actual_buff_count = m_sInput_buff_property.actualcount;
2150 #ifdef USE_ION
2151         // For ION memory allocations of the allocated buffer size
2152         // must be 4k aligned, hence aligning the input buffer
2153         // size to 4k.
2154         m_sInput_buff_property.datasize = ALIGN(m_sInput_buff_property.datasize, SZ_4K);
2155 #endif
2156         *buff_size = m_sInput_buff_property.datasize;
2157         num_input_planes = fmt.fmt.pix_mp.num_planes;
2158         extra_idx = EXTRADATA_IDX(num_input_planes);
2159 
2160         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
2161             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
2162         } else if (extra_idx >= VIDEO_MAX_PLANES) {
2163             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx);
2164             return false;
2165         }
2166         input_extradata_info.buffer_size =  ALIGN(extra_data_size, SZ_4K);
2167         input_extradata_info.count = MAX_V4L2_BUFS;
2168         input_extradata_info.size = input_extradata_info.buffer_size * input_extradata_info.count;
2169         venc_handle->m_client_in_extradata_info.set_extradata_info(input_extradata_info.buffer_size,m_sInput_buff_property.actualcount);
2170     } else {
2171         unsigned int extra_idx = 0;
2172         memset(&fmt, 0, sizeof(fmt));
2173         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2174         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2175         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2176         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2177 
2178         ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
2179         if (ret) {
2180             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x\n",
2181                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2182                 fmt.fmt.pix_mp.pixelformat);
2183             return false;
2184         }
2185 
2186         m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2187         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2188         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2189         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2190         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2191 
2192         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2193         if (ret) {
2194             DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
2195                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2196                 fmt.fmt.pix_mp.pixelformat);
2197             return false;
2198         }
2199         m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2200 
2201         control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
2202 
2203         ret = ioctl(m_nDriver_fd,  VIDIOC_G_CTRL, &control);
2204         if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
2205             DEBUG_PRINT_ERROR("Driver returned invalid data port = %d ret = %d Count = %d",
2206                 port, ret, (unsigned int)control.value);
2207             return false;
2208         }
2209         minCount = control.value;
2210 
2211         if (mBatchSize) {
2212             // If we're in batch mode, we'd like to end up in a situation where
2213             // driver is able to own mBatchSize buffers and we'd also own atleast
2214             // mBatchSize buffers
2215             minCount = MAX((unsigned int)control.value, mBatchSize) + mBatchSize;
2216             DEBUG_PRINT_LOW("set min count %d as mBatchSize %d", minCount, mBatchSize);
2217         }
2218 
2219         /* Need more buffers for HFR usecase */
2220         if (operating_rate >= 120 || (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) >= 120) {
2221             minCount = MAX(minCount, 16);
2222             DEBUG_PRINT_HIGH("fps %d, operating rate %d, output min count %d",
2223                    (int)(m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den), operating_rate, minCount);
2224         }
2225 
2226         m_sOutput_buff_property.mincount = minCount;
2227 
2228         if (m_sOutput_buff_property.actualcount < m_sOutput_buff_property.mincount)
2229             m_sOutput_buff_property.actualcount = m_sOutput_buff_property.mincount;
2230 
2231         *min_buff_count = m_sOutput_buff_property.mincount;
2232         *actual_buff_count = m_sOutput_buff_property.actualcount;
2233         *buff_size = m_sOutput_buff_property.datasize;
2234         num_output_planes = fmt.fmt.pix_mp.num_planes;
2235         extra_idx = EXTRADATA_IDX(num_output_planes);
2236 
2237         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
2238             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
2239         } else if (extra_idx >= VIDEO_MAX_PLANES) {
2240             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
2241             return false;
2242         }
2243 
2244         output_extradata_info.buffer_size = ALIGN(extra_data_size, SZ_4K);
2245         output_extradata_info.count = m_sOutput_buff_property.actualcount;
2246         output_extradata_info.size = output_extradata_info.buffer_size * output_extradata_info.count;
2247         venc_handle->m_client_out_extradata_info.set_extradata_info(output_extradata_info.buffer_size,output_extradata_info.count);
2248     }
2249 
2250     DEBUG_PRINT_HIGH("venc_get_buf_req: port %d, wxh %dx%d, format %#x, driver min count %d, "
2251         "updated min count %d, act count %d, size %d, num planes %d",
2252         port, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.pixelformat,
2253         control.value, *min_buff_count, *actual_buff_count, *buff_size, fmt.fmt.pix_mp.num_planes);
2254 
2255     return true;
2256 }
2257 
venc_set_param(void * paramData,OMX_INDEXTYPE index)2258 bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index)
2259 {
2260     DEBUG_PRINT_LOW("venc_set_param index 0x%x", index);
2261     struct v4l2_format fmt;
2262     struct v4l2_requestbuffers bufreq;
2263     int ret;
2264     bool isCBR;
2265 
2266     switch ((int)index) {
2267         case OMX_IndexParamPortDefinition:
2268             {
2269                 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2270                 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2271 
2272                 if (portDefn->nPortIndex == PORT_INDEX_IN) {
2273                     if (!venc_set_encode_framerate(portDefn->format.video.xFramerate)) {
2274                         return false;
2275                     }
2276 
2277                     if (enable_mv_narrow_searchrange &&
2278                         (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height) >=
2279                         (OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT)) {
2280                         if (venc_set_searchrange() == false) {
2281                             DEBUG_PRINT_ERROR("ERROR: Failed to set search range");
2282                         }
2283                     }
2284 
2285                     unsigned long inputformat = venc_get_color_format(portDefn->format.video.eColorFormat);
2286 
2287                     if (m_sVenc_cfg.input_height != portDefn->format.video.nFrameHeight ||
2288                             m_sVenc_cfg.input_width != portDefn->format.video.nFrameWidth ||
2289                             m_sInput_buff_property.actualcount != portDefn->nBufferCountActual ||
2290                             m_sVenc_cfg.inputformat != inputformat) {
2291 
2292                         DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
2293                             portDefn->nPortIndex, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
2294                             portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
2295                             m_sInput_buff_property.actualcount, portDefn->nBufferCountActual,
2296                             m_sVenc_cfg.inputformat, inputformat);
2297 
2298                         if (portDefn->nBufferCountActual < m_sInput_buff_property.mincount) {
2299                             DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
2300                                 portDefn->nBufferCountActual, m_sInput_buff_property.mincount, portDefn->nPortIndex);
2301                             return false;
2302                         }
2303 
2304                         m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight;
2305                         m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth;
2306                         m_sVenc_cfg.inputformat = inputformat;
2307                         m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
2308 
2309                         memset(&fmt, 0, sizeof(fmt));
2310                         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2311                         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2312                         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2313                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2314                         fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
2315                         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2316                             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x, colorspace %#x",
2317                                  fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2318                                  fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
2319                             hw_overload = errno == EBUSY;
2320                             return false;
2321                         }
2322                         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2323 
2324                         bufreq.memory = V4L2_MEMORY_USERPTR;
2325                         bufreq.count = portDefn->nBufferCountActual;
2326                         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2327                         if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2328                             DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
2329                             return false;
2330                         }
2331 
2332                         if (num_input_planes > 1)
2333                             input_extradata_info.count = m_sInput_buff_property.actualcount + 1;
2334 
2335                         if (!downscalar_enabled) {
2336                             m_sVenc_cfg.dvs_height = portDefn->format.video.nFrameHeight;
2337                             m_sVenc_cfg.dvs_width = portDefn->format.video.nFrameWidth;
2338                         }
2339                         memset(&fmt, 0, sizeof(fmt));
2340                         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2341                         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2342                         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2343                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2344 
2345                         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2346                             DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed");
2347                             hw_overload = errno == EBUSY;
2348                             return false;
2349                         }
2350 
2351                         m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2352 
2353                     } else {
2354                         DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
2355                             portDefn->nPortIndex);
2356                     }
2357                 } else if (portDefn->nPortIndex == PORT_INDEX_OUT) {
2358 
2359                     unsigned long codectype = venc_get_codectype(portDefn->format.video.eCompressionFormat);
2360 
2361                     //Don't worry about width/height if downscalar is enabled.
2362                     if (((m_sVenc_cfg.dvs_height != portDefn->format.video.nFrameHeight ||
2363                             m_sVenc_cfg.dvs_width != portDefn->format.video.nFrameWidth) && !downscalar_enabled) ||
2364                             m_sOutput_buff_property.actualcount != portDefn->nBufferCountActual ||
2365                             m_sVenc_cfg.codectype != codectype) {
2366 
2367                         if (portDefn->nBufferCountActual < m_sOutput_buff_property.mincount) {
2368                             DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
2369                                 portDefn->nBufferCountActual, m_sOutput_buff_property.mincount, portDefn->nPortIndex);
2370                             return false;
2371                         }
2372 
2373                         //If downscalar is enabled. Correct width/height is populated no need to replace with port def width/height
2374                         if (!downscalar_enabled) {
2375                             DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
2376                                             portDefn->nPortIndex, m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
2377                                             portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
2378                                             m_sOutput_buff_property.actualcount, portDefn->nBufferCountActual,
2379                                             m_sVenc_cfg.codectype, codectype);
2380                             m_sVenc_cfg.dvs_height = portDefn->format.video.nFrameHeight;
2381                             m_sVenc_cfg.dvs_width = portDefn->format.video.nFrameWidth;
2382                         }
2383 
2384                         m_sVenc_cfg.codectype = codectype;
2385                         m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual;
2386 
2387                         memset(&fmt, 0, sizeof(fmt));
2388                         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2389                         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2390                         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2391                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2392                         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2393                             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x",
2394                                  fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2395                                  fmt.fmt.pix_mp.pixelformat);
2396                             hw_overload = errno == EBUSY;
2397                             return false;
2398                         }
2399                         m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2400 
2401                         if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_TME) {
2402                             if (!venc_set_target_bitrate(portDefn->format.video.nBitrate)) {
2403                                 return false;
2404                             }
2405                         }
2406 
2407                         bufreq.memory = V4L2_MEMORY_USERPTR;
2408                         bufreq.count = portDefn->nBufferCountActual;
2409                         bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2410                         if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2411                             DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
2412                             return false;
2413                         }
2414 
2415                         if (num_output_planes > 1)
2416                             output_extradata_info.count = m_sOutput_buff_property.actualcount;
2417                     } else {
2418                         DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
2419                             portDefn->nPortIndex);
2420                     }
2421                 } else {
2422                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index (%d) for OMX_IndexParamPortDefinition", portDefn->nPortIndex);
2423                 }
2424             }
2425             break;
2426         case OMX_IndexParamVideoPortFormat:
2427             {
2428                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt;
2429                 portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2430                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat");
2431 
2432                 if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
2433                     if (!venc_set_color_format(portFmt->eColorFormat)) {
2434                         return false;
2435                     }
2436                 } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2437                     if (!venc_set_encode_framerate(portFmt->xFramerate)) {
2438                         return false;
2439                     }
2440                 } else {
2441                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat");
2442                 }
2443                     break;
2444             }
2445         case OMX_IndexParamVideoBitrate:
2446             {
2447                 OMX_VIDEO_PARAM_BITRATETYPE* pParam;
2448                 pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
2449                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate");
2450 
2451                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2452                     if (!venc_set_ratectrl_cfg(pParam->eControlRate)) {
2453                         DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed");
2454                         return false;
2455                     }
2456 
2457                     if (!venc_set_target_bitrate(pParam->nTargetBitrate)) {
2458                         DEBUG_PRINT_ERROR("ERROR: Target Bit Rate setting failed");
2459                         return false;
2460                     }
2461                 } else {
2462                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate");
2463                 }
2464 
2465                 break;
2466             }
2467         case OMX_IndexParamVideoAvc:
2468             {
2469                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc");
2470                 OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
2471                 OMX_U32 bFrames = 0;
2472 
2473                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2474                     DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d",
2475                             pParam->eProfile,pParam->eLevel);
2476 
2477                     if (!venc_set_profile (pParam->eProfile)) {
2478                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2479                                 pParam->eProfile);
2480                         return false;
2481                     } else {
2482                         if ((pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) &&
2483                             (pParam->eProfile != (OMX_VIDEO_AVCPROFILETYPE) QOMX_VIDEO_AVCProfileConstrainedBaseline)) {
2484                             if (pParam->nBFrames) {
2485                                 bFrames = pParam->nBFrames;
2486                             }
2487                         } else {
2488                             if (pParam->nBFrames) {
2489                                 DEBUG_PRINT_ERROR("Warning: B frames not supported");
2490                                 bFrames = 0;
2491                             }
2492                         }
2493                     }
2494 
2495                     if(!venc_set_level(OMX_VIDEO_LEVEL_UNKNOWN)) {
2496                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2497                         return false;
2498                     }
2499 
2500                     if (!venc_set_intra_period (pParam->nPFrames, bFrames)) {
2501                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2502                         return false;
2503                     }
2504                     if (!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) {
2505                         DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed");
2506                         return false;
2507                     }
2508                     if (!venc_set_inloop_filter (pParam->eLoopFilterMode)) {
2509                         DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed");
2510                         return false;
2511                     }
2512 
2513                     if (!venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB, pParam->nSliceHeaderSpacing)) {
2514                         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config");
2515                         return false;
2516                     }
2517                 } else {
2518                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAvc");
2519                 }
2520 
2521                 //TBD, lot of other variables to be updated, yet to decide
2522                 break;
2523             }
2524         case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
2525             {
2526                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoVp8");
2527                 OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
2528 
2529                 //TODO: Set VP8 level/profile currently based on driver change
2530                 if (!venc_set_profile (pParam->eProfile)) {
2531                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2532                             pParam->eProfile);
2533                     return false;
2534                 }
2535                 if (!venc_set_level (OMX_VIDEO_LEVEL_UNKNOWN)) {
2536                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2537                     return false;
2538                 }
2539                 if(venc_set_vpx_error_resilience(pParam->bErrorResilientMode) == false) {
2540                     DEBUG_PRINT_ERROR("ERROR: Failed to set vpx error resilience");
2541                     return false;
2542                 }
2543                 break;
2544             }
2545             case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
2546             {
2547                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoHevc");
2548                 OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
2549 
2550                 if (!venc_set_profile (pParam->eProfile)) {
2551                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2552                                         pParam->eProfile);
2553                     return false;
2554                 }
2555                 if (!venc_set_level (OMX_VIDEO_LEVEL_UNKNOWN)) {
2556                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2557                     return false;
2558                 }
2559                 if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable))
2560                     DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder");
2561 
2562                 OMX_U32 fps = m_sVenc_cfg.fps_den ? m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den : 30;
2563                 OMX_U32 nPFrames = pParam->nKeyFrameInterval > 0 ? pParam->nKeyFrameInterval - 1 : fps - 1;
2564                 if (!venc_set_intra_period (nPFrames, 0 /* nBFrames */)) {
2565                     DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2566                     return false;
2567                 }
2568                 break;
2569             }
2570             case (OMX_INDEXTYPE)OMX_IndexParamVideoTme:
2571             {
2572                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoTme");
2573                 QOMX_VIDEO_PARAM_TMETYPE * pParam = (QOMX_VIDEO_PARAM_TMETYPE*)paramData;
2574 
2575                 if (!venc_set_profile(pParam->eProfile)) {
2576                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2577                                         pParam->eProfile);
2578                     return false;
2579                 }
2580                 if (!venc_set_level(pParam->eLevel)) {
2581                     DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level %d",
2582                                       pParam->eLevel);
2583                     return false;
2584                 }
2585                 break;
2586             }
2587         case (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid:
2588             {
2589                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidImageGrid. Ignore!");
2590                 break;
2591             }
2592         case OMX_IndexParamVideoIntraRefresh:
2593             {
2594                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh");
2595                 OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh_param =
2596                     (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData;
2597 
2598                 if (intra_refresh_param->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2599                     intra_refresh.irmode     = intra_refresh_param->eRefreshMode;
2600                     intra_refresh.mbcount    = intra_refresh_param->nCirMBs;
2601                     intra_refresh.framecount = 0;
2602                 } else {
2603                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh");
2604                 }
2605 
2606                 break;
2607             }
2608         case OMX_IndexParamVideoAndroidVp8Encoder:
2609             {
2610                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidVp8Encoder");
2611                 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8EncodeParams =
2612                     (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)paramData;
2613 
2614                 if (vp8EncodeParams->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2615                      int pFrames = vp8EncodeParams->nKeyFrameInterval - 1;
2616                      if (venc_set_intra_period(pFrames, 0) == false) {
2617                          DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2618                          return false;
2619                      }
2620 
2621                  } else {
2622                      DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAndroidVp8Encoder");
2623                  }
2624                  break;
2625             }
2626         case OMX_IndexParamVideoErrorCorrection:
2627             {
2628                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection");
2629                 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience =
2630                     (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData;
2631 
2632                 if (error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2633                     if (venc_set_error_resilience(error_resilience) == false) {
2634                         DEBUG_PRINT_ERROR("ERROR: Setting Error Correction failed");
2635                         return false;
2636                     }
2637                 } else {
2638                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection");
2639                 }
2640 
2641                 break;
2642             }
2643          case OMX_QcomIndexParamVideoSliceSpacing:
2644             {
2645                 DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoSliceSpacing");
2646                 QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE *slice_spacing =
2647                     (QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE*)paramData;
2648 
2649                 if (slice_spacing->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2650                     if (!venc_set_multislice_cfg(slice_spacing->eSliceMode, slice_spacing->nSliceSize)) {
2651                         DEBUG_PRINT_ERROR("ERROR: Setting Slice Spacing failed");
2652                         return false;
2653                     }
2654                 } else {
2655                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexParamVideoSliceSpacing");
2656                 }
2657 
2658                 break;
2659             }
2660         case OMX_IndexParamVideoProfileLevelCurrent:
2661             {
2662                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent");
2663                 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level =
2664                     (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
2665 
2666                 if (profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2667                     if (!venc_set_profile(profile_level->eProfile)) {
2668                         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating Profile");
2669                         return false;
2670                     }
2671                     if (!venc_set_level(profile_level->eLevel)) {
2672                         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating level");
2673                         return false;
2674                     }
2675                 } else {
2676                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent");
2677                 }
2678 
2679                 break;
2680             }
2681         case OMX_IndexParamVideoQuantization:
2682             {
2683                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization");
2684                 OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp =
2685                     (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData;
2686                 if (session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2687                     if (venc_set_qp(session_qp->nQpI,
2688                                 session_qp->nQpP,
2689                                 session_qp->nQpB,
2690                                 ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP) == false) {
2691                         DEBUG_PRINT_ERROR("ERROR: Setting Session QP failed");
2692                         return false;
2693                     }
2694                 } else {
2695                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoQuantization");
2696                 }
2697 
2698                 break;
2699             }
2700         case QOMX_IndexParamVideoInitialQp:
2701             {
2702                 DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexParamVideoInitialQp");
2703                 QOMX_EXTNINDEX_VIDEO_INITIALQP *initial_qp =
2704                     (QOMX_EXTNINDEX_VIDEO_INITIALQP *)paramData;
2705                 if (initial_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2706                     if (venc_set_qp(initial_qp->nQpI,
2707                                 initial_qp->nQpP,
2708                                 initial_qp->nQpB,
2709                                 initial_qp->bEnableInitQp) == false) {
2710                         DEBUG_PRINT_ERROR("ERROR: Setting Initial QP failed");
2711                         return false;
2712                     }
2713                 } else {
2714                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for QOMX_IndexParamVideoInitialQp");
2715                 }
2716 
2717                 break;
2718             }
2719         case OMX_QcomIndexParamVideoIPBQPRange:
2720             {
2721                 DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoIPBQPRange");
2722                 OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *session_qp_range =
2723                     (OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *)paramData;
2724                 if(session_qp_range->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
2725                     if ( venc_set_session_qp_range (session_qp_range) == false) {
2726                         DEBUG_PRINT_ERROR("ERROR: Setting QP range failed");
2727                         return false;
2728                     }
2729                 }
2730 
2731                 break;
2732             }
2733         case OMX_QcomIndexEnableSliceDeliveryMode:
2734             {
2735                 QOMX_EXTNINDEX_PARAMTYPE* pParam =
2736                     (QOMX_EXTNINDEX_PARAMTYPE*)paramData;
2737 
2738                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
2739                     if (venc_set_slice_delivery_mode(pParam->bEnable) == false) {
2740                         DEBUG_PRINT_ERROR("Setting slice delivery mode failed");
2741                         return false;
2742                     }
2743                 } else {
2744                     DEBUG_PRINT_ERROR("OMX_QcomIndexEnableSliceDeliveryMode "
2745                             "called on wrong port(%u)", (unsigned int)pParam->nPortIndex);
2746                     return false;
2747                 }
2748 
2749                 break;
2750             }
2751         case OMX_ExtraDataFrameDimension:
2752             {
2753                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataFrameDimension");
2754                 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2755 
2756                 if (venc_set_extradata(OMX_ExtraDataFrameDimension, extra_data) == false) {
2757                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataFrameDimension failed");
2758                     return false;
2759                 }
2760 
2761                 extradata = true;
2762                 break;
2763             }
2764         case OMX_ExtraDataVideoEncoderSliceInfo:
2765             {
2766                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderSliceInfo");
2767                 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2768 
2769                 if (venc_set_extradata(OMX_ExtraDataVideoEncoderSliceInfo, extra_data) == false) {
2770                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoEncoderSliceInfo failed");
2771                     return false;
2772                 }
2773 
2774                 extradata = true;
2775                 break;
2776             }
2777         case OMX_ExtraDataVideoEncoderMBInfo:
2778             {
2779                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderMBInfo");
2780                 OMX_BOOL extra_data =  *(OMX_BOOL *)(paramData);
2781 
2782                 if (venc_set_extradata(OMX_ExtraDataVideoEncoderMBInfo, extra_data) == false) {
2783                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoEncoderMBInfo failed");
2784                     return false;
2785                 }
2786 
2787                 extradata = true;
2788                 break;
2789             }
2790         case OMX_ExtraDataVideoLTRInfo:
2791             {
2792                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoLTRInfo");
2793                 OMX_BOOL extra_data =  *(OMX_BOOL *)(paramData);
2794                 if (venc_set_extradata(OMX_ExtraDataVideoLTRInfo, extra_data) == false) {
2795                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoLTRInfo failed");
2796                     return false;
2797                 }
2798                 extradata = true;
2799                 break;
2800             }
2801         case OMX_QcomIndexParamSequenceHeaderWithIDR:
2802             {
2803                 PrependSPSPPSToIDRFramesParams * pParam =
2804                     (PrependSPSPPSToIDRFramesParams *)paramData;
2805 
2806                 DEBUG_PRINT_LOW("set inband sps/pps: %d", pParam->bEnable);
2807                 if(venc_set_inband_video_header(pParam->bEnable) == false) {
2808                     DEBUG_PRINT_ERROR("ERROR: set inband sps/pps failed");
2809                     return false;
2810                 }
2811 
2812                 break;
2813             }
2814         case OMX_QcomIndexParamAUDelimiter:
2815             {
2816                 OMX_QCOM_VIDEO_CONFIG_AUD * pParam =
2817                     (OMX_QCOM_VIDEO_CONFIG_AUD *)paramData;
2818 
2819                 DEBUG_PRINT_LOW("set AU Delimiters: %d", pParam->bEnable);
2820                 if(venc_set_au_delimiter(pParam->bEnable) == false) {
2821                     DEBUG_PRINT_ERROR("ERROR: set AU delimiter failed");
2822                     return false;
2823                 }
2824 
2825                 break;
2826             }
2827         case OMX_QcomIndexConfigH264EntropyCodingCabac:
2828             {
2829                 QOMX_VIDEO_H264ENTROPYCODINGTYPE * pParam =
2830                     (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)paramData;
2831 
2832                 DEBUG_PRINT_LOW("set Entropy info : %d", pParam->bCabac);
2833                 if(venc_set_entropy_config (pParam->bCabac, 0) == false) {
2834                     DEBUG_PRINT_ERROR("ERROR: set Entropy failed");
2835                     return false;
2836                 }
2837 
2838                 break;
2839             }
2840         case OMX_QcomIndexParamH264VUITimingInfo:
2841             {
2842                 OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
2843                         (OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *)paramData;
2844                 DEBUG_PRINT_LOW("Set VUI timing info: %d", pParam->bEnable);
2845                 if(venc_set_vui_timing_info(pParam->bEnable) == false) {
2846                     DEBUG_PRINT_ERROR("ERROR: Failed to set vui timing info to %d", pParam->bEnable);
2847                     return false;
2848                 } else {
2849                     vui_timing_info.enabled = (unsigned int) pParam->bEnable;
2850                 }
2851                 break;
2852             }
2853         case OMX_QcomIndexParamPeakBitrate:
2854             {
2855                 OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam =
2856                         (OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *)paramData;
2857                 DEBUG_PRINT_LOW("Set peak bitrate: %u", (unsigned int)pParam->nPeakBitrate);
2858                 if(venc_set_peak_bitrate(pParam->nPeakBitrate) == false) {
2859                     DEBUG_PRINT_ERROR("ERROR: Failed to set peak bitrate to %u", (unsigned int)pParam->nPeakBitrate);
2860                     return false;
2861                 } else {
2862                     peak_bitrate.peakbitrate = (unsigned int) pParam->nPeakBitrate;
2863                 }
2864                 break;
2865             }
2866        case OMX_QcomIndexParamSetMVSearchrange:
2867             {
2868                DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexParamSetMVSearchrange");
2869                is_searchrange_set = true;
2870                if (!venc_set_searchrange()) {
2871                    DEBUG_PRINT_ERROR("ERROR: Failed to set search range");
2872                    return false;
2873                }
2874             }
2875             break;
2876         case OMX_QcomIndexParamVideoLTRCount:
2877             {
2878                 DEBUG_PRINT_LOW("venc_set_param: OMX_QcomIndexParamVideoLTRCount");
2879                 OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE* pParam =
2880                         (OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData;
2881                 if (pParam->nCount > 0) {
2882                     if (venc_set_ltrmode(1, pParam->nCount) == false) {
2883                         DEBUG_PRINT_ERROR("ERROR: Enable LTR mode failed");
2884                         return false;
2885                     }
2886                 } else {
2887                     if (venc_set_ltrmode(0, 0) == false) {
2888                         DEBUG_PRINT_ERROR("ERROR: Disable LTR mode failed");
2889                         return false;
2890                     }
2891                 }
2892                 break;
2893             }
2894         case OMX_QcomIndexParamBatchSize:
2895             {
2896                 OMX_PARAM_U32TYPE* pParam =
2897                     (OMX_PARAM_U32TYPE*)paramData;
2898 
2899                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
2900                     DEBUG_PRINT_ERROR("For the moment, client-driven batching not supported"
2901                             " on output port");
2902                     return false;
2903                 }
2904                 break;
2905             }
2906         case OMX_QcomIndexParamVencAspectRatio:
2907             {
2908                 if (!venc_set_aspectratio(paramData)) {
2909                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexParamVencAspectRatio failed");
2910                     return false;
2911                 }
2912                 break;
2913             }
2914         case OMX_QTIIndexParamVideoEnableRoiInfo:
2915             {
2916                 struct v4l2_control control;
2917                 OMX_BOOL extra_data =  *(OMX_BOOL *)(paramData);
2918                 if (extra_data == OMX_FALSE) {
2919                     DEBUG_PRINT_INFO("OMX_QTIIndexParamVideoEnableRoiInfo: bEnableRoiInfo is false");
2920                     break;
2921                 }
2922                 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
2923                         m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
2924                     DEBUG_PRINT_ERROR("OMX_QTIIndexParamVideoEnableRoiInfo is not supported for %lu codec", m_sVenc_cfg.codectype);
2925                     return false;
2926                 }
2927                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
2928                 control.value = V4L2_MPEG_VIDC_EXTRADATA_ROI_QP;
2929                 DEBUG_PRINT_LOW("Setting param OMX_QTIIndexParamVideoEnableRoiInfo");
2930                 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2931                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableRoiInfo failed");
2932                     return false;
2933                 }
2934                 m_roi_enabled = true;
2935                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE;
2936                 if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control)) {
2937                     DEBUG_PRINT_ERROR("ERROR: Getting V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE failed");
2938                 } else {
2939                     DEBUG_PRINT_LOW("ROI type: %d", control.value);
2940                     m_roi_type = control.value;
2941                 }
2942                 break;
2943             }
2944         case OMX_QTIIndexParamLowLatencyMode:
2945             {
2946                 QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE *pParam =
2947                     (QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
2948 
2949                 if (!venc_set_lowlatency_mode(pParam->bEnableLowLatencyMode)) {
2950                      DEBUG_PRINT_ERROR("Setting low latency mode failed");
2951                      return false;
2952                 }
2953                 break;
2954             }
2955         case OMX_IndexParamAndroidVideoTemporalLayering:
2956             {
2957                 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE hierData;
2958                 memcpy(&hierData, paramData, sizeof(hierData));
2959 
2960                 if (!venc_validate_temporal_extn(hierData)) {
2961                     DEBUG_PRINT_ERROR("set_param: Failed to validate temporal settings");
2962                     return false;
2963                 }
2964 
2965                 venc_copy_temporal_settings(hierData);
2966 
2967                 break;
2968             }
2969         case OMX_QTIIndexParamDisablePQ:
2970             {
2971                 QOMX_DISABLETYPE * pParam = (QOMX_DISABLETYPE *)paramData;
2972                 DEBUG_PRINT_LOW("venc_set_param: OMX_QTIIndexParamDisablePQ: %d", pParam->bDisable);
2973                 break;
2974             }
2975         case OMX_QTIIndexParamIframeSizeType:
2976             {
2977                 QOMX_VIDEO_IFRAMESIZE* pParam =
2978                     (QOMX_VIDEO_IFRAMESIZE *)paramData;
2979                 isCBR = rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR ||
2980                         rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
2981                 if (!isCBR) {
2982                     DEBUG_PRINT_ERROR("venc_set_param: OMX_QTIIndexParamIframeSizeType not allowed for this configuration isCBR(%d)",
2983                         isCBR);
2984                     return false;
2985                 }
2986                 if (!venc_set_iframesize_type(pParam->eType)) {
2987                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamIframeSizeType failed");
2988                     return false;
2989                 }
2990                 break;
2991             }
2992         case OMX_QTIIndexParamEnableAVTimerTimestamps:
2993             {
2994                 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
2995                 mUseAVTimerTimestamps = pParam->bEnable == OMX_TRUE;
2996                 DEBUG_PRINT_INFO("AVTimer timestamps enabled");
2997                 break;
2998             }
2999         case OMX_QcomIndexParamVideoDownScalar:
3000             {
3001                 QOMX_INDEXDOWNSCALAR *pParam = (QOMX_INDEXDOWNSCALAR *)paramData;
3002                 downscalar_enabled = pParam->bEnable;
3003 
3004                 DEBUG_PRINT_INFO("Downscalar settings: Enabled : %d Width : %u Height %u",
3005                     pParam->bEnable, pParam->nOutputWidth, pParam->nOutputHeight);
3006                 if (downscalar_enabled) {
3007                     m_sVenc_cfg.dvs_width = pParam->nOutputWidth;
3008                     m_sVenc_cfg.dvs_height = pParam->nOutputHeight;
3009 
3010                     memset(&fmt, 0, sizeof(fmt));
3011                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3012                     fmt.fmt.pix_mp.width = pParam->nOutputWidth;
3013                     fmt.fmt.pix_mp.height = pParam->nOutputHeight;
3014                     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
3015                     if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3016                         DEBUG_PRINT_ERROR("Failed to set format on capture port");
3017                         return false;
3018                     }
3019                     m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
3020                 }
3021                 break;
3022             }
3023         case OMX_QTIIndexParamColorSpaceConversion:
3024             {
3025                 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3026                 csc_enable = pParam->bEnable;
3027                 DEBUG_PRINT_INFO("CSC settings: Enabled : %d ", pParam->bEnable);
3028                 break;
3029             }
3030         case OMX_QTIIndexParamEnableLinearColorFormat:
3031             {
3032                 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3033                 mUseLinearColorFormat = pParam->bEnable ? REQUEST_LINEAR_COLOR_ALL : 0;
3034                 DEBUG_PRINT_INFO("Linear Color Format Enabled : %d ", pParam->bEnable);
3035                 break;
3036             }
3037         case OMX_QTIIndexParamVideoEnableBlur:
3038             {
3039                 OMX_QTI_VIDEO_CONFIG_BLURINFO *pParam = (OMX_QTI_VIDEO_CONFIG_BLURINFO *)paramData;
3040                 if (!venc_set_blur_resolution(pParam)) {
3041                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableBlur failed");
3042                     return false;
3043                 }
3044                 break;
3045             }
3046         case OMX_QTIIndexParamNativeRecorder:
3047             {
3048                 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3049                 mIsNativeRecorder = pParam->bEnable == OMX_TRUE;
3050                 DEBUG_PRINT_INFO("Native recorder encode session %d", pParam->bEnable);
3051                 break;
3052             }
3053         default:
3054             DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
3055                     index);
3056             break;
3057     }
3058 
3059     return true;
3060 }
3061 
venc_set_config(void * configData,OMX_INDEXTYPE index)3062 bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
3063 {
3064 
3065     DEBUG_PRINT_LOW("Inside venc_set_config");
3066 
3067     switch ((int)index) {
3068         case OMX_IndexConfigVideoBitrate:
3069             {
3070                 OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *)
3071                     configData;
3072                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoBitrate");
3073 
3074                 if (bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3075                     if (venc_set_target_bitrate(bit_rate->nEncodeBitrate) == false) {
3076                         DEBUG_PRINT_ERROR("ERROR: Setting Target Bit rate failed");
3077                         return false;
3078                     }
3079                 } else {
3080                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate");
3081                 }
3082 
3083                 break;
3084             }
3085         case OMX_IndexConfigVideoFramerate:
3086             {
3087                 OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *)
3088                     configData;
3089                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoFramerate");
3090 
3091                 if (frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3092                     if (venc_set_encode_framerate(frame_rate->xEncodeFramerate) == false) {
3093                         DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
3094                         return false;
3095                     }
3096                 } else {
3097                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
3098                 }
3099 
3100                 break;
3101             }
3102         case QOMX_IndexConfigVideoIntraperiod:
3103             {
3104                 DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod");
3105                 QOMX_VIDEO_INTRAPERIODTYPE *intraperiod =
3106                     (QOMX_VIDEO_INTRAPERIODTYPE *)configData;
3107 
3108                 if (intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
3109                     if (venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) {
3110                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
3111                         return false;
3112                     }
3113 
3114                     if (venc_set_idr_period(intraperiod->nIDRPeriod) == false) {
3115                         DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
3116                         return false;
3117                     }
3118                     client_req_disable_bframe = (intraperiod->nBFrames == 0) ? true : false;
3119                 }
3120 
3121                 break;
3122             }
3123         case OMX_IndexConfigVideoIntraVOPRefresh:
3124             {
3125                 OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)
3126                     configData;
3127                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh");
3128 
3129                 if (intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3130                     if (venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) {
3131                         DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
3132                         return false;
3133                     }
3134                 } else {
3135                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
3136                 }
3137 
3138                 break;
3139             }
3140         case OMX_IndexConfigCommonMirror:
3141             {
3142                 OMX_CONFIG_MIRRORTYPE *mirror = (OMX_CONFIG_MIRRORTYPE*) configData;
3143                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigCommonMirror");
3144 
3145                 if (venc_set_mirror(mirror->eMirror) == false) {
3146                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigCommonMirror failed");
3147                     return false;
3148                 }
3149                 break;
3150             }
3151         case OMX_IndexConfigCommonRotate:
3152             {
3153                 OMX_CONFIG_ROTATIONTYPE *config_rotation =
3154                     reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
3155                 OMX_U32 nFrameWidth;
3156                 if (!config_rotation) {
3157                    return false;
3158                 }
3159                 if (true == deinterlace_enabled) {
3160                     DEBUG_PRINT_ERROR("ERROR: Rotation is not supported with deinterlacing");
3161                     return false;
3162                 }
3163                 if(venc_set_vpe_rotation(config_rotation->nRotation) == false) {
3164                     DEBUG_PRINT_ERROR("ERROR: Dimension Change for Rotation failed");
3165                     return false;
3166                 }
3167 
3168                 break;
3169             }
3170         case OMX_IndexConfigVideoAVCIntraPeriod:
3171             {
3172                 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *avc_iperiod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD*) configData;
3173                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigVideoAVCIntraPeriod");
3174 
3175                 if (venc_set_intra_period(avc_iperiod->nPFrames, intra_period.num_bframes) == false) {
3176                     DEBUG_PRINT_ERROR("ERROR: Setting intra period failed");
3177                     return false;
3178                 }
3179                 if (venc_set_idr_period(avc_iperiod->nIDRPeriod) == false) {
3180                     DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
3181                     return false;
3182                 }
3183                 break;
3184             }
3185         case OMX_IndexConfigVideoVp8ReferenceFrame:
3186             {
3187                 OMX_VIDEO_VP8REFERENCEFRAMETYPE* vp8refframe = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) configData;
3188                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoVp8ReferenceFrame");
3189                 if ((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
3190                         (vp8refframe->bUseGoldenFrame)) {
3191                     if(venc_set_useltr(0x1) == false) {
3192                         DEBUG_PRINT_ERROR("ERROR: use goldenframe failed");
3193                         return false;
3194                     }
3195                 } else if((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
3196                         (vp8refframe->bGoldenFrameRefresh)) {
3197                     if(venc_set_markltr(0x1) == false) {
3198                         DEBUG_PRINT_ERROR("ERROR: Setting goldenframe failed");
3199                         return false;
3200                     }
3201                 } else {
3202                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoVp8ReferenceFrame");
3203                 }
3204                 break;
3205             }
3206         case OMX_QcomIndexConfigVideoLTRUse:
3207             {
3208                 OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE*)configData;
3209                 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRUse");
3210                 if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3211                     if (venc_set_useltr(pParam->nID) == false) {
3212                         DEBUG_PRINT_ERROR("ERROR: Use LTR failed");
3213                         return false;
3214                     }
3215                 } else {
3216                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRUse");
3217                 }
3218                 break;
3219             }
3220         case OMX_QcomIndexConfigVideoLTRMark:
3221             {
3222                 OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE*)configData;
3223                 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRMark");
3224                 if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3225                     if (venc_set_markltr(pParam->nID) == false) {
3226                         DEBUG_PRINT_ERROR("ERROR: Mark LTR failed");
3227                         return false;
3228                     }
3229                 }  else {
3230                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRMark");
3231                 }
3232                 break;
3233             }
3234         case OMX_IndexConfigAndroidVideoTemporalLayering:
3235             {
3236                 OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pParam =
3237                     (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *) configData;
3238                 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE temporalParams;
3239 
3240                 memset(&temporalParams, 0x0, sizeof(temporalParams));
3241                 temporalParams.nPLayerCountActual      = pParam->nPLayerCountActual;
3242                 temporalParams.bBitrateRatiosSpecified = pParam->bBitrateRatiosSpecified;
3243                 temporalParams.ePattern                = pParam->ePattern;
3244                 temporalParams.nLayerCountMax          = temporal_layers_config.nMaxLayers;
3245 
3246                 if (temporalParams.bBitrateRatiosSpecified == OMX_TRUE) {
3247                     for (OMX_U32 i = 0; i < temporalParams.nPLayerCountActual; ++i) {
3248                         temporalParams.nBitrateRatios[i] = pParam->nBitrateRatios[i];
3249                     }
3250                 }
3251 
3252                 if (!venc_validate_temporal_extn(temporalParams)) {
3253                     DEBUG_PRINT_ERROR("set_param: Failed to validate temporal settings");
3254                     return false;
3255                 }
3256 
3257                 venc_copy_temporal_settings(temporalParams);
3258 
3259                 // Set temporal layers with these settings
3260                 if (!venc_reconfigure_temporal_settings()) {
3261                     DEBUG_PRINT_ERROR("Reconfiguring temporal settings failed");
3262                     return false;
3263                 }
3264 
3265                 break;
3266             }
3267         case OMX_QcomIndexConfigBaseLayerId:
3268             {
3269                 OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID* pParam =
3270                     (OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID*) configData;
3271                 if (venc_set_baselayerid(pParam->nPID) == false) {
3272                     DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigBaseLayerId failed");
3273                     return false;
3274                 }
3275                 break;
3276             }
3277         case OMX_IndexParamAndroidVideoTemporalLayering:
3278             {
3279                 DEBUG_PRINT_ERROR("TemporalLayer: Changing layer-configuration dynamically is not supported!");
3280                 return false;
3281             }
3282         case OMX_QcomIndexConfigQp:
3283             {
3284                 OMX_QCOM_VIDEO_CONFIG_QP* pParam =
3285                     (OMX_QCOM_VIDEO_CONFIG_QP*) configData;
3286                 DEBUG_PRINT_LOW("Set_config: nQP %d", pParam->nQP);
3287                 if (venc_set_qp(pParam->nQP,
3288                                 pParam->nQP,
3289                                 pParam->nQP,
3290                                 ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP ) == false) {
3291                     DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigQp failed");
3292                     return false;
3293                 }
3294                 break;
3295             }
3296         case OMX_IndexConfigPriority:
3297             {
3298                 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
3299                 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
3300                 if (!venc_set_priority(priority->nU32)) {
3301                     DEBUG_PRINT_ERROR("Failed to set priority");
3302                     return false;
3303                 }
3304                 sess_priority.priority = priority->nU32;
3305                 break;
3306             }
3307         case OMX_IndexConfigOperatingRate:
3308             {
3309                 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
3310                 DEBUG_PRINT_LOW("Set_config: operating rate %u", rate->nU32);
3311                 if (!venc_set_operatingrate(rate->nU32)) {
3312                     DEBUG_PRINT_ERROR("Failed to set operating rate");
3313                     return false;
3314                 }
3315                 break;
3316             }
3317         case OMX_IndexConfigAndroidIntraRefresh:
3318             {
3319                 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intra_refresh_period = (OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)configData;
3320                 DEBUG_PRINT_LOW("OMX_IndexConfigAndroidIntraRefresh : num frames = %d", intra_refresh_period->nRefreshPeriod);
3321 
3322                 if (intra_refresh_period->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
3323                     intra_refresh.framecount = intra_refresh_period->nRefreshPeriod;
3324                     intra_refresh.irmode     = OMX_VIDEO_IntraRefreshMax;
3325                     intra_refresh.mbcount    = 0;
3326                 } else {
3327                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoIntraRefreshType");
3328                 }
3329                 break;
3330             }
3331         case OMX_QTIIndexConfigVideoBlurResolution:
3332         {
3333              OMX_QTI_VIDEO_CONFIG_BLURINFO *blur = (OMX_QTI_VIDEO_CONFIG_BLURINFO *)configData;
3334              if (blur->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3335                  DEBUG_PRINT_LOW("Set_config: blur resolution: %u", blur->nBlurInfo);
3336                  if(!venc_set_blur_resolution(blur)) {
3337                     DEBUG_PRINT_ERROR("Failed to set Blur Resolution");
3338                     return false;
3339                  }
3340              } else {
3341                   DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QTIIndexConfigVideoBlurResolution");
3342                   return false;
3343              }
3344              break;
3345         }
3346         case OMX_QcomIndexConfigH264Transform8x8:
3347         {
3348             OMX_CONFIG_BOOLEANTYPE *pEnable = (OMX_CONFIG_BOOLEANTYPE *) configData;
3349             DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigH264Transform8x8");
3350             if (venc_h264_transform_8x8(pEnable->bEnabled) == false) {
3351                 DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigH264Transform8x8");
3352                 return false;
3353             }
3354             break;
3355         }
3356         case OMX_QTIIndexConfigDescribeColorAspects:
3357             {
3358                 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
3359 
3360                 OMX_U32 color_space = MSM_VIDC_BT601_6_625;
3361                 OMX_U32 full_range = 0;
3362                 OMX_U32 matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
3363                 OMX_U32 transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
3364 
3365                 switch((ColorAspects::Primaries)(params->sAspects.mPrimaries)) {
3366                     case ColorAspects::PrimariesBT709_5:
3367                         color_space = MSM_VIDC_BT709_5;
3368                         break;
3369                     case ColorAspects::PrimariesBT470_6M:
3370                         color_space = MSM_VIDC_BT470_6_M;
3371                         break;
3372                     case ColorAspects::PrimariesBT601_6_625:
3373                         color_space = MSM_VIDC_BT601_6_625;
3374                         break;
3375                     case ColorAspects::PrimariesBT601_6_525:
3376                         color_space = MSM_VIDC_BT601_6_525;
3377                         break;
3378                     case ColorAspects::PrimariesGenericFilm:
3379                         color_space = MSM_VIDC_GENERIC_FILM;
3380                         break;
3381                     case ColorAspects::PrimariesBT2020:
3382                         color_space = MSM_VIDC_BT2020;
3383                         break;
3384                     default:
3385                         color_space = MSM_VIDC_BT601_6_625;
3386                         //params->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
3387                         break;
3388                 }
3389                 switch((ColorAspects::Range)params->sAspects.mRange) {
3390                     case ColorAspects::RangeFull:
3391                         full_range = 1;
3392                         break;
3393                     case ColorAspects::RangeLimited:
3394                         full_range = 0;
3395                         break;
3396                     default:
3397                         break;
3398                 }
3399                 switch((ColorAspects::Transfer)params->sAspects.mTransfer) {
3400                     case ColorAspects::TransferSMPTE170M:
3401                         transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
3402                         break;
3403                     case ColorAspects::TransferUnspecified:
3404                         transfer_chars = MSM_VIDC_TRANSFER_UNSPECIFIED;
3405                         break;
3406                     case ColorAspects::TransferGamma22:
3407                         transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_M;
3408                         break;
3409                     case ColorAspects::TransferGamma28:
3410                         transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_BG;
3411                         break;
3412                     case ColorAspects::TransferSMPTE240M:
3413                         transfer_chars = MSM_VIDC_TRANSFER_SMPTE_240M;
3414                         break;
3415                     case ColorAspects::TransferLinear:
3416                         transfer_chars = MSM_VIDC_TRANSFER_LINEAR;
3417                         break;
3418                     case ColorAspects::TransferXvYCC:
3419                         transfer_chars = MSM_VIDC_TRANSFER_IEC_61966;
3420                         break;
3421                     case ColorAspects::TransferBT1361:
3422                         transfer_chars = MSM_VIDC_TRANSFER_BT_1361;
3423                         break;
3424                     case ColorAspects::TransferSRGB:
3425                         transfer_chars = MSM_VIDC_TRANSFER_SRGB;
3426                         break;
3427                     default:
3428                         //params->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
3429                         transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
3430                         break;
3431                 }
3432                 switch((ColorAspects::MatrixCoeffs)params->sAspects.mMatrixCoeffs) {
3433                     case ColorAspects::MatrixUnspecified:
3434                         matrix_coeffs = MSM_VIDC_MATRIX_UNSPECIFIED;
3435                         break;
3436                     case ColorAspects::MatrixBT709_5:
3437                         matrix_coeffs = MSM_VIDC_MATRIX_BT_709_5;
3438                         break;
3439                     case ColorAspects::MatrixBT470_6M:
3440                         matrix_coeffs = MSM_VIDC_MATRIX_FCC_47;
3441                         break;
3442                     case ColorAspects::MatrixBT601_6:
3443                         matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
3444                         break;
3445                     case ColorAspects::MatrixSMPTE240M:
3446                         matrix_coeffs = MSM_VIDC_MATRIX_SMPTE_240M;
3447                         break;
3448                     case ColorAspects::MatrixBT2020:
3449                         matrix_coeffs = MSM_VIDC_MATRIX_BT_2020;
3450                         break;
3451                     case ColorAspects::MatrixBT2020Constant:
3452                         matrix_coeffs = MSM_VIDC_MATRIX_BT_2020_CONST;
3453                         break;
3454                     default:
3455                         //params->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
3456                         matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
3457                         break;
3458                 }
3459                 if (!venc_set_colorspace(color_space, full_range,
3460                             transfer_chars, matrix_coeffs)) {
3461 
3462                     DEBUG_PRINT_ERROR("Failed to set operating rate");
3463                     return false;
3464                 }
3465                 break;
3466             }
3467         case OMX_QTIIndexConfigVideoRoiInfo:
3468         {
3469             if(!venc_set_roi_qp_info((OMX_QTI_VIDEO_CONFIG_ROIINFO *)configData)) {
3470                 DEBUG_PRINT_ERROR("Failed to set ROI QP info");
3471                 return false;
3472             }
3473             break;
3474         }
3475         case OMX_IndexConfigVideoNalSize:
3476         {
3477             if(!venc_set_nal_size((OMX_VIDEO_CONFIG_NALSIZE *)configData)) {
3478                 DEBUG_PRINT_LOW("Failed to set Nal size info");
3479                 return false;
3480             }
3481             break;
3482         }
3483         case OMX_QTIIndexConfigVideoRoiRectRegionInfo:
3484         {
3485             if(!venc_set_roi_region_qp_info((OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *)configData)) {
3486                 DEBUG_PRINT_ERROR("Failed to set ROI Region QP info");
3487                 return false;
3488             }
3489             break;
3490         }
3491         default:
3492             DEBUG_PRINT_ERROR("Unsupported config index = %u", index);
3493             break;
3494     }
3495 
3496     return true;
3497 }
3498 
venc_handle_empty_eos_buffer(void)3499 bool venc_dev::venc_handle_empty_eos_buffer( void)
3500 {
3501     struct v4l2_encoder_cmd enc;
3502     int rc = 0;
3503 
3504     if (!streaming[OUTPUT_PORT]) {
3505         enum v4l2_buf_type buf_type;
3506         struct v4l2_control control;
3507         int ret = 0;
3508 
3509         /* If first ETB is an EOS with 0 filled length there is a limitation */
3510         /* for which we need to combine sequence header with 1st frame       */
3511         control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
3512         control.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME;
3513         DEBUG_PRINT_LOW("Combining sequence header with 1st frame ");
3514         ret = ioctl(m_nDriver_fd,  VIDIOC_S_CTRL, &control);
3515         if (ret) {
3516             DEBUG_PRINT_ERROR("Failed to set header mode");
3517             return false;
3518         }
3519 
3520         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3521 
3522         DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
3523         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
3524         if (ret) {
3525             DEBUG_PRINT_ERROR("Failed to call streamon");
3526             if (errno == EBUSY) {
3527                 hw_overload = true;
3528             }
3529             return false;
3530         } else {
3531             streaming[OUTPUT_PORT] = true;
3532         }
3533     }
3534 
3535     memset(&enc, 0, sizeof(enc));
3536     enc.cmd = V4L2_ENC_CMD_STOP;
3537     DEBUG_PRINT_LOW("Sending : Encoder STOP comamnd");
3538     rc = ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc);
3539     if (rc) {
3540         DEBUG_PRINT_ERROR("Failed : Encoder STOP comamnd");
3541         return false;
3542     }
3543     return true;
3544 }
3545 
venc_stop(void)3546 unsigned venc_dev::venc_stop( void)
3547 {
3548     struct venc_msg venc_msg;
3549     struct v4l2_requestbuffers bufreq;
3550     int rc = 0, ret = 0;
3551 
3552     if (!stopped) {
3553         enum v4l2_buf_type cap_type;
3554 
3555         if (streaming[OUTPUT_PORT]) {
3556             cap_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3557             rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
3558 
3559             if (rc) {
3560                 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
3561                         cap_type, rc);
3562             } else
3563                 streaming[OUTPUT_PORT] = false;
3564 
3565             DEBUG_PRINT_LOW("Releasing registered buffers from driver on o/p port");
3566             bufreq.memory = V4L2_MEMORY_USERPTR;
3567             bufreq.count = 0;
3568             bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3569             ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
3570 
3571             if (ret) {
3572                 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS OUTPUT MPLANE Failed");
3573                 return false;
3574             }
3575         }
3576 
3577         if (!rc && streaming[CAPTURE_PORT]) {
3578             cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3579             rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
3580 
3581             if (rc) {
3582                 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
3583                         cap_type, rc);
3584             } else
3585                 streaming[CAPTURE_PORT] = false;
3586 
3587             DEBUG_PRINT_LOW("Releasing registered buffers from driver on capture port");
3588             bufreq.memory = V4L2_MEMORY_USERPTR;
3589             bufreq.count = 0;
3590             bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3591             ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
3592 
3593             if (ret) {
3594                 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS CAPTURE MPLANE Failed");
3595                 return false;
3596             }
3597         }
3598 
3599         if (!rc && !ret) {
3600             venc_stop_done();
3601             stopped = 1;
3602             /*set flag to re-configure when started again*/
3603             resume_in_stopped = 1;
3604         }
3605     }
3606 
3607     return rc;
3608 }
3609 
is_streamon_done(OMX_U32 port)3610 bool venc_dev::is_streamon_done(OMX_U32 port)
3611 {
3612     return streaming[port];
3613 }
3614 
venc_pause(void)3615 unsigned venc_dev::venc_pause(void)
3616 {
3617     pthread_mutex_lock(&pause_resume_mlock);
3618     paused = true;
3619     pthread_mutex_unlock(&pause_resume_mlock);
3620     return 0;
3621 }
3622 
venc_resume(void)3623 unsigned venc_dev::venc_resume(void)
3624 {
3625     pthread_mutex_lock(&pause_resume_mlock);
3626     paused = false;
3627     pthread_mutex_unlock(&pause_resume_mlock);
3628 
3629     return pthread_cond_signal(&pause_resume_cond);
3630 }
3631 
venc_start_done(void)3632 unsigned venc_dev::venc_start_done(void)
3633 {
3634     struct venc_msg venc_msg;
3635     venc_msg.msgcode = VEN_MSG_START;
3636     venc_msg.statuscode = VEN_S_SUCCESS;
3637     venc_handle->async_message_process(venc_handle,&venc_msg);
3638     return 0;
3639 }
3640 
venc_stop_done(void)3641 unsigned venc_dev::venc_stop_done(void)
3642 {
3643     struct venc_msg venc_msg;
3644     free_extradata_all();
3645     venc_msg.msgcode=VEN_MSG_STOP;
3646     venc_msg.statuscode=VEN_S_SUCCESS;
3647     venc_handle->async_message_process(venc_handle,&venc_msg);
3648     return 0;
3649 }
3650 
venc_set_message_thread_id(pthread_t tid)3651 unsigned venc_dev::venc_set_message_thread_id(pthread_t tid)
3652 {
3653     async_thread_created = true;
3654     m_tid=tid;
3655     return 0;
3656 }
3657 
venc_set_vqzip_defaults()3658 bool venc_dev::venc_set_vqzip_defaults()
3659 {
3660     struct v4l2_control control;
3661     int rc = 0, num_mbs_per_frame;
3662 
3663     num_mbs_per_frame = m_sVenc_cfg.input_height * m_sVenc_cfg.input_width;
3664 
3665     switch (num_mbs_per_frame) {
3666     case OMX_CORE_720P_WIDTH  * OMX_CORE_720P_HEIGHT:
3667     case OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT:
3668     case OMX_CORE_4KUHD_WIDTH * OMX_CORE_4KUHD_HEIGHT:
3669     case OMX_CORE_4KDCI_WIDTH * OMX_CORE_4KDCI_HEIGHT:
3670         break;
3671     default:
3672         DEBUG_PRINT_ERROR("VQZIP is not supported for this resoultion : %lu X %lu",
3673             m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
3674         return false;
3675     }
3676 
3677     control.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
3678     control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF;
3679     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3680     if (rc)
3681         DEBUG_PRINT_ERROR("Failed to set Rate Control OFF for VQZIP");
3682 
3683     control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
3684     control.value = INT_MAX;
3685 
3686     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3687     if (rc)
3688         DEBUG_PRINT_ERROR("Failed to set P frame period for VQZIP");
3689 
3690     control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
3691     control.value = 0;
3692 
3693     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3694     if (rc)
3695         DEBUG_PRINT_ERROR("Failed to set B frame period for VQZIP");
3696 
3697     control.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
3698     control.value = 1;
3699 
3700     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3701     if (rc)
3702         DEBUG_PRINT_ERROR("Failed to set IDR period for VQZIP");
3703 
3704     return true;
3705 }
venc_set_extradata_hdr10metadata()3706 bool venc_dev::venc_set_extradata_hdr10metadata()
3707 {
3708     struct v4l2_control control;
3709 
3710     /* HDR10 Metadata is enabled by default for HEVC Main10 profile. */
3711     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC &&
3712         codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) {
3713 
3714         control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
3715         control.value = V4L2_MPEG_VIDC_EXTRADATA_HDR10PLUS_METADATA;
3716 
3717         DEBUG_PRINT_HIGH("venc_set_extradata:: HDR10PLUS_METADATA");
3718 
3719         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3720             DEBUG_PRINT_ERROR("ERROR: Set extradata HDR10PLUS_METADATA failed %d", errno);
3721             return false;
3722         }
3723         m_hdr10meta_enabled = true;
3724         extradata = true;
3725 
3726         //Get upated buffer requirement as enable extradata leads to two buffer planes
3727         venc_get_buf_req (&venc_handle->m_sInPortDef.nBufferCountMin,
3728                                  &venc_handle->m_sInPortDef.nBufferCountActual,
3729                                  &venc_handle->m_sInPortDef.nBufferSize,
3730                                  venc_handle->m_sInPortDef.nPortIndex);
3731     }
3732 
3733     return true;
3734 }
3735 
venc_start(void)3736 unsigned venc_dev::venc_start(void)
3737 {
3738     enum v4l2_buf_type buf_type;
3739     int ret, r;
3740     struct v4l2_control control;
3741 
3742     memset(&control, 0, sizeof(control));
3743 
3744     if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults())
3745         return 1;
3746 
3747     if (!venc_set_priority(sess_priority.priority)) {
3748         DEBUG_PRINT_ERROR("Failed to set priority");
3749         return 1;
3750     }
3751     // Client can set intra refresh period in terms of frames.
3752     // This requires reconfiguration on port redefinition as
3753     // mbcount for IR depends on encode resolution.
3754     if (!venc_reconfigure_intra_refresh_period()) {
3755         DEBUG_PRINT_ERROR("Reconfiguring intra refresh period failed");
3756         return 1;
3757     }
3758 
3759     if (!venc_reconfigure_intra_period()) {
3760         DEBUG_PRINT_ERROR("Reconfiguring intra period failed");
3761         return 1;
3762     }
3763 
3764     // re-configure the temporal layers as RC-mode and key-frame interval
3765     // might have changed since the client last configured the layers.
3766     if (!venc_reconfigure_temporal_settings()) {
3767         DEBUG_PRINT_ERROR("Reconfiguring temporal settings failed");
3768         return 1;
3769     }
3770 
3771     // Note HP settings could change GOP structure
3772     if (!venc_set_intra_period(intra_period.num_pframes, intra_period.num_bframes)) {
3773         DEBUG_PRINT_ERROR("TemporalLayer: Failed to set nPframes/nBframes");
3774         return OMX_ErrorUndefined;
3775     }
3776 
3777     // If Hybrid HP is enable, LTR needs to be reset
3778     if (!venc_reconfigure_ltrmode()) {
3779         DEBUG_PRINT_ERROR("Reconfiguring LTR mode failed");
3780         return 1;
3781     }
3782 
3783     if (hdr10metadata_supported == true) {
3784         venc_set_extradata_hdr10metadata();
3785     }
3786 
3787     venc_config_print();
3788 
3789     /* set buffercount before start */
3790     venc_reconfig_reqbufs();
3791     resume_in_stopped = 0;
3792 
3793     /* Check if slice_delivery mode is enabled & max slices is sufficient for encoding complete frame */
3794     if (slice_mode.enable && multislice.mslice_size &&
3795             (m_sVenc_cfg.dvs_width *  m_sVenc_cfg.dvs_height)/(256 * multislice.mslice_size) >= MAX_SUPPORTED_SLICES_PER_FRAME) {
3796         DEBUG_PRINT_ERROR("slice_mode: %lu, max slices (%lu) should be less than (%d)", slice_mode.enable,
3797                 (m_sVenc_cfg.dvs_width *  m_sVenc_cfg.dvs_height)/(256 * multislice.mslice_size),
3798                 MAX_SUPPORTED_SLICES_PER_FRAME);
3799         return 1;
3800     }
3801 
3802     if (m_codec == OMX_VIDEO_CodingImageHEIC && mIsGridset) {
3803         struct v4l2_format fmt;
3804         memset(&fmt, 0, sizeof(fmt));
3805         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3806         fmt.fmt.pix_mp.height = DEFAULT_TILE_DIMENSION;
3807         fmt.fmt.pix_mp.width = DEFAULT_TILE_DIMENSION;
3808         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
3809         DEBUG_PRINT_INFO("set format type %d, wxh %dx%d, pixelformat %#x",
3810             fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
3811             fmt.fmt.pix_mp.pixelformat);
3812         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3813             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x",
3814                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
3815                 fmt.fmt.pix_mp.pixelformat);
3816             hw_overload = errno == EBUSY;
3817             return false;
3818         }
3819     }
3820 
3821     buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3822     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
3823     ret=ioctl(m_nDriver_fd, VIDIOC_STREAMON,&buf_type);
3824 
3825     if (ret)
3826         return 1;
3827 
3828     streaming[CAPTURE_PORT] = true;
3829 
3830     stopped = 0;
3831     return 0;
3832 }
3833 
hiermode_string(int val)3834 inline const char* hiermode_string(int val)
3835 {
3836     switch(val)
3837     {
3838     case HIER_NONE:
3839         return "No Hier";
3840     case HIER_P:
3841         return "Hier-P";
3842     case HIER_B:
3843         return "Hier-B";
3844     case HIER_P_HYBRID:
3845         return "Hybrid Hier-P";
3846     default:
3847         return "No hier";
3848     }
3849 }
3850 
bitrate_type_string(int val)3851 inline const char* bitrate_type_string(int val)
3852 {
3853     switch(val)
3854     {
3855     case V4L2_MPEG_MSM_VIDC_DISABLE:
3856         return "CUMULATIVE";
3857     case V4L2_MPEG_MSM_VIDC_ENABLE:
3858         return "LAYER WISE";
3859     default:
3860         return "Unknown Bitrate Type";
3861     }
3862 }
3863 
codec_as_string(unsigned long codec)3864 static const char *codec_as_string(unsigned long codec) {
3865     switch (codec) {
3866     case V4L2_PIX_FMT_H264:
3867         return "H264";
3868     case V4L2_PIX_FMT_HEVC:
3869         return "HEVC";
3870     case V4L2_PIX_FMT_VP8:
3871         return "VP8";
3872     default:
3873         return "UNKOWN";
3874     }
3875 }
3876 
venc_config_print()3877 void venc_dev::venc_config_print()
3878 {
3879 
3880     DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %s, Profile %ld, level : %ld",
3881             codec_as_string(m_sVenc_cfg.codectype), codec_profile.profile, profile_level.level);
3882 
3883     DEBUG_PRINT_HIGH("ENC_CONFIG: Input Width: %ld, Height:%ld, Fps: %ld",
3884             m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
3885             m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
3886 
3887     DEBUG_PRINT_HIGH("ENC_CONFIG: Output Width: %ld, Height:%ld, Fps: %ld",
3888             m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
3889             m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
3890 
3891     DEBUG_PRINT_HIGH("ENC_CONFIG: Color Space: Primaries = %u, Range = %u, Transfer Chars = %u, Matrix Coeffs = %u",
3892             color_space.primaries, color_space.range, color_space.transfer_chars, color_space.matrix_coeffs);
3893 
3894     DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld",
3895             bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes);
3896 
3897     DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %ld, qpP: %ld, qpb: %ld enableqp : %ld",
3898             session_qp.iframeqp, session_qp.pframeqp, session_qp.bframeqp, session_qp.enableqp);
3899 
3900     DEBUG_PRINT_HIGH("ENC_CONFIG: minIQP: %lu, maxIQP: %lu minPQP : %lu maxPQP : %lu minBQP : %lu maxBQP : %lu",
3901             session_ipb_qp_values.min_i_qp, session_ipb_qp_values.max_i_qp,
3902             session_ipb_qp_values.min_p_qp, session_ipb_qp_values.max_p_qp,
3903             session_ipb_qp_values.min_b_qp, session_ipb_qp_values.max_b_qp);
3904 
3905     DEBUG_PRINT_HIGH("ENC_CONFIG: VOP_Resolution: %ld, Slice-Mode: %ld, Slize_Size: %ld",
3906             voptimecfg.voptime_resolution, multislice.mslice_mode,
3907             multislice.mslice_size);
3908 
3909     DEBUG_PRINT_HIGH("ENC_CONFIG: EntropyMode: %d, CabacModel: %ld",
3910             entropy.longentropysel, entropy.cabacmodel);
3911 
3912     DEBUG_PRINT_HIGH("ENC_CONFIG: DB-Mode: %ld, alpha: %ld, Beta: %ld",
3913             dbkfilter.db_mode, dbkfilter.slicealpha_offset,
3914             dbkfilter.slicebeta_offset);
3915 
3916     DEBUG_PRINT_HIGH("ENC_CONFIG: HEC: %ld, IDR Period: %ld",
3917             hec.header_extension, idrperiod.idrperiod);
3918 
3919     DEBUG_PRINT_HIGH("ENC_CONFIG: LTR Enabled: %d, Count: %d",
3920             ltrinfo.enabled, ltrinfo.count);
3921 
3922     if (temporal_layers_config.nPLayers) {
3923         DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: P-layers: %u, B-layers: %u, Adjusted I-frame-interval: %lu",
3924                 temporal_layers_config.nPLayers, temporal_layers_config.nBLayers,
3925                 intra_period.num_pframes + intra_period.num_bframes + 1);
3926 
3927         for (OMX_U32 l = 0; temporal_layers_config.bIsBitrateRatioValid
3928                 && (l < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers); ++l) {
3929             DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: layer[%d] bitrate %% = %u%%",
3930                     l, temporal_layers_config.nTemporalLayerBitrateFraction[l]);
3931         }
3932     } else {
3933 
3934         DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d",
3935                 temporal_layers_config.nPLayers, hiermode_string(temporal_layers_config.hier_mode), vpx_err_resilience.enable);
3936 
3937         DEBUG_PRINT_HIGH("ENC_CONFIG: Hier params: Frame Interval : %d, MinQP: %d, Max_QP: %d",
3938                 temporal_layers_config.nKeyFrameInterval, temporal_layers_config.nMinQuantizer, temporal_layers_config.nMaxQuantizer);
3939 
3940         DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layer0: %d, Layer1: %d, Later2: %d, Layer3: %d, Layer4: %d, Layer5: %d",
3941                 temporal_layers_config.nTemporalLayerBitrateRatio[0], temporal_layers_config.nTemporalLayerBitrateRatio[1],
3942                 temporal_layers_config.nTemporalLayerBitrateRatio[2], temporal_layers_config.nTemporalLayerBitrateRatio[3],
3943                 temporal_layers_config.nTemporalLayerBitrateRatio[4], temporal_layers_config.nTemporalLayerBitrateRatio[5]);
3944     }
3945 
3946     DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled);
3947 
3948     DEBUG_PRINT_HIGH("ENC_CONFIG: Peak bitrate: %d", peak_bitrate.peakbitrate);
3949 
3950     DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %s", sess_priority.priority ? "NonRealTime" : "RealTime");
3951 
3952     DEBUG_PRINT_HIGH("ENC_CONFIG: ROI : %u", m_roi_enabled);
3953 
3954     DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate);
3955 }
3956 
venc_reconfig_reqbufs()3957 bool venc_dev::venc_reconfig_reqbufs()
3958 {
3959     struct v4l2_requestbuffers bufreq;
3960 
3961     DEBUG_PRINT_HIGH("venc_reconfig_reqbufs: output_mplane %lu, capture_mplane %lu",
3962         m_sInput_buff_property.actualcount, m_sOutput_buff_property.actualcount);
3963 
3964     bufreq.memory = V4L2_MEMORY_USERPTR;
3965     bufreq.count = m_sInput_buff_property.actualcount;
3966     bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3967     if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
3968         DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: OUTPUT_MPLANE (count %d) failed", bufreq.count);
3969         return false;
3970     }
3971 
3972     bufreq.memory = V4L2_MEMORY_USERPTR;
3973     bufreq.count = m_sOutput_buff_property.actualcount;
3974     bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3975     if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
3976         DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: CAPTURE_MPLANE (count %d) failed", bufreq.count);
3977         return false;
3978     }
3979     return true;
3980 }
3981 
venc_flush(unsigned port)3982 unsigned venc_dev::venc_flush( unsigned port)
3983 {
3984     struct v4l2_encoder_cmd enc;
3985     DEBUG_PRINT_LOW("in %s", __func__);
3986 
3987     for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
3988         fd_list[i] = 0;
3989     }
3990 
3991     enc.cmd = V4L2_QCOM_CMD_FLUSH;
3992     enc.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT | V4L2_QCOM_CMD_FLUSH_CAPTURE;
3993 
3994     if (ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc)) {
3995         DEBUG_PRINT_ERROR("Flush Port (%d) Failed ", port);
3996         return -1;
3997     }
3998 
3999     return 0;
4000 }
4001 
4002 //allocating I/P memory from pmem and register with the device
allocate_extradata(unsigned port)4003 bool venc_dev::allocate_extradata(unsigned port)
4004 {
4005     int rc = 0;
4006     unsigned int extra_idx = 0;
4007 
4008     // PORT_INDEX_IN = 0
4009     // PORT_INDEX_OUT = 1
4010     struct port_info_s {
4011         int num_planes;
4012         struct extradata_buffer_info *extradata_info;
4013         int flag;
4014     }port_info[2] = {
4015         {
4016             .num_planes = num_input_planes,
4017             .extradata_info = &input_extradata_info,
4018             .flag = 0
4019         },
4020         {
4021             .num_planes = num_output_planes,
4022             .extradata_info = &output_extradata_info,
4023             .flag = 0
4024         }
4025     };
4026 
4027     if (port != PORT_INDEX_IN && port != PORT_INDEX_OUT) {
4028         DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index ");
4029         return false;
4030     }
4031 
4032     extra_idx = EXTRADATA_IDX(port_info[port].num_planes);
4033     if ((port_info[port].num_planes > 1) && (extra_idx)) {
4034         rc = allocate_extradata(port_info[port].extradata_info,
4035                                 port_info[port].flag);
4036         if (rc) {
4037             DEBUG_PRINT_ERROR("Failed to allocate extradata: %d\n", rc);
4038             return false;
4039         }
4040     }
4041 
4042     return true;
4043 }
4044 
venc_free_buf(void * buf_addr,unsigned port)4045 bool venc_dev::venc_free_buf(void *buf_addr, unsigned port)
4046 {
4047     struct pmem *pmem_tmp;
4048     struct venc_bufferpayload dev_buffer;
4049 
4050     memset(&dev_buffer, 0, sizeof(dev_buffer));
4051     pmem_tmp = (struct pmem *)buf_addr;
4052 
4053     if (port == PORT_INDEX_IN) {
4054         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
4055         dev_buffer.fd  = pmem_tmp->fd;
4056         dev_buffer.maped_size = pmem_tmp->size;
4057         dev_buffer.sz = pmem_tmp->size;
4058         dev_buffer.offset = pmem_tmp->offset;
4059         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
4060                 dev_buffer.pbuffer, \
4061                 dev_buffer.fd, \
4062                 dev_buffer.offset, \
4063                 dev_buffer.maped_size);
4064 
4065     } else if (port == PORT_INDEX_OUT) {
4066         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
4067         dev_buffer.fd  = pmem_tmp->fd;
4068         dev_buffer.sz = pmem_tmp->size;
4069         dev_buffer.maped_size = pmem_tmp->size;
4070         dev_buffer.offset = pmem_tmp->offset;
4071 
4072         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
4073                 dev_buffer.pbuffer, \
4074                 dev_buffer.fd, \
4075                 dev_buffer.offset, \
4076                 dev_buffer.maped_size);
4077     } else {
4078         DEBUG_PRINT_ERROR("ERROR: venc_free_buf:Invalid Port Index ");
4079         return false;
4080     }
4081 
4082     return true;
4083 }
4084 
venc_color_align(OMX_BUFFERHEADERTYPE * buffer,OMX_U32 width,OMX_U32 height)4085 bool venc_dev::venc_color_align(OMX_BUFFERHEADERTYPE *buffer,
4086         OMX_U32 width, OMX_U32 height)
4087 {
4088     OMX_U32 y_stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width),
4089             y_scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height),
4090             uv_stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, width),
4091             uv_scanlines = VENUS_UV_SCANLINES(COLOR_FMT_NV12, height),
4092             src_chroma_offset = width * height;
4093 
4094     if (buffer->nAllocLen >= VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height)) {
4095         OMX_U8* src_buf = buffer->pBuffer, *dst_buf = buffer->pBuffer;
4096         //Do chroma first, so that we can convert it in-place
4097         src_buf += width * height;
4098         dst_buf += y_stride * y_scanlines;
4099         for (int line = height / 2 - 1; line >= 0; --line) {
4100             /* Align the length to 16 for better memove performance. */
4101             memmove(dst_buf + line * uv_stride,
4102                     src_buf + line * width,
4103                     ALIGN(width, 16));
4104         }
4105 
4106         dst_buf = src_buf = buffer->pBuffer;
4107         //Copy the Y next
4108         for (int line = height - 1; line > 0; --line) {
4109             /* Align the length to 16 for better memove performance. */
4110             memmove(dst_buf + line * y_stride,
4111                     src_buf + line * width,
4112                     ALIGN(width, 16));
4113         }
4114         /* Inform driver to do cache flush on total buffer */
4115         buffer->nFilledLen = buffer->nAllocLen;
4116     } else {
4117         DEBUG_PRINT_ERROR("Failed to align Chroma. from %u to %u : \
4118                 Insufficient bufferLen=%u v/s Required=%u",
4119                 (unsigned int)(width*height), (unsigned int)src_chroma_offset, (unsigned int)buffer->nAllocLen,
4120                 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height));
4121         return false;
4122     }
4123 
4124     return true;
4125 }
4126 
venc_get_vui_timing_info(OMX_U32 * enabled)4127 bool venc_dev::venc_get_vui_timing_info(OMX_U32 *enabled)
4128 {
4129     if (!enabled) {
4130         DEBUG_PRINT_ERROR("Null pointer error");
4131         return false;
4132     } else {
4133         *enabled = vui_timing_info.enabled;
4134         return true;
4135     }
4136 }
4137 
venc_get_vqzip_sei_info(OMX_U32 * enabled)4138 bool venc_dev::venc_get_vqzip_sei_info(OMX_U32 *enabled)
4139 {
4140     if (!enabled) {
4141         DEBUG_PRINT_ERROR("Null pointer error");
4142         return false;
4143     } else {
4144         *enabled = vqzip_sei_info.enabled;
4145         return true;
4146     }
4147 }
4148 
venc_get_peak_bitrate(OMX_U32 * peakbitrate)4149 bool venc_dev::venc_get_peak_bitrate(OMX_U32 *peakbitrate)
4150 {
4151     if (!peakbitrate) {
4152         DEBUG_PRINT_ERROR("Null pointer error");
4153         return false;
4154     } else {
4155         *peakbitrate = peak_bitrate.peakbitrate;
4156         return true;
4157     }
4158 }
4159 
venc_get_batch_size(OMX_U32 * size)4160 bool venc_dev::venc_get_batch_size(OMX_U32 *size)
4161 {
4162     if (!size) {
4163         DEBUG_PRINT_ERROR("Null pointer error");
4164         return false;
4165     } else {
4166         *size = mBatchSize;
4167         return true;
4168     }
4169 }
4170 
4171 
venc_empty_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)4172 bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, unsigned fd)
4173 {
4174     struct pmem *temp_buffer;
4175     struct v4l2_buffer buf;
4176     struct v4l2_requestbuffers bufreq;
4177     struct v4l2_plane plane[VIDEO_MAX_PLANES];
4178     int rc = 0, extra_idx, c2d_enabled = 0;
4179     bool interlace_flag = false;
4180     struct OMX_BUFFERHEADERTYPE *bufhdr;
4181     LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
4182     temp_buffer = (struct pmem *)buffer;
4183 
4184     memset (&buf, 0, sizeof(buf));
4185     memset (&plane, 0, sizeof(plane));
4186 
4187     if (buffer == NULL) {
4188         DEBUG_PRINT_ERROR("ERROR: venc_etb: buffer is NULL");
4189         return false;
4190     }
4191 
4192     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
4193     bufreq.memory = V4L2_MEMORY_USERPTR;
4194     bufreq.count = m_sInput_buff_property.actualcount;
4195     bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4196 
4197     DEBUG_PRINT_LOW("Input buffer length %u, Timestamp = %lld", (unsigned int)bufhdr->nFilledLen, bufhdr->nTimeStamp);
4198 
4199     if (pmem_data_buf) {
4200         DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
4201         plane[0].m.userptr = (unsigned long)pmem_data_buf;
4202         plane[0].data_offset = bufhdr->nOffset;
4203         plane[0].length = bufhdr->nAllocLen;
4204         plane[0].bytesused = bufhdr->nFilledLen;
4205     } else {
4206         // --------------------------------------------------------------------------------------
4207         // [Usage]             [metadatamode] [Type]        [color_format] [Where is buffer info]
4208         // ---------------------------------------------------------------------------------------
4209         // Camera-2              1            CameraSource   0              meta-handle
4210         // Camera-3              1            GrallocSource  0              gralloc-private-handle
4211         // surface encode (RBG)  1            GrallocSource  1              bufhdr (color-converted)
4212         // CPU (Eg: MediaCodec)  0            --             0              bufhdr
4213         // ---------------------------------------------------------------------------------------
4214         if (metadatamode) {
4215             plane[0].m.userptr = index;
4216             meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
4217 
4218             if (!meta_buf) {
4219                 if (!bufhdr->nFilledLen) {
4220                     if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS) {
4221                         DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
4222                         DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
4223                         return false;
4224                     }
4225                     DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
4226                     return false;
4227                 }
4228             } else if (!color_format) { // Metadata mode
4229 
4230                 if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
4231                     native_handle_t *hnd = (native_handle_t*)meta_buf->meta_handle;
4232                     if (!hnd) {
4233                         DEBUG_PRINT_ERROR("ERROR: venc_etb: handle is NULL");
4234                         return false;
4235                     }
4236                     int usage = 0;
4237                     usage = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_USAGE);
4238                     usage = usage > 0 ? usage : 0;
4239 
4240                     if (!streaming[OUTPUT_PORT] && !(m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGB32 ||
4241                         m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGBA8888_UBWC)) {
4242 
4243                         unsigned int is_csc_enabled = 0;
4244                         struct v4l2_format fmt;
4245                         OMX_COLOR_FORMATTYPE color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
4246 
4247                         color_format = (OMX_COLOR_FORMATTYPE)MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_COLORFORMAT);
4248 
4249                         memset(&fmt, 0, sizeof(fmt));
4250                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709 ||
4251                                 usage & private_handle_t::PRIV_FLAGS_ITU_R_601) {
4252                             DEBUG_PRINT_ERROR("Camera buffer color format is not 601_FR.");
4253                             DEBUG_PRINT_ERROR(" This leads to unknown color space");
4254                         }
4255                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) {
4256                             if (is_csc_enabled) {
4257                                 struct v4l2_control control;
4258                                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
4259                                 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4260                                 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4261                                     DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC for 601_to_709");
4262                                 } else {
4263                                     DEBUG_PRINT_INFO("venc_empty_buf: Will convert 601-FR to 709");
4264                                     fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
4265                                     venc_set_colorspace(MSM_VIDC_BT709_5, 0,
4266                                             MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
4267                                 }
4268                             } else {
4269                                 venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
4270                                         MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
4271                                 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
4272                             }
4273                         }
4274                         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4275                         m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
4276                         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
4277                         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
4278                         if (usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
4279                             usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) {
4280                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
4281                         }
4282 
4283                         if (color_format > 0 && !venc_set_color_format(color_format)) {
4284                             DEBUG_PRINT_ERROR("Failed setting color format in Camerasource %lx", m_sVenc_cfg.inputformat);
4285                             return false;
4286                         }
4287 
4288                         if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
4289                             DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
4290                             return false;
4291                         }
4292                     }
4293 
4294                     // Setting batch mode is sticky. We do not expect camera to change
4295                     // between batch and normal modes at runtime.
4296                     if (mBatchSize) {
4297                         if ((unsigned int)MetaBufferUtil::getBatchSize(hnd) != mBatchSize) {
4298                             DEBUG_PRINT_ERROR("Don't support dynamic batch sizes (changed from %d->%d)",
4299                                     mBatchSize, MetaBufferUtil::getBatchSize(hnd));
4300                             return false;
4301                         }
4302 
4303                         return venc_empty_batch ((OMX_BUFFERHEADERTYPE*)buffer, index);
4304                     }
4305 
4306                     int offset = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_OFFSET);
4307                     int length = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_SIZE);
4308                     if (offset < 0 || length < 0) {
4309                         DEBUG_PRINT_ERROR("Invalid meta buffer handle!");
4310                         return false;
4311                     }
4312                     plane[0].data_offset = offset;
4313                     plane[0].length = length;
4314                     plane[0].bytesused = length;
4315                     DEBUG_PRINT_LOW("venc_empty_buf: camera buf: fd = %d filled %d of %d flag 0x%x format 0x%lx",
4316                             fd, plane[0].bytesused, plane[0].length, buf.flags, m_sVenc_cfg.inputformat);
4317                 } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
4318                     VideoGrallocMetadata *meta_buf = (VideoGrallocMetadata *)bufhdr->pBuffer;
4319                     private_handle_t *handle = (private_handle_t *)meta_buf->pHandle;
4320 
4321                     if (!handle) {
4322                         DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
4323                         return false;
4324                     }
4325                     interlace_flag = is_ubwc_interlaced(handle);
4326 
4327                     if (mUseAVTimerTimestamps) {
4328                         uint64_t avTimerTimestampNs = bufhdr->nTimeStamp * 1000;
4329                         if (getMetaData(handle, GET_VT_TIMESTAMP, &avTimerTimestampNs) == 0
4330                                 && avTimerTimestampNs > 0) {
4331                             bufhdr->nTimeStamp = avTimerTimestampNs / 1000;
4332                             DEBUG_PRINT_LOW("AVTimer TS : %llu us", (unsigned long long)bufhdr->nTimeStamp);
4333                         }
4334                     }
4335 
4336                     if (!streaming[OUTPUT_PORT]) {
4337                         // Moment of truth... actual colorspace is known here..
4338                         if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
4339                             DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData colorPrimaries=%d colorRange=%d "
4340                                              "transfer=%d matrixcoefficients=%d"
4341                                              "dynamicMetaDataValid %u dynamicMetaDataLen %u",
4342                                              colorData.colorPrimaries, colorData.range,
4343                                              colorData.transfer, colorData.matrixCoefficients,
4344                                              colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
4345                         }
4346 
4347                         struct v4l2_format fmt;
4348                         memset(&fmt, 0, sizeof(fmt));
4349                         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4350 
4351                         bool isUBWC = ((handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
4352                                         handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) &&
4353                                        is_gralloc_source_ubwc);
4354 
4355                         char grallocFormatStr[200];
4356                         get_gralloc_format_as_string(grallocFormatStr, sizeof(grallocFormatStr), handle->format);
4357                         DEBUG_PRINT_LOW("gralloc format 0x%x (%s) (%s)",
4358                             handle->format, grallocFormatStr, isUBWC ? "UBWC" : "Linear");
4359 
4360                         if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) {
4361                             m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_NV12_UBWC : V4L2_PIX_FMT_NV12;
4362                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 %s", isUBWC ? "UBWC" : "Linear");
4363                         } else if (handle->format == HAL_PIXEL_FORMAT_NV12_HEIF) {
4364                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
4365                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_512");
4366                         } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC) {
4367                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
4368                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_UBWC");
4369                         } else if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) {
4370                             // In case of RGB, conversion to YUV is handled within encoder.
4371                             // Disregard the Colorspace in gralloc-handle in case of RGB and use
4372                             //   [a] 601 for non-UBWC case : C2D output is (apparently) 601-LR
4373                             //   [b] 601 for UBWC case     : Venus can convert to 601-LR or FR. use LR for now.
4374                             //set colormetadata corresponding to ITU_R_601;
4375                             colorData.colorPrimaries =  ColorPrimaries_BT601_6_525;
4376                             colorData.range = Range_Limited;
4377                             colorData.transfer = Transfer_SMPTE_170M;
4378                             colorData.matrixCoefficients = MatrixCoEff_BT601_6_525;
4379                             m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_RGBA8888_UBWC : V4L2_PIX_FMT_RGB32;
4380                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = RGBA8888 %s", isUBWC ? "UBWC" : "Linear");
4381                         } else if (handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
4382                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
4383                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 Linear");
4384                         } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC ||
4385                                    handle->format == HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS) {
4386                             if ((m_codec == OMX_VIDEO_CodingHEVC) &&
4387                                  (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10)) {
4388                                 m_sVenc_cfg.inputformat =
4389                                     (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC)?
4390                                              V4L2_PIX_FMT_NV12_TP10_UBWC :
4391                                              V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
4392                                 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = 10bit");
4393                             } else {
4394                                 DEBUG_PRINT_ERROR("ENC_CONFIG: 10bit colorformat not supported for this codec and profile");
4395                                 return false;
4396                             }
4397 
4398                             if(colorData.masteringDisplayInfo.colorVolumeSEIEnabled ||
4399                                colorData.contentLightLevel.lightLevelSEIEnabled) {
4400                                 if (!venc_set_hdr_info(colorData.masteringDisplayInfo, colorData.contentLightLevel)) {
4401                                     DEBUG_PRINT_ERROR("HDR10-PQ Info Setting failed");
4402                                     return false;
4403                                 } else {
4404                                     DEBUG_PRINT_INFO("Encoding in HDR10-PQ mode");
4405                                 }
4406                             } else {
4407                                 DEBUG_PRINT_INFO("Encoding in HLG mode");
4408                             }
4409                         } else if (handle->format == QOMX_COLOR_FormatYVU420SemiPlanar) {
4410                            m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
4411                            DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV21 Linear");
4412                         } else {
4413                             DEBUG_PRINT_ERROR("Color format is not recoganized. Format 0x%X", handle->format);
4414                             return false;
4415                         }
4416 
4417                         DEBUG_PRINT_INFO("color_space.primaries %d colorData.colorPrimaries %d, is_csc_custom_matrix_enabled=%d",
4418                                          color_space.primaries, colorData.colorPrimaries, is_csc_custom_matrix_enabled);
4419 
4420                         if (csc_enable) {
4421                             struct v4l2_control control;
4422 
4423                             /* Set Camera Color Space. When we set CSC, this will be passed to
4424                                fimrware as the InputPrimaries */
4425                             venc_set_colorspace(colorData.colorPrimaries, colorData.range,
4426                                                 colorData.transfer, colorData.matrixCoefficients);
4427 
4428                             control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
4429                             control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4430                             if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4431                                 DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC");
4432                             }
4433                             else {
4434                                 if (is_csc_custom_matrix_enabled) {
4435                                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX;
4436                                     control.value = 1;
4437                                     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4438                                         DEBUG_PRINT_ERROR("venc_empty_buf: Failed to enable VPE CSC custom matrix");
4439                                     } else {
4440                                         DEBUG_PRINT_INFO("venc_empty_buf: Enabled VPE CSC custom matrix");
4441                                     }
4442                                 }
4443                                 /* Change Colorspace to 709*/
4444                                 colorData.colorPrimaries =  ColorPrimaries_BT709_5;
4445                                 colorData.range = Range_Limited;
4446                                 colorData.transfer = Transfer_sRGB;
4447                                 colorData.matrixCoefficients = MatrixCoEff_BT709_5;
4448                             }
4449                         }
4450 
4451                         /* Enum values from gralloc ColorMetaData matches with the driver values
4452                            as it is standard compliant */
4453                         venc_set_colorspace(colorData.colorPrimaries, colorData.range,
4454                                             colorData.transfer, colorData.matrixCoefficients);
4455 
4456                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
4457                         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
4458                         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
4459                         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
4460                             DEBUG_PRINT_ERROR("Failed setting color format in Grallocsource %lx", m_sVenc_cfg.inputformat);
4461                             return false;
4462                         }
4463                         if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
4464                             DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
4465                             return false;
4466                         }
4467                     } else {
4468                         if (m_hdr10meta_enabled) {
4469                             if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
4470                                 DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData dynamicMetaDataValid=%u dynamicMetaDataLen=%u",
4471                                                  colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
4472                             }
4473                         }
4474                     } // Check OUTPUT Streaming
4475 
4476                     struct UBWCStats cam_ubwc_stats[2];
4477                     unsigned long long int compression_ratio = 1 << 16;
4478 
4479                     if (getMetaData(handle, GET_UBWC_CR_STATS_INFO, (void *)cam_ubwc_stats) == 0) {
4480                         if (cam_ubwc_stats[0].bDataValid) {
4481                             switch (cam_ubwc_stats[0].version) {
4482                             case UBWC_1_0:
4483                                 {
4484                                     // Camera hw doesn't support UBWC stats in trinket and sends
4485                                     // a hardcoded compression factor in nCRStatsTile32
4486                                     compression_ratio = cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32;
4487                                 }
4488                                 break;
4489                             case UBWC_2_0:
4490                             case UBWC_3_0:
4491                                 {
4492                                     unsigned long long int sum = 0, weighted_sum = 0;
4493 
4494                                     DEBUG_PRINT_HIGH("Field 0 : 32 Tile = %d 64 Tile = %d 96 Tile = %d "
4495                                        "128 Tile = %d 160 Tile = %d 192 Tile = %d 256 Tile = %d\n",
4496                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32,
4497                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64,
4498                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96,
4499                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128,
4500                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160,
4501                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192,
4502                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256);
4503 
4504                                     weighted_sum =
4505                                         32  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
4506                                         64  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
4507                                         96  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
4508                                         128 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
4509                                         160 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
4510                                         192 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
4511                                         256 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
4512 
4513                                     sum =
4514                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
4515                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
4516                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
4517                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
4518                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
4519                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
4520                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
4521 
4522                                     compression_ratio = (weighted_sum && sum) ?
4523                                         ((256 * sum) << 16) / weighted_sum : compression_ratio;
4524                                 }
4525                                 break;
4526                             default:
4527                                 break;
4528                             }
4529                         }
4530                     }
4531 
4532                     uint32_t encodePerfMode = 0;
4533                     if (getMetaData(handle, GET_VIDEO_PERF_MODE, &encodePerfMode) == 0) {
4534                         if (encodePerfMode == OMX_TRUE) {
4535                             buf.flags |= V4L2_QCOM_BUF_FLAG_PERF_MODE;
4536                         }
4537                         // Clear SET_VIDEO_PERF_MODE in buffer handle
4538                         setMetaData(handle, SET_VIDEO_PERF_MODE, 0);
4539                     }
4540                     fd = handle->fd;
4541                     plane[0].data_offset = 0;
4542                     plane[0].length = handle->size;
4543                     plane[0].bytesused = handle->size;
4544                     plane[0].reserved[2] = (unsigned long int)compression_ratio;
4545                     char v4l2ColorFormatStr[200];
4546                     get_v4l2_color_format_as_string(v4l2ColorFormatStr, sizeof(v4l2ColorFormatStr), m_sVenc_cfg.inputformat);
4547                     DEBUG_PRINT_LOW("venc_empty_buf: Opaque camera buf: fd = %d "
4548                                 ": filled %d of %d format 0x%lx (%s) CR %d", fd, plane[0].bytesused,
4549                                 plane[0].length, m_sVenc_cfg.inputformat, v4l2ColorFormatStr, plane[0].reserved[2]);
4550                 }
4551             } else {
4552                 // Metadata mode
4553                 // color_format == 1 ==> RGBA to YUV Color-converted buffer
4554                 // Buffers color-converted via C2D have 601-Limited color
4555                 if (!streaming[OUTPUT_PORT]) {
4556                     c2d_enabled = 1;
4557                     DEBUG_PRINT_HIGH("Setting colorspace 601-L for Color-converted buffer");
4558                     venc_set_colorspace(MSM_VIDC_BT601_6_625, 0 /*range-limited*/,
4559                             MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
4560                 }
4561                 plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
4562                 plane[0].data_offset = bufhdr->nOffset;
4563                 plane[0].length = bufhdr->nAllocLen;
4564                 plane[0].bytesused = bufhdr->nFilledLen;
4565                 DEBUG_PRINT_LOW("venc_empty_buf: Opaque non-camera buf: fd = %d filled %d of %d",
4566                         fd, plane[0].bytesused, plane[0].length);
4567             }
4568         } else { // Not Metadata mode
4569             plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
4570             plane[0].data_offset = bufhdr->nOffset;
4571             plane[0].length = bufhdr->nAllocLen;
4572             plane[0].bytesused = bufhdr->nFilledLen;
4573             DEBUG_PRINT_LOW("venc_empty_buf: non-camera buf: fd = %d filled %d of %d",
4574                     fd, plane[0].bytesused, plane[0].length);
4575         }
4576     }
4577 
4578     if (!streaming[OUTPUT_PORT] && (c2d_enabled ||
4579         (m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_TP10_UBWC &&
4580          m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_UBWC))) {
4581         if (bframe_implicitly_enabled) {
4582             DEBUG_PRINT_HIGH("Disabling implicitly enabled B-frames");
4583             intra_period.num_pframes = nPframes_cache;
4584             if (!_venc_set_intra_period(intra_period.num_pframes, 0)) {
4585                 DEBUG_PRINT_ERROR("Failed to set nPframes/nBframes");
4586                 return OMX_ErrorUndefined;
4587             }
4588         }
4589     }
4590 
4591     extra_idx = EXTRADATA_IDX(num_input_planes);
4592 
4593     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4594         OMX_U32 extradata_index;
4595         if (!venc_get_index_from_fd(fd, &extradata_index)) {
4596             return false;
4597         }
4598 
4599         plane[extra_idx].bytesused = 0;
4600         plane[extra_idx].length = input_extradata_info.size;
4601         plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size);
4602 #ifdef USE_ION
4603         plane[extra_idx].reserved[0] = input_extradata_info.ion.data_fd;
4604 #endif
4605         plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index;
4606         plane[extra_idx].reserved[2] = input_extradata_info.size;
4607         plane[extra_idx].data_offset = 0;
4608     } else if (extra_idx >= VIDEO_MAX_PLANES) {
4609         DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
4610         return false;
4611     }
4612 
4613     buf.index = index;
4614     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4615     buf.memory = V4L2_MEMORY_USERPTR;
4616     plane[0].reserved[0] = fd;
4617     plane[0].reserved[1] = 0;
4618     buf.m.planes = plane;
4619     buf.length = num_input_planes;
4620     buf.timestamp.tv_sec = bufhdr->nTimeStamp / 1000000;
4621     buf.timestamp.tv_usec = (bufhdr->nTimeStamp % 1000000);
4622 
4623     if (!handle_input_extradata(buf)) {
4624         DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
4625         return false;
4626     }
4627     VIDC_TRACE_INT_LOW("ETB-TS", bufhdr->nTimeStamp / 1000);
4628 
4629     if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
4630         buf.flags |= V4L2_QCOM_BUF_FLAG_EOS;
4631 
4632     if (!plane[0].bytesused) {
4633         if (buf.flags & V4L2_QCOM_BUF_FLAG_EOS) {
4634             DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
4635             DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
4636             return false;
4637         }
4638         DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
4639         return false;
4640     }
4641 
4642     if (m_debug.in_buffer_log) {
4643         venc_input_log_buffers(bufhdr, fd, plane[0].data_offset, m_sVenc_cfg.inputformat, interlace_flag);
4644     }
4645     if (m_debug.extradata_log && extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4646         DEBUG_PRINT_ERROR("Extradata Addr 0x%llx, Buffer Addr = 0x%x", (OMX_U64)input_extradata_info.uaddr, (unsigned int)plane[extra_idx].m.userptr);
4647         venc_extradata_log_buffers((char *)plane[extra_idx].m.userptr, true);
4648     }
4649     rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4650 
4651     if (rc) {
4652         DEBUG_PRINT_ERROR("Failed to qbuf (etb) to driver");
4653         return false;
4654     }
4655 
4656     etb++;
4657 
4658     if (!streaming[OUTPUT_PORT]) {
4659         enum v4l2_buf_type buf_type;
4660         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4661         int ret;
4662 
4663         if (!downscalar_enabled) {
4664             OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
4665 
4666             if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
4667                 return false;
4668             }
4669 
4670             if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
4671                 return false;
4672             }
4673 
4674             // Tiling in HEIC requires output WxH to be Tile size; difference is permitted
4675             if (!(m_codec == OMX_VIDEO_CodingImageHEIC) &&
4676                 inp_width * inp_height != out_width * out_height) {
4677                 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
4678                 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
4679                 return false;
4680             }
4681         }
4682 
4683         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
4684 
4685         if (ret) {
4686             DEBUG_PRINT_ERROR("Failed to call streamon");
4687             if (errno == EBUSY) {
4688                 hw_overload = true;
4689             }
4690             return false;
4691         } else {
4692             streaming[OUTPUT_PORT] = true;
4693         }
4694     }
4695 
4696     return true;
4697 }
4698 
venc_empty_batch(OMX_BUFFERHEADERTYPE * bufhdr,unsigned index)4699 bool venc_dev::venc_empty_batch(OMX_BUFFERHEADERTYPE *bufhdr, unsigned index)
4700 {
4701     struct v4l2_buffer buf;
4702     struct v4l2_plane plane[VIDEO_MAX_PLANES];
4703     int rc = 0, extra_idx, numBufs;
4704     struct v4l2_control control;
4705     LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
4706     native_handle_t *hnd = NULL;
4707 
4708     if (bufhdr == NULL) {
4709         DEBUG_PRINT_ERROR("ERROR: %s: buffer is NULL", __func__);
4710         return false;
4711     }
4712 
4713     bool status = true;
4714     if (metadatamode) {
4715         plane[0].m.userptr = index;
4716         meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
4717 
4718         if (!color_format) {
4719             if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
4720                 hnd = (native_handle_t*)meta_buf->meta_handle;
4721                 if (!hnd) {
4722                     DEBUG_PRINT_ERROR("venc_empty_batch: invalid handle !");
4723                     return false;
4724                 } else if (MetaBufferUtil::getBatchSize(hnd) > kMaxBuffersInBatch) {
4725                     DEBUG_PRINT_ERROR("venc_empty_batch: Too many buffers (%d) in batch. "
4726                             "Max = %d", MetaBufferUtil::getBatchSize(hnd), kMaxBuffersInBatch);
4727                     status = false;
4728                 }
4729                 DEBUG_PRINT_LOW("venc_empty_batch: Batch of %d bufs", MetaBufferUtil::getBatchSize(hnd));
4730             } else {
4731                 DEBUG_PRINT_ERROR("Batch supported for CameraSource buffers only !");
4732                 status = false;
4733             }
4734         } else {
4735             DEBUG_PRINT_ERROR("Batch supported for Camera buffers only !");
4736             status = false;
4737         }
4738     } else {
4739         DEBUG_PRINT_ERROR("Batch supported for metabuffer mode only !");
4740         status = false;
4741     }
4742 
4743     if (status) {
4744         OMX_TICKS bufTimeStamp = 0ll;
4745         int numBufs = MetaBufferUtil::getBatchSize(hnd);
4746         int v4l2Ids[kMaxBuffersInBatch] = {-1};
4747         for (int i = 0; i < numBufs; ++i) {
4748             v4l2Ids[i] = mBatchInfo.registerBuffer(index);
4749             if (v4l2Ids[i] < 0) {
4750                 DEBUG_PRINT_ERROR("Failed to register buffer");
4751                 // TODO: cleanup the map and purge all slots of current index
4752                 status = false;
4753                 break;
4754             }
4755         }
4756         for (int i = 0; i < numBufs; ++i) {
4757             int v4l2Id = v4l2Ids[i];
4758             int usage = 0;
4759 
4760             memset(&buf, 0, sizeof(buf));
4761             memset(&plane, 0, sizeof(plane));
4762 
4763             DEBUG_PRINT_LOW("Batch: registering %d as %d", index, v4l2Id);
4764             buf.index = (unsigned)v4l2Id;
4765             buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4766             buf.memory = V4L2_MEMORY_USERPTR;
4767             plane[0].reserved[0] = MetaBufferUtil::getFdAt(hnd, i);
4768             plane[0].reserved[1] = 0;
4769             plane[0].data_offset = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_OFFSET);
4770             plane[0].m.userptr = (unsigned long)meta_buf;
4771             plane[0].length = plane[0].bytesused = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_SIZE);
4772             buf.m.planes = plane;
4773             buf.length = num_input_planes;
4774 
4775             usage = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_USAGE);
4776             usage = usage > 0 ? usage : 0;
4777 
4778             extra_idx = EXTRADATA_IDX(num_input_planes);
4779 
4780             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4781                 int fd = plane[0].reserved[0];
4782                 OMX_U32 extradata_index;
4783                 if (!venc_get_index_from_fd(fd, &extradata_index)) {
4784                     return false;
4785                 }
4786 
4787                 plane[extra_idx].bytesused = 0;
4788                 plane[extra_idx].length = input_extradata_info.size;
4789                 plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size);
4790                 plane[extra_idx].reserved[0] = input_extradata_info.ion.data_fd;
4791                 plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index;
4792                 plane[extra_idx].reserved[2] = input_extradata_info.size;
4793                 plane[extra_idx].data_offset = 0;
4794             } else if (extra_idx >= VIDEO_MAX_PLANES) {
4795                 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
4796                 return false;
4797             }
4798 
4799             if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
4800                 buf.flags |= V4L2_QCOM_BUF_FLAG_EOS;
4801 #if NEED_TO_REVISIT
4802             if (i != numBufs - 1) {
4803                 buf.flags |= V4L2_MSM_BUF_FLAG_DEFER;
4804                 DEBUG_PRINT_LOW("for buffer %d (etb #%d) in batch of %d, marking as defer",
4805                         i, etb + 1, numBufs);
4806             }
4807 #endif
4808             // timestamp differences from camera are in nano-seconds
4809             bufTimeStamp = bufhdr->nTimeStamp + MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_TIMESTAMP) / 1000;
4810 
4811             DEBUG_PRINT_LOW(" Q Batch [%d of %d] : buf=%p fd=%d len=%d TS=%lld",
4812                 i, numBufs, bufhdr, plane[0].reserved[0], plane[0].length, bufTimeStamp);
4813             buf.timestamp.tv_sec = bufTimeStamp / 1000000;
4814             buf.timestamp.tv_usec = (bufTimeStamp % 1000000);
4815 
4816             if (!handle_input_extradata(buf)) {
4817                 DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
4818                 return false;
4819             }
4820             VIDC_TRACE_INT_LOW("ETB-TS", bufTimeStamp / 1000);
4821 
4822             rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4823             if (rc) {
4824                 DEBUG_PRINT_ERROR("%s: Failed to qbuf (etb) to driver", __func__);
4825                 return false;
4826             }
4827 
4828             etb++;
4829         }
4830     }
4831 
4832     if (status && !streaming[OUTPUT_PORT]) {
4833         enum v4l2_buf_type buf_type;
4834         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4835         int ret;
4836 
4837         if (!downscalar_enabled) {
4838             OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
4839 
4840             if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
4841                 return false;
4842             }
4843 
4844             if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
4845                 return false;
4846             }
4847 
4848             if (inp_width * inp_height != out_width * out_height) {
4849                 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
4850                 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
4851                 return false;
4852             }
4853         }
4854 
4855         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
4856         if (ret) {
4857             DEBUG_PRINT_ERROR("Failed to call streamon");
4858             if (errno == EBUSY) {
4859                 hw_overload = true;
4860             }
4861             status = false;
4862         } else {
4863             streaming[OUTPUT_PORT] = true;
4864         }
4865     }
4866 
4867     return status;
4868 }
4869 
venc_fill_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)4870 bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd)
4871 {
4872     struct pmem *temp_buffer = NULL;
4873     struct venc_buffer  frameinfo;
4874     struct v4l2_buffer buf;
4875     struct v4l2_plane plane[VIDEO_MAX_PLANES];
4876     int rc = 0;
4877     unsigned int extra_idx;
4878     struct OMX_BUFFERHEADERTYPE *bufhdr;
4879 
4880     if (buffer == NULL)
4881         return false;
4882 
4883     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
4884 
4885     if (pmem_data_buf) {
4886         DEBUG_PRINT_LOW("Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf);
4887         plane[0].m.userptr = (unsigned long)pmem_data_buf;
4888     } else {
4889         DEBUG_PRINT_LOW("Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
4890         plane[0].m.userptr = (unsigned long)bufhdr->pBuffer;
4891     }
4892 
4893     memset(&buf, 0, sizeof(buf));
4894     memset(&plane, 0, sizeof(plane));
4895 
4896     buf.index = index;
4897     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4898     buf.memory = V4L2_MEMORY_USERPTR;
4899     plane[0].length = bufhdr->nAllocLen;
4900     plane[0].bytesused = bufhdr->nFilledLen;
4901     plane[0].reserved[0] = fd;
4902     plane[0].reserved[1] = 0;
4903     plane[0].data_offset = bufhdr->nOffset;
4904     buf.m.planes = plane;
4905     buf.length = num_output_planes;
4906     buf.flags = 0;
4907 
4908     if (venc_handle->is_secure_session()) {
4909         if (venc_handle->allocate_native_handle) {
4910             native_handle_t *handle_t = (native_handle_t *)(bufhdr->pBuffer);
4911             plane[0].length = handle_t->data[3];
4912         } else {
4913             output_metabuffer *meta_buf = (output_metabuffer *)(bufhdr->pBuffer);
4914             native_handle_t *handle_t = meta_buf->nh;
4915             plane[0].length = handle_t->data[3];
4916         }
4917     }
4918 
4919     if (mBatchSize) {
4920         // Should always mark first buffer as DEFER, since 0 % anything is 0, just offset by 1
4921         // This results in the first batch being of size mBatchSize + 1, but thats good because
4922         // we need an extra FTB for the codec specific data.
4923 #if NEED_TO_REVISIT
4924         if (!ftb || ftb % mBatchSize) {
4925             buf.flags |= V4L2_MSM_BUF_FLAG_DEFER;
4926             DEBUG_PRINT_LOW("for ftb buffer %d marking as defer", ftb + 1);
4927         }
4928 #endif
4929     }
4930 
4931     extra_idx = EXTRADATA_IDX(num_output_planes);
4932 
4933     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4934         plane[extra_idx].bytesused = 0;
4935         plane[extra_idx].length = output_extradata_info.buffer_size;
4936         plane[extra_idx].m.userptr = (unsigned long) (output_extradata_info.uaddr + index * output_extradata_info.buffer_size);
4937 #ifdef USE_ION
4938         plane[extra_idx].reserved[0] = output_extradata_info.ion.data_fd;
4939 #endif
4940         plane[extra_idx].reserved[1] = output_extradata_info.buffer_size * index;
4941         plane[extra_idx].data_offset = 0;
4942     } else if (extra_idx >= VIDEO_MAX_PLANES) {
4943         DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx);
4944         return false;
4945     }
4946 
4947     rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4948 
4949     if (rc) {
4950         DEBUG_PRINT_ERROR("Failed to qbuf (ftb) to driver");
4951         return false;
4952     }
4953 
4954     ftb++;
4955     return true;
4956 }
4957 
venc_set_inband_video_header(OMX_BOOL enable)4958 bool venc_dev::venc_set_inband_video_header(OMX_BOOL enable)
4959 {
4960     struct v4l2_control control;
4961 
4962     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
4963         return false;
4964     }
4965 
4966     control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
4967     if(enable) {
4968         control.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME;
4969     } else {
4970         control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
4971     }
4972 
4973     DEBUG_PRINT_HIGH("Set inband sps/pps: %d", enable);
4974     if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
4975         DEBUG_PRINT_ERROR("Request for inband sps/pps failed");
4976         return false;
4977     }
4978     return true;
4979 }
4980 
venc_set_au_delimiter(OMX_BOOL enable)4981 bool venc_dev::venc_set_au_delimiter(OMX_BOOL enable)
4982 {
4983     struct v4l2_control control;
4984 
4985     control.id = V4L2_CID_MPEG_VIDC_VIDEO_AU_DELIMITER;
4986     if(enable) {
4987         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4988     } else {
4989         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
4990     }
4991 
4992     DEBUG_PRINT_HIGH("Set AU delimiters: %d", enable);
4993     if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
4994         DEBUG_PRINT_ERROR("Request for AU delimiters failed");
4995         return false;
4996     }
4997     return true;
4998 }
4999 
venc_get_index_from_fd(OMX_U32 buffer_fd,OMX_U32 * index)5000 bool venc_dev::venc_get_index_from_fd(OMX_U32 buffer_fd, OMX_U32 *index)
5001 {
5002     for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
5003         if (fd_list[i] == buffer_fd) {
5004             DEBUG_PRINT_HIGH("FD : %d found at index = %d", buffer_fd, i);
5005             *index = i;
5006             return true;
5007         }
5008     }
5009 
5010     for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
5011         if (fd_list[i] == 0) {
5012             DEBUG_PRINT_HIGH("FD : %d added at index = %d", buffer_fd, i);
5013             fd_list[i] = buffer_fd;
5014             *index = i;
5015             return true;
5016         }
5017     }
5018     DEBUG_PRINT_ERROR("Couldn't get index from fd : %d",buffer_fd);
5019     return false;
5020 }
5021 
venc_set_extradata(OMX_U32 extra_data,OMX_BOOL enable)5022 bool venc_dev::venc_set_extradata(OMX_U32 extra_data, OMX_BOOL enable)
5023 {
5024     struct v4l2_control control;
5025 
5026     DEBUG_PRINT_HIGH("venc_set_extradata:: %x", (int) extra_data);
5027 
5028     if (enable == OMX_FALSE) {
5029         /* No easy way to turn off extradata to the driver
5030          * at the moment */
5031         return false;
5032     }
5033 
5034     control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
5035     switch (extra_data) {
5036         case OMX_ExtraDataVideoLTRInfo:
5037             control.value = V4L2_MPEG_VIDC_EXTRADATA_LTR;
5038             break;
5039 #ifdef V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP
5040         case OMX_ExtraDataFrameDimension:
5041             control.value = V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP;
5042             break;
5043 #endif
5044         default:
5045             DEBUG_PRINT_ERROR("Unrecognized extradata index 0x%x", (unsigned int)extra_data);
5046             return false;
5047     }
5048 
5049     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
5050         DEBUG_PRINT_ERROR("ERROR: Request for setting extradata (%x) failed %d",
5051                 (unsigned int)extra_data, errno);
5052         return false;
5053     }
5054 
5055     return true;
5056 }
5057 
venc_set_slice_delivery_mode(OMX_U32 enable)5058 bool venc_dev::venc_set_slice_delivery_mode(OMX_U32 enable)
5059 {
5060     struct v4l2_control control;
5061 
5062     if (enable) {
5063         control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE;
5064         control.value = 1;
5065         DEBUG_PRINT_LOW("Set slice_delivery_mode: %d", control.value);
5066 
5067         if (multislice.mslice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5068             if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
5069                 DEBUG_PRINT_ERROR("Request for setting slice delivery mode failed");
5070                 return false;
5071             } else {
5072                 DEBUG_PRINT_LOW("Successfully set Slice delivery mode id: %d, value=%d", control.id, control.value);
5073                 slice_mode.enable = 1;
5074             }
5075         } else {
5076             DEBUG_PRINT_ERROR("Failed to set slice delivery mode, slice_mode [%lu] "
5077                     "is not MB BASED or [%lu] is not H264 codec ", multislice.mslice_mode,
5078                     m_sVenc_cfg.codectype);
5079         }
5080     } else {
5081         DEBUG_PRINT_ERROR("Slice_DELIVERY_MODE not enabled");
5082     }
5083 
5084     return true;
5085 }
5086 
venc_set_colorspace(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer_chars,OMX_U32 matrix_coeffs)5087 bool venc_dev::venc_set_colorspace(OMX_U32 primaries, OMX_U32 range,
5088     OMX_U32 transfer_chars, OMX_U32 matrix_coeffs)
5089 {
5090     int rc;
5091     struct v4l2_control control;
5092 
5093     DEBUG_PRINT_LOW("Setting color space : Primaries = %d, Range = %d, Trans = %d, Matrix = %d",
5094         primaries, range, transfer_chars, matrix_coeffs);
5095 
5096     control.id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE;
5097     control.value = primaries;
5098 
5099     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5100     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5101 
5102     if (rc) {
5103         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE");
5104         return false;
5105     }
5106 
5107     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5108 
5109     color_space.primaries = control.value;
5110 
5111     control.id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE;
5112     control.value = range;
5113 
5114     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5115     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5116 
5117     if (rc) {
5118         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE");
5119         return false;
5120     }
5121 
5122     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5123 
5124     color_space.range = control.value;
5125 
5126     control.id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS;
5127     control.value = transfer_chars;
5128 
5129     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5130     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5131 
5132     if (rc) {
5133         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS");
5134         return false;
5135     }
5136 
5137     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5138 
5139     color_space.transfer_chars = control.value;
5140 
5141     control.id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS;
5142     control.value = matrix_coeffs;
5143 
5144     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5145     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5146 
5147     if (rc) {
5148         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS");
5149         return false;
5150     }
5151 
5152     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5153 
5154     color_space.matrix_coeffs = control.value;
5155 
5156     return true;
5157 }
5158 
venc_set_qp(OMX_U32 i_frame_qp,OMX_U32 p_frame_qp,OMX_U32 b_frame_qp,OMX_U32 enable)5159 bool venc_dev::venc_set_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp, OMX_U32 enable)
5160 {
5161     int rc;
5162     struct v4l2_control control;
5163 
5164     control.id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP;
5165     control.value = i_frame_qp;
5166 
5167     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5168     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5169 
5170     if (rc) {
5171         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5172         return false;
5173     }
5174     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5175     session_qp.iframeqp = control.value;
5176 
5177     control.id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP;
5178     control.value = p_frame_qp;
5179 
5180     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5181     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5182 
5183     if (rc) {
5184         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5185         return false;
5186     }
5187     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5188     session_qp.pframeqp = control.value;
5189 
5190     control.id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP;
5191     control.value = b_frame_qp;
5192     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5193 
5194     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5195     if (rc) {
5196         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5197         return false;
5198     }
5199     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5200     session_qp.bframeqp = control.value;
5201 
5202     control.id = V4L2_CID_MPEG_VIDC_VIDEO_QP_MASK;
5203     control.value = enable;
5204 
5205     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5206     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5207 
5208     if (rc) {
5209         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5210         return false;
5211     }
5212     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5213     session_qp.enableqp = control.value;
5214 
5215     return true;
5216 }
5217 
venc_set_session_qp_range(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE * qp_range)5218 bool venc_dev::venc_set_session_qp_range(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE* qp_range)
5219 {
5220     int rc;
5221     struct v4l2_ext_control ctrl[7];
5222     struct v4l2_ext_controls controls;
5223 
5224     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LAYER_ID;
5225     ctrl[0].value = MSM_VIDC_ALL_LAYER_ID;
5226 
5227     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN;
5228     ctrl[1].value = qp_range->minIQP;
5229 
5230     ctrl[2].id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX;
5231     ctrl[2].value = qp_range->maxIQP;
5232 
5233     ctrl[3].id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN;
5234     ctrl[3].value = qp_range->minPQP;
5235 
5236     ctrl[4].id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX;
5237     ctrl[4].value = qp_range->maxPQP;
5238 
5239     ctrl[5].id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN;
5240     ctrl[5].value = qp_range->minBQP;
5241 
5242     ctrl[6].id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX;
5243     ctrl[6].value = qp_range->maxBQP;
5244 
5245     controls.count = 7;
5246     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
5247     controls.controls = ctrl;
5248 
5249     if(ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
5250         DEBUG_PRINT_ERROR("Failed to set QP range");
5251             return false;
5252     }
5253 
5254     session_ipb_qp_values.min_i_qp = qp_range->minIQP;
5255     session_ipb_qp_values.max_i_qp = qp_range->maxIQP;
5256     session_ipb_qp_values.min_p_qp = qp_range->minPQP;
5257     session_ipb_qp_values.max_p_qp = qp_range->maxPQP;
5258     session_ipb_qp_values.min_b_qp = qp_range->minBQP;
5259     session_ipb_qp_values.max_b_qp = qp_range->maxBQP;
5260     return true;
5261 }
5262 
venc_set_profile(OMX_U32 eProfile)5263 bool venc_dev::venc_set_profile(OMX_U32 eProfile)
5264 {
5265     int rc;
5266     struct v4l2_control control;
5267 
5268     DEBUG_PRINT_LOW("venc_set_profile:: eProfile = %u",
5269             (unsigned int)eProfile);
5270 
5271     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5272         control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
5273     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
5274         //In driver VP8 profile is hardcoded. No need to set anything from here
5275         return true;
5276     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5277         control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
5278     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
5279         control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_PROFILE;
5280     } else {
5281         DEBUG_PRINT_ERROR("Wrong CODEC");
5282         return false;
5283     }
5284 
5285     if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, eProfile, &control.value)) {
5286         DEBUG_PRINT_ERROR("Cannot find v4l2 profile for OMX profile : %d Codec : %lu ",
5287                           eProfile, m_sVenc_cfg.codectype);
5288         return false;
5289     }
5290 
5291     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5292     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5293 
5294     if (rc) {
5295         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5296         return false;
5297     }
5298     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5299 
5300     codec_profile.profile = control.value;
5301 
5302     if (hdr10metadata_supported == true) {
5303         if (venc_set_extradata_hdr10metadata() == false)
5304         {
5305             DEBUG_PRINT_ERROR("Failed to set extradata HDR10PLUS_METADATA");
5306             return false;
5307         }
5308     }
5309     return true;
5310 }
5311 
venc_set_level(OMX_U32 eLevel)5312 bool venc_dev::venc_set_level(OMX_U32 eLevel)
5313 {
5314     int rc;
5315     struct v4l2_control control;
5316 
5317     DEBUG_PRINT_LOW("venc_set_level:: eLevel = %u",
5318                     (unsigned int)eLevel);
5319 
5320     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5321         control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
5322         control.value = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN;
5323     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
5324         control.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
5325         control.value = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
5326     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5327         control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
5328         control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN;
5329     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
5330         control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_LEVEL;
5331         control.value = V4L2_MPEG_VIDC_VIDEO_TME_LEVEL_INTEGER;
5332     } else {
5333         DEBUG_PRINT_ERROR("Wrong CODEC");
5334         return false;
5335     }
5336 
5337     /* If OMX_VIDEO_LEVEL_UNKNOWN then set default values assigned above  */
5338     if (eLevel != OMX_VIDEO_LEVEL_UNKNOWN) {
5339         if (!profile_level_converter::convert_omx_level_to_v4l2(m_sVenc_cfg.codectype, eLevel, &control.value)) {
5340             DEBUG_PRINT_LOW("Warning: Cannot find v4l2 level for OMX level : %d Codec : %lu Setting unknown level",
5341                               eLevel, m_sVenc_cfg.codectype);
5342         }
5343     }
5344 
5345     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5346     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5347     if (rc) {
5348         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5349         return false;
5350     }
5351 
5352     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5353 
5354     profile_level.level = control.value;
5355 
5356     return true;
5357 }
5358 
venc_set_voptiming_cfg(OMX_U32 TimeIncRes)5359 bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes)
5360 {
5361 
5362     struct venc_voptimingcfg vop_timing_cfg;
5363 
5364     DEBUG_PRINT_LOW("venc_set_voptiming_cfg: TimeRes = %u",
5365             (unsigned int)TimeIncRes);
5366 
5367     vop_timing_cfg.voptime_resolution = TimeIncRes;
5368 
5369     voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution;
5370     return true;
5371 }
5372 
venc_reconfigure_intra_refresh_period()5373 bool venc_dev::venc_reconfigure_intra_refresh_period() {
5374 
5375     DEBUG_PRINT_LOW("venc_reconfigure_intra_refresh_period");
5376     if (intra_refresh.framecount) {
5377         OMX_U32 mb_size = 16;
5378         // Firmware will re-calculate mbcount if codec is HEVC.
5379         OMX_U32 num_mbs_per_frame = (ALIGN(m_sVenc_cfg.dvs_height, mb_size)/mb_size) * (ALIGN(m_sVenc_cfg.dvs_width, mb_size)/mb_size);
5380         OMX_U32 num_intra_refresh_mbs = 0;
5381         num_intra_refresh_mbs = ceil(num_mbs_per_frame / intra_refresh.framecount);
5382 
5383         intra_refresh.irmode     = OMX_VIDEO_IntraRefreshRandom;
5384         intra_refresh.mbcount    = num_intra_refresh_mbs;
5385     }
5386 
5387     if (venc_set_intra_refresh() == false) {
5388         DEBUG_PRINT_ERROR("ERROR: Setting Intra refresh failed");
5389         return false;
5390     }
5391 
5392     return true;
5393 }
5394 
venc_reconfigure_intra_period()5395 bool venc_dev::venc_reconfigure_intra_period()
5396 {
5397     int  rc;
5398     bool isValidCodec        = false;
5399     bool isValidResolution   = false;
5400     bool isValidFps          = false;
5401     bool isValidOpRate       = false;
5402     bool isValidLayerCount   = false;
5403     bool enableBframes       = false;
5404     bool isValidLtrSetting   = false;
5405     bool isValidRcMode       = false;
5406     struct v4l2_control control;
5407 
5408     DEBUG_PRINT_LOW("venc_reconfigure_intra_period");
5409 
5410     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 &&
5411         ((codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) ||
5412          (codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_HIGH))) {
5413         isValidCodec = true;
5414     }
5415 
5416     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC &&
5417         ((codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) ||
5418          (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) ||
5419          (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC)) &&
5420          (m_codec != OMX_VIDEO_CodingImageHEIC)) {
5421         isValidCodec = true;
5422     }
5423 
5424     if ((m_sVenc_cfg.input_width <= VENC_BFRAME_MAX_WIDTH && m_sVenc_cfg.input_height <= VENC_BFRAME_MAX_HEIGHT) ||
5425         (m_sVenc_cfg.input_width <= VENC_BFRAME_MAX_HEIGHT && m_sVenc_cfg.input_height <= VENC_BFRAME_MAX_WIDTH)) {
5426         isValidResolution = true;
5427     }
5428 
5429     if ((m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) <= VENC_BFRAME_MAX_FPS) {
5430         isValidFps = true;
5431     }
5432 
5433     if (operating_rate <= VENC_BFRAME_MAX_FPS) {
5434         isValidOpRate = true;
5435     }
5436 
5437     if (temporal_layers_config.nPLayers <= 1) {
5438         isValidLayerCount = true;
5439     }
5440 
5441     if (rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
5442         isValidRcMode = true;
5443     }
5444 
5445     isValidLtrSetting = ltrinfo.enabled ? false : true;
5446 
5447     enableBframes = isValidResolution   &&
5448                     isValidFps          &&
5449                     isValidOpRate       &&
5450                     isValidLayerCount   &&
5451                     isValidLtrSetting   &&
5452                     isValidRcMode       &&
5453                     isValidCodec        &&
5454                     !low_latency_mode   &&
5455                     !client_req_disable_bframe;
5456 
5457     DEBUG_PRINT_LOW("B-frame enablement = %u; Conditions for Resolution = %u, FPS = %u,"
5458                      "Operating rate = %u, Layer condition = %u, LTR = %u, RC = %u"
5459                      "Codec/Profile = %u Client request to disable = %u LowLatency : %u \n isNativeRecorder : %u",
5460                      enableBframes, isValidResolution, isValidFps, isValidOpRate,
5461                      isValidLayerCount, isValidLtrSetting, isValidRcMode, isValidCodec, client_req_disable_bframe,
5462                      low_latency_mode, mIsNativeRecorder);
5463 
5464     if (enableBframes && intra_period.num_bframes == 0 && intra_period.num_pframes > VENC_BFRAME_MAX_COUNT
5465             && mIsNativeRecorder) {
5466         intra_period.num_bframes = VENC_BFRAME_MAX_COUNT;
5467         nPframes_cache = intra_period.num_pframes;
5468         intra_period.num_pframes = intra_period.num_pframes / (1 + intra_period.num_bframes);
5469         bframe_implicitly_enabled = true;
5470     } else if (!enableBframes && intra_period.num_bframes > 0) {
5471         intra_period.num_pframes = intra_period.num_pframes + (intra_period.num_pframes * intra_period.num_bframes);
5472         intra_period.num_bframes = 0;
5473     }
5474 
5475     if (!venc_calibrate_gop())
5476     {
5477         DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
5478         return false;
5479     }
5480 
5481     control.id    = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
5482     control.value = intra_period.num_pframes;
5483 
5484     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5485 
5486     if (rc) {
5487         DEBUG_PRINT_ERROR("Failed to set control V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES");
5488         return false;
5489     }
5490 
5491     DEBUG_PRINT_LOW("Success IOCTL set control for V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES value=%d", control.value);
5492 
5493     control.id    = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
5494     control.value = intra_period.num_bframes;
5495 
5496     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5497 
5498     if (rc) {
5499         DEBUG_PRINT_ERROR("Failed to set control V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES");
5500         return false;
5501     }
5502 
5503     DEBUG_PRINT_LOW("Success IOCTL set control for V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES value=%lu", intra_period.num_bframes);
5504 
5505     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 ||
5506         m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5507         /*
5508          * This call is to ensure default idr period is set if client
5509          * did not set it using index OMX_IndexConfigVideoAVCIntraPeriod.
5510          */
5511         if (venc_set_idr_period(idrperiod.idrperiod) == false) {
5512             DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
5513             return false;
5514         }
5515     }
5516 
5517     return true;
5518 }
5519 
venc_set_grid_enable()5520 bool venc_dev::venc_set_grid_enable()
5521 {
5522     int rc;
5523     struct v4l2_control control;
5524 
5525     DEBUG_PRINT_LOW("venc_set_grid_enable");
5526     control.id = V4L2_CID_MPEG_VIDC_IMG_GRID_ENABLE;
5527     control.value = 1;
5528     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5529 
5530     if (rc) {
5531         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5532         return false;
5533     }
5534 
5535     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5536     mIsGridset = true;
5537     return true;
5538 }
5539 
venc_set_intra_period(OMX_U32 nPFrames,OMX_U32 nBFrames)5540 bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
5541 {
5542     DEBUG_PRINT_LOW("venc_set_intra_period: nPFrames = %u, nBFrames: %u", (unsigned int)nPFrames, (unsigned int)nBFrames);
5543 
5544     if ((streaming[OUTPUT_PORT] || streaming[CAPTURE_PORT]) && (intra_period.num_bframes != nBFrames)) {
5545         DEBUG_PRINT_ERROR("Invalid settings, Cannot change B frame count dynamically");
5546         return false;
5547     }
5548     return _venc_set_intra_period(nPFrames, nBFrames);
5549 }
5550 
_venc_set_intra_period(OMX_U32 nPFrames,OMX_U32 nBFrames)5551 bool venc_dev::_venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
5552 {
5553     int rc;
5554     struct v4l2_control control;
5555     char property_value[PROPERTY_VALUE_MAX] = {0};
5556 
5557     if ((m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
5558         m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) ||
5559         m_codec == OMX_VIDEO_CodingImageHEIC) {
5560         nBFrames = 0;
5561     }
5562 
5563     if ((codec_profile.profile != V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) &&
5564         (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN)             &&
5565         (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN)        &&
5566         (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10)      &&
5567         (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC) &&
5568         (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) {
5569         nBFrames = 0;
5570     }
5571 
5572     if (temporal_layers_config.nPLayers > 1 && nBFrames) {
5573         DEBUG_PRINT_ERROR("Invalid settings, bframes cannot be enabled with HP. Resetting it to 0");
5574         nBFrames = 0;
5575     }
5576 
5577     if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES, nBFrames) || (nBFrames > VENC_BFRAME_MAX_COUNT)) {
5578         DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u bframes", nBFrames);
5579         return false;
5580     }
5581 
5582     intra_period.num_pframes = nPFrames;
5583     intra_period.num_bframes = nBFrames;
5584 
5585     if (!venc_calibrate_gop())
5586     {
5587         DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
5588         return false;
5589     }
5590 
5591     control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
5592     control.value = intra_period.num_pframes;
5593     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5594 
5595     if (rc) {
5596         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5597         return false;
5598     }
5599     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5600 
5601     control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
5602     control.value = intra_period.num_bframes;
5603     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5604 
5605     if (rc) {
5606         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5607         return false;
5608     }
5609     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5610 
5611     return true;
5612 }
5613 
venc_set_idr_period(OMX_U32 nIDRPeriod)5614 bool venc_dev::venc_set_idr_period(OMX_U32 nIDRPeriod)
5615 {
5616     int rc = 0;
5617     struct v4l2_control control;
5618 
5619     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
5620         m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
5621         // don't return error if idr period is zero even though invalid codectype
5622         if (!nIDRPeriod)
5623             return true;
5624 
5625         DEBUG_PRINT_ERROR("venc_set_idr_period: invalid codedtype (%#lx)",
5626             m_sVenc_cfg.codectype);
5627         return false;
5628     }
5629 
5630     DEBUG_PRINT_LOW("venc_set_idr_period: nIDRPeriod: %u", (unsigned int)nIDRPeriod);
5631     control.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
5632     control.value = nIDRPeriod;
5633     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5634     if (rc) {
5635         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5636         return false;
5637     }
5638     idrperiod.idrperiod = nIDRPeriod;
5639 
5640     return true;
5641 }
5642 
venc_set_entropy_config(OMX_BOOL enable,OMX_U32 i_cabac_level)5643 bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level)
5644 {
5645     int rc = 0;
5646     struct v4l2_control control;
5647 
5648     DEBUG_PRINT_LOW("venc_set_entropy_config: CABAC = %u level: %u", enable, (unsigned int)i_cabac_level);
5649 
5650     if (enable && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) &&
5651             (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE)) {
5652         control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
5653     } else if (!enable) {
5654         control.value =  V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
5655     } else {
5656         DEBUG_PRINT_ERROR("Invalid Entropy mode for Baseline Profile");
5657         return false;
5658     }
5659 
5660     control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5661 
5662     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5663     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5664 
5665     if (rc) {
5666         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5667         return false;
5668     }
5669 
5670     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5671     entropy.longentropysel = control.value;
5672 
5673     return true;
5674 }
5675 
venc_set_multislice_cfg(OMX_U32 nSlicemode,OMX_U32 nSlicesize)5676 bool venc_dev::venc_set_multislice_cfg(OMX_U32 nSlicemode, OMX_U32 nSlicesize)
5677 {
5678     int rc;
5679     int slice_id = 0;
5680     struct v4l2_control control;
5681     bool status = true;
5682 
5683     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263 || nSlicesize == 0) {
5684         nSlicemode = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
5685         nSlicesize = 0;
5686     }
5687 
5688     if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
5689         if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, nSlicesize)) {
5690             DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
5691             return false;
5692         }
5693         slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
5694 
5695     } else if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
5696         if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, nSlicesize)) {
5697             DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
5698             return false;
5699         }
5700         slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
5701 
5702     } else if (nSlicesize) {
5703         DEBUG_PRINT_ERROR("Invalid settings, unexpected slicemode = %u and slice size = %u", nSlicemode, nSlicesize);
5704         return false;
5705     }
5706 
5707     control.id    = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
5708     control.value = nSlicemode;
5709 
5710     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5711     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5712 
5713     if (rc) {
5714         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5715         return false;
5716     }
5717 
5718     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5719 
5720     if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) {
5721         return status;
5722     }
5723 
5724     control.id    = slice_id;
5725     control.value = nSlicesize;
5726 
5727     DEBUG_PRINT_LOW("Calling SLICE_MB IOCTL set control for id=%d, val=%d", control.id, control.value);
5728     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5729 
5730     if (rc) {
5731         DEBUG_PRINT_ERROR("Failed to set control");
5732         return false;
5733     }
5734 
5735     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5736 
5737     multislice.mslice_mode = nSlicemode;
5738     multislice.mslice_size = nSlicesize;
5739 
5740     return status;
5741 }
5742 
venc_set_intra_refresh()5743 bool venc_dev::venc_set_intra_refresh()
5744 {
5745     bool status = true;
5746     int rc;
5747     struct v4l2_control control_mode;
5748     control_mode.id   = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE_CYCLIC;
5749     control_mode.value = 0;
5750     // There is no disabled mode.  Disabled mode is indicated by a 0 count.
5751     if (intra_refresh.irmode == OMX_VIDEO_IntraRefreshMax || intra_refresh.mbcount == 0) {
5752         return status;
5753     } else if (intra_refresh.irmode == OMX_VIDEO_IntraRefreshCyclic ||
5754                intra_refresh.irmode == OMX_VIDEO_IntraRefreshRandom) {
5755         control_mode.value  = intra_refresh.mbcount;
5756     } else {
5757         DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:"
5758                 " mb mode:%lu", intra_refresh.irmode);
5759         return false;
5760     }
5761 
5762     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%u, val=%d", control_mode.id, control_mode.value);
5763     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_mode);
5764 
5765     if (rc) {
5766         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control_mode.id, control_mode.value);
5767         return false;
5768     }
5769 
5770     return status;
5771 }
5772 
venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE * error_resilience)5773 bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience)
5774 {
5775     bool status = true;
5776     struct venc_headerextension hec_cfg;
5777     struct venc_multiclicecfg multislice_cfg;
5778     int rc;
5779     OMX_U32 resynchMarkerSpacingBytes = 0;
5780     struct v4l2_control control;
5781 
5782     memset(&control, 0, sizeof(control));
5783 
5784     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) {
5785         if (error_resilience->bEnableHEC) {
5786             hec_cfg.header_extension = 1;
5787         } else {
5788             hec_cfg.header_extension = 0;
5789         }
5790 
5791         hec.header_extension = error_resilience->bEnableHEC;
5792     }
5793 
5794     if (error_resilience->bEnableRVLC) {
5795         DEBUG_PRINT_ERROR("RVLC is not Supported");
5796         return false;
5797     }
5798 
5799     if (( m_sVenc_cfg.codectype != V4L2_PIX_FMT_H263) &&
5800             (error_resilience->bEnableDataPartitioning)) {
5801         DEBUG_PRINT_ERROR("DataPartioning are not Supported for MPEG4/H264");
5802         return false;
5803     }
5804 
5805     if (error_resilience->nResynchMarkerSpacing) {
5806         resynchMarkerSpacingBytes = error_resilience->nResynchMarkerSpacing;
5807         resynchMarkerSpacingBytes = ALIGN(resynchMarkerSpacingBytes, 8) >> 3;
5808     }
5809 
5810     status = venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, resynchMarkerSpacingBytes);
5811 
5812     return status;
5813 }
5814 
venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)5815 bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)
5816 {
5817     int rc;
5818     struct v4l2_control control;
5819     control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE;
5820     control.value=0;
5821 
5822     if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable) {
5823         control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED;
5824     } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisable) {
5825         control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED;
5826     } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary) {
5827         control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY;
5828     }
5829 
5830     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5831     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5832 
5833     if (rc) {
5834         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5835         return false;
5836     }
5837 
5838     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5839 
5840     dbkfilter.db_mode=control.value;
5841 
5842     control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA;
5843     control.value=0;
5844 
5845     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5846     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5847 
5848     if (rc) {
5849         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5850         return false;
5851     }
5852 
5853     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5854     control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA;
5855     control.value=0;
5856     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5857     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5858 
5859     if (rc) {
5860         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5861         return false;
5862     }
5863 
5864     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5865 
5866 
5867     dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0;
5868     return true;
5869 }
5870 
venc_set_target_bitrate(OMX_U32 nTargetBitrate)5871 bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate)
5872 {
5873     DEBUG_PRINT_LOW("venc_set_target_bitrate: bitrate = %u",
5874             (unsigned int)nTargetBitrate);
5875     struct v4l2_control control;
5876     int rc = 0;
5877 
5878     if (vqzip_sei_info.enabled) {
5879         DEBUG_PRINT_HIGH("For VQZIP 1.0, Bitrate setting is not supported");
5880         return true;
5881     }
5882 
5883     if (rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
5884         control.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY;
5885     else
5886         control.id = V4L2_CID_MPEG_VIDEO_BITRATE;
5887     control.value = nTargetBitrate;
5888 
5889     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5890     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5891     if (rc) {
5892         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5893         return false;
5894     }
5895 
5896     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5897 
5898     if (control.id == V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY)
5899         return true;
5900 
5901     m_sVenc_cfg.targetbitrate = control.value;
5902     bitrate.target_bitrate = control.value;
5903 
5904     // Configure layer-wise bitrate if temporal layers are enabled and layer-wise distribution
5905     //  has been specified
5906     if (temporal_layers_config.bIsBitrateRatioValid && temporal_layers_config.nPLayers) {
5907         OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0},
5908                 numLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers;
5909 
5910         DEBUG_PRINT_LOW("TemporalLayer: configuring layerwise bitrate");
5911         for (OMX_U32 i = 0; i < numLayers; ++i) {
5912             layerBitrates[i] =
5913                     (temporal_layers_config.nTemporalLayerBitrateFraction[i] * bitrate.target_bitrate) / 100;
5914             DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)",
5915                     i, temporal_layers_config.nTemporalLayerBitrateFraction[i],
5916                     layerBitrates[i], bitrate.target_bitrate);
5917         }
5918         if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) {
5919             return false;
5920         }
5921     }
5922 
5923     return true;
5924 }
5925 
venc_set_encode_framerate(OMX_U32 encode_framerate)5926 bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate)
5927 {
5928     struct v4l2_streamparm parm;
5929     int rc = 0;
5930     struct venc_framerate frame_rate_cfg;
5931     Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator);
5932     parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5933     parm.parm.output.timeperframe.numerator = frame_rate_cfg.fps_denominator;
5934     parm.parm.output.timeperframe.denominator = frame_rate_cfg.fps_numerator;
5935 
5936     if (vqzip_sei_info.enabled) {
5937         DEBUG_PRINT_HIGH("For VQZIP 1.0, Framerate setting is not supported");
5938         return true;
5939     }
5940 
5941 
5942     if (frame_rate_cfg.fps_numerator > 0)
5943         rc = ioctl(m_nDriver_fd, VIDIOC_S_PARM, &parm);
5944 
5945     if (rc) {
5946         DEBUG_PRINT_ERROR("ERROR: Request for setting framerate failed");
5947         return false;
5948     }
5949 
5950     m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator;
5951     m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator;
5952 
5953     return true;
5954 }
5955 
venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat)5956 unsigned long venc_dev::venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat)
5957 {
5958     unsigned long codectype = V4L2_PIX_FMT_H264;
5959 
5960     switch ((int)eCompressionFormat) {
5961     case OMX_VIDEO_CodingAVC:
5962         codectype = V4L2_PIX_FMT_H264;
5963         break;
5964     case OMX_VIDEO_CodingVP8:
5965         codectype = V4L2_PIX_FMT_VP8;
5966         break;
5967     case OMX_VIDEO_CodingVP9:
5968         codectype = V4L2_PIX_FMT_VP9;
5969         break;
5970     case OMX_VIDEO_CodingHEVC:
5971     case OMX_VIDEO_CodingImageHEIC:
5972         codectype = V4L2_PIX_FMT_HEVC;
5973         break;
5974     case QOMX_VIDEO_CodingTME:
5975         codectype = V4L2_PIX_FMT_TME;
5976         break;
5977     default:
5978         DEBUG_PRINT_ERROR("Unsupported eCompressionFormat %#x", eCompressionFormat);
5979         codectype = V4L2_PIX_FMT_H264;
5980         break;
5981     }
5982 
5983     return codectype;
5984 }
5985 
venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)5986 unsigned long venc_dev::venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)
5987 {
5988     unsigned long format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
5989 
5990     switch ((int)eColorFormat) {
5991     case OMX_COLOR_FormatYUV420SemiPlanar:
5992     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
5993         format = V4L2_PIX_FMT_NV12;
5994         break;
5995     case QOMX_COLOR_FormatYVU420SemiPlanar:
5996         format = V4L2_PIX_FMT_NV21;
5997         break;
5998     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
5999         format = V4L2_PIX_FMT_NV12_UBWC;
6000         break;
6001     case QOMX_COLOR_Format32bitRGBA8888:
6002         format = V4L2_PIX_FMT_RGB32;
6003         break;
6004     case QOMX_COLOR_Format32bitRGBA8888Compressed:
6005         format = V4L2_PIX_FMT_RGBA8888_UBWC;
6006         break;
6007     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
6008         format = V4L2_PIX_FMT_NV12_TP10_UBWC;
6009         break;
6010     case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
6011         format = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
6012         break;
6013     default:
6014         DEBUG_PRINT_INFO("WARN: Unsupported eColorFormat %#x", eColorFormat);
6015         format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
6016         break;
6017     }
6018 
6019     if (m_codec == OMX_VIDEO_CodingImageHEIC)
6020         format = V4L2_PIX_FMT_NV12_512;
6021 
6022     return format;
6023 }
6024 
venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)6025 bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)
6026 {
6027     struct v4l2_format fmt;
6028     int color_space = 0;
6029     DEBUG_PRINT_LOW("venc_set_color_format: color_format = %u ", color_format);
6030 
6031     switch ((int)color_format) {
6032         case OMX_COLOR_FormatYUV420SemiPlanar:
6033         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
6034             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
6035             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6036             break;
6037         case QOMX_COLOR_FormatYVU420SemiPlanar:
6038             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
6039             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6040             break;
6041         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
6042             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
6043             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6044             break;
6045         case QOMX_COLOR_Format32bitRGBA8888:
6046             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGB32;
6047             break;
6048         case QOMX_COLOR_Format32bitRGBA8888Compressed:
6049             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGBA8888_UBWC;
6050             break;
6051         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
6052             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_TP10_UBWC;
6053             break;
6054         case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
6055             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
6056             break;
6057         default:
6058             DEBUG_PRINT_HIGH("WARNING: Unsupported Color format [%d]", color_format);
6059             m_sVenc_cfg.inputformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
6060             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6061             DEBUG_PRINT_HIGH("Default color format NV12 UBWC is set");
6062             break;
6063     }
6064 
6065     if (m_codec == OMX_VIDEO_CodingImageHEIC)
6066         m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
6067 
6068     memset(&fmt, 0, sizeof(fmt));
6069     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6070     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
6071     fmt.fmt.pix_mp.colorspace = color_space;
6072     fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
6073     fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
6074 
6075     if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
6076         DEBUG_PRINT_ERROR("Failed setting color format %x", color_format);
6077         return false;
6078     }
6079 
6080     return true;
6081 }
6082 
venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)6083 bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)
6084 {
6085     DEBUG_PRINT_LOW("venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh);
6086 
6087     if (intra_vop_refresh == OMX_TRUE) {
6088         struct v4l2_control control;
6089         int rc;
6090         control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME;
6091         control.value = 1;
6092 
6093         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6094         if (rc) {
6095             DEBUG_PRINT_ERROR("Failed to set Intra Frame Request control");
6096             return false;
6097         }
6098         DEBUG_PRINT_HIGH("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6099     } else {
6100         DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect");
6101     }
6102 
6103     return true;
6104 }
6105 
venc_calibrate_gop()6106 bool venc_dev::venc_calibrate_gop()
6107 {
6108     int ratio, sub_gop_size, gop_size, nPframes, nBframes, nLayers;
6109     int num_sub_gops_in_a_gop;
6110     nPframes = intra_period.num_pframes;
6111     nBframes = intra_period.num_bframes;
6112     nLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers;
6113 
6114     if (!nPframes && nLayers) {
6115         DEBUG_PRINT_ERROR("nPframes should be non-zero when nLayers are present\n");
6116         return false;
6117     }
6118 
6119     if (nBframes && !nPframes) {
6120         DEBUG_PRINT_ERROR("nPframes should be non-zero when nBframes is non-zero\n");
6121         return false;
6122     }
6123 
6124     if (nLayers > 1) { /*Multi-layer encoding*/
6125         sub_gop_size = 1 << (nLayers - 1);
6126         /* Actual GOP definition is nPframes + nBframes + 1 but for the sake of
6127          * below calculations we are ignoring +1 . Ignoring +1 in below
6128          * calculations is not a mistake but intentional.
6129          */
6130         gop_size = MAX(sub_gop_size, ROUND(nPframes + (nPframes * nBframes), sub_gop_size));
6131         num_sub_gops_in_a_gop = gop_size/sub_gop_size;
6132         if (nBframes) { /*Hier-B case*/
6133         /*
6134             * Frame Type--> I  B  B  B  P  B  B  B  P  I  B  B  P ...
6135             * Layer -->     0  2  1  2  0  2  1  2  0  0  2  1  2 ...
6136             * nPframes = 2, nBframes = 3, nLayers = 3
6137             *
6138             * Intention is to keep the intraperiod as close as possible to what is desired
6139             * by the client while adjusting nPframes and nBframes to meet other constraints.
6140             * eg1: Input by client: nPframes =  9, nBframes = 14, nLayers = 2
6141             *    Output of this fn: nPframes = 12, nBframes = 12, nLayers = 2
6142             *
6143             * eg2: Input by client: nPframes = 9, nBframes = 4, nLayers = 2
6144             *    Output of this fn: nPframes = 7, nBframes = 7, nLayers = 2
6145             */
6146             nPframes = num_sub_gops_in_a_gop;
6147             nBframes = sub_gop_size - 1;
6148         } else { /*Hier-P case*/
6149             /*
6150             * Frame Type--> I  P  P  P  P  P  P  P  I  P  P  P  P ...
6151             * Layer-->      0  2  1  2  0  2  1  2  0  2  1  2  0 ...
6152             * nPframes =  7, nBframes = 0, nLayers = 3
6153             *
6154             * Intention is to keep the intraperiod as close as possible to what is desired
6155             * by the client while adjusting nPframes and nBframes to meet other constraints.
6156             * eg1: Input by client: nPframes = 9, nBframes = 0, nLayers = 3
6157             *    Output of this fn: nPframes = 7, nBframes = 0, nLayers = 3
6158             *
6159             * eg2: Input by client: nPframes = 10, nBframes = 0, nLayers = 3
6160             *     Output of this fn:nPframes = 12, nBframes = 0, nLayers = 3
6161             */
6162             nPframes = gop_size - 1;
6163         }
6164     } else { /*Single-layer encoding*/
6165             /*
6166             * No special handling needed for single layer
6167             */
6168        DEBUG_PRINT_LOW("Clip num of P and B frames, nPframes: %d nBframes: %d",
6169                        nPframes,nBframes);
6170        if ((unsigned int)nPframes > VENC_INFINITE_GOP) {
6171           nPframes =  VENC_INFINITE_GOP;
6172        }
6173        if ((unsigned int)nBframes > VENC_INFINITE_GOP) {
6174           nBframes =  VENC_INFINITE_GOP;
6175        }
6176     }
6177 
6178     DEBUG_PRINT_LOW("P/B Frames changed from: %ld/%ld to %d/%d",
6179         intra_period.num_pframes, intra_period.num_bframes, nPframes, nBframes);
6180     intra_period.num_pframes = nPframes;
6181     intra_period.num_bframes = nBframes;
6182     return true;
6183 }
6184 
venc_set_bitrate_type(OMX_U32 type)6185 bool venc_dev::venc_set_bitrate_type(OMX_U32 type)
6186 {
6187     struct v4l2_control control;
6188     int rc = 0;
6189     control.id = V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE;
6190     control.value = type;
6191     DEBUG_PRINT_LOW("Set Bitrate type to %s for %d \n", bitrate_type_string(type), type);
6192     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6193     if (rc) {
6194         DEBUG_PRINT_ERROR("Request to set Bitrate type to %s failed",
6195             bitrate_type_string(type));
6196         return false;
6197     }
6198     return true;
6199 }
6200 
venc_set_layer_bitrates(OMX_U32 * layerBitrate,OMX_U32 numLayers)6201 bool venc_dev::venc_set_layer_bitrates(OMX_U32 *layerBitrate, OMX_U32 numLayers)
6202 {
6203     DEBUG_PRINT_LOW("venc_set_layer_bitrates");
6204     struct v4l2_ext_control ctrl[2];
6205     struct v4l2_ext_controls controls;
6206     int rc = 0;
6207     OMX_U32 i;
6208 
6209     if (!venc_set_bitrate_type(V4L2_MPEG_MSM_VIDC_ENABLE)) {
6210         DEBUG_PRINT_ERROR("Failed to set layerwise bitrate type %d", rc);
6211         return false;
6212     }
6213 
6214     for (OMX_U32 i = 0; i < numLayers && i < OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS; ++i) {
6215         if (!layerBitrate[i]) {
6216             DEBUG_PRINT_ERROR("Invalid bitrate settings for layer %d", i);
6217             return false;
6218         } else {
6219             ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LAYER_ID;
6220             ctrl[0].value = i;
6221             ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE;
6222             ctrl[1].value = layerBitrate[i];
6223 
6224             controls.count = 2;
6225             controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6226             controls.controls = ctrl;
6227 
6228             rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6229             if (rc) {
6230                 DEBUG_PRINT_ERROR("Failed to set layerwise bitrate %d", rc);
6231                 return false;
6232             }
6233 
6234             DEBUG_PRINT_LOW("Layerwise bitrate configured successfully for layer : %u bitrate : %u ",i, layerBitrate[i]);
6235         }
6236     }
6237     return true;
6238 }
6239 
6240 
venc_set_ltrmode(OMX_U32 enable,OMX_U32 count)6241 bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
6242 {
6243     DEBUG_PRINT_LOW("venc_set_ltrmode: enable = %u", (unsigned int)enable);
6244     struct v4l2_ext_control ctrl[2];
6245     struct v4l2_ext_controls controls;
6246     int rc;
6247 
6248     if (enable && temporal_layers_config.hier_mode == HIER_P_HYBRID) {
6249         DEBUG_PRINT_ERROR("Invalid settings, LTR is being enabled with HybridHP");
6250         return false;
6251     }
6252 
6253     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT;
6254     if (enable && count > 0)
6255         ctrl[0].value = count;
6256     else if (enable)
6257         ctrl[0].value = 1;
6258     else
6259         ctrl[0].value = 0;
6260 
6261     controls.count = 1;
6262     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6263     controls.controls = ctrl;
6264 
6265     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d id=%x, val=%d",
6266                     controls.controls[0].id, controls.controls[0].value,
6267                     controls.controls[1].id, controls.controls[1].value);
6268 
6269     rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6270     if (rc) {
6271         DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc);
6272         return false;
6273     }
6274     ltrinfo.enabled = enable;
6275     ltrinfo.count = count;
6276 
6277     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d id=%x, val=%d",
6278                     controls.controls[0].id, controls.controls[0].value,
6279                     controls.controls[1].id, controls.controls[1].value);
6280     return true;
6281 }
6282 
venc_set_useltr(OMX_U32 frameIdx)6283 bool venc_dev::venc_set_useltr(OMX_U32 frameIdx)
6284 {
6285     DEBUG_PRINT_LOW("venc_use_goldenframe");
6286     int rc = true;
6287     struct v4l2_control control;
6288 
6289     control.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME;
6290     control.value = frameIdx;
6291 
6292     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6293     if (rc) {
6294         DEBUG_PRINT_ERROR("Failed to set use_ltr %d", rc);
6295         return false;
6296     }
6297 
6298     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6299                     control.id, control.value);
6300     return true;
6301 }
6302 
venc_set_markltr(OMX_U32 frameIdx)6303 bool venc_dev::venc_set_markltr(OMX_U32 frameIdx)
6304 {
6305     DEBUG_PRINT_LOW("venc_set_goldenframe");
6306     int rc = true;
6307     struct v4l2_control control;
6308 
6309     control.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME;
6310     control.value = frameIdx;
6311 
6312     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6313     if (rc) {
6314         DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc);
6315         return false;
6316     }
6317 
6318     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6319                     control.id, control.value);
6320     return true;
6321 }
6322 
venc_set_mirror(OMX_U32 mirror)6323 bool venc_dev::venc_set_mirror(OMX_U32 mirror)
6324 {
6325     DEBUG_PRINT_LOW("venc_set_mirror");
6326     int rc = true;
6327     struct v4l2_control control;
6328 
6329     control.id = V4L2_CID_MPEG_VIDC_VIDEO_FLIP;
6330     control.value = mirror;
6331 
6332     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6333     if (rc) {
6334         DEBUG_PRINT_ERROR("Failed to set mirror %d", rc);
6335         return false;
6336     }
6337 
6338     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6339                     control.id, control.value);
6340     return true;
6341 }
6342 
venc_set_vpe_rotation(OMX_S32 rotation_angle)6343 bool venc_dev::venc_set_vpe_rotation(OMX_S32 rotation_angle)
6344 {
6345     DEBUG_PRINT_LOW("venc_set_vpe_rotation: rotation angle = %d", (int)rotation_angle);
6346     struct v4l2_control control;
6347     int rc;
6348     struct v4l2_format fmt;
6349     struct v4l2_requestbuffers bufreq;
6350 
6351     if ((OMX_S32)m_rotation.rotation == rotation_angle) {
6352         DEBUG_PRINT_HIGH("venc_set_vpe_rotation: rotation (%d) not changed", rotation_angle);
6353         return true;
6354     }
6355 
6356     control.id = V4L2_CID_ROTATE;
6357     control.value = rotation_angle;
6358 
6359     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6360     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6361     if (rc) {
6362         DEBUG_PRINT_HIGH("Failed to set VPE Rotation control");
6363         return false;
6364     }
6365     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6366 
6367     /* successfully set rotation_angle, save it */
6368     m_rotation.rotation = rotation_angle;
6369 
6370     return true;
6371 }
6372 
venc_set_searchrange()6373 bool venc_dev::venc_set_searchrange()
6374 {
6375     DEBUG_PRINT_LOW("venc_set_searchrange");
6376     struct v4l2_control control;
6377     struct v4l2_ext_control ctrl[6];
6378     struct v4l2_ext_controls controls;
6379     int rc;
6380 
6381     if ((m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) ||
6382                (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8)) {
6383         ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE;
6384         ctrl[0].value = 16;
6385         ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_Y_RANGE;
6386         ctrl[1].value = 4;
6387         ctrl[2].id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_X_RANGE;
6388         ctrl[2].value = 16;
6389         ctrl[3].id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_Y_RANGE;
6390         ctrl[3].value = 4;
6391         ctrl[4].id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_X_RANGE;
6392         ctrl[4].value = 12;
6393         ctrl[5].id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_Y_RANGE;
6394         ctrl[5].value = 4;
6395     } else {
6396         DEBUG_PRINT_ERROR("Invalid codec type");
6397         return false;
6398     }
6399     controls.count = 6;
6400     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6401     controls.controls = ctrl;
6402 
6403     DEBUG_PRINT_LOW(" Calling IOCTL set control for"
6404         "id=%x, val=%d id=%x, val=%d"
6405         "id=%x, val=%d id=%x, val=%d"
6406         "id=%x, val=%d id=%x, val=%d",
6407         controls.controls[0].id, controls.controls[0].value,
6408         controls.controls[1].id, controls.controls[1].value,
6409         controls.controls[2].id, controls.controls[2].value,
6410         controls.controls[3].id, controls.controls[3].value,
6411         controls.controls[4].id, controls.controls[4].value,
6412         controls.controls[5].id, controls.controls[5].value);
6413 
6414     rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6415     if (rc) {
6416         DEBUG_PRINT_ERROR("Failed to set search range %d", rc);
6417         return false;
6418     }
6419     return true;
6420 }
6421 
venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)6422 bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
6423 {
6424     bool status = true;
6425     struct v4l2_control control;
6426     int rc = 0;
6427     control.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
6428 
6429     int temp = eControlRate;
6430     switch ((OMX_U32)eControlRate) {
6431         case OMX_Video_ControlRateDisable:
6432             control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF;
6433             break;
6434         case OMX_Video_ControlRateVariableSkipFrames:
6435             (supported_rc_modes & RC_VBR_VFR) ?
6436                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR :
6437                 status = false;
6438             break;
6439         case OMX_Video_ControlRateVariable:
6440             (supported_rc_modes & RC_VBR_CFR) ?
6441                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR :
6442                 status = false;
6443             break;
6444         case OMX_Video_ControlRateConstantSkipFrames:
6445             (supported_rc_modes & RC_CBR_VFR) ?
6446                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR :
6447                 status = false;
6448             break;
6449         case OMX_Video_ControlRateConstant:
6450             (supported_rc_modes & RC_CBR_CFR) ?
6451                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
6452                 status = false;
6453             break;
6454         case QOMX_Video_ControlRateMaxBitrate:
6455             (supported_rc_modes & RC_MBR_CFR) ?
6456                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR:
6457                 status = false;
6458             break;
6459         case QOMX_Video_ControlRateMaxBitrateSkipFrames:
6460             (supported_rc_modes & RC_MBR_VFR) ?
6461                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR:
6462                 status = false;
6463             break;
6464         case OMX_Video_ControlRateConstantQuality:
6465             (supported_rc_modes & RC_CQ) ?
6466                 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CQ:
6467                 status = false;
6468             break;
6469         default:
6470             status = false;
6471             break;
6472     }
6473 
6474     if (status) {
6475 
6476         DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6477         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6478 
6479         if (rc) {
6480             DEBUG_PRINT_ERROR("Failed to set control");
6481             return false;
6482         }
6483 
6484         DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6485 
6486         rate_ctrl.rcmode = control.value;
6487     }
6488 
6489     {
6490         DEBUG_PRINT_LOW("Set bitrate savings %d", mBitrateSavingsEnable);
6491         control.id = V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS;
6492         control.value = mBitrateSavingsEnable;
6493         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6494         if (rc) {
6495             DEBUG_PRINT_HIGH("Non-Fatal: Request to set bitrate savings failed");
6496         }
6497     }
6498 
6499 #ifdef _VQZIP_
6500     if (eControlRate == OMX_Video_ControlRateVariable && (supported_rc_modes & RC_VBR_CFR)
6501             && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
6502         /* Enable VQZIP SEI by default for camcorder RC modes */
6503 
6504         control.id = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI;
6505         control.value = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI_ENABLE;
6506         DEBUG_PRINT_HIGH("Set VQZIP SEI:");
6507         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
6508             DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed");
6509         }
6510     }
6511 #endif
6512 
6513     return status;
6514 }
6515 
venc_set_aspectratio(void * nSar)6516 bool venc_dev::venc_set_aspectratio(void *nSar)
6517 {
6518     int rc;
6519     struct v4l2_control control;
6520     struct v4l2_ext_control ctrl[2];
6521     struct v4l2_ext_controls controls;
6522     QOMX_EXTNINDEX_VIDEO_VENC_SAR *sar;
6523 
6524     sar = (QOMX_EXTNINDEX_VIDEO_VENC_SAR *) nSar;
6525 
6526     ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_WIDTH;
6527     ctrl[0].value = sar->nSARWidth;
6528     ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_HEIGHT;
6529     ctrl[1].value = sar->nSARHeight;
6530 
6531     controls.count = 2;
6532     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6533     controls.controls = ctrl;
6534 
6535     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x val=%d, id=%x val=%d",
6536                     controls.controls[0].id, controls.controls[0].value,
6537                     controls.controls[1].id, controls.controls[1].value);
6538 
6539     rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6540     if (rc) {
6541         DEBUG_PRINT_ERROR("Failed to set SAR %d", rc);
6542         return false;
6543     }
6544 
6545     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x val=%d, id=%x val=%d",
6546                     controls.controls[0].id, controls.controls[0].value,
6547                     controls.controls[1].id, controls.controls[1].value);
6548     return true;
6549 }
6550 
venc_set_lowlatency_mode(OMX_BOOL enable)6551 bool venc_dev::venc_set_lowlatency_mode(OMX_BOOL enable)
6552 {
6553     int rc = 0;
6554     struct v4l2_control control;
6555 
6556     control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
6557     if (enable)
6558         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6559     else
6560         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6561 
6562     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6563     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6564     if (rc) {
6565         DEBUG_PRINT_ERROR("Failed to set lowlatency control");
6566         return false;
6567     }
6568     low_latency_mode = enable;
6569     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6570 
6571     return true;
6572 }
6573 
venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type)6574 bool venc_dev::venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type)
6575 {
6576     struct v4l2_control control;
6577     control.id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE;
6578 
6579     switch (type) {
6580         case QOMX_IFRAMESIZE_DEFAULT:
6581             control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
6582             break;
6583         case QOMX_IFRAMESIZE_MEDIUM:
6584             control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM;
6585             break;
6586         case QOMX_IFRAMESIZE_HUGE:
6587             control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE;
6588             break;
6589         case QOMX_IFRAMESIZE_UNLIMITED:
6590             control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED;
6591             break;
6592         default:
6593             DEBUG_PRINT_INFO("Unknown Iframe Size found setting it to default");
6594             control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
6595     }
6596 
6597     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6598         DEBUG_PRINT_ERROR("Failed to set iframe size hint");
6599         return false;
6600     }
6601 
6602     return true;
6603 }
6604 
venc_set_baselayerid(OMX_U32 baseid)6605 bool venc_dev::venc_set_baselayerid(OMX_U32 baseid)
6606 {
6607     struct v4l2_control control;
6608     if (temporal_layers_config.hier_mode == HIER_P) {
6609         control.id = V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID;
6610         control.value = baseid;
6611         DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
6612         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6613             DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
6614             return false;
6615         }
6616         return true;
6617     } else {
6618         DEBUG_PRINT_ERROR("Invalid mode set for V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID: %d",
6619                 temporal_layers_config.hier_mode);
6620         return false;
6621     }
6622 }
6623 
venc_set_vui_timing_info(OMX_BOOL enable)6624 bool venc_dev::venc_set_vui_timing_info(OMX_BOOL enable)
6625 {
6626     struct v4l2_control control;
6627     int rc = 0;
6628     control.id = V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO;
6629 
6630     if (enable)
6631         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6632     else
6633         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6634 
6635     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6636     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6637     if (rc) {
6638         DEBUG_PRINT_ERROR("Failed to set VUI timing info control");
6639         return false;
6640     }
6641     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6642     return true;
6643 }
6644 
venc_set_peak_bitrate(OMX_U32 nPeakBitrate)6645 bool venc_dev::venc_set_peak_bitrate(OMX_U32 nPeakBitrate)
6646 {
6647     struct v4l2_control control;
6648     int rc = 0;
6649     control.id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
6650     control.value = nPeakBitrate;
6651 
6652     DEBUG_PRINT_LOW("venc_set_peak_bitrate: bitrate = %u", (unsigned int)nPeakBitrate);
6653 
6654     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6655     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6656 
6657     if (rc) {
6658         DEBUG_PRINT_ERROR("Failed to set peak bitrate control");
6659         return false;
6660     }
6661 
6662     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6663 
6664     return true;
6665 }
6666 
venc_set_vpx_error_resilience(OMX_BOOL enable)6667 bool venc_dev::venc_set_vpx_error_resilience(OMX_BOOL enable)
6668 {
6669     struct v4l2_control control;
6670     int rc = 0;
6671     control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE;
6672 
6673     if (enable)
6674         control.value = 1;
6675     else
6676         control.value = 0;
6677 
6678     DEBUG_PRINT_LOW("venc_set_vpx_error_resilience: %d", control.value);
6679 
6680     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6681 
6682     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6683     if (rc) {
6684         DEBUG_PRINT_ERROR("Failed to set VPX Error Resilience");
6685         return false;
6686     }
6687     vpx_err_resilience.enable = 1;
6688     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6689     return true;
6690 }
6691 
venc_set_priority(OMX_U32 priority)6692 bool venc_dev::venc_set_priority(OMX_U32 priority) {
6693     struct v4l2_control control;
6694 
6695     DEBUG_PRINT_LOW("venc_set_priority: %s", priority ? "NonRealTime" : "RealTime");
6696     control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
6697     if (priority == 0)
6698         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6699     else
6700         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6701 
6702     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6703         DEBUG_PRINT_ERROR("Failed to set V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_%s",
6704                 priority == 0 ? "ENABLE" : "DISABLE");
6705         return false;
6706     }
6707     return true;
6708 }
6709 
venc_set_operatingrate(OMX_U32 rate)6710 bool venc_dev::venc_set_operatingrate(OMX_U32 rate) {
6711     struct v4l2_control control;
6712 
6713     control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
6714     control.value = rate;
6715 
6716     DEBUG_PRINT_LOW("venc_set_operating_rate: %u fps", rate >> 16);
6717     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%u", control.id, control.value);
6718 
6719     if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6720         hw_overload = errno == EBUSY;
6721         DEBUG_PRINT_ERROR("Failed to set operating rate %d fps (%s)",
6722                 rate >> 16, hw_overload ? "HW overload" : strerror(errno));
6723         return false;
6724     }
6725     if (rate == QOMX_VIDEO_HIGH_PERF_OPERATING_MODE) {
6726         DEBUG_PRINT_LOW("Turbo mode requested");
6727         client_req_turbo_mode = true;
6728     } else {
6729         operating_rate = rate >> 16;
6730         client_req_turbo_mode = false;
6731         DEBUG_PRINT_LOW("Operating Rate Set = %d fps",  rate >> 16);
6732     }
6733 
6734     return true;
6735 }
6736 
venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO * roiInfo)6737 bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo)
6738 {
6739     struct roidata roi;
6740 
6741     if (!m_roi_enabled) {
6742         DEBUG_PRINT_ERROR("ROI info not enabled");
6743         return false;
6744     }
6745 
6746     if (!roiInfo) {
6747         DEBUG_PRINT_ERROR("No ROI info present");
6748         return false;
6749     }
6750     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
6751     m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
6752         DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
6753         return false;
6754     }
6755 
6756     memset(&roi, 0, sizeof(struct roidata));
6757 
6758     roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
6759     roi.info.nTimeStamp = roiInfo->nTimeStamp;
6760     memcpy(roi.info.pRoiMBInfo, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
6761 
6762     roi.dirty = true;
6763 
6764     pthread_mutex_lock(&m_roilock);
6765     DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
6766     m_roilist.push_back(roi);
6767     pthread_mutex_unlock(&m_roilock);
6768 
6769     return true;
6770 }
6771 
venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO * blurInfo)6772 bool venc_dev::venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO *blurInfo)
6773 {
6774     struct v4l2_ext_control ctrl[2];
6775     struct v4l2_ext_controls controls;
6776 
6777     int blur_width = 0, blur_height = 0;
6778 
6779     switch (blurInfo->nBlurInfo) {
6780         case 0:
6781             blur_width = 0;
6782             blur_height = 0;
6783             [[fallthrough]];
6784         case 1:
6785             blur_width = 1;
6786             blur_height = 1;
6787             [[fallthrough]];
6788         default:
6789             blur_width = blurInfo->nBlurInfo >> 16;
6790             blur_height = blurInfo->nBlurInfo & 0xFFFF;
6791             DEBUG_PRINT_LOW("Custom blur resolution %ux%u", blur_width, blur_height);
6792             break;
6793     }
6794 
6795     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH;
6796     ctrl[0].value = blur_width;
6797 
6798     ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT;
6799     ctrl[1].value = blur_height;
6800 
6801     controls.count = 2;
6802     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6803     controls.controls = ctrl;
6804 
6805     if(ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
6806         DEBUG_PRINT_ERROR("Failed to set blur resoltion");
6807         return false;
6808     }
6809     DEBUG_PRINT_LOW("Blur resolution set = %u x %u", blur_width, blur_height);
6810     return true;
6811 
6812 }
6813 
venc_h264_transform_8x8(OMX_BOOL enable)6814 bool venc_dev::venc_h264_transform_8x8(OMX_BOOL enable)
6815 {
6816     struct v4l2_control control;
6817 
6818     control.id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM;
6819     if (enable)
6820         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6821     else
6822         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6823 
6824     DEBUG_PRINT_LOW("Set h264_transform_8x8 mode: %d", control.value);
6825     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6826         DEBUG_PRINT_ERROR("set control: H264 transform 8x8 failed");
6827         return false;
6828     }
6829 
6830     return true;
6831 }
6832 
venc_get_temporal_layer_caps(OMX_U32 * nMaxLayers,OMX_U32 * nMaxBLayers,OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE * eSupportedPattern)6833 bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers,
6834         OMX_U32 *nMaxBLayers, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE *eSupportedPattern) {
6835     struct v4l2_queryctrl query_ctrl;
6836 
6837     if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC || m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
6838         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
6839     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
6840         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
6841     } else {
6842         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone;
6843     }
6844 
6845     if(venc_check_for_hybrid_hp(*eSupportedPattern)) {
6846         query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6847     } else {
6848         query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
6849     }
6850 
6851     DEBUG_PRINT_LOW("TemporalLayer: Querying P layer caps");
6852     if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
6853         DEBUG_PRINT_ERROR("TemporalLayer: Query control P layer caps failed");
6854         return false;
6855     }
6856 
6857     //Return +1 as driver works on num max enhancement layers and OMX on num layers
6858     *nMaxLayers = query_ctrl.maximum + 1;
6859 
6860     query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS;
6861     DEBUG_PRINT_LOW("TemporalLayer: Querying B layer caps");
6862     if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
6863         DEBUG_PRINT_ERROR("TemporalLayer: Query control B layer caps faile");
6864         return false;
6865     }
6866 
6867     *nMaxBLayers = query_ctrl.maximum;
6868     return true;
6869 }
6870 
venc_check_for_hybrid_hp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern)6871 bool venc_dev::venc_check_for_hybrid_hp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern) {
6872     //Hybrid HP is only for H264 and VBR CFR
6873     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264) {
6874         DEBUG_PRINT_LOW("TemporalLayer: Hybrid HierP is not supported for non H264");
6875         return false;
6876     }
6877 
6878     if (ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
6879         DEBUG_PRINT_LOW("TemporalLayer: The pattern must be Android for Hybrid HP");
6880         return false;
6881     }
6882     if (rate_ctrl.rcmode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
6883         DEBUG_PRINT_LOW("TemporalLayer: RC must be VBR CFR for HybridHP");
6884         return false;
6885     }
6886     return true;
6887 }
6888 
venc_check_for_hierp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern)6889 bool venc_dev::venc_check_for_hierp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern) {
6890 
6891     if (ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
6892         DEBUG_PRINT_LOW("TemporalLayer: Incorrect Pattern for H264/HEVC");
6893         return false;
6894     }
6895 
6896     return true;
6897 }
6898 
venc_find_hier_type(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6899 int venc_dev::venc_find_hier_type(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6900 
6901     enum hier_type hier;
6902 
6903     if (venc_check_for_hybrid_hp(temporal_settings.ePattern)) {
6904         hier = HIER_P_HYBRID;
6905     } else if (venc_check_for_hierp(temporal_settings.ePattern)) {
6906         hier = HIER_P;
6907     } else {
6908         hier = HIER_NONE;
6909     }
6910 
6911     if (!venc_validate_temporal_extn(temporal_settings)) {
6912         hier = HIER_NONE;
6913     }
6914 
6915     return hier;
6916 }
6917 
venc_set_hp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6918 OMX_ERRORTYPE venc_dev::venc_set_hp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6919 
6920     struct v4l2_control control;
6921     OMX_U32 maxLayerCount = 0;
6922 
6923     control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS;
6924     control.value = temporal_settings.nLayerCountMax - 1;
6925 
6926     DEBUG_PRINT_LOW("TemporalLayer: Setting HP with max layers: %u num layers : %u",
6927                     temporal_settings.nLayerCountMax - 1,
6928                     temporal_settings.nPLayerCountActual - 1);
6929 
6930     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6931         DEBUG_PRINT_ERROR("TemporalLayer: Failed to set max HP layers to %u", control.value);
6932         return OMX_ErrorUnsupportedSetting;
6933     }
6934 
6935     maxLayerCount = control.value + 1;
6936 
6937     control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
6938     control.value = temporal_settings.nPLayerCountActual - 1;
6939     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6940         DEBUG_PRINT_ERROR("TemporalLayer: Failed to set hybrid hierp/hierp NumLayers : %u", control.value);
6941         return OMX_ErrorUnsupportedSetting;
6942     }
6943 
6944     temporal_layers_config.ePattern     = temporal_settings.ePattern;
6945     temporal_layers_config.hier_mode    = HIER_P;
6946     temporal_layers_config.nPLayers     = control.value + 1;
6947     temporal_layers_config.nMaxLayers   = maxLayerCount;
6948     temporal_layers_config.nBLayers     = 0;
6949     temporal_layers_config.nMaxBLayers  = 0;
6950 
6951     return OMX_ErrorNone;
6952 }
6953 
venc_set_hhp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6954 OMX_ERRORTYPE venc_dev::venc_set_hhp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6955 
6956     struct v4l2_control control;
6957 
6958     control.id      = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6959     control.value   = temporal_settings.nPLayerCountActual - 1;
6960 
6961     DEBUG_PRINT_LOW("TemporalLayer: Setting HybridHP with num layers : %u", control.value);
6962 
6963     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6964         DEBUG_PRINT_ERROR("TemporalLayer: Failed to set hybrid HP. Try HierP");
6965         return OMX_ErrorUnsupportedSetting;
6966     }
6967 
6968     temporal_layers_config.ePattern     = temporal_settings.ePattern;
6969     temporal_layers_config.hier_mode    = HIER_P_HYBRID;
6970     temporal_layers_config.nPLayers     = control.value + 1;
6971     temporal_layers_config.nMaxLayers   = control.value + 1;
6972     temporal_layers_config.nBLayers     = 0;
6973     temporal_layers_config.nMaxBLayers  = 0;
6974     if (ltrinfo.enabled) {
6975         if (!venc_set_ltrmode(0, 0)) {
6976             DEBUG_PRINT_ERROR("TemporalLayer: Failed to disable LTR when HybridHP is enabled");
6977             return OMX_ErrorUndefined;
6978         }
6979     }
6980     return OMX_ErrorNone;
6981 }
venc_disable_hhp()6982 OMX_ERRORTYPE venc_dev::venc_disable_hhp() {
6983 
6984     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264) {
6985         return OMX_ErrorNone;
6986     }
6987 
6988     struct v4l2_control control;
6989 
6990     control.id      = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6991     control.value   = 0;
6992 
6993     if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control)) {
6994         DEBUG_PRINT_ERROR("TemporalLayer: Failed to get hybrid HP");
6995         return OMX_ErrorUnsupportedSetting;
6996     }
6997 
6998     if (control.value != 0) {
6999         control.value = 0;
7000 
7001         DEBUG_PRINT_LOW("TemporalLayer: Disabling HybridHP");
7002 
7003         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7004             DEBUG_PRINT_ERROR("TemporalLayer: Failed to disable hybrid HP");
7005             return OMX_ErrorUnsupportedSetting;
7006         }
7007     }
7008 
7009     return OMX_ErrorNone;
7010 }
7011 
venc_disable_hp()7012 OMX_ERRORTYPE venc_dev::venc_disable_hp() {
7013 
7014     struct v4l2_control control;
7015 
7016     control.id      = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS;
7017     control.value   = 0;
7018 
7019     DEBUG_PRINT_LOW("TemporalLayer: Disabling HP");
7020 
7021     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7022         DEBUG_PRINT_ERROR("TemporalLayer: Failed to reset max HP layers to %u", control.value);
7023         return OMX_ErrorUnsupportedSetting;
7024     }
7025 
7026     control.id      = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
7027     control.value   = 0;
7028 
7029     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7030         DEBUG_PRINT_ERROR("TemporalLayer: Failed to reset HP layers to %u", control.value);
7031         return OMX_ErrorUnsupportedSetting;
7032     }
7033 
7034     return OMX_ErrorNone;
7035 }
7036 
venc_set_bitrate_ratio(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7037 OMX_ERRORTYPE venc_dev::venc_set_bitrate_ratio(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7038 
7039     OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0};
7040     OMX_U32 numLayers = temporal_settings.nPLayerCountActual + temporal_settings.nBLayerCountActual;
7041 
7042     if (temporal_settings.bBitrateRatiosSpecified == OMX_FALSE) {
7043         DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio not specified. Will use cumulative");
7044 
7045         if (!venc_set_bitrate_type(V4L2_MPEG_MSM_VIDC_DISABLE)) {
7046             return OMX_ErrorUnsupportedSetting;
7047         }
7048         return OMX_ErrorNone;
7049     }
7050 
7051     DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio specified");
7052 
7053     for (OMX_U32 i = 0; i < numLayers; ++i) {
7054         OMX_U32 previousLayersAccumulatedBitrateRatio = (i == 0) ? 0 : temporal_settings.nBitrateRatios[i-1];
7055         OMX_U32 currentLayerBitrateRatio = temporal_settings.nBitrateRatios[i] - previousLayersAccumulatedBitrateRatio;
7056         if (previousLayersAccumulatedBitrateRatio > temporal_settings.nBitrateRatios[i]) {
7057             DEBUG_PRINT_ERROR("TemporalLayer: invalid bitrate ratio for layer %d.. Will fallback to cumulative", i);
7058             return OMX_ErrorBadParameter;
7059         } else {
7060             layerBitrates[i] = (currentLayerBitrateRatio * bitrate.target_bitrate) / 100;
7061             temporal_layers_config.nTemporalLayerBitrateRatio[i] = temporal_settings.nBitrateRatios[i];
7062             temporal_layers_config.nTemporalLayerBitrateFraction[i] = currentLayerBitrateRatio;
7063             DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)",
7064                     i, currentLayerBitrateRatio, layerBitrates[i], bitrate.target_bitrate);
7065         }
7066     }
7067 
7068     temporal_layers_config.bIsBitrateRatioValid = OMX_TRUE;
7069 
7070     // Setting layerwise bitrate makes sense only if target bitrate is configured, else defer until later
7071     if (bitrate.target_bitrate > 0) {
7072         if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) {
7073             DEBUG_PRINT_ERROR("TemporalLayer: Failed to set layer bitrate");
7074             return OMX_ErrorUnsupportedSetting;
7075         }
7076     } else {
7077         DEBUG_PRINT_HIGH("TemporalLayer: Defer setting layerwise bitrate since target bitrate is not yet set");
7078     }
7079 
7080     return OMX_ErrorNone;
7081 }
7082 
venc_validate_temporal_settings()7083 bool venc_dev::venc_validate_temporal_settings() {
7084 
7085     if (intra_period.num_bframes > 0 || intra_period.num_pframes == 0) {
7086         DEBUG_PRINT_HIGH("TemporalLayer: Invalid P-frame/B-frame settings for Hier layers");
7087         return false;
7088     }
7089     return true;
7090 }
7091 
venc_validate_temporal_extn(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7092 bool venc_dev::venc_validate_temporal_extn(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7093 
7094     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 && m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC &&
7095         temporal_settings.nPLayerCountActual > 1) {
7096         DEBUG_PRINT_LOW("TemporalLayer: Layer encoding supported for H264 & HEVC");
7097         return false;
7098     }
7099 
7100     if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS, temporal_settings.nBLayerCountMax - 1) &&
7101         (temporal_settings.nBLayerCountMax > 0)) {
7102         DEBUG_PRINT_INFO("WARN: TemporalLayer: Invalid settings, hardware doesn't"
7103                     " support %u HB layers", temporal_settings.nBLayerCountMax);
7104         return false;
7105     }
7106 
7107     if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS, temporal_settings.nLayerCountMax - 1) &&
7108         !venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE, temporal_settings.nLayerCountMax - 1)) {
7109         DEBUG_PRINT_INFO("WARN: TemporalLayer: Invalid settings, hardware doesn't"
7110                     " support %u temporal layers", temporal_settings.nLayerCountMax);
7111         return false;
7112     }
7113 
7114     if (temporal_settings.nPLayerCountActual > temporal_settings.nLayerCountMax) {
7115         DEBUG_PRINT_HIGH("TemporalLayer: Invalid num of max layers");
7116         return false;
7117     }
7118 
7119     if (temporal_settings.ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
7120         DEBUG_PRINT_LOW("TemporalLayer: The pattern must be Android for Hybrid HP");
7121         return false;
7122     }
7123 
7124     if ((streaming[CAPTURE_PORT] == true || streaming[OUTPUT_PORT] == true) && (temporal_layers_config.hier_mode == HIER_P_HYBRID)) {
7125         DEBUG_PRINT_HIGH("TemporalLayer: Cannot change Hybrid HP settings during streaming");
7126         return false;
7127     }
7128 
7129     if ((streaming[CAPTURE_PORT] == true || streaming[OUTPUT_PORT] == true) &&
7130         ((temporal_settings.nPLayerCountActual > temporal_layers_config.nMaxLayers) ||
7131          (temporal_settings.nLayerCountMax    != temporal_layers_config.nMaxLayers))) {
7132         DEBUG_PRINT_HIGH("TemporalLayer: Invalid value for Layer count during streaming");
7133         return false;
7134     }
7135 
7136     return true;
7137 }
7138 
venc_set_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7139 OMX_ERRORTYPE venc_dev::venc_set_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7140 
7141     if (venc_find_hier_type(temporal_settings) == HIER_P) {
7142 
7143         if (venc_disable_hhp() != OMX_ErrorNone) {
7144             return OMX_ErrorUnsupportedSetting;
7145         }
7146         if (venc_set_hp(temporal_settings) != OMX_ErrorNone) {
7147             return OMX_ErrorUnsupportedSetting;
7148         }
7149         if (venc_set_bitrate_ratio(temporal_settings) != OMX_ErrorNone) {
7150             return OMX_ErrorUnsupportedSetting;
7151         }
7152 
7153 
7154     } else if (venc_find_hier_type(temporal_settings) == HIER_P_HYBRID) {
7155 
7156         if (venc_disable_hp() != OMX_ErrorNone) {
7157             return OMX_ErrorUnsupportedSetting;
7158         }
7159         if (venc_set_hhp(temporal_settings) != OMX_ErrorNone) {
7160             return OMX_ErrorUnsupportedSetting;
7161         }
7162         if (venc_set_bitrate_ratio(temporal_settings) != OMX_ErrorNone) {
7163             return OMX_ErrorUnsupportedSetting;
7164         }
7165 
7166     } else {
7167 
7168         if (venc_disable_hhp() != OMX_ErrorNone) {
7169             return OMX_ErrorUnsupportedSetting;
7170         }
7171         if (venc_disable_hp() != OMX_ErrorNone) {
7172             return OMX_ErrorUnsupportedSetting;
7173         }
7174         memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
7175     }
7176 
7177     return OMX_ErrorNone;
7178 }
7179 
venc_copy_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporalParams)7180 void venc_dev::venc_copy_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporalParams) {
7181 
7182     OMX_U32 previousLayersAccumulatedBitrateRatio = 0;
7183     memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
7184 
7185     temporal_layers_config.nMaxLayers           = temporalParams.nLayerCountMax ;
7186     temporal_layers_config.nMaxBLayers          = temporalParams.nBLayerCountMax ;
7187     temporal_layers_config.ePattern             = temporalParams.ePattern;
7188     temporal_layers_config.nPLayers             = temporalParams.nPLayerCountActual;
7189     temporal_layers_config.nBLayers             = temporalParams.nBLayerCountActual;
7190     temporal_layers_config.bIsBitrateRatioValid = temporalParams.bBitrateRatiosSpecified;
7191 
7192     if (temporalParams.bBitrateRatiosSpecified == OMX_TRUE) {
7193         for (OMX_U32 i = 0; i < temporalParams.nPLayerCountActual + temporalParams.nBLayerCountActual; ++i) {
7194             previousLayersAccumulatedBitrateRatio = (i == 0) ? 0 : temporalParams.nBitrateRatios[i-1];
7195             temporal_layers_config.nTemporalLayerBitrateRatio[i] = temporalParams.nBitrateRatios[i];
7196             temporal_layers_config.nTemporalLayerBitrateFraction[i] =
7197                     temporalParams.nBitrateRatios[i] - previousLayersAccumulatedBitrateRatio;
7198         }
7199     }
7200 
7201     if (temporalParams.nPLayerCountActual <= 1 ||
7202         temporalParams.ePattern == OMX_VIDEO_AndroidTemporalLayeringPatternNone) {
7203         client_req_disable_temporal_layers = true;
7204     } else {
7205         client_req_disable_temporal_layers = false;
7206     }
7207 }
7208 
venc_reconfigure_temporal_settings()7209 bool venc_dev::venc_reconfigure_temporal_settings() {
7210 
7211     OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE temporalParams;
7212     memset(&temporalParams, 0x0, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE));
7213 
7214     DEBUG_PRINT_HIGH("TemporalLayer: Reconfigure temporal layer settings");
7215 
7216     if (!venc_validate_temporal_settings()) {
7217         DEBUG_PRINT_HIGH("TemporalLayer: Cannot enable temporal layers");
7218         return true;
7219     }
7220 
7221     temporalParams.nLayerCountMax           = temporal_layers_config.nMaxLayers;
7222     temporalParams.nBLayerCountMax          = temporal_layers_config.nMaxBLayers;
7223     temporalParams.ePattern                 = temporal_layers_config.ePattern;
7224     temporalParams.nPLayerCountActual       = temporal_layers_config.nPLayers;
7225     temporalParams.nBLayerCountActual       = temporal_layers_config.nBLayers;
7226     temporalParams.bBitrateRatiosSpecified  = temporal_layers_config.bIsBitrateRatioValid;
7227 
7228     if (temporal_layers_config.bIsBitrateRatioValid == OMX_TRUE) {
7229         for (OMX_U32 i = 0; i < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers; ++i) {
7230             temporalParams.nBitrateRatios[i] =
7231                     temporal_layers_config.nTemporalLayerBitrateRatio[i];
7232         }
7233     }
7234 
7235     if (venc_set_temporal_settings(temporalParams) != OMX_ErrorNone) {
7236         DEBUG_PRINT_ERROR("TemporalLayer: Failed to set temporal settings");
7237         return false;
7238     }
7239 
7240     return true;
7241 }
7242 
venc_reconfigure_ltrmode()7243 bool venc_dev::venc_reconfigure_ltrmode() {
7244 
7245     if ((ltrinfo.enabled == true) && (temporal_layers_config.hier_mode == HIER_P_HYBRID) &&
7246             (temporal_layers_config.nPLayers > 1)) {
7247 
7248         if (!venc_set_ltrmode(0, 0)) {
7249             DEBUG_PRINT_ERROR("Failed to disable LTR when HybridHP is enabled");
7250             return false;
7251         }
7252     }
7253     return true;
7254 }
7255 
venc_get_hevc_profile(OMX_U32 * profile)7256 bool venc_dev::venc_get_hevc_profile(OMX_U32* profile)
7257 {
7258     if (profile == nullptr) return false;
7259 
7260     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
7261         if(profile_level_converter::convert_v4l2_profile_to_omx(V4L2_PIX_FMT_HEVC, codec_profile.profile, (int*)profile)) {
7262             return true;
7263         } else return false;
7264     } else return false;
7265 }
7266 
venc_get_consumer_usage(OMX_U32 * usage)7267 void venc_dev::venc_get_consumer_usage(OMX_U32* usage) {
7268 
7269     OMX_U32 eProfile = 0;
7270     bool hevc = venc_get_hevc_profile(&eProfile);
7271 
7272     /* Initialize to zero & update as per required color format */
7273     *usage = 0;
7274 
7275     if (hevc && eProfile == (OMX_U32)OMX_VIDEO_HEVCProfileMain10HDR10) {
7276         DEBUG_PRINT_INFO("Setting 10-bit consumer usage bits");
7277         *usage |= GRALLOC_USAGE_PRIVATE_10BIT_VIDEO;
7278         if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_10_BIT) {
7279             *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7280             DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 10-bit linear color requested");
7281         }
7282     } else if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_8_BIT) {
7283         *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7284         DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 8-bit linear color requested");
7285     }
7286 
7287     if (m_codec == OMX_VIDEO_CodingImageHEIC) {
7288         DEBUG_PRINT_INFO("Clear UBWC and set HEIF consumer usage bit");
7289         *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7290         *usage |= GRALLOC_USAGE_PRIVATE_HEIF_VIDEO;
7291     }
7292 
7293     if (!strncmp(m_platform_name, "trinket", 7)) {
7294         if (m_sVenc_cfg.input_width < 640 || m_sVenc_cfg.input_height < 480) {
7295             *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7296         }
7297     }
7298 
7299     DEBUG_PRINT_INFO("venc_get_consumer_usage 0x%x", *usage);
7300 }
7301 
venc_get_profile_level(OMX_U32 * eProfile,OMX_U32 * eLevel)7302 bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
7303 {
7304     bool status = true;
7305 
7306     if (eProfile == NULL || eLevel == NULL) {
7307         return false;
7308     }
7309 
7310     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
7311         switch (codec_profile.profile) {
7312             case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
7313                 *eProfile = OMX_VIDEO_AVCProfileBaseline;
7314                 break;
7315             case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
7316                 *eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
7317                 break;
7318             case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
7319                 *eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
7320                 break;
7321             case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
7322                 *eProfile = OMX_VIDEO_AVCProfileMain;
7323                 break;
7324             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
7325                 *eProfile = OMX_VIDEO_AVCProfileHigh;
7326                 break;
7327             case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
7328                 *eProfile = OMX_VIDEO_AVCProfileExtended;
7329                 break;
7330             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
7331                 *eProfile = OMX_VIDEO_AVCProfileHigh10;
7332                 break;
7333             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
7334                 *eProfile = OMX_VIDEO_AVCProfileHigh422;
7335                 break;
7336             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
7337                 *eProfile = OMX_VIDEO_AVCProfileHigh444;
7338                 break;
7339             default:
7340                 *eProfile = OMX_VIDEO_AVCProfileMax;
7341                 status = false;
7342                 break;
7343         }
7344 
7345         if (!status) {
7346             return status;
7347         }
7348 
7349         switch (profile_level.level) {
7350             case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
7351                 *eLevel = OMX_VIDEO_AVCLevel1;
7352                 break;
7353             case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
7354                 *eLevel = OMX_VIDEO_AVCLevel1b;
7355                 break;
7356             case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
7357                 *eLevel = OMX_VIDEO_AVCLevel11;
7358                 break;
7359             case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
7360                 *eLevel = OMX_VIDEO_AVCLevel12;
7361                 break;
7362             case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
7363                 *eLevel = OMX_VIDEO_AVCLevel13;
7364                 break;
7365             case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
7366                 *eLevel = OMX_VIDEO_AVCLevel2;
7367                 break;
7368             case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
7369                 *eLevel = OMX_VIDEO_AVCLevel21;
7370                 break;
7371             case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
7372                 *eLevel = OMX_VIDEO_AVCLevel22;
7373                 break;
7374             case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
7375                 *eLevel = OMX_VIDEO_AVCLevel3;
7376                 break;
7377             case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
7378                 *eLevel = OMX_VIDEO_AVCLevel31;
7379                 break;
7380             case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
7381                 *eLevel = OMX_VIDEO_AVCLevel32;
7382                 break;
7383             case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
7384                 *eLevel = OMX_VIDEO_AVCLevel4;
7385                 break;
7386             case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
7387                 *eLevel = OMX_VIDEO_AVCLevel41;
7388                 break;
7389             case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
7390                 *eLevel = OMX_VIDEO_AVCLevel42;
7391                 break;
7392             case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
7393                 *eLevel = OMX_VIDEO_AVCLevel5;
7394                 break;
7395             case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
7396                 *eLevel = OMX_VIDEO_AVCLevel51;
7397                 break;
7398             case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
7399                 *eLevel = OMX_VIDEO_AVCLevel52;
7400                 break;
7401             default :
7402                 *eLevel = OMX_VIDEO_AVCLevelMax;
7403                 status = false;
7404                 break;
7405         }
7406     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
7407         switch (codec_profile.profile) {
7408             case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
7409                 *eProfile = OMX_VIDEO_VP8ProfileMain;
7410                 break;
7411             default:
7412                 *eProfile = OMX_VIDEO_VP8ProfileMax;
7413                 status = false;
7414                 break;
7415         }
7416         if (!status) {
7417             return status;
7418         }
7419 
7420         switch (profile_level.level) {
7421             case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
7422                 *eLevel = OMX_VIDEO_VP8Level_Version0;
7423                 break;
7424             case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
7425                 *eLevel = OMX_VIDEO_VP8Level_Version1;
7426                 break;
7427             default:
7428                 *eLevel = OMX_VIDEO_VP8LevelMax;
7429                 status = false;
7430                 break;
7431         }
7432     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
7433         switch (codec_profile.profile) {
7434             case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
7435                 *eProfile = OMX_VIDEO_HEVCProfileMain;
7436                 break;
7437             case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
7438                 *eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
7439                 break;
7440             case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC:
7441                 *eProfile = OMX_VIDEO_HEVCProfileMainStill;
7442                 break;
7443             default:
7444                 *eProfile = OMX_VIDEO_HEVCProfileMax;
7445                 status = false;
7446                 break;
7447         }
7448         if (!status) {
7449             return status;
7450         }
7451 
7452         switch (profile_level.level) {
7453             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
7454                 *eLevel = OMX_VIDEO_HEVCMainTierLevel1;
7455                 break;
7456             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
7457                 *eLevel = OMX_VIDEO_HEVCHighTierLevel1;
7458                 break;
7459             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
7460                 *eLevel = OMX_VIDEO_HEVCMainTierLevel2;
7461                 break;
7462             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
7463                 *eLevel = OMX_VIDEO_HEVCHighTierLevel2;
7464                 break;
7465             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
7466                 *eLevel = OMX_VIDEO_HEVCMainTierLevel21;
7467                 break;
7468             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
7469                 *eLevel = OMX_VIDEO_HEVCHighTierLevel21;
7470                 break;
7471             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
7472                 *eLevel = OMX_VIDEO_HEVCMainTierLevel3;
7473                 break;
7474             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
7475                 *eLevel = OMX_VIDEO_HEVCHighTierLevel3;
7476                 break;
7477             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
7478                 *eLevel = OMX_VIDEO_HEVCMainTierLevel31;
7479                 break;
7480             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
7481                 *eLevel = OMX_VIDEO_HEVCHighTierLevel31;
7482                 break;
7483             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
7484                 *eLevel = OMX_VIDEO_HEVCMainTierLevel4;
7485                 break;
7486             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
7487                 *eLevel = OMX_VIDEO_HEVCHighTierLevel4;
7488                 break;
7489             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
7490                 *eLevel = OMX_VIDEO_HEVCMainTierLevel41;
7491                 break;
7492             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
7493                 *eLevel = OMX_VIDEO_HEVCHighTierLevel41;
7494                 break;
7495             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
7496                 *eLevel = OMX_VIDEO_HEVCMainTierLevel5;
7497                 break;
7498             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
7499                 *eLevel = OMX_VIDEO_HEVCHighTierLevel5;
7500                 break;
7501             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
7502                 *eLevel = OMX_VIDEO_HEVCMainTierLevel51;
7503                 break;
7504             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
7505                 *eLevel = OMX_VIDEO_HEVCHighTierLevel51;
7506                 break;
7507             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
7508                 *eLevel = OMX_VIDEO_HEVCMainTierLevel52;
7509                 break;
7510             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
7511                 *eLevel = OMX_VIDEO_HEVCHighTierLevel52;
7512                 break;
7513             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
7514                 *eLevel = OMX_VIDEO_HEVCMainTierLevel6;
7515                 break;
7516             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
7517                 *eLevel = OMX_VIDEO_HEVCHighTierLevel6;
7518                 break;
7519             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
7520                 *eLevel = OMX_VIDEO_HEVCMainTierLevel61;
7521                 break;
7522             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
7523                 *eLevel = OMX_VIDEO_HEVCHighTierLevel61;
7524                 break;
7525             case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
7526                 *eLevel = OMX_VIDEO_HEVCMainTierLevel62;
7527                 break;
7528             default:
7529                 *eLevel = OMX_VIDEO_HEVCHighTiermax;
7530                 status = false;
7531                 break;
7532         }
7533     }
7534 
7535     return status;
7536 }
7537 
venc_set_nal_size(OMX_VIDEO_CONFIG_NALSIZE * nalSizeInfo)7538 bool venc_dev::venc_set_nal_size (OMX_VIDEO_CONFIG_NALSIZE *nalSizeInfo) {
7539     struct v4l2_control gControl;
7540     struct v4l2_control sControl;
7541 
7542     DEBUG_PRINT_HIGH("set video stream format - nal size - %u", nalSizeInfo->nNaluBytes);
7543     gControl.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
7544 
7545     if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &gControl)) {
7546         DEBUG_PRINT_ERROR("get control: video stream format failed");
7547         return false;
7548     }
7549 
7550     sControl.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
7551     switch (nalSizeInfo->nNaluBytes) {
7552             case 0:
7553                 sControl.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
7554                 break;
7555             case 4:
7556                 sControl.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
7557                 break;
7558             default:
7559                 return false;
7560         }
7561 
7562     if ((1 << sControl.value) & gControl.value) {
7563         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &sControl)) {
7564             DEBUG_PRINT_ERROR("set control: video stream format failed - %u",
7565                     (unsigned int)nalSizeInfo->nNaluBytes);
7566             return false;
7567         }
7568         return true;
7569     }
7570 
7571     return false;
7572 
7573 }
7574 
7575 #ifdef _ANDROID_ICS_
venc_set_meta_mode(bool mode)7576 bool venc_dev::venc_set_meta_mode(bool mode)
7577 {
7578     metadatamode = mode;
7579     return true;
7580 }
7581 #endif
7582 
venc_is_video_session_supported(unsigned long width,unsigned long height)7583 bool venc_dev::venc_is_video_session_supported(unsigned long width,
7584         unsigned long height)
7585 {
7586     if ((width * height < capability.min_width *  capability.min_height) ||
7587             (width * height > capability.max_width *  capability.max_height)) {
7588         DEBUG_PRINT_ERROR(
7589                 "Unsupported video resolution WxH = (%lu)x(%lu) supported range = min (%d)x(%d) - max (%d)x(%d)",
7590                 width, height, capability.min_width, capability.min_height,
7591                 capability.max_width, capability.max_height);
7592         return false;
7593     }
7594 
7595     DEBUG_PRINT_LOW("video session supported");
7596     return true;
7597 }
7598 
BatchInfo()7599 venc_dev::BatchInfo::BatchInfo()
7600     : mNumPending(0) {
7601     pthread_mutex_init(&mLock, NULL);
7602     for (int i = 0; i < kMaxBufs; ++i) {
7603         mBufMap[i] = kBufIDFree;
7604     }
7605 }
7606 
registerBuffer(int bufferId)7607 int venc_dev::BatchInfo::registerBuffer(int bufferId) {
7608     pthread_mutex_lock(&mLock);
7609     int availId = 0;
7610     for( ; availId < kMaxBufs && mBufMap[availId] != kBufIDFree; ++availId);
7611     if (availId >= kMaxBufs) {
7612         DEBUG_PRINT_ERROR("Failed to find free entry !");
7613         pthread_mutex_unlock(&mLock);
7614         return -1;
7615     }
7616     mBufMap[availId] = bufferId;
7617     mNumPending++;
7618     pthread_mutex_unlock(&mLock);
7619     return availId;
7620 }
7621 
retrieveBufferAt(int v4l2Id)7622 int venc_dev::BatchInfo::retrieveBufferAt(int v4l2Id) {
7623     pthread_mutex_lock(&mLock);
7624     if (v4l2Id >= kMaxBufs || v4l2Id < 0) {
7625         DEBUG_PRINT_ERROR("Batch: invalid index %d", v4l2Id);
7626         pthread_mutex_unlock(&mLock);
7627         return -1;
7628     }
7629     if (mBufMap[v4l2Id] == kBufIDFree) {
7630         DEBUG_PRINT_ERROR("Batch: buffer @ %d was not registered !", v4l2Id);
7631         pthread_mutex_unlock(&mLock);
7632         return -1;
7633     }
7634     int bufferId = mBufMap[v4l2Id];
7635     mBufMap[v4l2Id] = kBufIDFree;
7636     mNumPending--;
7637     pthread_mutex_unlock(&mLock);
7638     return bufferId;
7639 }
7640 
isPending(int bufferId)7641 bool venc_dev::BatchInfo::isPending(int bufferId) {
7642     pthread_mutex_lock(&mLock);
7643     int existsId = 0;
7644     for(; existsId < kMaxBufs && mBufMap[existsId] != bufferId; ++existsId);
7645     pthread_mutex_unlock(&mLock);
7646     return existsId < kMaxBufs;
7647 }
7648 
venc_set_hdr_info(const MasteringDisplay & mastering_disp_info,const ContentLightLevel & content_light_level_info)7649 bool venc_dev::venc_set_hdr_info(const MasteringDisplay& mastering_disp_info,
7650                             const ContentLightLevel& content_light_level_info)
7651 {
7652     struct v4l2_ext_control ctrl[13];
7653     struct v4l2_ext_controls controls;
7654     const unsigned int RGB_PRIMARY_TABLE[] = {
7655         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_00,
7656         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_01,
7657         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_10,
7658         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_11,
7659         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_20,
7660         V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_21,
7661     };
7662 
7663     memset(&controls, 0, sizeof(controls));
7664     memset(ctrl, 0, sizeof(ctrl));
7665 
7666     controls.count = 11;
7667     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
7668     controls.controls = ctrl;
7669 
7670     ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO;
7671     ctrl[0].value = V4L2_MPEG_MSM_VIDC_ENABLE;
7672 
7673     /* ctrl[1] - ctrl[6] */
7674     for (int i = 0; i < 3; i++) {
7675         int first_idx = 2*i+1;
7676         int second_idx = 2*i+2;
7677         ctrl[first_idx].id = RGB_PRIMARY_TABLE[first_idx-1];
7678         ctrl[first_idx].value = mastering_disp_info.primaries.rgbPrimaries[i][0];
7679 
7680         ctrl[second_idx].id = RGB_PRIMARY_TABLE[second_idx-1];
7681         ctrl[second_idx].value = mastering_disp_info.primaries.rgbPrimaries[i][1];
7682     }
7683 
7684     ctrl[7].id = V4L2_CID_MPEG_VIDC_VENC_WHITEPOINT_X;
7685     ctrl[7].value = mastering_disp_info.primaries.whitePoint[0];
7686 
7687     ctrl[8].id = V4L2_CID_MPEG_VIDC_VENC_WHITEPOINT_Y;
7688     ctrl[8].value = mastering_disp_info.primaries.whitePoint[1];
7689 
7690     ctrl[9].id = V4L2_CID_MPEG_VIDC_VENC_MAX_DISP_LUM;
7691     // maxDisplayLuminance is in cd/m^2 scale. But the standard requires this field
7692     // to be in 0.0001 cd/m^2 scale. So, multiply with LUMINANCE_MULTIPLICATION_FACTOR
7693     // and give to be driver
7694     ctrl[9].value = mastering_disp_info.maxDisplayLuminance * LUMINANCE_MULTIPLICATION_FACTOR;
7695 
7696     ctrl[10].id = V4L2_CID_MPEG_VIDC_VENC_MIN_DISP_LUM;
7697     ctrl[10].value = mastering_disp_info.minDisplayLuminance;
7698 
7699     if (ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
7700         DEBUG_PRINT_ERROR("VIDIOC_S_EXT_CTRLS failed for HDR Info : Disp SEI");
7701         return false;
7702     }
7703 
7704     memset(&controls, 0, sizeof(controls));
7705     memset(ctrl, 0, sizeof(ctrl));
7706 
7707     controls.count = 3;
7708     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
7709     controls.controls = ctrl;
7710 
7711     ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO;
7712     ctrl[0].value = V4L2_MPEG_MSM_VIDC_ENABLE;
7713 
7714     ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_MAX_CLL;
7715     ctrl[1].value = content_light_level_info.maxContentLightLevel;
7716 
7717     ctrl[2].id = V4L2_CID_MPEG_VIDC_VENC_MAX_FLL;
7718     ctrl[2].value = content_light_level_info.minPicAverageLightLevel;
7719 
7720     if (ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
7721         DEBUG_PRINT_ERROR("VIDIOC_S_EXT_CTRLS failed for HDR Info : CLL SEI");
7722         return false;
7723     }
7724 
7725     return true;
7726 }
7727 
7728 #ifdef _VQZIP_
venc_dev_vqzip()7729 venc_dev::venc_dev_vqzip::venc_dev_vqzip()
7730 {
7731     mLibHandle = NULL;
7732     pthread_mutex_init(&lock, NULL);
7733 }
7734 
init()7735 bool venc_dev::venc_dev_vqzip::init()
7736 {
7737     bool status = true;
7738     if (mLibHandle) {
7739         DEBUG_PRINT_ERROR("VQZIP init called twice");
7740         status = false;
7741     }
7742     if (status) {
7743         mLibHandle = dlopen("libvqzip.so", RTLD_NOW);
7744         if (mLibHandle) {
7745             mVQZIPInit = (vqzip_init_t)
7746                 dlsym(mLibHandle,"VQZipInit");
7747             mVQZIPDeInit = (vqzip_deinit_t)
7748                 dlsym(mLibHandle,"VQZipDeInit");
7749             mVQZIPComputeStats = (vqzip_compute_stats_t)
7750                 dlsym(mLibHandle,"VQZipComputeStats");
7751             if (!mVQZIPInit || !mVQZIPDeInit || !mVQZIPComputeStats)
7752                 status = false;
7753         } else {
7754             DEBUG_PRINT_ERROR("FATAL ERROR: could not dlopen libvqzip.so: %s", dlerror());
7755             status = false;
7756         }
7757         if (status) {
7758             mVQZIPHandle = mVQZIPInit();
7759         }
7760     }
7761     if (!status && mLibHandle) {
7762         dlclose(mLibHandle);
7763         mLibHandle = NULL;
7764         mVQZIPHandle = NULL;
7765         mVQZIPInit = NULL;
7766         mVQZIPDeInit = NULL;
7767         mVQZIPComputeStats = NULL;
7768     }
7769     return status;
7770 }
7771 
fill_stats_data(void * pBuf,void * extraData)7772 int venc_dev::venc_dev_vqzip::fill_stats_data(void* pBuf, void* extraData)
7773 {
7774     VQZipStatus result;
7775     VQZipStats *pStats = (VQZipStats *)extraData;
7776     pConfig.pSEIPayload = NULL;
7777     unsigned long size;
7778 
7779     if (!pBuf || !pStats || !mVQZIPHandle) {
7780         DEBUG_PRINT_ERROR("Invalid data passed to stats function");
7781     }
7782     result = mVQZIPComputeStats(mVQZIPHandle, (void* )pBuf, &pConfig, pStats);
7783     return result;
7784 }
7785 
deinit()7786 void venc_dev::venc_dev_vqzip::deinit()
7787 {
7788     if (mLibHandle) {
7789         pthread_mutex_lock(&lock);
7790         dlclose(mLibHandle);
7791         mVQZIPDeInit(mVQZIPHandle);
7792         mLibHandle = NULL;
7793         mVQZIPHandle = NULL;
7794         mVQZIPInit = NULL;
7795         mVQZIPDeInit = NULL;
7796         mVQZIPComputeStats = NULL;
7797         pthread_mutex_unlock(&lock);
7798     }
7799 }
7800 
~venc_dev_vqzip()7801 venc_dev::venc_dev_vqzip::~venc_dev_vqzip()
7802 {
7803     DEBUG_PRINT_HIGH("Destroy C2D instance");
7804     if (mLibHandle) {
7805         dlclose(mLibHandle);
7806     }
7807     mLibHandle = NULL;
7808     pthread_mutex_destroy(&lock);
7809 }
7810 #endif
7811 
7812 /*=================================================================================
7813  * Function:   venc_set_roi_region_qp_info
7814  * @brief      set the config of OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO and store
7815  *             the info in the list
7816  * Parameters:
7817  * @param      OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo:
7818  *             the config to be set
7819  * Return value:
7820  *             bool: return true if the config is set successfully
7821 *==================================================================================*/
venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO * roiRegionInfo)7822 bool venc_dev::venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo)
7823 {
7824     if (!m_roi_enabled || (m_roi_type == 0)) {
7825         DEBUG_PRINT_ERROR("ROI-Region: roi is invalid (enable:%u, type:%d)",
7826                 m_roi_enabled, m_roi_type);
7827         return false;
7828     }
7829     if (!roiRegionInfo) {
7830         DEBUG_PRINT_ERROR("ROI-Region: no region info present");
7831         return false;
7832     }
7833     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
7834             m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
7835         DEBUG_PRINT_ERROR("ROI-Region: is not supported for %d codec",
7836                 (OMX_U32) m_sVenc_cfg.codectype);
7837         return false;
7838     }
7839 
7840     pthread_mutex_lock(&m_roilock);
7841     DEBUG_PRINT_LOW("ROI-Region: add region with timestamp %lld us.", roiRegionInfo->nTimeStamp);
7842     mRoiRegionList.push_back(*roiRegionInfo);
7843     pthread_mutex_unlock(&m_roilock);
7844     return true;
7845 }
7846 
7847 /*=================================================================================
7848  * Function:   append_extradata_roi_region_qp_info
7849  * @brief      fill the roi info in the extradata of input Buffer
7850  * Parameters:
7851  * @param      OMX_OTHER_EXTRADATATYPE *data: the address of the extradata buffer
7852  *             OMX_TICKS timestamp:  the timestamp of the input Buffer
7853  *             OMX_U32: the available size of the extradata buffer
7854  * Return value:
7855  *             OMX_U32: the filled size
7856 *==================================================================================*/
append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE * data,OMX_TICKS timestamp,OMX_U32 freeSize)7857 OMX_U32 venc_dev::append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE *data,
7858         OMX_TICKS timestamp, OMX_U32 freeSize)
7859 {
7860     bool found = false;
7861     pthread_mutex_lock(&m_roilock);
7862     if (mRoiRegionList.size() == 0) {
7863         pthread_mutex_unlock(&m_roilock);
7864         return 0;
7865     }
7866     std::list<OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO>::iterator it =
7867             mRoiRegionList.begin();
7868     while (it != mRoiRegionList.end()) {
7869         if (it->nTimeStamp < timestamp) {
7870             it = mRoiRegionList.erase(it);
7871             continue;
7872         } else if (it->nTimeStamp == timestamp) {
7873             found = true;
7874             break;
7875         }
7876         it++;
7877     }
7878     pthread_mutex_unlock(&m_roilock);
7879     if (!found) {
7880         DEBUG_PRINT_LOW("ROI-Region: no region roi data was found");
7881         return 0;
7882     }
7883     OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO regionInfo = *it;
7884     bool isHevc = m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC ? true:false;
7885     OMX_U32 height = m_sVenc_cfg.dvs_height;
7886     OMX_U32 width = m_sVenc_cfg.dvs_width;
7887     OMX_U32 mbAlign = isHevc ? 32 : 16;
7888     OMX_U8 mbBit = isHevc ? 5 : 4;
7889     OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
7890     OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
7891     OMX_U32 numBytes, mbLeft, mbTop, mbRight, mbBottom = 0;
7892     OMX_S8 deltaQP = 0;
7893     DEBUG_PRINT_LOW("ROI-Region: clip(%ux%u: %s), mb(%ux%u), region(num:%u, ts:%lld)",
7894             width, height, isHevc ? "hevc" : "avc",
7895             mbRow, mbCol, regionInfo.nRegionNum, regionInfo.nTimeStamp);
7896 
7897     if (m_roi_type == V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BYTE) {
7898         OMX_U32 mbRowAligned = ALIGN(mbRow, 8);
7899         numBytes = mbRowAligned * mbCol * 2;
7900         OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
7901 
7902         data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload), 256)
7903                             + numBytesAligned;
7904         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
7905         if (data->nSize > freeSize) {
7906             DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
7907                     freeSize, data->nSize);
7908             data->nDataSize = 0;
7909             data->nSize = 0;
7910             return 0;
7911         }
7912 
7913         data->nVersion.nVersion = OMX_SPEC_VERSION;
7914         data->nPortIndex = 0;
7915         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
7916         struct msm_vidc_roi_deltaqp_payload *roiData =
7917                 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
7918         roiData->b_roi_info = true;
7919         roiData->mbi_info_size = numBytesAligned;
7920         roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256)
7921                 - (unsigned long)roiData->data);
7922         OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);
7923         OMX_U32 mb = 0;
7924         OMX_U16 *pData = NULL;
7925 
7926         for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
7927             mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
7928             mbTop = regionInfo.nRegions[i].nTop >> mbBit;
7929             mbRight = regionInfo.nRegions[i].nRight >> mbBit;
7930             mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
7931             deltaQP = regionInfo.nRegions[i].nDeltaQP;
7932             if (mbLeft >= mbRow || mbRight >= mbRow
7933                     || mbTop >= mbCol || mbBottom >= mbCol) {
7934                 continue;
7935             }
7936             for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
7937                 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
7938                     mb = row * mbRowAligned + col;
7939                     pData = exDataBuf + mb;
7940                     *pData = (1 << 11) | ((deltaQP & 0x3F) << 4);
7941                 }
7942             }
7943         }
7944         DEBUG_PRINT_LOW("ROI-Region(2Byte): set roi: raw size: %u", numBytesAligned);
7945     } else if (m_roi_type == V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BIT) {
7946         numBytes = (mbRow * mbCol * 2 + 7) >> 3;
7947         data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload) + numBytes;
7948         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
7949 
7950         if (data->nSize > freeSize) {
7951             DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
7952                     freeSize, data->nSize);
7953             data->nDataSize = 0;
7954             data->nSize = 0;
7955             return 0;
7956         }
7957 
7958         data->nVersion.nVersion = OMX_SPEC_VERSION;
7959         data->nPortIndex = 0;
7960         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
7961         struct msm_vidc_roi_qp_payload *roiData =
7962                 (struct msm_vidc_roi_qp_payload *)(data->data);
7963         roiData->b_roi_info = true;
7964         roiData->mbi_info_size = numBytes;
7965         roiData->lower_qp_offset = 0;
7966         roiData->upper_qp_offset = 0;
7967         OMX_U8 flag = 0x1;
7968         OMX_U32 mb, mb_byte = 0;
7969         OMX_U8 mb_bit = 0;
7970         OMX_U8 *pData = NULL;
7971 
7972         for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
7973             mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
7974             mbTop = regionInfo.nRegions[i].nTop >> mbBit;
7975             mbRight = regionInfo.nRegions[i].nRight >> mbBit;
7976             mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
7977             deltaQP = regionInfo.nRegions[i].nDeltaQP;
7978             if (mbLeft >= mbRow || mbRight >= mbRow
7979                     || mbTop >= mbCol || mbBottom >= mbCol
7980                     || deltaQP == 0) {
7981                 continue;
7982             }
7983             // choose the minimum absolute value for lower and upper offset
7984             if (deltaQP < 0) {
7985                 if (roiData->lower_qp_offset == 0) {
7986                     roiData->lower_qp_offset = deltaQP;
7987                 } else if (roiData->lower_qp_offset < deltaQP) {
7988                     roiData->lower_qp_offset = deltaQP;
7989                 }
7990                 flag = 0x1;
7991             } else {
7992                 if (roiData->upper_qp_offset == 0) {
7993                     roiData->upper_qp_offset = deltaQP;
7994                 } else if (roiData->upper_qp_offset > deltaQP) {
7995                     roiData->upper_qp_offset = deltaQP;
7996                 }
7997                 flag = 0x2;
7998             }
7999             for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
8000                 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
8001                     mb = row * mbRow + col;
8002                     mb_byte = mb >> 2;
8003                     mb_bit = (3 - (mb & 0x3)) << 1;
8004                     pData = (OMX_U8 *)roiData->data + mb_byte;
8005                     *pData |= (flag << mb_bit);
8006                 }
8007             }
8008         }
8009         DEBUG_PRINT_LOW("ROI-Region(2Bit):set roi low:%d,up:%d", roiData->lower_qp_offset, roiData->upper_qp_offset);
8010     }
8011     return data->nSize;
8012 }
8013 
8014