1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010-2020 The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 #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 USE_ION
39 #include <linux/msm_ion.h>
40 #endif
41 #include<linux/v4l2-controls.h>
42 
43 #include <math.h>
44 #include <media/msm_media_info.h>
45 #include <cutils/properties.h>
46 #include <media/hardware/HardwareAPI.h>
47 
48 #ifdef _ANDROID_
49 #include <media/hardware/HardwareAPI.h>
50 #include <gralloc_priv.h>
51 #endif
52 
53 #ifdef _USE_GLIB_
54 #include <glib.h>
55 #define strlcpy g_strlcpy
56 #endif
57 
58 #include <qdMetaData.h>
59 #include <color_metadata.h>
60 #include "PlatformConfig.h"
61 
62 #define ATRACE_TAG ATRACE_TAG_VIDEO
63 #include <utils/Trace.h>
64 
65 #define YUV_STATS_LIBRARY_NAME "libgpustats.so" // UBWC case: use GPU library
66 
67 #undef ALIGN
68 #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
69 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
70 #define MAXDPB 16
71 #ifndef MIN
72 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
73 #endif
74 #ifndef MAX
75 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
76 #endif
77 
78 #define ROUND(__sz, __align) (((__sz) + ((__align>>1))) & (~(__align-1)))
79 #define MAX_PROFILE_PARAMS 6
80 #define HEVC_MAIN_START 0
81 #define HEVC_MAIN10_START (HEVC_MAIN_START + 13)
82 #define POLL_TIMEOUT 1000
83 #define MAX_SUPPORTED_SLICES_PER_FRAME 28 /* Max supported slices with 32 output buffers */
84 
85 #define SZ_4K 0x1000
86 #define SZ_1M 0x100000
87 
88 
89 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
90 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
91 
92 //TODO: remove once gerrit : 2680400 is merged
93 #define VIDC_HAL_PIXEL_FORMAT_NV12_LINEAR_FLEX  HAL_PIXEL_FORMAT_NV12_LINEAR_FLEX
94 #define VIDC_HAL_PIXEL_FORMAT_NV12_UBWC_FLEX HAL_PIXEL_FORMAT_NV12_UBWC_FLEX
95 
96 #define BUFFER_LOG_LOC "/data/vendor/media"
97 
98 #undef LOG_TAG
99 #define LOG_TAG "OMX-VENC: venc_dev"
100 
101 #define LUMINANCE_MULTIPLICATION_FACTOR 10000
102 
103 //constructor
venc_dev(class omx_venc * venc_class)104 venc_dev::venc_dev(class omx_venc *venc_class)
105 {
106     //nothing to do
107     int i = 0;
108     venc_handle = venc_class;
109     etb = ebd = ftb = fbd = 0;
110     m_poll_efd = -1;
111 
112     struct v4l2_control control;
113     for (i = 0; i < MAX_PORT; i++)
114         streaming[i] = false;
115 
116     stopped = 1;
117     paused = false;
118     async_thread_created = false;
119     async_thread_force_stop = false;
120     color_format = 0;
121     hw_overload = false;
122     mBatchSize = 0;
123     m_roi_enabled = false;
124     m_roi_type = ROI_NONE;
125     m_cvp_meta_enabled = false;
126     m_cvp_first_metadata = false;
127     low_latency_mode = false;
128     m_bDimensionsNeedFlip = false;
129     pthread_mutex_init(&m_roilock, NULL);
130     pthread_mutex_init(&m_configlock, NULL);
131     pthread_mutex_init(&pause_resume_mlock, NULL);
132     pthread_cond_init(&pause_resume_cond, NULL);
133     memset(&input_extradata_info, 0, sizeof(input_extradata_info));
134     memset(&output_extradata_info, 0, sizeof(output_extradata_info));
135     for (int i = 0; i < VIDEO_MAX_FRAME; i++) {
136         input_extradata_info.ion[i].data_fd = -1;
137         output_extradata_info.ion[i].data_fd = -1;
138     }
139     memset(&idrperiod, 0, sizeof(idrperiod));
140     memset(&multislice, 0, sizeof(multislice));
141     memset(&m_sVenc_cfg, 0, sizeof(m_sVenc_cfg));
142     memset(&rate_ctrl, 0, sizeof(rate_ctrl));
143     memset(&bitrate, 0, sizeof(bitrate));
144     memset(&intra_period, 0, sizeof(intra_period));
145     memset(&codec_profile, 0, sizeof(codec_profile));
146     memset(&set_param, 0, sizeof(set_param));
147     memset(&time_inc, 0, sizeof(time_inc));
148     memset(&m_sInput_buff_property, 0, sizeof(m_sInput_buff_property));
149     memset(&m_sOutput_buff_property, 0, sizeof(m_sOutput_buff_property));
150     memset(&session_qp, 0, sizeof(session_qp));
151     memset(&session_ipb_qp_values, 0, sizeof(session_ipb_qp_values));
152     memset(&entropy, 0, sizeof(entropy));
153     memset(&dbkfilter, 0, sizeof(dbkfilter));
154     memset(&intra_refresh, 0, sizeof(intra_refresh));
155     memset(&hec, 0, sizeof(hec));
156     memset(&voptimecfg, 0, sizeof(voptimecfg));
157     memset(&capability, 0, sizeof(capability));
158     memset(&m_debug,0,sizeof(m_debug));
159     sess_priority.priority = 1;
160     operating_rate = 30;
161     memset(&color_space, 0x0, sizeof(color_space));
162     memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
163     bframe_implicitly_enabled = false;
164     intra_period.num_pframes = 29;
165     intra_period.num_bframes = 0;
166     m_hdr10meta_enabled = false;
167 
168     Platform::Config::getInt32(Platform::vidc_enc_log_in,
169             (int32_t *)&m_debug.in_buffer_log, 0);
170     Platform::Config::getInt32(Platform::vidc_enc_log_out,
171             (int32_t *)&m_debug.out_buffer_log, 0);
172     Platform::Config::getInt32(Platform::vidc_enc_csc_custom_matrix,
173             (int32_t *)&is_csc_custom_matrix_enabled, 0);
174     Platform::Config::getInt32(Platform::vidc_enc_auto_blur_disable,
175             (int32_t *)&is_auto_blur_disabled, 0);
176     Platform::Config::getInt32(Platform::vidc_disable_hdr,
177             (int32_t *)&m_disable_hdr, 0);
178 
179     char property_value[PROPERTY_VALUE_MAX] = {0};
180 
181     property_get("vendor.vidc.enc.log.in", property_value, "0");
182     m_debug.in_buffer_log |= atoi(property_value);
183 
184     property_value[0] = '\0';
185     property_get("vendor.vidc.enc.log.out", property_value, "0");
186     m_debug.out_buffer_log |= atoi(property_value);
187 
188     property_get("vendor.vidc.enc.log.extradata", property_value, "0");
189     m_debug.extradata_log = atoi(property_value);
190 
191     property_get("vendor.vidc.cvp.log.in", property_value, "0");
192     m_debug.cvp_log |= atoi(property_value);
193 
194 #ifdef _UBWC_
195     property_get("vendor.gralloc.disable_ubwc", property_value, "0");
196     if(!(strncmp(property_value, "1", PROPERTY_VALUE_MAX)) ||
197         !(strncmp(property_value, "true", PROPERTY_VALUE_MAX))) {
198         is_gralloc_source_ubwc = 0;
199     } else {
200         is_gralloc_source_ubwc = 1;
201     }
202 #else
203     is_gralloc_source_ubwc = 0;
204 #endif
205 
206      property_value[0] = '\0';
207      property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
208      if (*property_value)
209          strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
210 
211     mUseAVTimerTimestamps = false;
212     mIsGridset = false;
213     Platform::Config::getInt32(Platform::vidc_enc_linear_color_format,
214             (int32_t *)&mUseLinearColorFormat, 0);
215     Platform::Config::getInt32(Platform::vidc_enc_bitrate_savings_enable,
216             (int32_t *)&mBitrateSavingsEnable, 3);
217     Platform::Config::getInt32(Platform::vidc_enc_quality_boost_enable,
218             (int32_t *)&mQualityBoostRequested, 0);
219     mQualityBoostEligible = false;
220 
221     profile_level_converter::init();
222 }
223 
~venc_dev()224 venc_dev::~venc_dev()
225 {
226     if (m_roi_enabled) {
227         std::list<roidata>::iterator iter;
228         pthread_mutex_lock(&m_roilock);
229         for (iter = m_roilist.begin(); iter != m_roilist.end(); iter++) {
230             DEBUG_PRINT_HIGH("roidata with timestamp (%lld) should have been removed already",
231                 iter->info.nTimeStamp);
232         }
233         m_roilist.clear();
234         mRoiRegionList.clear();
235         pthread_mutex_unlock(&m_roilock);
236     }
237     pthread_mutex_destroy(&m_roilock);
238 
239     std::list<dynamicConfig>::iterator iter;
240     pthread_mutex_lock(&m_configlock);
241     for (iter = m_configlist.begin(); iter != m_configlist.end(); iter++) {
242         DEBUG_PRINT_HIGH("dynamic config data with timestamp (%lld) should have been removed already",
243             iter->timestamp);
244     }
245     m_configlist.clear();
246     pthread_mutex_unlock(&m_configlock);
247     pthread_mutex_destroy(&m_configlock);
248 }
249 
async_venc_message_thread(void * input)250 void* venc_dev::async_venc_message_thread (void *input)
251 {
252     struct venc_msg venc_msg;
253     omx_video* omx_venc_base = NULL;
254     omx_venc *omx = reinterpret_cast<omx_venc*>(input);
255     omx_venc_base = reinterpret_cast<omx_video*>(input);
256     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
257 
258     prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0);
259     struct v4l2_plane plane[VIDEO_MAX_PLANES];
260     struct pollfd pfds[2];
261     struct v4l2_buffer v4l2_buf;
262     struct v4l2_event dqevent;
263     struct statistics stats;
264     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
265     pfds[1].events = POLLIN | POLLERR;
266     pfds[0].fd = omx->handle->m_nDriver_fd;
267     pfds[1].fd = omx->handle->m_poll_efd;
268     int error_code = 0,rc=0;
269 
270     memset(&stats, 0, sizeof(statistics));
271     memset(&v4l2_buf, 0, sizeof(v4l2_buf));
272 
273     while (!omx->handle->async_thread_force_stop) {
274         pthread_mutex_lock(&omx->handle->pause_resume_mlock);
275 
276         if (omx->handle->paused) {
277             venc_msg.msgcode = VEN_MSG_PAUSE;
278             venc_msg.statuscode = VEN_S_SUCCESS;
279 
280             if (omx->async_message_process(input, &venc_msg) < 0) {
281                 DEBUG_PRINT_ERROR("ERROR: Failed to process pause msg");
282                 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
283                 break;
284             }
285 
286             /* Block here until the IL client resumes us again */
287             pthread_cond_wait(&omx->handle->pause_resume_cond,
288                     &omx->handle->pause_resume_mlock);
289 
290             venc_msg.msgcode = VEN_MSG_RESUME;
291             venc_msg.statuscode = VEN_S_SUCCESS;
292 
293             if (omx->async_message_process(input, &venc_msg) < 0) {
294                 DEBUG_PRINT_ERROR("ERROR: Failed to process resume msg");
295                 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
296                 break;
297             }
298             memset(&stats, 0, sizeof(statistics));
299         }
300 
301         pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
302 
303         rc = poll(pfds, 2, POLL_TIMEOUT);
304 
305         if (!rc) {
306             DEBUG_PRINT_HIGH("Poll timedout, pipeline stalled due to client/firmware ETB: %d, EBD: %d, FTB: %d, FBD: %d",
307                     omx->handle->etb, omx->handle->ebd, omx->handle->ftb, omx->handle->fbd);
308             continue;
309         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
310             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
311             break;
312         }
313 
314         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
315             DEBUG_PRINT_ERROR("async_venc_message_thread interrupted to be exited");
316             break;
317         }
318 
319         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
320             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
321             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
322             v4l2_buf.length = omx->handle->num_output_planes;
323             v4l2_buf.m.planes = plane;
324 
325             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
326                 venc_msg.msgcode=VEN_MSG_OUTPUT_BUFFER_DONE;
327                 venc_msg.statuscode=VEN_S_SUCCESS;
328                 omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf.index;
329                 venc_msg.buf.len= v4l2_buf.m.planes->bytesused;
330                 venc_msg.buf.offset = v4l2_buf.m.planes->data_offset;
331                 venc_msg.buf.flags = 0;
332                 venc_msg.buf.ptrbuffer = (OMX_U8 *)omx_venc_base->m_pOutput_pmem[v4l2_buf.index].buffer;
333                 venc_msg.buf.clientdata=(void*)omxhdr;
334                 venc_msg.buf.timestamp = (int64_t) v4l2_buf.timestamp.tv_sec * (int64_t) 1000000 + (int64_t) v4l2_buf.timestamp.tv_usec;
335 
336                 /* TODO: ideally report other types of frames as well
337                  * for now it doesn't look like IL client cares about
338                  * other types
339                  */
340                 if (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
341                     venc_msg.buf.flags |= QOMX_VIDEO_PictureTypeIDR;
342                     venc_msg.buf.flags |= OMX_BUFFERFLAG_SYNCFRAME;
343                 }
344                 if (v4l2_buf.flags & V4L2_BUF_FLAG_PFRAME) {
345                     venc_msg.buf.flags |= OMX_VIDEO_PictureTypeP;
346                 } else if (v4l2_buf.flags & V4L2_BUF_FLAG_BFRAME) {
347                     venc_msg.buf.flags |= OMX_VIDEO_PictureTypeB;
348                 }
349 
350                 if (v4l2_buf.flags & V4L2_BUF_FLAG_CODECCONFIG)
351                     venc_msg.buf.flags |= OMX_BUFFERFLAG_CODECCONFIG;
352 
353                 if (v4l2_buf.flags & V4L2_BUF_FLAG_EOS)
354                     venc_msg.buf.flags |= OMX_BUFFERFLAG_EOS;
355 
356                 if (omx->handle->num_output_planes > 1 && v4l2_buf.m.planes->bytesused)
357                     venc_msg.buf.flags |= OMX_BUFFERFLAG_EXTRADATA;
358 
359                 if (omxhdr->nFilledLen)
360                     venc_msg.buf.flags |= OMX_BUFFERFLAG_ENDOFFRAME;
361 
362                 omx->handle->fbd++;
363                 stats.bytes_generated += venc_msg.buf.len;
364 
365                 if (omx->async_message_process(input,&venc_msg) < 0) {
366                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
367                     break;
368                 }
369             }
370         }
371 
372         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
373             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
374             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
375             v4l2_buf.m.planes = plane;
376             v4l2_buf.length = omx->handle->num_input_planes;
377 
378             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
379                 venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE;
380                 venc_msg.statuscode=VEN_S_SUCCESS;
381                 omx->handle->ebd++;
382 
383                 if (omx->handle->mBatchSize) {
384                     int bufIndex = omx->handle->mBatchInfo.retrieveBufferAt(v4l2_buf.index);
385                     if (bufIndex < 0) {
386                         DEBUG_PRINT_ERROR("Retrieved invalid buffer %d", v4l2_buf.index);
387                         break;
388                     }
389                     if (omx->handle->mBatchInfo.isPending(bufIndex)) {
390                         DEBUG_PRINT_LOW(" EBD for %d [v4l2-id=%d].. batch still pending",
391                                 bufIndex, v4l2_buf.index);
392                         //do not return to client yet
393                         continue;
394                     }
395                     v4l2_buf.index = bufIndex;
396                 }
397                 if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion)
398                     omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf.index];
399                 else
400                     omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index];
401 
402                 venc_msg.buf.clientdata=(void*)omxhdr;
403 
404                 DEBUG_PRINT_LOW("sending EBD %p [id=%d]", omxhdr, v4l2_buf.index);
405                 if (omx->async_message_process(input,&venc_msg) < 0) {
406                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
407                     break;
408                 }
409             }
410         }
411 
412         if (pfds[0].revents & POLLPRI) {
413             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
414 
415             if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
416                 venc_msg.msgcode = VEN_MSG_FLUSH_INPUT_DONE;
417                 venc_msg.statuscode = VEN_S_SUCCESS;
418 
419                 if (omx->async_message_process(input,&venc_msg) < 0) {
420                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
421                     break;
422                 }
423 
424                 venc_msg.msgcode = VEN_MSG_FLUSH_OUPUT_DONE;
425                 venc_msg.statuscode = VEN_S_SUCCESS;
426 
427                 if (omx->async_message_process(input,&venc_msg) < 0) {
428                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
429                     break;
430                 }
431             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
432                 DEBUG_PRINT_ERROR("HW Overload received");
433                 venc_msg.statuscode = VEN_S_EFAIL;
434                 venc_msg.msgcode = VEN_MSG_HW_OVERLOAD;
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_SYS_ERROR){
441                 DEBUG_PRINT_ERROR("ERROR: Encoder is in bad state");
442                 venc_msg.msgcode = VEN_MSG_INDICATION;
443                 venc_msg.statuscode=VEN_S_EFAIL;
444 
445                 if (omx->async_message_process(input,&venc_msg) < 0) {
446                     DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
447                     break;
448                 }
449             }
450         }
451 
452         /* calc avg. fps, bitrate */
453         OMX_U64 current_time;
454         OMX_U64 prev_time;
455         struct timespec curr_tv;
456         clock_gettime(CLOCK_MONOTONIC, &curr_tv);
457         current_time = (OMX_U64)curr_tv.tv_sec * 1000000000ULL + (OMX_U64)curr_tv.tv_nsec;
458         prev_time = (OMX_U64)stats.prev_tv.tv_sec * 1000000000ULL + (OMX_U64)stats.prev_tv.tv_nsec;
459         if (current_time < prev_time) {
460             stats.prev_tv = curr_tv;
461             stats.bytes_generated = 0;
462             stats.prev_fbd = omx->handle->fbd;
463         } else if (current_time - prev_time  >= 1000000000ULL) {    // timestamp is in nano_seconds
464             OMX_U32 num_fbd = omx->handle->fbd - stats.prev_fbd;
465             OMX_U64 time_diff = current_time - prev_time;
466             if (stats.prev_tv.tv_sec && num_fbd && time_diff) {
467                 float framerate = ((OMX_U64)num_fbd * 1000000000ULL) / (float)time_diff;
468                 OMX_U64 bitrate = ((OMX_U64)stats.bytes_generated * 8 / (float)num_fbd) * framerate;
469                 DEBUG_PRINT_INFO("stats: avg. fps %0.2f, bitrate %llu",
470                     framerate, bitrate);
471             }
472             stats.prev_tv = curr_tv;
473             stats.bytes_generated = 0;
474             stats.prev_fbd = omx->handle->fbd;
475         }
476 
477     }
478 
479     DEBUG_PRINT_HIGH("omx_venc: Async Thread exit");
480     return NULL;
481 }
482 
483 static const int event_type[] = {
484     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
485     V4L2_EVENT_MSM_VIDC_SYS_ERROR
486 };
487 
subscribe_to_events(int fd)488 static OMX_ERRORTYPE subscribe_to_events(int fd)
489 {
490     OMX_ERRORTYPE eRet = OMX_ErrorNone;
491     struct v4l2_event_subscription sub;
492     int array_sz = sizeof(event_type)/sizeof(int);
493     int i,rc;
494     memset(&sub, 0, sizeof(sub));
495 
496     if (fd < 0) {
497        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
498         return OMX_ErrorBadParameter;
499     }
500 
501     for (i = 0; i < array_sz; ++i) {
502         memset(&sub, 0, sizeof(sub));
503         sub.type = event_type[i];
504         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
505 
506         if (rc) {
507            DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
508             break;
509         }
510     }
511 
512     if (i < array_sz) {
513         for (--i; i >=0 ; i--) {
514             memset(&sub, 0, sizeof(sub));
515             sub.type = event_type[i];
516             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
517 
518             if (rc)
519                DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
520         }
521 
522         eRet = OMX_ErrorNotImplemented;
523     }
524 
525     return eRet;
526 }
527 
venc_query_cap(struct v4l2_queryctrl & cap)528 bool inline venc_dev::venc_query_cap(struct v4l2_queryctrl &cap) {
529 
530     if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &cap)) {
531         DEBUG_PRINT_ERROR("Query caps for id = %u failed", cap.id);
532         return false;
533     }
534     return true;
535 }
536 
venc_validate_range(OMX_S32 id,OMX_S32 val)537 bool venc_dev::venc_validate_range(OMX_S32 id, OMX_S32 val) {
538 
539     struct v4l2_queryctrl cap;
540     memset(&cap, 0, sizeof(struct v4l2_queryctrl));
541 
542     cap.id = id;
543     if (venc_query_cap(cap)) {
544         if (val >= cap.minimum && val <= cap.maximum) {
545             return true;
546         } else {
547             DEBUG_PRINT_INFO("id = %u, value = %u, min = %u, max = %u",
548                 cap.id, val, cap.minimum, cap.maximum);
549         }
550     }
551     return false;
552 }
553 
get_roi_for_timestamp(struct roidata & roi,OMX_TICKS timestamp)554 void venc_dev::get_roi_for_timestamp(struct roidata &roi, OMX_TICKS timestamp)
555 {
556     std::list<roidata>::iterator iter;
557     bool found = false;
558 
559     memset(&roi, 0, sizeof(struct roidata));
560     roi.dirty = false;
561 
562     pthread_mutex_lock(&m_roilock);
563     iter = m_roilist.begin();
564     while (iter != m_roilist.end()) {
565         if (iter->info.nTimeStamp < timestamp) {
566             /* remove previous roi data */
567             iter = m_roilist.erase(iter);
568             /* iter++ is not required as erase would do it */
569             continue;
570         } else if (iter->info.nTimeStamp == timestamp){
571             found = true;
572             roi = *iter;
573             break;
574         }
575         iter++;
576     }
577     if (found) {
578         DEBUG_PRINT_LOW("found roidata with timestamp %lld us", roi.info.nTimeStamp);
579     }
580     pthread_mutex_unlock(&m_roilock);
581 }
582 
handle_dynamic_config(OMX_BUFFERHEADERTYPE * bufferHdr)583 bool venc_dev::handle_dynamic_config(OMX_BUFFERHEADERTYPE *bufferHdr)
584 {
585     std::list<dynamicConfig>::iterator iter;
586     OMX_TICKS timestamp = bufferHdr->nTimeStamp;
587     bool ret = false;
588 
589     pthread_mutex_lock(&m_configlock);
590     iter = m_configlist.begin();
591     while (iter != m_configlist.end()) {
592         if (iter->timestamp > timestamp) {
593             iter++;
594             continue;
595         }
596         DEBUG_PRINT_LOW("found dynamic config with timestamp %lld us", iter->timestamp);
597         switch ((int)iter->type) {
598             case OMX_QcomIndexConfigVideoLTRUse:
599                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_QcomIndexConfigVideoLTRUse");
600                 if (!venc_config_useLTR(&iter->config_data.useltr))
601                     goto bailout;
602                 break;
603             case OMX_QcomIndexConfigVideoLTRMark:
604                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_QcomIndexConfigVideoLTRMark");
605                 if (!venc_config_markLTR(&iter->config_data.markltr))
606                     goto bailout;
607                 break;
608             case OMX_IndexConfigVideoFramerate:
609                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_IndexConfigVideoFramerate");
610                 if (!venc_config_framerate(&iter->config_data.framerate))
611                     goto bailout;
612                 break;
613             case OMX_QcomIndexConfigQp:
614                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_QcomIndexConfigQp");
615                 if (!venc_config_qp(&iter->config_data.configqp))
616                     goto bailout;
617                 break;
618             case QOMX_IndexConfigVideoIntraperiod:
619                 DEBUG_PRINT_LOW("handle_dynamic_config:QOMX_IndexConfigVideoIntraperiod");
620                 if (!set_nP_frames(iter->config_data.intraperiod.nPFrames))
621                     goto bailout;
622                 break;
623             case OMX_IndexConfigVideoVp8ReferenceFrame:
624                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_IndexConfigVideoVp8ReferenceFrame");
625                 if (!venc_config_vp8refframe(&iter->config_data.vp8refframe))
626                     goto bailout;
627                 break;
628             case OMX_IndexConfigVideoIntraVOPRefresh:
629                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_IndexConfigVideoIntraVOPRefresh");
630                 if (!venc_config_intravoprefresh(&iter->config_data.intravoprefresh))
631                     goto bailout;
632                 break;
633             case OMX_IndexConfigVideoBitrate:
634                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_IndexConfigVideoBitrate");
635                 if (!venc_config_bitrate(&iter->config_data.bitrate))
636                     goto bailout;
637                 break;
638             case OMX_IndexConfigCommonMirror:
639                 DEBUG_PRINT_LOW("handle_dynamic_config: OMX_IndexConfigCommonMirror");
640                 if (!venc_set_mirror(iter->config_data.mirror.eMirror))
641                     goto bailout;
642                 break;
643             default:
644                 DEBUG_PRINT_ERROR("Unsupported dynamic config type %d with timestamp %lld us", iter->type, iter->timestamp);
645                 goto bailout;
646         }
647         iter = m_configlist.erase(iter);
648     }
649     ret = true;
650 
651 bailout:
652     pthread_mutex_unlock(&m_configlock);
653     return ret;
654 }
655 
handle_input_extradata(struct v4l2_buffer buf)656 bool venc_dev::handle_input_extradata(struct v4l2_buffer buf)
657 {
658     unsigned int filled_len = 0;
659     unsigned int index = buf.index;
660     int height = m_sVenc_cfg.input_height;
661     int width = m_sVenc_cfg.input_width;
662     OMX_TICKS nTimeStamp = static_cast<OMX_TICKS>(buf.timestamp.tv_sec) * 1000000 + buf.timestamp.tv_usec;
663     int fd = buf.m.planes[0].reserved[MSM_VIDC_BUFFER_FD];
664     char *p_extradata = NULL;
665     OMX_OTHER_EXTRADATATYPE *data = NULL;
666     struct roidata roi;
667     bool status = true;
668     OMX_U32 packet_size = 0;
669     OMX_U32 payload_size = 0;
670 
671     if (!EXTRADATA_IDX(num_input_planes)) {
672         DEBUG_PRINT_LOW("Input extradata not enabled");
673         return true;
674     }
675 
676     if (!input_extradata_info.ion[index].uaddr) {
677         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
678         return true;
679     }
680 
681     DEBUG_PRINT_HIGH("Processing Extradata for Buffer = %lld", nTimeStamp); // Useful for debugging
682     sync_start_rw(input_extradata_info.ion[index].data_fd);
683 
684     p_extradata = input_extradata_info.ion[index].uaddr;
685     data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
686     memset((void *)(data), 0, (input_extradata_info.buffer_size)); // clear stale data in current buffer
687 
688     if (m_cvp_meta_enabled && !(buf.flags & V4L2_BUF_FLAG_CVPMETADATA_SKIP)) {
689         packet_size = sizeof(struct msm_vidc_extradata_header) - sizeof(unsigned int)
690                            + cvpMetadata.size;
691 
692         if (filled_len + packet_size <= input_extradata_info.buffer_size) {
693             struct  msm_vidc_enc_cvp_metadata_payload *payload_cvp;
694             data->nSize = ALIGN(packet_size, 4);
695             data->nVersion.nVersion = OMX_SPEC_VERSION;
696             data->nPortIndex = PORT_INDEX_IN;
697             data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_CVP_METADATA;
698             data->nDataSize = cvpMetadata.size;
699             payload_cvp = (struct  msm_vidc_enc_cvp_metadata_payload *)(data->data);
700             memcpy(payload_cvp->data, cvpMetadata.payload, cvpMetadata.size);
701             filled_len += data->nSize;
702             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
703         } else {
704             DEBUG_PRINT_ERROR("Insufficient size for CVPMetadata: required %u buffer_size %lu filled_len %u",
705                packet_size, input_extradata_info.buffer_size, filled_len);
706             status = false;
707             goto bailout;
708         }
709     }
710     cvpMetadata.size = 0;
711 
712       /*
713        * Below code is based on these points.
714        * 1) As _PQ_ not defined in Napali :
715        *     a) Send data to Venus as ROI.
716        *     b) ROI enabled : Processed under unlocked context.
717        *     c) ROI disabled : Nothing to fill.
718        *     d) pq enabled : Not possible.
719        * 2) Normal ROI handling.
720        *     By this time if client sets next ROI, then we shouldn't process new ROI here.
721        */
722 
723     memset(&roi, 0, sizeof(struct roidata));
724     roi.dirty = false;
725     if (m_roi_enabled) {
726         get_roi_for_timestamp(roi, nTimeStamp);
727     }
728 
729     if (roi.dirty) {
730         OMX_U32 mbAlign = 16;
731         if (m_codec == OMX_VIDEO_CodingHEVC) {
732             mbAlign = 32;
733         }
734         OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
735         OMX_U32 mbRowAligned = ((mbRow + 7) >> 3) << 3;
736         OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
737         OMX_U32 numBytes = mbRowAligned * mbCol * 2;
738         OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
739 
740         data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload),256)
741                             + numBytesAligned;
742         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
743         if (data->nSize > input_extradata_info.buffer_size  - filled_len) {
744            DEBUG_PRINT_ERROR("Buffer size (%lu) is less than ROI extradata size (%u)",
745                              (input_extradata_info.buffer_size - filled_len) ,data->nSize);
746            status = false;
747            goto bailout;
748         }
749 
750         data->nVersion.nVersion = OMX_SPEC_VERSION;
751         data->nPortIndex = 0;
752         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
753         struct msm_vidc_roi_deltaqp_payload *roiData =
754                 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
755         roiData->b_roi_info = true;
756         roiData->mbi_info_size = numBytesAligned;
757         /* Video hardware expects ROI QP data to be aligned to 256,
758          * And its offset should be available in roiData->data[0].
759          *  -----------------
760          *  | unsigned int b_roi_info;   |
761          *  | int mbi_info_size;         |
762          *  ----------------------------
763          *  | data[0] = n                | => Contains Offset value to 256 aligned address
764          *  | .                          |
765          *  | .                          |
766          *  | .                          |
767          *  | data+n  <ROI data start>   | => 256 aligned address
768          *  ----------------------------
769          */
770         roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256) - (unsigned long)roiData->data);
771 
772         OMX_U8* tempBuf = (OMX_U8*)roi.info.pRoiMBInfo;
773         OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);;
774         OMX_U16* pBuf;
775         OMX_U8 clientROI;
776 
777         /* Convert input extradata format to HW compatible format
778          * Input        : 1byte per MB
779          * HW Format    : 2bytes per MB. (1 << 11) | ((clientROI & 0x3F)<< 4)
780          * MB Row must be aligned to 8
781          */
782         for (OMX_U32 j = 0;j < mbCol; j++)
783         {
784             pBuf = exDataBuf + j*mbRowAligned;
785             for (OMX_U32 i = 0;i < mbRow; i++)
786             {
787                 clientROI = *tempBuf++;
788                 *pBuf++ = (1 << 11) | ((clientROI & 0x3F)<< 4);
789             }
790         }
791         filled_len += data->nSize;
792         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
793     } else {
794         // m_roilist didn't contain any ROI info with OMX_IndexConfigVideoRoiInfo.
795         // then we can check mRoiRegionList which may contain the roi from vendor extension.
796         OMX_U32 freeSize = input_extradata_info.buffer_size - filled_len;
797         OMX_U32 appendSize = append_extradata_roi_region_qp_info(data, nTimeStamp, freeSize);
798         filled_len += appendSize;
799         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + appendSize);
800     }
801 
802     if (m_roi_enabled) {
803         if (roi.dirty) {
804             DEBUG_PRINT_LOW("free roidata with timestamp %lld us", roi.info.nTimeStamp);
805             roi.dirty = false;
806         }
807     }
808 
809     /* HDR10Plus MetaData information. Enabled by Default. */
810     payload_size = sizeof(struct msm_vidc_hdr10plus_metadata_payload) - sizeof(unsigned int)
811                                 + colorData.dynamicMetaDataLen;
812     packet_size = (sizeof(OMX_OTHER_EXTRADATATYPE) + payload_size + 3)&(~3);
813 
814     if (m_hdr10meta_enabled && (filled_len + packet_size <= input_extradata_info.buffer_size) && colorData.dynamicMetaDataLen > 0) {
815         struct msm_vidc_hdr10plus_metadata_payload *payload;
816 
817         data->nSize = packet_size;
818         data->nVersion.nVersion = OMX_SPEC_VERSION;
819         data->nPortIndex = 0;
820         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_HDR10PLUS_METADATA;
821         data->nDataSize = payload_size;
822 
823         payload = (struct  msm_vidc_hdr10plus_metadata_payload *)(data->data);
824         payload->size = colorData.dynamicMetaDataLen;
825         memcpy(payload->data, colorData.dynamicMetaDataPayload, colorData.dynamicMetaDataLen);
826 
827         filled_len += data->nSize;
828         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
829     } else if (colorData.dynamicMetaDataLen == 0) {
830         DEBUG_PRINT_HIGH("DynamicMetaDataLength == 0 Skip writing metadata.");
831     } else {
832         if (m_hdr10meta_enabled) {
833             DEBUG_PRINT_HIGH("Insufficient size for HDR10Metadata: Required %u Available %lu",
834                              packet_size, (input_extradata_info.buffer_size - filled_len));
835         }
836     }
837 
838     data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
839     data->nVersion.nVersion = OMX_SPEC_VERSION;
840     data->eType = OMX_ExtraDataNone;
841     data->nDataSize = 0;
842     data->data[0] = 0;
843 
844 bailout:
845     sync_end_rw(input_extradata_info.ion[index].data_fd);
846     return status;
847 }
848 
venc_handle_client_input_extradata(void * buffer)849 bool venc_dev::venc_handle_client_input_extradata(void *buffer)
850 {
851     OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
852     OMX_OTHER_EXTRADATATYPE *p_extra = (OMX_OTHER_EXTRADATATYPE*)p_bufhdr->pBuffer;
853     while(p_extra->eType != OMX_ExtraDataNone) {
854         switch((int)p_extra->eType) {
855             case OMX_ExtraDataInputROIInfo:
856             {
857                 OMX_QTI_VIDEO_CONFIG_ROIINFO* roiInfo = reinterpret_cast<OMX_QTI_VIDEO_CONFIG_ROIINFO*>(p_extra->data);
858                 struct roidata roi;
859                 if (!m_roi_enabled) {
860                     DEBUG_PRINT_ERROR("ROI info not enabled");
861                     return false;
862                 }
863 
864                 if (!roiInfo) {
865                     DEBUG_PRINT_ERROR("No ROI info present");
866                     return false;
867                 }
868                 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
869                 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
870                     DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
871                     return false;
872                 }
873 
874                 memset(&roi, 0, sizeof(struct roidata));
875 
876                 roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
877                 roi.info.nTimeStamp = roiInfo->nTimeStamp;
878                 memcpy(roi.info.pRoiMBInfo, &roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
879 
880                 roi.dirty = true;
881 
882                 pthread_mutex_lock(&m_roilock);
883                 DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
884                 m_roilist.push_back(roi);
885                 pthread_mutex_unlock(&m_roilock);
886                 break;
887             }
888         }
889         p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
890     }
891     return true;
892 }
893 
handle_output_extradata(void * buffer,int index)894 bool venc_dev::handle_output_extradata(void *buffer, int index)
895 {
896     OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer;
897     OMX_OTHER_EXTRADATATYPE *p_clientextra = NULL;
898     struct msm_vidc_extradata_header *p_extradata = NULL;
899     OMX_U32 remaining_fw_extradata_size = 0;
900 
901     if(venc_handle->m_client_output_extradata_mem_ptr && venc_handle->m_sExtraData
902         && venc_handle->m_client_out_extradata_info.getSize() >=
903         output_extradata_info.buffer_size) {
904         p_clientextra = (OMX_OTHER_EXTRADATATYPE * )
905             ((venc_handle->m_client_output_extradata_mem_ptr + index) ->pBuffer);
906     }
907     if (p_clientextra == NULL) {
908         DEBUG_PRINT_ERROR("Client Extradata buffers not allocated\n");
909         return false;
910     }
911 
912     if (!output_extradata_info.ion[index].uaddr) {
913         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
914         return false;
915     }
916     p_extradata = (struct msm_vidc_extradata_header *)output_extradata_info.ion[index].uaddr;
917 
918     memcpy(p_clientextra, p_extradata, output_extradata_info.buffer_size);
919 
920     /* just for debugging */
921     remaining_fw_extradata_size = output_extradata_info.buffer_size;
922     while (remaining_fw_extradata_size >= sizeof(OMX_OTHER_EXTRADATATYPE) &&
923             remaining_fw_extradata_size >= p_extradata->size &&
924             p_extradata->type != MSM_VIDC_EXTRADATA_NONE) {
925 
926         switch (p_extradata->type) {
927             case MSM_VIDC_EXTRADATA_METADATA_LTRINFO:
928             {
929                 DEBUG_PRINT_LOW("LTRInfo Extradata = 0x%x", *((OMX_U32 *)p_extradata->data));
930                 break;
931             }
932             default:
933                 /* No idea what this stuff is, just skip over it */
934                 DEBUG_PRINT_HIGH("Found an unrecognised extradata (%x) ignoring it",
935                         p_extradata->type);
936                 break;
937         }
938 
939         remaining_fw_extradata_size -= p_extradata->size;
940         p_extradata = (struct msm_vidc_extradata_header *) (
941             ((char *)p_extradata) + p_extradata->size);
942     }
943 
944     return true;
945 }
946 
venc_set_format(int format)947 int venc_dev::venc_set_format(int format)
948 {
949     int rc = true;
950 
951     if (format) {
952         color_format = format;
953 
954         switch (color_format) {
955         case NV12_128m:
956         case NV12_512:
957             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m);
958         case NV12_UBWC:
959             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed);
960         case YCbCr420_VENUS_P010:
961             return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
962         default:
963             return false;
964         }
965 
966     } else {
967         color_format = 0;
968         rc = false;
969     }
970 
971     return rc;
972 }
973 
venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)974 OMX_ERRORTYPE venc_dev::venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
975 {
976     OMX_ERRORTYPE eRet = OMX_ErrorNone;
977     struct v4l2_queryctrl profile_cap, level_cap, tier_cap;
978     int v4l2_profile;
979     int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
980                             QOMX_VIDEO_AVCProfileBaseline,
981                             QOMX_VIDEO_AVCProfileMain,
982                             QOMX_VIDEO_AVCProfileConstrainedHigh,
983                             QOMX_VIDEO_AVCProfileHigh };
984     int hevc_profiles[5] = { OMX_VIDEO_HEVCProfileMain,
985                              OMX_VIDEO_HEVCProfileMain10,
986                              OMX_VIDEO_HEVCProfileMainStill,
987                              OMX_VIDEO_HEVCProfileMain10HDR10,
988                              OMX_VIDEO_HEVCProfileMain10HDR10Plus };
989 
990     if (!profileLevelType)
991         return OMX_ErrorBadParameter;
992 
993     memset(&tier_cap, 0, sizeof(struct v4l2_queryctrl));
994     memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
995     memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
996 
997     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
998         level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
999         profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
1000     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1001         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
1002         profile_cap.id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE;
1003     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1004         tier_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_TIER;
1005         level_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL;
1006         profile_cap.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE;
1007     } else {
1008         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
1009         return OMX_ErrorInvalidComponent;
1010     }
1011 
1012     if (profile_cap.id) {
1013         if(!venc_query_cap(profile_cap)) {
1014             DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
1015             return OMX_ErrorHardware;
1016         }
1017     }
1018 
1019     if (level_cap.id) {
1020         if(!venc_query_cap(level_cap)) {
1021             DEBUG_PRINT_ERROR("Getting capabilities for level failed");
1022             return OMX_ErrorHardware;
1023         }
1024     }
1025 
1026     if (tier_cap.id) {
1027         if(!venc_query_cap(tier_cap)) {
1028             DEBUG_PRINT_ERROR("Getting capabilities for tier failed");
1029             return OMX_ErrorHardware;
1030         }
1031     }
1032 
1033     /* Get the corresponding omx level from v4l2 level */
1034     if (!profile_level_converter::convert_v4l2_level_to_omx(m_sVenc_cfg.codectype, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
1035         DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
1036         return OMX_ErrorHardware;
1037     }
1038     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC && tier_cap.maximum == V4L2_MPEG_VIDEO_HEVC_TIER_HIGH) {
1039         /* handle HEVC high tier */
1040         profileLevelType->eLevel <<= 1;
1041     }
1042 
1043     /* For given profile index get corresponding profile that needs to be supported */
1044     if (profileLevelType->nPortIndex != 1) {
1045         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on output port only %u",
1046                             (unsigned int)profileLevelType->nPortIndex);
1047         return OMX_ErrorBadPortIndex;
1048     }
1049 
1050     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1051         if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
1052             profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
1053         } else {
1054             DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1055                     (unsigned int)profileLevelType->nProfileIndex);
1056             return OMX_ErrorNoMore;
1057         }
1058     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1059         if (profileLevelType->nProfileIndex == 0) {
1060             profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
1061         } else {
1062             DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1063                     (unsigned int)profileLevelType->nProfileIndex);
1064             return OMX_ErrorNoMore;
1065         }
1066     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1067         if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
1068             profileLevelType->eProfile =  hevc_profiles[profileLevelType->nProfileIndex];
1069         } else {
1070             DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1071                     (unsigned int)profileLevelType->nProfileIndex);
1072             return OMX_ErrorNoMore;
1073         }
1074     }
1075 
1076     /* Check if the profile is supported by driver or not  */
1077     /* During query caps of profile driver sends a mask of */
1078     /* of all v4l2 profiles supported(in the flags field)  */
1079     if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, profileLevelType->eProfile, &v4l2_profile)) {
1080         DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
1081         return OMX_ErrorHardware;
1082     }
1083 
1084     DEBUG_PRINT_INFO("v4l2 profile : %d flags : %d ", v4l2_profile, profile_cap.flags);
1085     if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
1086         DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
1087         eRet = OMX_ErrorNoMore;
1088     }
1089 
1090     if (m_disable_hdr & ENC_HDR_DISABLE_FLAG) {
1091         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1092             if (profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10 ||
1093                 profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10HDR10 ||
1094                 profileLevelType->eProfile == OMX_VIDEO_HEVCProfileMain10HDR10Plus) {
1095                 DEBUG_PRINT_LOW("%s: HDR profile unsupported", __FUNCTION__);
1096                 return OMX_ErrorHardware;
1097             }
1098         }
1099     }
1100 
1101     DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
1102             (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
1103     return eRet;
1104 }
1105 
venc_get_supported_color_format(unsigned index,OMX_U32 * colorFormat)1106 bool venc_dev::venc_get_supported_color_format(unsigned index, OMX_U32 *colorFormat) {
1107 #ifdef _UBWC_
1108     //we support following formats
1109     //index 0 - Compressed (UBWC) Venus flavour of YUV420SP
1110     //index 1 - Venus flavour of YUV420SP
1111     //index 2 - Compressed (UBWC) TP10 (10bit packed)
1112     //index 3 - Compressed (UBWC) Venus flavour of RGBA8888
1113     //index 4 - Venus flavour of RGBA8888
1114     //index 5 - opaque which internally maps to YUV420SP.
1115     //index 6 - vannilla YUV420SP
1116     //this can be extended in the future
1117     int supportedFormats[] = {
1118         [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed,
1119         [1] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1120         [2] = QOMX_COLOR_FormatYVU420SemiPlanar,
1121         [3] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed,
1122         [4] = QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus,
1123         [5] = QOMX_COLOR_Format32bitRGBA8888Compressed,
1124         [6] = QOMX_COLOR_Format32bitRGBA8888,
1125         [7] = QOMX_COLOR_FormatAndroidOpaque,
1126         [8] = OMX_COLOR_FormatYUV420SemiPlanar,
1127     };
1128 #else
1129     //we support two formats
1130     //index 0 - Venus flavour of YUV420SP
1131     //index 1 - opaque which internally maps to YUV420SP.
1132     //index 2 - vannilla YUV420SP
1133     //this can be extended in the future
1134     int supportedFormats[] = {
1135         [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1136         [1] = QOMX_COLOR_FormatYVU420SemiPlanar,
1137         [2] = QOMX_COLOR_FormatAndroidOpaque,
1138         [3] = OMX_COLOR_FormatYUV420SemiPlanar,
1139     };
1140 #endif
1141     if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1))
1142         return false;
1143     *colorFormat = supportedFormats[index];
1144     return true;
1145 }
1146 
allocate_extradata(struct extradata_buffer_info * extradata_info,int flags)1147 OMX_ERRORTYPE venc_dev::allocate_extradata(struct extradata_buffer_info *extradata_info, int flags)
1148 {
1149     if (extradata_info->allocated)
1150         return OMX_ErrorNone;
1151 
1152     if (!extradata_info->buffer_size || !extradata_info->count) {
1153         DEBUG_PRINT_ERROR("Invalid extradata buffer size(%lu) or count(%d) for port %d",
1154             extradata_info->buffer_size, extradata_info->count, extradata_info->port_index);
1155         return OMX_ErrorUndefined;
1156     }
1157 
1158 #ifdef USE_ION
1159 
1160     for (int i = 0; i < extradata_info->count; i++) {
1161         if (extradata_info->ion[i].data_fd != -1) {
1162             venc_handle->ion_unmap(extradata_info->ion[i].data_fd,
1163                     (void *)extradata_info->ion[i].uaddr, extradata_info->buffer_size);
1164             venc_handle->free_ion_memory(&extradata_info->ion[i]);
1165         }
1166 
1167         // ION_IOC_MAP defined @ bionic/libc/kernel/uapi/linux/ion.h not in kernel,
1168         // and this ioctl uses "struct ion_fd_data" with handle member
1169         // Refer alloc_map_ion_memory definition @omx_video_base.cpp
1170         bool status = venc_handle->alloc_map_ion_memory(
1171                 extradata_info->buffer_size, &extradata_info->ion[i], flags);
1172 
1173         if (status == false) {
1174             DEBUG_PRINT_ERROR("Failed to alloc extradata memory\n");
1175             return OMX_ErrorInsufficientResources;
1176         }
1177 
1178         extradata_info->ion[i].uaddr = (char *)venc_handle->ion_map(extradata_info->ion[i].data_fd,
1179                                                 extradata_info->buffer_size);
1180 
1181         if (extradata_info->ion[i].uaddr == MAP_FAILED) {
1182             DEBUG_PRINT_ERROR("Failed to map extradata memory\n");
1183             venc_handle->free_ion_memory(&extradata_info->ion[i]);
1184             return OMX_ErrorInsufficientResources;
1185         } else {
1186             DEBUG_PRINT_HIGH("memset extradata buffer size %lu", extradata_info->buffer_size);
1187             memset((char *)extradata_info->ion[i].uaddr, 0, extradata_info->buffer_size);
1188         }
1189     }
1190 #else
1191     (void)flags;
1192 #endif
1193     extradata_info->allocated = OMX_TRUE;
1194     return OMX_ErrorNone;
1195 }
1196 
free_extradata(struct extradata_buffer_info * extradata_info)1197 void venc_dev::free_extradata(struct extradata_buffer_info *extradata_info)
1198 {
1199 #ifdef USE_ION
1200 
1201     if (extradata_info == NULL) {
1202         return;
1203     }
1204 
1205     for (int i = 0; i < extradata_info->count; i++) {
1206         if (extradata_info->ion[i].uaddr) {
1207             venc_handle->ion_unmap(extradata_info->ion[i].data_fd,
1208                     (void *)extradata_info->ion[i].uaddr, extradata_info->buffer_size);
1209             extradata_info->ion[i].uaddr = NULL;
1210             venc_handle->free_ion_memory(&extradata_info->ion[i]);
1211         }
1212         memset(&extradata_info->ion[i].alloc_data, 0, sizeof(struct ion_allocation_data));
1213     }
1214     extradata_info->buffer_size = 0;
1215     extradata_info->count = 0;
1216     extradata_info->allocated = OMX_FALSE;
1217 #else
1218     (void)extradata_info;
1219 #endif // USE_ION
1220 }
1221 
free_extradata_all()1222 void venc_dev::free_extradata_all()
1223 {
1224     free_extradata(&output_extradata_info);
1225     free_extradata(&input_extradata_info);
1226 }
1227 
venc_get_output_log_flag()1228 bool venc_dev::venc_get_output_log_flag()
1229 {
1230     return (m_debug.out_buffer_log == 1);
1231 }
1232 
venc_cvp_log_buffers(const char * metadataName,uint32_t buffer_len,uint8_t * buf)1233 int venc_dev::venc_cvp_log_buffers(const char *metadataName, uint32_t buffer_len, uint8_t *buf)
1234 {
1235     if (!m_debug.cvpfile && m_debug.cvp_log) {
1236         int size = 0;
1237 
1238         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 ||
1239             m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1240                 size = snprintf(m_debug.cvpfile_name, PROPERTY_VALUE_MAX, "%s/enc_cvp_%lu_%lu_%p.bin",
1241                         m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1242         }
1243 
1244         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1245             DEBUG_PRINT_ERROR("Failed to open cvp file: %s for logging size:%d",
1246                     m_debug.cvpfile_name, size);
1247         }
1248 
1249         m_debug.cvpfile = fopen(m_debug.cvpfile_name, "ab");
1250         if (!m_debug.cvpfile) {
1251             DEBUG_PRINT_ERROR("Failed to open cvp file: %s for logging errno:%d",
1252                             m_debug.cvpfile_name, errno);
1253             m_debug.cvpfile_name[0] = '\0';
1254             return -1;
1255         }
1256     }
1257 
1258     if (m_debug.cvpfile) {
1259         // Truncate or Zero-filled to match the string size to 5
1260         char name[6] = {0};
1261         for(int i=0; i<5 && i<strlen(metadataName); i++) {
1262             name[i] = metadataName[i];
1263         }
1264         fwrite(name, 5, 1, m_debug.cvpfile);                            // Metadata name
1265         fwrite(&buffer_len, sizeof(buffer_len), 1, m_debug.cvpfile);    // Blob size
1266         fwrite(buf, buffer_len, 1, m_debug.cvpfile);                    // Blob data
1267     }
1268     return 0;
1269 }
1270 
1271 
venc_output_log_buffers(const char * buffer_addr,int buffer_len,uint64_t timestamp)1272 int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len, uint64_t timestamp)
1273 {
1274     if (venc_handle->is_secure_session()) {
1275         DEBUG_PRINT_ERROR("logging secure output buffers is not allowed!");
1276         return -1;
1277     }
1278 
1279     if (!m_debug.outfile) {
1280         int size = 0;
1281         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1282            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.264",
1283                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1284         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1285            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%ld_%ld_%p.265",
1286                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1287         } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1288            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.ivf",
1289                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1290         }
1291 
1292         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1293              DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1294                                 m_debug.outfile_name, size);
1295         }
1296         m_debug.outfile = fopen(m_debug.outfile_name, "ab");
1297         if (!m_debug.outfile) {
1298             DEBUG_PRINT_ERROR("Failed to open output file: %s for logging errno:%d",
1299                                m_debug.outfile_name, errno);
1300             m_debug.outfile_name[0] = '\0';
1301             return -1;
1302         }
1303         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1304             int fps = m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
1305             IvfFileHeader ivfFileHeader(false, m_sVenc_cfg.input_width,
1306                                         m_sVenc_cfg.input_height, fps, 1, 0);
1307             fwrite(&ivfFileHeader, sizeof(ivfFileHeader), 1, m_debug.outfile);
1308         }
1309     }
1310     if (m_debug.outfile && buffer_len) {
1311         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1312             IvfFrameHeader ivfFrameHeader(buffer_len, timestamp);
1313             fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.outfile);
1314         }
1315         DEBUG_PRINT_LOW("%s buffer_len:%d", __func__, buffer_len);
1316         fwrite(buffer_addr, buffer_len, 1, m_debug.outfile);
1317     }
1318     return 0;
1319 }
1320 
venc_extradata_log_buffers(char * buffer_addr,int index,bool input)1321 int venc_dev::venc_extradata_log_buffers(char *buffer_addr, int index, bool input)
1322 {
1323     int fd;
1324 
1325     if (input)
1326         fd = input_extradata_info.ion[index].data_fd;
1327     else
1328         fd = output_extradata_info.ion[index].data_fd;
1329 
1330     sync_start_read(fd);
1331     if (!m_debug.extradatafile && m_debug.extradata_log) {
1332         int size = 0;
1333 
1334         if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 ||
1335             m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC ||
1336             m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1337             size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1338                             m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1339         }
1340         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1341              DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging size:%d",
1342                                 m_debug.extradatafile_name, size);
1343         }
1344 
1345         m_debug.extradatafile = fopen(m_debug.extradatafile_name, "ab");
1346         if (!m_debug.extradatafile) {
1347             DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging errno:%d",
1348                                m_debug.extradatafile_name, errno);
1349             m_debug.extradatafile_name[0] = '\0';
1350             sync_end_read(fd);
1351             return -1;
1352         }
1353     }
1354 
1355     if (m_debug.extradatafile && buffer_addr) {
1356         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
1357         do {
1358             p_extra = (OMX_OTHER_EXTRADATATYPE *)(!p_extra ? buffer_addr :
1359                     ((char *)p_extra) + p_extra->nSize);
1360             fwrite(p_extra, p_extra->nSize, 1, m_debug.extradatafile);
1361         } while (p_extra->eType != OMX_ExtraDataNone);
1362     }
1363     sync_end_read(fd);
1364     return 0;
1365 }
1366 
venc_input_log_buffers(OMX_BUFFERHEADERTYPE * pbuffer,int fd,int plane_offset,unsigned long inputformat,bool interlaced)1367 int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset,
1368         unsigned long inputformat, bool interlaced) {
1369     int status = 0;
1370     if (venc_handle->is_secure_session()) {
1371         DEBUG_PRINT_ERROR("logging secure input buffers is not allowed!");
1372         return -1;
1373     }
1374 
1375     sync_start_read(fd);
1376     if (!m_debug.infile) {
1377         int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%lu_%lu_%p.yuv",
1378                             m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1379         if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1380              DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1381                                 m_debug.infile_name, size);
1382         }
1383         m_debug.infile = fopen (m_debug.infile_name, "ab");
1384         if (!m_debug.infile) {
1385             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1386             m_debug.infile_name[0] = '\0';
1387             status = -1;
1388             goto bailout;
1389         }
1390     }
1391 
1392     if (m_debug.infile && pbuffer && pbuffer->nFilledLen) {
1393         unsigned long stride, scanlines;
1394         unsigned long color_format;
1395         unsigned long i, msize;
1396         unsigned char *pvirt = NULL, *ptemp = NULL;
1397         unsigned char *temp = (unsigned char *)pbuffer->pBuffer;
1398 
1399         color_format = get_media_colorformat(inputformat);
1400 
1401         msize = VENUS_BUFFER_SIZE_USED(color_format, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,interlaced);
1402         const unsigned int extra_size = VENUS_EXTRADATA_SIZE(m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
1403 
1404         if (metadatamode == 1) {
1405             pvirt= (unsigned char *)mmap(NULL, msize, PROT_READ|PROT_WRITE,MAP_SHARED, fd, plane_offset);
1406             if (pvirt == MAP_FAILED) {
1407                 DEBUG_PRINT_ERROR("%s mmap failed", __func__);
1408                 status = -1;
1409                 goto bailout;
1410             }
1411             ptemp = pvirt;
1412         } else {
1413             ptemp = temp;
1414         }
1415 
1416         if (color_format == COLOR_FMT_NV12) {
1417             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1418             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1419 
1420             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1421                 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1422                 ptemp += stride;
1423             }
1424             if (metadatamode == 1) {
1425                 ptemp = pvirt + (stride * scanlines);
1426             } else {
1427                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1428             }
1429             for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1430                 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1431                 ptemp += stride;
1432             }
1433         } else if (color_format == COLOR_FMT_NV12_512) {
1434             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1435             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1436 
1437             for (i = 0; i < scanlines; i++) {
1438                 fwrite(ptemp, stride, 1, m_debug.infile);
1439                 ptemp += stride;
1440             }
1441             if (metadatamode == 1) {
1442                 ptemp = pvirt + (stride * scanlines);
1443             } else {
1444                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1445             }
1446             for (i = 0; i < scanlines/2; i++) {
1447                 fwrite(ptemp, stride, 1, m_debug.infile);
1448                 ptemp += stride;
1449             }
1450         } else if (color_format == COLOR_FMT_RGBA8888) {
1451             stride = VENUS_RGB_STRIDE(color_format, m_sVenc_cfg.input_width);
1452             scanlines = VENUS_RGB_SCANLINES(color_format, m_sVenc_cfg.input_height);
1453 
1454             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1455                 fwrite(ptemp, m_sVenc_cfg.input_width * 4, 1, m_debug.infile);
1456                 ptemp += stride;
1457             }
1458         } else if (color_format == COLOR_FMT_NV12_UBWC || color_format == COLOR_FMT_NV12_BPP10_UBWC || color_format == COLOR_FMT_RGBA8888_UBWC) {
1459             fwrite(ptemp, msize, 1, m_debug.infile);
1460         } else if(color_format == COLOR_FMT_P010) {
1461             stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1462             scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1463 
1464             for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1465                 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1466                 ptemp += stride;
1467             }
1468             if (metadatamode == 1) {
1469                 ptemp = pvirt + (stride * scanlines);
1470             } else {
1471                 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1472             }
1473             for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1474                 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1475                 ptemp += stride;
1476             }
1477         }
1478 
1479         if (metadatamode == 1 && pvirt) {
1480             munmap(pvirt, msize);
1481         }
1482     }
1483 bailout:
1484     sync_end_read(fd);
1485     return status;
1486 }
1487 
venc_open(OMX_U32 codec)1488 bool venc_dev::venc_open(OMX_U32 codec)
1489 {
1490     int r, minqp = 0, maxqp = 127;
1491     unsigned int alignment = 0,buffer_size = 0, temp =0;
1492     struct v4l2_control control;
1493     OMX_STRING device_name = (OMX_STRING)"/dev/video33";
1494     char property_value[PROPERTY_VALUE_MAX] = {0};
1495     FILE *soc_file = NULL;
1496     char buffer[10];
1497 
1498     m_nDriver_fd = open (device_name, O_RDWR);
1499     if ((int)m_nDriver_fd < 0) {
1500         DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure");
1501         return false;
1502     }
1503     m_poll_efd = eventfd(0, 0);
1504     if (m_poll_efd < 0) {
1505         DEBUG_PRINT_ERROR("Failed to open event fd(%s)", strerror(errno));
1506         return false;
1507     }
1508     DEBUG_PRINT_LOW("m_nDriver_fd = %u", (unsigned int)m_nDriver_fd);
1509 
1510     // set the basic configuration of the video encoder driver
1511     m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH;
1512     m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT;
1513     m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH;
1514     m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT;
1515     m_sVenc_cfg.fps_num = 30;
1516     m_sVenc_cfg.fps_den = 1;
1517     m_sVenc_cfg.targetbitrate = 64000;
1518     m_sVenc_cfg.inputformat= V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1519     m_rotation.rotation = 0;
1520     m_codec = codec;
1521     downscalar_enabled = OMX_FALSE;
1522 
1523     if (codec == OMX_VIDEO_CodingAVC) {
1524         m_sVenc_cfg.codectype = V4L2_PIX_FMT_H264;
1525         codec_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1526         profile_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1527         idrperiod.idrperiod = 1;
1528         minqp = 0;
1529         maxqp = 51;
1530     } else if (codec == OMX_VIDEO_CodingVP8) {
1531         m_sVenc_cfg.codectype = V4L2_PIX_FMT_VP8;
1532         codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
1533         profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
1534         minqp = 0;
1535         maxqp = 127;
1536     } else if (codec == OMX_VIDEO_CodingHEVC || codec == OMX_VIDEO_CodingImageHEIC) {
1537         m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC;
1538         idrperiod.idrperiod = 1;
1539         minqp = 0;
1540         maxqp = 51;
1541         if (codec == OMX_VIDEO_CodingImageHEIC) {
1542             m_sVenc_cfg.input_width = DEFAULT_TILE_DIMENSION;
1543             m_sVenc_cfg.input_height= DEFAULT_TILE_DIMENSION;
1544             m_sVenc_cfg.dvs_width = DEFAULT_TILE_DIMENSION;
1545             m_sVenc_cfg.dvs_height = DEFAULT_TILE_DIMENSION;
1546             codec_profile.profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
1547         } else
1548             codec_profile.profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN;
1549         profile_level.level = V4L2_MPEG_VIDEO_HEVC_LEVEL_1;
1550     }
1551 
1552     session_ipb_qp_values.min_qp_packed = minqp | (minqp << 8) | (minqp << 16);
1553     session_ipb_qp_values.max_qp_packed = maxqp | (maxqp << 8) | (maxqp << 16);
1554 
1555     int ret;
1556     ret = subscribe_to_events(m_nDriver_fd);
1557 
1558     if (ret) {
1559         DEBUG_PRINT_ERROR("Subscribe Event Failed");
1560         return false;
1561     }
1562 
1563     struct v4l2_fmtdesc fdesc;
1564     struct v4l2_format fmt;
1565     struct v4l2_requestbuffers bufreq;
1566     struct v4l2_capability cap;
1567 
1568     ret = ioctl(m_nDriver_fd, VIDIOC_QUERYCAP, &cap);
1569 
1570     if (ret) {
1571         DEBUG_PRINT_ERROR("Failed to query capabilities");
1572     } else {
1573         DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1574                 " version = %d, capabilities = %x", cap.driver, cap.card,
1575                 cap.bus_info, cap.version, cap.capabilities);
1576     }
1577 
1578     ret=0;
1579     fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1580     fdesc.index=0;
1581 
1582     while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1583         DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1584                 fdesc.pixelformat, fdesc.flags);
1585         fdesc.index++;
1586     }
1587 
1588     fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1589     fdesc.index=0;
1590 
1591     while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1592         DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1593                 fdesc.pixelformat, fdesc.flags);
1594         fdesc.index++;
1595     }
1596 
1597     if(venc_handle->is_secure_session()) {
1598         control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1599         control.value = 1;
1600         DEBUG_PRINT_HIGH("ioctl: open secure device");
1601         ret=ioctl(m_nDriver_fd, VIDIOC_S_CTRL,&control);
1602         if (ret) {
1603             DEBUG_PRINT_ERROR("ioctl: open secure dev fail, rc %d", ret);
1604             return false;
1605         }
1606     }
1607 
1608     if (venc_handle->is_secure_session()) {
1609         m_sOutput_buff_property.alignment = SZ_1M;
1610         m_sInput_buff_property.alignment  = SZ_1M;
1611     } else {
1612         m_sOutput_buff_property.alignment = SZ_4K;
1613         m_sInput_buff_property.alignment  = SZ_4K;
1614     }
1615 
1616     if (m_codec == OMX_VIDEO_CodingImageHEIC) {
1617         if (!venc_set_grid_enable()) {
1618             DEBUG_PRINT_ERROR("Failed to enable grid");
1619             return false;
1620         }
1621     }
1622 
1623     memset(&fmt, 0, sizeof(fmt));
1624     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1625     fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
1626     fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
1627     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
1628 
1629     /*TODO: Return values not handled properly in this function anywhere.
1630      * Need to handle those.*/
1631     ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1632 
1633     if (ret) {
1634         DEBUG_PRINT_ERROR("Failed to set format on capture port");
1635         return false;
1636     }
1637 
1638     m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1639 
1640     memset(&fmt, 0, sizeof(fmt));
1641     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1642     fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
1643     fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
1644     fmt.fmt.pix_mp.pixelformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1645     fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
1646 
1647     ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1648     m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1649 
1650     bufreq.memory = V4L2_MEMORY_USERPTR;
1651     bufreq.count = 2;
1652 
1653     bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1654     ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1655     m_sInput_buff_property.mincount = m_sInput_buff_property.actualcount = bufreq.count;
1656 
1657     bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1658     bufreq.count = 2;
1659     ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1660     m_sOutput_buff_property.mincount = m_sOutput_buff_property.actualcount = bufreq.count;
1661 
1662     resume_in_stopped = 0;
1663     metadatamode = 0;
1664 
1665     struct v4l2_frmsizeenum frmsize;
1666 
1667     //Get the hardware capabilities
1668     memset((void *)&frmsize,0,sizeof(frmsize));
1669     frmsize.index = 0;
1670     frmsize.pixel_format = m_sVenc_cfg.codectype;
1671     ret = ioctl(m_nDriver_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize);
1672 
1673     if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
1674         DEBUG_PRINT_ERROR("Failed to get framesizes");
1675         return false;
1676     }
1677 
1678     if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1679         capability.min_width = frmsize.stepwise.min_width;
1680         capability.max_width = frmsize.stepwise.max_width;
1681         capability.min_height = frmsize.stepwise.min_height;
1682         capability.max_height = frmsize.stepwise.max_height;
1683     }
1684 
1685     //Initialize non-default parameters
1686     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1687         control.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
1688         control.value = 0x7fffffff;
1689         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1690             DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAME\n");
1691     }
1692 
1693     //Disable auto blur by default
1694     if (is_auto_blur_disabled) {
1695         control.id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS;
1696         control.value = 0x2;
1697         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1698            DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS\n");
1699     }
1700 
1701 
1702     /* Enable Low power mode by default for better power */
1703 
1704     input_extradata_info.port_index = OUTPUT_PORT;
1705     output_extradata_info.port_index = CAPTURE_PORT;
1706 
1707     return true;
1708 }
1709 
unsubscribe_to_events(int fd)1710 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
1711 {
1712     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1713     struct v4l2_event_subscription sub;
1714     int array_sz = sizeof(event_type)/sizeof(int);
1715     int i,rc;
1716 
1717     if (fd < 0) {
1718        DEBUG_PRINT_ERROR("Invalid input: %d", fd);
1719         return OMX_ErrorBadParameter;
1720     }
1721 
1722     for (i = 0; i < array_sz; ++i) {
1723         memset(&sub, 0, sizeof(sub));
1724         sub.type = event_type[i];
1725         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1726 
1727         if (rc) {
1728            DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
1729             break;
1730         }
1731     }
1732 
1733     return eRet;
1734 }
1735 
venc_close()1736 void venc_dev::venc_close()
1737 {
1738     DEBUG_PRINT_LOW("venc_close: fd = %u", (unsigned int)m_nDriver_fd);
1739 
1740     if ((int)m_nDriver_fd >= 0) {
1741         DEBUG_PRINT_HIGH("venc_close E");
1742 
1743         if(eventfd_write(m_poll_efd, 1)) {
1744             DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
1745             async_thread_force_stop = true;
1746         }
1747 
1748         if (async_thread_created)
1749             pthread_join(m_tid,NULL);
1750 
1751         if (venc_handle->msg_thread_created) {
1752             venc_handle->msg_thread_created = false;
1753             venc_handle->msg_thread_stop = true;
1754             post_message(venc_handle, omx_video::OMX_COMPONENT_CLOSE_MSG);
1755             DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
1756             pthread_join(venc_handle->msg_thread_id, NULL);
1757         }
1758         DEBUG_PRINT_HIGH("venc_close X");
1759         unsubscribe_to_events(m_nDriver_fd);
1760         close(m_poll_efd);
1761         close(m_nDriver_fd);
1762         m_nDriver_fd = -1;
1763     }
1764 
1765     if (m_debug.infile) {
1766         fclose(m_debug.infile);
1767         m_debug.infile = NULL;
1768     }
1769 
1770     if (m_debug.outfile) {
1771         fclose(m_debug.outfile);
1772         m_debug.outfile = NULL;
1773     }
1774 
1775     if (m_debug.extradatafile) {
1776         fclose(m_debug.extradatafile);
1777         m_debug.extradatafile = NULL;
1778     }
1779 
1780     if (m_debug.cvpfile) {
1781         fclose(m_debug.cvpfile);
1782         m_debug.cvpfile = NULL;
1783     }
1784 }
1785 
venc_set_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)1786 bool venc_dev::venc_set_buf_req(OMX_U32 *min_buff_count,
1787         OMX_U32 *actual_buff_count,
1788         OMX_U32 *buff_size,
1789         OMX_U32 port)
1790 {
1791     (void)min_buff_count, (void)buff_size;
1792     unsigned long temp_count = 0;
1793 
1794     if (port == 0) {
1795         if (*actual_buff_count > m_sInput_buff_property.mincount) {
1796             temp_count = m_sInput_buff_property.actualcount;
1797             m_sInput_buff_property.actualcount = *actual_buff_count;
1798             DEBUG_PRINT_LOW("I/P Count set to %u", (unsigned int)*actual_buff_count);
1799         }
1800     } else {
1801         if (*actual_buff_count > m_sOutput_buff_property.mincount) {
1802             temp_count = m_sOutput_buff_property.actualcount;
1803             m_sOutput_buff_property.actualcount = *actual_buff_count;
1804             DEBUG_PRINT_LOW("O/P Count set to %u", (unsigned int)*actual_buff_count);
1805         }
1806     }
1807 
1808     return true;
1809 
1810 }
1811 
venc_loaded_start()1812 bool venc_dev::venc_loaded_start()
1813 {
1814     return true;
1815 }
1816 
venc_loaded_stop()1817 bool venc_dev::venc_loaded_stop()
1818 {
1819     return true;
1820 }
1821 
venc_loaded_start_done()1822 bool venc_dev::venc_loaded_start_done()
1823 {
1824     return true;
1825 }
1826 
venc_loaded_stop_done()1827 bool venc_dev::venc_loaded_stop_done()
1828 {
1829     return true;
1830 }
1831 
venc_get_seq_hdr(void * buffer,unsigned buffer_size,unsigned * header_len)1832 bool venc_dev::venc_get_seq_hdr(void *buffer,
1833         unsigned buffer_size, unsigned *header_len)
1834 {
1835     (void) buffer, (void) buffer_size, (void) header_len;
1836     return true;
1837 }
1838 
venc_get_dimensions(OMX_U32 portIndex,OMX_U32 * w,OMX_U32 * h)1839 bool venc_dev::venc_get_dimensions(OMX_U32 portIndex, OMX_U32 *w, OMX_U32 *h) {
1840     struct v4l2_format fmt;
1841     memset(&fmt, 0, sizeof(fmt));
1842     fmt.type = portIndex == PORT_INDEX_OUT ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1843             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1844 
1845     if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
1846         DEBUG_PRINT_ERROR("Failed to get format on %s port",
1847                 portIndex == PORT_INDEX_OUT ? "capture" : "output");
1848         return false;
1849     }
1850     *w = fmt.fmt.pix_mp.width;
1851     *h = fmt.fmt.pix_mp.height;
1852     return true;
1853 }
1854 
venc_get_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)1855 bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
1856         OMX_U32 *actual_buff_count,
1857         OMX_U32 *buff_size,
1858         OMX_U32 port)
1859 {
1860     struct v4l2_format fmt;
1861     unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
1862     int ret;
1863     int extra_idx = 0;
1864     struct v4l2_control control;
1865     unsigned int minCount = 0;
1866 
1867     memset(&control, 0, sizeof(control));
1868     memset(&fmt, 0, sizeof(fmt));
1869 
1870     if (port == 0) {
1871         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1872         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
1873         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
1874         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
1875         fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
1876         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
1877         if (ret) {
1878             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x, colorspace %d\n",
1879                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1880                 fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
1881             return false;
1882         }
1883         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1884 
1885         control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
1886         ret = ioctl(m_nDriver_fd,  VIDIOC_G_CTRL, &control);
1887         if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
1888             DEBUG_PRINT_ERROR("Driver returned invalid data, port = %d ret = %d Count = %d",
1889                 port, ret, (unsigned int)control.value);
1890             return false;
1891         }
1892 
1893         // Request MAX_V4L2_BUFS from V4L2 in batch mode.
1894         // Keep the original count for the client
1895         if (metadatamode && mBatchSize) {
1896             minCount = MAX_V4L2_BUFS;
1897             DEBUG_PRINT_LOW("Set buffer count = %d as metadata mode and batchmode enabled", minCount);
1898         }
1899 
1900         minCount = MAX((unsigned int)control.value, minCount);
1901         m_sInput_buff_property.mincount = minCount;
1902         m_sInput_buff_property.actualcount = m_sInput_buff_property.mincount;
1903 
1904         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1905         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
1906         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
1907         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
1908         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
1909         if (ret) {
1910             DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
1911                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1912                 fmt.fmt.pix_mp.pixelformat);
1913             return false;
1914         }
1915         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1916 
1917         *min_buff_count = m_sInput_buff_property.mincount;
1918         *actual_buff_count = m_sInput_buff_property.actualcount;
1919 #ifdef USE_ION
1920         // For ION memory allocations of the allocated buffer size
1921         // must be 4k aligned, hence aligning the input buffer
1922         // size to 4k.
1923         m_sInput_buff_property.datasize = ALIGN(m_sInput_buff_property.datasize, SZ_4K);
1924 #endif
1925         *buff_size = m_sInput_buff_property.datasize;
1926         num_input_planes = fmt.fmt.pix_mp.num_planes;
1927         extra_idx = EXTRADATA_IDX(num_input_planes);
1928 
1929         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
1930             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
1931         } else if (extra_idx >= VIDEO_MAX_PLANES) {
1932             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx);
1933             return false;
1934         }
1935         input_extradata_info.buffer_size =  ALIGN(extra_data_size, SZ_4K);
1936         input_extradata_info.count = m_sInput_buff_property.actualcount;
1937         venc_handle->m_client_in_extradata_info.set_extradata_info(input_extradata_info.buffer_size,m_sInput_buff_property.actualcount);
1938     } else {
1939         unsigned int extra_idx = 0;
1940         memset(&fmt, 0, sizeof(fmt));
1941         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1942         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
1943         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
1944         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
1945 
1946         ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1947         if (ret) {
1948             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x\n",
1949                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1950                 fmt.fmt.pix_mp.pixelformat);
1951             return false;
1952         }
1953 
1954         m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1955         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1956         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
1957         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
1958         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
1959 
1960         ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
1961         if (ret) {
1962             DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
1963                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1964                 fmt.fmt.pix_mp.pixelformat);
1965             return false;
1966         }
1967         m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1968 
1969         control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
1970 
1971         ret = ioctl(m_nDriver_fd,  VIDIOC_G_CTRL, &control);
1972         if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
1973             DEBUG_PRINT_ERROR("Driver returned invalid data port = %d ret = %d Count = %d",
1974                 port, ret, (unsigned int)control.value);
1975             return false;
1976         }
1977         minCount = control.value;
1978 
1979         if (mBatchSize) {
1980             // If we're in batch mode, we'd like to end up in a situation where
1981             // driver is able to own mBatchSize buffers and we'd also own atleast
1982             // mBatchSize buffers
1983             minCount = MAX((unsigned int)control.value, mBatchSize) + mBatchSize;
1984             DEBUG_PRINT_LOW("set min count %d as mBatchSize %d", minCount, mBatchSize);
1985         }
1986 
1987         m_sOutput_buff_property.mincount = minCount;
1988         m_sOutput_buff_property.actualcount = m_sOutput_buff_property.mincount;
1989 
1990         *min_buff_count = m_sOutput_buff_property.mincount;
1991         *actual_buff_count = m_sOutput_buff_property.actualcount;
1992         *buff_size = m_sOutput_buff_property.datasize;
1993         num_output_planes = fmt.fmt.pix_mp.num_planes;
1994         extra_idx = EXTRADATA_IDX(num_output_planes);
1995 
1996         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
1997             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
1998         } else if (extra_idx >= VIDEO_MAX_PLANES) {
1999             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
2000             return false;
2001         }
2002 
2003         output_extradata_info.buffer_size = ALIGN(extra_data_size, SZ_4K);
2004         output_extradata_info.count = m_sOutput_buff_property.actualcount;
2005         venc_handle->m_client_out_extradata_info.set_extradata_info(output_extradata_info.buffer_size,output_extradata_info.count);
2006     }
2007 
2008     DEBUG_PRINT_HIGH("venc_get_buf_req: port %d, wxh %dx%d, format %#x, driver min count %d, "
2009         "updated min count %d, act count %d, size %d, num planes %d",
2010         port, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.pixelformat,
2011         control.value, *min_buff_count, *actual_buff_count, *buff_size, fmt.fmt.pix_mp.num_planes);
2012 
2013     return true;
2014 }
2015 
venc_handle_empty_eos_buffer(void)2016 bool venc_dev::venc_handle_empty_eos_buffer( void)
2017 {
2018     struct v4l2_encoder_cmd enc;
2019     int rc = 0;
2020 
2021     if (!streaming[OUTPUT_PORT]) {
2022         enum v4l2_buf_type buf_type;
2023         struct v4l2_control control;
2024         int ret = 0;
2025 
2026         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2027 
2028         DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
2029         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
2030         if (ret) {
2031             DEBUG_PRINT_ERROR("Failed to call streamon");
2032             if (errno == EBUSY) {
2033                 hw_overload = true;
2034             }
2035             return false;
2036         } else {
2037             streaming[OUTPUT_PORT] = true;
2038         }
2039     }
2040 
2041     memset(&enc, 0, sizeof(enc));
2042     enc.cmd = V4L2_ENC_CMD_STOP;
2043     DEBUG_PRINT_LOW("Sending : Encoder STOP comamnd");
2044     rc = ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc);
2045     if (rc) {
2046         DEBUG_PRINT_ERROR("Failed : Encoder STOP comamnd");
2047         return false;
2048     }
2049     return true;
2050 }
2051 
venc_stop(void)2052 unsigned venc_dev::venc_stop( void)
2053 {
2054     struct venc_msg venc_msg;
2055     struct v4l2_requestbuffers bufreq;
2056     int rc = 0, ret = 0;
2057 
2058     if (!stopped) {
2059         enum v4l2_buf_type cap_type;
2060 
2061         if (streaming[OUTPUT_PORT]) {
2062             cap_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2063             rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
2064 
2065             if (rc) {
2066                 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
2067                         cap_type, rc);
2068             } else
2069                 streaming[OUTPUT_PORT] = false;
2070 
2071             DEBUG_PRINT_LOW("Releasing registered buffers from driver on o/p port");
2072             bufreq.memory = V4L2_MEMORY_USERPTR;
2073             bufreq.count = 0;
2074             bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2075             ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
2076 
2077             if (ret) {
2078                 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS OUTPUT MPLANE Failed");
2079                 return false;
2080             }
2081         }
2082 
2083         if (!rc && streaming[CAPTURE_PORT]) {
2084             cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2085             rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
2086 
2087             if (rc) {
2088                 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
2089                         cap_type, rc);
2090             } else
2091                 streaming[CAPTURE_PORT] = false;
2092 
2093             DEBUG_PRINT_LOW("Releasing registered buffers from driver on capture port");
2094             bufreq.memory = V4L2_MEMORY_USERPTR;
2095             bufreq.count = 0;
2096             bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2097             ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
2098 
2099             if (ret) {
2100                 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS CAPTURE MPLANE Failed");
2101                 return false;
2102             }
2103         }
2104 
2105         if (!rc && !ret) {
2106             venc_stop_done();
2107             stopped = 1;
2108             /*set flag to re-configure when started again*/
2109             resume_in_stopped = 1;
2110         }
2111     }
2112 
2113     return rc;
2114 }
2115 
is_streamon_done(OMX_U32 port)2116 bool venc_dev::is_streamon_done(OMX_U32 port)
2117 {
2118     return streaming[port];
2119 }
2120 
venc_pause(void)2121 unsigned venc_dev::venc_pause(void)
2122 {
2123     pthread_mutex_lock(&pause_resume_mlock);
2124     paused = true;
2125     pthread_mutex_unlock(&pause_resume_mlock);
2126     return 0;
2127 }
2128 
venc_resume(void)2129 unsigned venc_dev::venc_resume(void)
2130 {
2131     pthread_mutex_lock(&pause_resume_mlock);
2132     paused = false;
2133     pthread_mutex_unlock(&pause_resume_mlock);
2134 
2135     return pthread_cond_signal(&pause_resume_cond);
2136 }
2137 
venc_start_done(void)2138 unsigned venc_dev::venc_start_done(void)
2139 {
2140     struct venc_msg venc_msg;
2141     venc_msg.msgcode = VEN_MSG_START;
2142     venc_msg.statuscode = VEN_S_SUCCESS;
2143     venc_handle->async_message_process(venc_handle,&venc_msg);
2144     return 0;
2145 }
2146 
venc_stop_done(void)2147 unsigned venc_dev::venc_stop_done(void)
2148 {
2149     struct venc_msg venc_msg;
2150     free_extradata_all();
2151     venc_msg.msgcode=VEN_MSG_STOP;
2152     venc_msg.statuscode=VEN_S_SUCCESS;
2153     venc_handle->async_message_process(venc_handle,&venc_msg);
2154     return 0;
2155 }
2156 
venc_set_message_thread_id(pthread_t tid)2157 unsigned venc_dev::venc_set_message_thread_id(pthread_t tid)
2158 {
2159     async_thread_created = true;
2160     m_tid=tid;
2161     return 0;
2162 }
2163 
venc_set_extradata_hdr10metadata(OMX_U32 omx_profile)2164 bool venc_dev::venc_set_extradata_hdr10metadata(OMX_U32 omx_profile)
2165 {
2166     /* HDR10 Metadata is enabled by default for HEVC Main10PLUS profile. */
2167     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC &&
2168         omx_profile == OMX_VIDEO_HEVCProfileMain10HDR10Plus) {
2169         DEBUG_PRINT_HIGH("venc_set_extradata:: HDR10PLUS_METADATA");
2170         struct v4l2_control control;
2171         control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
2172         control.value = EXTRADATA_ENC_INPUT_HDR10PLUS;
2173 
2174         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2175             DEBUG_PRINT_ERROR("ERROR: Set extradata HDR10PLUS_METADATA failed %d", errno);
2176             return false;
2177         }
2178 
2179         m_hdr10meta_enabled = true;
2180 
2181         //Get upated buffer requirement as enable extradata leads to two buffer planes
2182         venc_get_buf_req (&venc_handle->m_sInPortDef.nBufferCountMin,
2183                           &venc_handle->m_sInPortDef.nBufferCountActual,
2184                           &venc_handle->m_sInPortDef.nBufferSize,
2185                           venc_handle->m_sInPortDef.nPortIndex);
2186     } else {
2187         m_hdr10meta_enabled = false;
2188     }
2189 
2190     return true;
2191 }
2192 
venc_start(void)2193 unsigned venc_dev::venc_start(void)
2194 {
2195     enum v4l2_buf_type buf_type;
2196     int ret, r;
2197     struct v4l2_control control;
2198 
2199     memset(&control, 0, sizeof(control));
2200 
2201     venc_config_print();
2202 
2203     /* set buffercount before start */
2204     venc_reconfig_reqbufs();
2205     resume_in_stopped = 0;
2206 
2207     buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2208     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2209     ret=ioctl(m_nDriver_fd, VIDIOC_STREAMON,&buf_type);
2210 
2211     if (ret)
2212         return 1;
2213 
2214     streaming[CAPTURE_PORT] = true;
2215 
2216     stopped = 0;
2217     return 0;
2218 }
2219 
hiermode_string(int val)2220 inline const char* hiermode_string(int val)
2221 {
2222     switch(val)
2223     {
2224     case HIER_NONE:
2225         return "No Hier";
2226     case HIER_P:
2227         return "Hier-P";
2228     case HIER_B:
2229         return "Hier-B";
2230     default:
2231         return "No hier";
2232     }
2233 }
2234 
bitrate_type_string(int val)2235 inline const char* bitrate_type_string(int val)
2236 {
2237     switch(val)
2238     {
2239     case V4L2_MPEG_MSM_VIDC_DISABLE:
2240         return "CUMULATIVE";
2241     case V4L2_MPEG_MSM_VIDC_ENABLE:
2242         return "LAYER WISE";
2243     default:
2244         return "Unknown Bitrate Type";
2245     }
2246 }
2247 
codec_as_string(unsigned long codec)2248 static const char *codec_as_string(unsigned long codec) {
2249     switch (codec) {
2250     case V4L2_PIX_FMT_H264:
2251         return "H264";
2252     case V4L2_PIX_FMT_HEVC:
2253         return "HEVC";
2254     case V4L2_PIX_FMT_VP8:
2255         return "VP8";
2256     default:
2257         return "UNKOWN";
2258     }
2259 }
2260 
venc_config_print()2261 void venc_dev::venc_config_print()
2262 {
2263 
2264     DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %s, Profile %ld, level : %ld",
2265             codec_as_string(m_sVenc_cfg.codectype), codec_profile.profile, profile_level.level);
2266 
2267     DEBUG_PRINT_HIGH("ENC_CONFIG: Input Width: %ld, Height:%ld, Fps: %ld",
2268             m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
2269             m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
2270 
2271     DEBUG_PRINT_HIGH("ENC_CONFIG: Output Width: %ld, Height:%ld, Fps: %ld",
2272             m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
2273             m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
2274 
2275     DEBUG_PRINT_HIGH("ENC_CONFIG: Color Space: Primaries = %u, Range = %u, Transfer Chars = %u, Matrix Coeffs = %u",
2276             color_space.primaries, color_space.range, color_space.transfer_chars, color_space.matrix_coeffs);
2277 
2278     DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld",
2279             bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes);
2280 
2281     DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %ld, qpP: %ld, qpb: %ld enableqp : %ld",
2282             session_qp.iframeqp, session_qp.pframeqp, session_qp.bframeqp, session_qp.enableqp);
2283 
2284     DEBUG_PRINT_HIGH("ENC_CONFIG: minQP: %lu, maxQP: %lu",
2285                      session_ipb_qp_values.min_qp_packed, session_ipb_qp_values.max_qp_packed);
2286 
2287     DEBUG_PRINT_HIGH("ENC_CONFIG: VOP_Resolution: %ld, Slice-Mode: %ld, Slize_Size: %ld",
2288             voptimecfg.voptime_resolution, multislice.mslice_mode,
2289             multislice.mslice_size);
2290 
2291     DEBUG_PRINT_HIGH("ENC_CONFIG: EntropyMode: %d, CabacModel: %ld",
2292             entropy.longentropysel, entropy.cabacmodel);
2293 
2294     DEBUG_PRINT_HIGH("ENC_CONFIG: DB-Mode: %ld, alpha: %ld, Beta: %ld",
2295             dbkfilter.db_mode, dbkfilter.slicealpha_offset,
2296             dbkfilter.slicebeta_offset);
2297 
2298     DEBUG_PRINT_HIGH("ENC_CONFIG: HEC: %ld, IDR Period: %ld",
2299             hec.header_extension, idrperiod.idrperiod);
2300 
2301     if (temporal_layers_config.nPLayers) {
2302         DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: P-layers: %u, B-layers: %u, Adjusted I-frame-interval: %lu",
2303                 temporal_layers_config.nPLayers, temporal_layers_config.nBLayers,
2304                 intra_period.num_pframes + intra_period.num_bframes + 1);
2305     }
2306 
2307     DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled);
2308 
2309     DEBUG_PRINT_HIGH("ENC_CONFIG: Peak bitrate: %d", peak_bitrate.peakbitrate);
2310 
2311     DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %s", sess_priority.priority ? "NonRealTime" : "RealTime");
2312 
2313     DEBUG_PRINT_HIGH("ENC_CONFIG: ROI : %u", m_roi_enabled);
2314 
2315     DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate);
2316 }
2317 
venc_reconfig_reqbufs()2318 bool venc_dev::venc_reconfig_reqbufs()
2319 {
2320     struct v4l2_requestbuffers bufreq;
2321 
2322     DEBUG_PRINT_HIGH("venc_reconfig_reqbufs: output_mplane %lu, capture_mplane %lu",
2323         m_sInput_buff_property.actualcount, m_sOutput_buff_property.actualcount);
2324 
2325     bufreq.memory = V4L2_MEMORY_USERPTR;
2326     bufreq.count = m_sInput_buff_property.actualcount;
2327     bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2328     if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2329         DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: OUTPUT_MPLANE (count %d) failed", bufreq.count);
2330         return false;
2331     }
2332 
2333     bufreq.memory = V4L2_MEMORY_USERPTR;
2334     bufreq.count = m_sOutput_buff_property.actualcount;
2335     bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2336     if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2337         DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: CAPTURE_MPLANE (count %d) failed", bufreq.count);
2338         return false;
2339     }
2340     return true;
2341 }
2342 
venc_flush(unsigned port)2343 unsigned venc_dev::venc_flush( unsigned port)
2344 {
2345     struct v4l2_encoder_cmd enc;
2346     DEBUG_PRINT_LOW("in %s", __func__);
2347 
2348     enc.cmd = V4L2_CMD_FLUSH;
2349     enc.flags = V4L2_CMD_FLUSH_OUTPUT | V4L2_CMD_FLUSH_CAPTURE;
2350 
2351     if (ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc)) {
2352         DEBUG_PRINT_ERROR("Flush Port (%d) Failed ", port);
2353         return -1;
2354     }
2355 
2356     return 0;
2357 }
2358 
2359 //allocating I/P memory from pmem and register with the device
allocate_extradata(unsigned port)2360 bool venc_dev::allocate_extradata(unsigned port)
2361 {
2362     int rc = 0;
2363     unsigned int extra_idx = 0;
2364 
2365     // PORT_INDEX_IN = 0
2366     // PORT_INDEX_OUT = 1
2367     struct port_info_s {
2368         int num_planes;
2369         struct extradata_buffer_info *extradata_info;
2370         int flag;
2371     }port_info[2] = {
2372         {
2373             .num_planes = num_input_planes,
2374             .extradata_info = &input_extradata_info,
2375             .flag = 0
2376         },
2377         {
2378             .num_planes = num_output_planes,
2379             .extradata_info = &output_extradata_info,
2380             .flag = 0
2381         }
2382     };
2383 
2384     if (port != PORT_INDEX_IN && port != PORT_INDEX_OUT) {
2385         DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index ");
2386         return false;
2387     }
2388 
2389     extra_idx = EXTRADATA_IDX(port_info[port].num_planes);
2390     if ((port_info[port].num_planes > 1) && (extra_idx)) {
2391         rc = allocate_extradata(port_info[port].extradata_info,
2392                                 port_info[port].flag);
2393         if (rc) {
2394             DEBUG_PRINT_ERROR("Failed to allocate extradata: %d\n", rc);
2395             return false;
2396         }
2397     }
2398 
2399     return true;
2400 }
2401 
venc_free_buf(void * buf_addr,unsigned port)2402 bool venc_dev::venc_free_buf(void *buf_addr, unsigned port)
2403 {
2404     struct pmem *pmem_tmp;
2405     struct venc_bufferpayload dev_buffer;
2406 
2407     memset(&dev_buffer, 0, sizeof(dev_buffer));
2408     pmem_tmp = (struct pmem *)buf_addr;
2409 
2410     if (port == PORT_INDEX_IN) {
2411         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
2412         dev_buffer.fd  = pmem_tmp->fd;
2413         dev_buffer.maped_size = pmem_tmp->size;
2414         dev_buffer.sz = pmem_tmp->size;
2415         dev_buffer.offset = pmem_tmp->offset;
2416         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
2417                 dev_buffer.pbuffer, \
2418                 dev_buffer.fd, \
2419                 dev_buffer.offset, \
2420                 dev_buffer.maped_size);
2421 
2422     } else if (port == PORT_INDEX_OUT) {
2423         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
2424         dev_buffer.fd  = pmem_tmp->fd;
2425         dev_buffer.sz = pmem_tmp->size;
2426         dev_buffer.maped_size = pmem_tmp->size;
2427         dev_buffer.offset = pmem_tmp->offset;
2428 
2429         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
2430                 dev_buffer.pbuffer, \
2431                 dev_buffer.fd, \
2432                 dev_buffer.offset, \
2433                 dev_buffer.maped_size);
2434     } else {
2435         DEBUG_PRINT_ERROR("ERROR: venc_free_buf:Invalid Port Index ");
2436         return false;
2437     }
2438 
2439     return true;
2440 }
2441 
venc_color_align(OMX_BUFFERHEADERTYPE * buffer,OMX_U32 width,OMX_U32 height)2442 bool venc_dev::venc_color_align(OMX_BUFFERHEADERTYPE *buffer,
2443         OMX_U32 width, OMX_U32 height)
2444 {
2445     OMX_U32 y_stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width),
2446             y_scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height),
2447             uv_stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, width),
2448             uv_scanlines = VENUS_UV_SCANLINES(COLOR_FMT_NV12, height),
2449             src_chroma_offset = width * height;
2450 
2451     if (buffer->nAllocLen >= VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height)) {
2452         OMX_U8* src_buf = buffer->pBuffer, *dst_buf = buffer->pBuffer;
2453         //Do chroma first, so that we can convert it in-place
2454         src_buf += width * height;
2455         dst_buf += y_stride * y_scanlines;
2456         for (int line = height / 2 - 1; line >= 0; --line) {
2457             /* Align the length to 16 for better memove performance. */
2458             memmove(dst_buf + line * uv_stride,
2459                     src_buf + line * width,
2460                     ALIGN(width, 16));
2461         }
2462 
2463         dst_buf = src_buf = buffer->pBuffer;
2464         //Copy the Y next
2465         for (int line = height - 1; line > 0; --line) {
2466             /* Align the length to 16 for better memove performance. */
2467             memmove(dst_buf + line * y_stride,
2468                     src_buf + line * width,
2469                     ALIGN(width, 16));
2470         }
2471         /* Inform driver to do cache flush on total buffer */
2472         buffer->nFilledLen = buffer->nAllocLen;
2473     } else {
2474         DEBUG_PRINT_ERROR("Failed to align Chroma. from %u to %u : \
2475                 Insufficient bufferLen=%u v/s Required=%u",
2476                 (unsigned int)(width*height), (unsigned int)src_chroma_offset, (unsigned int)buffer->nAllocLen,
2477                 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height));
2478         return false;
2479     }
2480 
2481     return true;
2482 }
2483 
venc_get_vui_timing_info(OMX_U32 * enabled)2484 bool venc_dev::venc_get_vui_timing_info(OMX_U32 *enabled)
2485 {
2486     if (!enabled) {
2487         DEBUG_PRINT_ERROR("Null pointer error");
2488         return false;
2489     } else {
2490         *enabled = vui_timing_info.enabled;
2491         return true;
2492     }
2493 }
2494 
venc_get_peak_bitrate(OMX_U32 * peakbitrate)2495 bool venc_dev::venc_get_peak_bitrate(OMX_U32 *peakbitrate)
2496 {
2497     if (!peakbitrate) {
2498         DEBUG_PRINT_ERROR("Null pointer error");
2499         return false;
2500     } else {
2501         *peakbitrate = peak_bitrate.peakbitrate;
2502         return true;
2503     }
2504 }
2505 
venc_get_batch_size(OMX_U32 * size)2506 bool venc_dev::venc_get_batch_size(OMX_U32 *size)
2507 {
2508     if (!size) {
2509         DEBUG_PRINT_ERROR("Null pointer error");
2510         return false;
2511     } else {
2512         *size = mBatchSize;
2513         return true;
2514     }
2515 }
2516 
venc_get_buffer_mode()2517 bool venc_dev::venc_get_buffer_mode()
2518 {
2519     return metadatamode;
2520 }
2521 
venc_is_avtimer_needed()2522 bool venc_dev::venc_is_avtimer_needed()
2523 {
2524     return mUseAVTimerTimestamps;
2525 }
2526 
venc_empty_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)2527 bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, unsigned fd)
2528 {
2529     struct pmem *temp_buffer;
2530     struct v4l2_buffer buf;
2531     struct v4l2_requestbuffers bufreq;
2532     struct v4l2_plane plane[VIDEO_MAX_PLANES];
2533     int rc = 0, extra_idx, c2d_enabled = 0;
2534     bool interlace_flag = false;
2535     struct OMX_BUFFERHEADERTYPE *bufhdr;
2536     LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
2537     temp_buffer = (struct pmem *)buffer;
2538 
2539     memset (&buf, 0, sizeof(buf));
2540     memset (&plane, 0, sizeof(plane));
2541 
2542     if (buffer == NULL) {
2543         DEBUG_PRINT_ERROR("ERROR: venc_etb: buffer is NULL");
2544         return false;
2545     }
2546 
2547     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
2548     bufreq.memory = V4L2_MEMORY_USERPTR;
2549     bufreq.count = m_sInput_buff_property.actualcount;
2550     bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2551 
2552     if (pmem_data_buf) {
2553         DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
2554         plane[0].m.userptr = (unsigned long)pmem_data_buf;
2555         plane[0].data_offset = bufhdr->nOffset;
2556         plane[0].length = bufhdr->nAllocLen;
2557         plane[0].bytesused = bufhdr->nFilledLen;
2558     } else {
2559         // --------------------------------------------------------------------------------------
2560         // [Usage]             [metadatamode] [Type]        [color_format] [Where is buffer info]
2561         // ---------------------------------------------------------------------------------------
2562         // Camera-2              1            CameraSource   0              meta-handle
2563         // Camera-3              1            GrallocSource  0              gralloc-private-handle
2564         // surface encode (RBG)  1            GrallocSource  1              bufhdr (color-converted)
2565         // CPU (Eg: MediaCodec)  0            --             0              bufhdr
2566         // ---------------------------------------------------------------------------------------
2567         if (metadatamode) {
2568             plane[0].m.userptr = index;
2569             meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
2570 
2571             if (!meta_buf) {
2572                 if (!bufhdr->nFilledLen) {
2573                     if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS) {
2574                         DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
2575                         DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
2576                         return false;
2577                     }
2578                     DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
2579                     return false;
2580                 }
2581             } else if (!color_format) { // Metadata mode
2582 
2583                 if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
2584                     native_handle_t *hnd = (native_handle_t*)meta_buf->meta_handle;
2585                     if (!hnd) {
2586                         DEBUG_PRINT_ERROR("ERROR: venc_etb: handle is NULL");
2587                         return false;
2588                     }
2589                     int usage = 0;
2590                     usage = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_USAGE);
2591                     usage = usage > 0 ? usage : 0;
2592 
2593                     if (!streaming[OUTPUT_PORT] && !(m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGB32 ||
2594                         m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGBA8888_UBWC)) {
2595 
2596                         unsigned int is_csc_enabled = 0;
2597                         struct v4l2_format fmt;
2598                         OMX_COLOR_FORMATTYPE color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2599 
2600                         color_format = (OMX_COLOR_FORMATTYPE)MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_COLORFORMAT);
2601 
2602                         memset(&fmt, 0, sizeof(fmt));
2603                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709 ||
2604                                 usage & private_handle_t::PRIV_FLAGS_ITU_R_601) {
2605                             DEBUG_PRINT_ERROR("Camera buffer color format is not 601_FR.");
2606                             DEBUG_PRINT_ERROR(" This leads to unknown color space");
2607                         }
2608                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) {
2609                             if (is_csc_enabled) {
2610                                 struct v4l2_control control;
2611                                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
2612                                 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
2613                                 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2614                                     DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC for 601_to_709");
2615                                 } else {
2616                                     DEBUG_PRINT_INFO("venc_empty_buf: Will convert 601-FR to 709");
2617                                     fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
2618                                     venc_set_colorspace(MSM_VIDC_BT709_5, 0,
2619                                             MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
2620                                 }
2621                             } else {
2622                                 venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
2623                                         MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
2624                                 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
2625                             }
2626                         }
2627                         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2628                         m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
2629                         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2630                         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2631                         if (usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
2632                             usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) {
2633                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
2634                         }
2635 
2636                         if (color_format > 0 && !venc_set_color_format(color_format)) {
2637                             DEBUG_PRINT_ERROR("Failed setting color format in Camerasource %lx", m_sVenc_cfg.inputformat);
2638                             return false;
2639                         }
2640 
2641                         if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2642                             DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
2643                             return false;
2644                         }
2645                     }
2646 
2647                     // Setting batch mode is sticky. We do not expect camera to change
2648                     // between batch and normal modes at runtime.
2649                     if (mBatchSize) {
2650                         if ((unsigned int)MetaBufferUtil::getBatchSize(hnd) != mBatchSize) {
2651                             DEBUG_PRINT_ERROR("Don't support dynamic batch sizes (changed from %d->%d)",
2652                                     mBatchSize, MetaBufferUtil::getBatchSize(hnd));
2653                             return false;
2654                         }
2655 
2656                         return venc_empty_batch ((OMX_BUFFERHEADERTYPE*)buffer, index);
2657                     }
2658 
2659                     int offset = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_OFFSET);
2660                     int length = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_SIZE);
2661                     if (offset < 0 || length < 0) {
2662                         DEBUG_PRINT_ERROR("Invalid meta buffer handle!");
2663                         return false;
2664                     }
2665                     plane[0].data_offset = offset;
2666                     plane[0].length = length;
2667                     plane[0].bytesused = length;
2668                     DEBUG_PRINT_LOW("venc_empty_buf: camera buf: fd = %d filled %d of %d flag 0x%x format 0x%lx",
2669                             fd, plane[0].bytesused, plane[0].length, buf.flags, m_sVenc_cfg.inputformat);
2670                 } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
2671                     VideoGrallocMetadata *meta_buf = (VideoGrallocMetadata *)bufhdr->pBuffer;
2672                     private_handle_t *handle = (private_handle_t *)meta_buf->pHandle;
2673 
2674                     if (!handle) {
2675                         DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
2676                         return false;
2677                     }
2678                     interlace_flag = is_ubwc_interlaced(handle);
2679 
2680                     if (mUseAVTimerTimestamps) {
2681                         uint64_t avTimerTimestampNs = bufhdr->nTimeStamp * 1000;
2682                         if (getMetaData(handle, GET_VT_TIMESTAMP, &avTimerTimestampNs) == 0
2683                                 && avTimerTimestampNs > 0) {
2684                             bufhdr->nTimeStamp = avTimerTimestampNs / 1000;
2685                             DEBUG_PRINT_LOW("AVTimer TS : %llu us", (unsigned long long)bufhdr->nTimeStamp);
2686                         }
2687                     }
2688 
2689                     if (!streaming[OUTPUT_PORT]) {
2690                         // Moment of truth... actual colorspace is known here..
2691                         if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
2692                             DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData colorPrimaries=%d colorRange=%d "
2693                                              "transfer=%d matrixcoefficients=%d"
2694                                              "dynamicMetaDataValid %u dynamicMetaDataLen %u",
2695                                              colorData.colorPrimaries, colorData.range,
2696                                              colorData.transfer, colorData.matrixCoefficients,
2697                                              colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
2698                         }
2699 
2700                         if (!venc_cvp_enable(handle)) {
2701                             DEBUG_PRINT_ERROR("ERROR: Setting CVP enable");
2702                             return false;
2703                         }
2704 
2705                         struct v4l2_format fmt;
2706                         memset(&fmt, 0, sizeof(fmt));
2707                         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2708 
2709                         bool isUBWC = ((handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
2710                                         handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) &&
2711                                        is_gralloc_source_ubwc);
2712 
2713                         char grallocFormatStr[200];
2714                         get_gralloc_format_as_string(grallocFormatStr, sizeof(grallocFormatStr), handle->format);
2715                         DEBUG_PRINT_LOW("gralloc format 0x%x (%s) (%s)",
2716                             handle->format, grallocFormatStr, isUBWC ? "UBWC" : "Linear");
2717 
2718                         if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) {
2719                             m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_NV12_UBWC : V4L2_PIX_FMT_NV12;
2720                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 %s", isUBWC ? "UBWC" : "Linear");
2721                         } else if (handle->format == HAL_PIXEL_FORMAT_NV12_HEIF) {
2722                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
2723                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_512");
2724                         } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC) {
2725                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
2726                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_UBWC");
2727                         } else if (handle->format == VIDC_HAL_PIXEL_FORMAT_NV12_LINEAR_FLEX) {
2728                              m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
2729                              DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 FLEX");
2730                         } else if (handle->format == VIDC_HAL_PIXEL_FORMAT_NV12_UBWC_FLEX) {
2731                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
2732                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 UBWC FLEX");
2733                         } else if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) {
2734                             // In case of RGB, conversion to YUV is handled within encoder.
2735                             // Disregard the Colorspace in gralloc-handle in case of RGB and use
2736                             //   [a] 601 for non-UBWC case : C2D output is (apparently) 601-LR
2737                             //   [b] 601 for UBWC case     : Venus can convert to 601-LR or FR. use LR for now.
2738                             //set colormetadata corresponding to ITU_R_601;
2739                             colorData.colorPrimaries =  ColorPrimaries_BT601_6_525;
2740                             colorData.range = Range_Limited;
2741                             colorData.transfer = Transfer_SMPTE_170M;
2742                             colorData.matrixCoefficients = MatrixCoEff_BT601_6_525;
2743                             m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_RGBA8888_UBWC : V4L2_PIX_FMT_RGB32;
2744                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = RGBA8888 %s", isUBWC ? "UBWC" : "Linear");
2745                         } else if (handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
2746                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
2747                             DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 Linear");
2748                         } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC ||
2749                                    handle->format == HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS) {
2750                             if (((m_codec == OMX_VIDEO_CodingHEVC) &&
2751                                  (codec_profile.profile == V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)) ||
2752                                      (csc_enable == true)) {
2753                                 m_sVenc_cfg.inputformat =
2754                                     (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC)?
2755                                              V4L2_PIX_FMT_NV12_TP10_UBWC :
2756                                              V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
2757                                 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = 10bit");
2758                             } else {
2759                                 DEBUG_PRINT_ERROR("ENC_CONFIG: 10bit colorformat not supported for this codec and profile");
2760                                 return false;
2761                             }
2762 
2763                             if(colorData.masteringDisplayInfo.colorVolumeSEIEnabled ||
2764                                colorData.contentLightLevel.lightLevelSEIEnabled) {
2765                                 if (!venc_set_hdr_info(colorData.masteringDisplayInfo, colorData.contentLightLevel)) {
2766                                     DEBUG_PRINT_ERROR("HDR10-PQ Info Setting failed");
2767                                     return false;
2768                                 } else {
2769                                     DEBUG_PRINT_INFO("Encoding in HDR10-PQ mode");
2770                                 }
2771                             } else {
2772                                 DEBUG_PRINT_INFO("Encoding in HLG mode");
2773                             }
2774                         } else if (handle->format == QOMX_COLOR_FormatYVU420SemiPlanar) {
2775                            m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
2776                            DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV21 Linear");
2777                         } else {
2778                             DEBUG_PRINT_ERROR("Color format is not recoganized. Format 0x%X", handle->format);
2779                             return false;
2780                         }
2781 
2782                         DEBUG_PRINT_INFO("color_space.primaries %d colorData.colorPrimaries %d, is_csc_custom_matrix_enabled=%d",
2783                                          color_space.primaries, colorData.colorPrimaries, is_csc_custom_matrix_enabled);
2784 
2785                         if (csc_enable) {
2786                             struct v4l2_control control;
2787                             control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
2788                             control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
2789                             if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2790                                 DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC");
2791                             }
2792                             else {
2793                                 if (is_csc_custom_matrix_enabled) {
2794                                     control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX;
2795                                     control.value = 1;
2796                                     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2797                                         DEBUG_PRINT_ERROR("venc_empty_buf: Failed to enable VPE CSC custom matrix");
2798                                     } else {
2799                                         DEBUG_PRINT_INFO("venc_empty_buf: Enabled VPE CSC custom matrix");
2800                                     }
2801                                 }
2802                             }
2803                         }
2804 
2805                         /* Enum values from gralloc ColorMetaData matches with the driver values
2806                            as it is standard compliant */
2807                         venc_set_colorspace(colorData.colorPrimaries, colorData.range,
2808                                             colorData.transfer, colorData.matrixCoefficients);
2809                         if ((handle->format == VIDC_HAL_PIXEL_FORMAT_NV12_LINEAR_FLEX) ||
2810                                 (handle->format == VIDC_HAL_PIXEL_FORMAT_NV12_UBWC_FLEX)) {
2811                             if (!venc_superframe_enable(handle)) {
2812                                 DEBUG_PRINT_ERROR("ERROR: Enabling Superframe");
2813                                 return false;
2814                             }
2815                         }
2816 
2817                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2818                         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2819                         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2820                         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2821                             DEBUG_PRINT_ERROR("Failed setting color format in Grallocsource %lx", m_sVenc_cfg.inputformat);
2822                             return false;
2823                         }
2824                         if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2825                             DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
2826                             return false;
2827                         }
2828                     } else {
2829                         if (m_hdr10meta_enabled) {
2830                             if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
2831                                 DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData dynamicMetaDataValid=%u dynamicMetaDataLen=%u",
2832                                                  colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
2833                             }
2834                         }
2835                     } // Check OUTPUT Streaming
2836 
2837                     if (!venc_get_cvp_metadata(handle, &buf))
2838                         return false;
2839 
2840                     struct UBWCStats cam_ubwc_stats[2];
2841                     unsigned long long int compression_ratio = 1 << 16;
2842 
2843                     if (getMetaData(handle, GET_UBWC_CR_STATS_INFO, (void *)cam_ubwc_stats) == 0) {
2844                         if (cam_ubwc_stats[0].bDataValid) {
2845                             switch (cam_ubwc_stats[0].version) {
2846                             case UBWC_2_0:
2847                             case UBWC_3_0:
2848                             case UBWC_4_0:
2849                                 {
2850                                     unsigned long long int sum = 0, weighted_sum = 0;
2851 
2852                                     DEBUG_PRINT_HIGH("Field 0 : 32 Tile = %d 64 Tile = %d 96 Tile = %d "
2853                                        "128 Tile = %d 160 Tile = %d 192 Tile = %d 256 Tile = %d\n",
2854                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32,
2855                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64,
2856                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96,
2857                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128,
2858                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160,
2859                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192,
2860                                        cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256);
2861 
2862                                     weighted_sum =
2863                                         32  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
2864                                         64  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
2865                                         96  * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
2866                                         128 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
2867                                         160 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
2868                                         192 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
2869                                         256 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
2870 
2871                                     sum =
2872                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
2873                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
2874                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
2875                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
2876                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
2877                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
2878                                         cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
2879 
2880                                     compression_ratio = (weighted_sum && sum) ?
2881                                         ((256 * sum) << 16) / weighted_sum : compression_ratio;
2882                                 }
2883                                 break;
2884                             default:
2885                                 break;
2886                             }
2887                         }
2888                     }
2889 
2890                     uint32_t encodePerfMode = 0;
2891                     if (getMetaData(handle, GET_VIDEO_PERF_MODE, &encodePerfMode) == 0) {
2892                         if (encodePerfMode == OMX_TRUE)
2893                             buf.flags |= V4L2_BUF_FLAG_PERF_MODE;
2894                         // Clear SET_VIDEO_PERF_MODE in buffer handle
2895                         setMetaData(handle, SET_VIDEO_PERF_MODE, 0);
2896                     }
2897                     fd = handle->fd;
2898                     plane[0].data_offset = 0;
2899                     plane[0].length = handle->size;
2900                     plane[0].bytesused = handle->size;
2901                     plane[0].reserved[MSM_VIDC_COMP_RATIO] = (unsigned long int)compression_ratio;
2902                     char v4l2ColorFormatStr[200];
2903                     get_v4l2_color_format_as_string(v4l2ColorFormatStr, sizeof(v4l2ColorFormatStr), m_sVenc_cfg.inputformat);
2904                     DEBUG_PRINT_LOW("venc_empty_buf: Opaque camera buf: fd = %d "
2905                                 ": filled %d of %d format 0x%lx (%s) CR %d", fd, plane[0].bytesused,
2906                                 plane[0].length, m_sVenc_cfg.inputformat, v4l2ColorFormatStr, plane[0].reserved[MSM_VIDC_COMP_RATIO]);
2907                 }
2908             } else {
2909                 // Metadata mode
2910                 // color_format == 1 ==> RGBA to YUV Color-converted buffer
2911                 // Buffers color-converted via C2D have 601 color
2912                 if (!streaming[OUTPUT_PORT]) {
2913                     c2d_enabled = 1;
2914                     DEBUG_PRINT_HIGH("Setting colorspace 601 for Color-converted buffer");
2915                     venc_set_colorspace(MSM_VIDC_BT601_6_625, color_space.range,
2916                             MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
2917                 }
2918                 plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
2919                 plane[0].data_offset = bufhdr->nOffset;
2920                 plane[0].length = bufhdr->nAllocLen;
2921                 plane[0].bytesused = bufhdr->nFilledLen;
2922                 DEBUG_PRINT_LOW("venc_empty_buf: Opaque non-camera buf: fd = %d filled %d of %d",
2923                         fd, plane[0].bytesused, plane[0].length);
2924             }
2925         } else { // Not Metadata mode
2926             plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
2927             plane[0].data_offset = bufhdr->nOffset;
2928             plane[0].length = bufhdr->nAllocLen;
2929             plane[0].bytesused = bufhdr->nFilledLen;
2930             DEBUG_PRINT_LOW("venc_empty_buf: non-camera buf: fd = %d filled %d of %d",
2931                     fd, plane[0].bytesused, plane[0].length);
2932         }
2933     }
2934 
2935     if (!handle_dynamic_config(bufhdr)) {
2936         DEBUG_PRINT_ERROR("%s Failed to set dynamic configs", __func__);
2937         return false;
2938     }
2939 
2940     if (!streaming[OUTPUT_PORT]) {
2941         enum v4l2_buf_type buf_type;
2942         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2943         int ret;
2944 
2945         // Some 3rd APPs use NativeRecorder to implement their applications
2946         // like screenrecorder, implicitly enable B-frame may cause issues.
2947         // So disallow implicit B-frame when input format is non-UBWC or RGBA(c2d enabled).
2948         if ((m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_TP10_UBWC &&
2949              m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_UBWC) || c2d_enabled) {
2950             DEBUG_PRINT_HIGH("Disallow implicitly enable B-frames");
2951             if (!set_native_recoder(OMX_FALSE)) {
2952                 DEBUG_PRINT_ERROR("Failed to set Native Recorder");
2953                 return false;
2954             }
2955         }
2956 
2957         venc_set_quality_boost((OMX_BOOL)c2d_enabled);
2958 
2959         if (!downscalar_enabled) {
2960             OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
2961 
2962             if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
2963                 return false;
2964             }
2965 
2966             if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
2967                 return false;
2968             }
2969 
2970             // Tiling in HEIC requires output WxH to be Tile size; difference is permitted
2971             if (!(m_codec == OMX_VIDEO_CodingImageHEIC) &&
2972                 inp_width * inp_height != out_width * out_height) {
2973                 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
2974                 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
2975                 return false;
2976             }
2977         }
2978 
2979         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
2980 
2981         if (ret) {
2982             DEBUG_PRINT_ERROR("Failed to call streamon");
2983             if (errno == EBUSY) {
2984                 hw_overload = true;
2985             }
2986             return false;
2987         } else {
2988             streaming[OUTPUT_PORT] = true;
2989         }
2990     }
2991 
2992     extra_idx = EXTRADATA_IDX(num_input_planes);
2993 
2994     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
2995         plane[extra_idx].bytesused = input_extradata_info.buffer_size;
2996         plane[extra_idx].length = input_extradata_info.buffer_size;
2997         plane[extra_idx].m.userptr = (unsigned long)input_extradata_info.ion[index].uaddr;
2998 #ifdef USE_ION
2999         plane[extra_idx].reserved[MSM_VIDC_BUFFER_FD] = input_extradata_info.ion[index].data_fd;
3000 #endif
3001         plane[extra_idx].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3002         plane[extra_idx].data_offset = 0;
3003     } else if (extra_idx >= VIDEO_MAX_PLANES) {
3004         DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
3005         return false;
3006     }
3007 
3008     buf.index = index;
3009     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3010     buf.memory = V4L2_MEMORY_USERPTR;
3011     plane[0].reserved[MSM_VIDC_BUFFER_FD] = fd;
3012     plane[0].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3013     buf.m.planes = plane;
3014     buf.length = num_input_planes;
3015     buf.timestamp.tv_sec = bufhdr->nTimeStamp / 1000000;
3016     buf.timestamp.tv_usec = (bufhdr->nTimeStamp % 1000000);
3017 
3018     if (!handle_input_extradata(buf)) {
3019         DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
3020         return false;
3021     }
3022 
3023     VIDC_TRACE_INT_LOW("ETB-TS", bufhdr->nTimeStamp / 1000);
3024 
3025     if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
3026         buf.flags |= V4L2_BUF_FLAG_EOS;
3027 
3028     if (!plane[0].bytesused) {
3029         if (buf.flags & V4L2_BUF_FLAG_EOS) {
3030             DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
3031             DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
3032             return false;
3033         }
3034         DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
3035         return false;
3036     }
3037 
3038     if (m_debug.in_buffer_log) {
3039         venc_input_log_buffers(bufhdr, fd, plane[0].data_offset, m_sVenc_cfg.inputformat, interlace_flag);
3040     }
3041     if (m_debug.extradata_log && extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
3042         DEBUG_PRINT_ERROR("Extradata Addr 0x%llx, Buffer Addr = 0x%x",
3043             (OMX_U64)input_extradata_info.ion[index].uaddr, (unsigned int)plane[index].m.userptr);
3044         venc_extradata_log_buffers((char *)plane[extra_idx].m.userptr, index, true);
3045     }
3046     print_v4l2_buffer("QBUF-ETB", &buf);
3047     rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
3048 
3049     if (rc) {
3050         DEBUG_PRINT_ERROR("Failed to qbuf (etb) to driver");
3051         return false;
3052     }
3053 
3054     etb++;
3055 
3056     return true;
3057 }
3058 
get_media_colorformat(unsigned long inputformat)3059 unsigned long venc_dev::get_media_colorformat(unsigned long inputformat)
3060 {
3061     unsigned long color_format;
3062     switch (inputformat) {
3063         case V4L2_PIX_FMT_NV12:
3064             color_format = COLOR_FMT_NV12;
3065             break;
3066         case V4L2_PIX_FMT_NV12_512:
3067             color_format = COLOR_FMT_NV12_512;
3068             break;
3069         case V4L2_PIX_FMT_NV12_UBWC:
3070             color_format = COLOR_FMT_NV12_UBWC;
3071             break;
3072         case V4L2_PIX_FMT_RGB32:
3073             color_format = COLOR_FMT_RGBA8888;
3074             break;
3075         case V4L2_PIX_FMT_RGBA8888_UBWC:
3076             color_format = COLOR_FMT_RGBA8888_UBWC;
3077             break;
3078         case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS:
3079             color_format = COLOR_FMT_P010;
3080             break;
3081         case V4L2_PIX_FMT_NV12_TP10_UBWC:
3082             color_format = COLOR_FMT_NV12_BPP10_UBWC;
3083             break;
3084         default:
3085             color_format = COLOR_FMT_NV12_UBWC;
3086             DEBUG_PRINT_ERROR("Unknown format %lx,default to NV12_UBWC", inputformat);
3087             break;
3088     }
3089     return color_format;
3090 }
3091 
venc_empty_batch(OMX_BUFFERHEADERTYPE * bufhdr,unsigned index)3092 bool venc_dev::venc_empty_batch(OMX_BUFFERHEADERTYPE *bufhdr, unsigned index)
3093 {
3094     struct v4l2_buffer buf;
3095     struct v4l2_plane plane[VIDEO_MAX_PLANES];
3096     int rc = 0, extra_idx, numBufs;
3097     struct v4l2_control control;
3098     LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
3099     native_handle_t *hnd = NULL;
3100 
3101     if (bufhdr == NULL) {
3102         DEBUG_PRINT_ERROR("ERROR: %s: buffer is NULL", __func__);
3103         return false;
3104     }
3105 
3106     bool status = true;
3107     if (metadatamode) {
3108         plane[0].m.userptr = index;
3109         meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
3110 
3111         if (!color_format) {
3112             if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
3113                 hnd = (native_handle_t*)meta_buf->meta_handle;
3114                 if (!hnd) {
3115                     DEBUG_PRINT_ERROR("venc_empty_batch: invalid handle !");
3116                     return false;
3117                 } else if (MetaBufferUtil::getBatchSize(hnd) > kMaxBuffersInBatch) {
3118                     DEBUG_PRINT_ERROR("venc_empty_batch: Too many buffers (%d) in batch. "
3119                             "Max = %d", MetaBufferUtil::getBatchSize(hnd), kMaxBuffersInBatch);
3120                     status = false;
3121                 }
3122                 DEBUG_PRINT_LOW("venc_empty_batch: Batch of %d bufs", MetaBufferUtil::getBatchSize(hnd));
3123             } else {
3124                 DEBUG_PRINT_ERROR("Batch supported for CameraSource buffers only !");
3125                 status = false;
3126             }
3127         } else {
3128             DEBUG_PRINT_ERROR("Batch supported for Camera buffers only !");
3129             status = false;
3130         }
3131     } else {
3132         DEBUG_PRINT_ERROR("Batch supported for metabuffer mode only !");
3133         status = false;
3134     }
3135 
3136     if (status) {
3137         OMX_TICKS bufTimeStamp = 0ll;
3138         int numBufs = MetaBufferUtil::getBatchSize(hnd);
3139         int v4l2Ids[kMaxBuffersInBatch] = {-1};
3140         for (int i = 0; i < numBufs; ++i) {
3141             v4l2Ids[i] = mBatchInfo.registerBuffer(index);
3142             if (v4l2Ids[i] < 0) {
3143                 DEBUG_PRINT_ERROR("Failed to register buffer");
3144                 // TODO: cleanup the map and purge all slots of current index
3145                 status = false;
3146                 break;
3147             }
3148         }
3149         for (int i = 0; i < numBufs; ++i) {
3150             int v4l2Id = v4l2Ids[i];
3151             int usage = 0;
3152 
3153             memset(&buf, 0, sizeof(buf));
3154             memset(&plane, 0, sizeof(plane));
3155 
3156             DEBUG_PRINT_LOW("Batch: registering %d as %d", index, v4l2Id);
3157             buf.index = (unsigned)v4l2Id;
3158             buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3159             buf.memory = V4L2_MEMORY_USERPTR;
3160             plane[0].reserved[MSM_VIDC_BUFFER_FD] = MetaBufferUtil::getFdAt(hnd, i);
3161             plane[0].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3162             plane[0].data_offset = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_OFFSET);
3163             plane[0].m.userptr = (unsigned long)meta_buf;
3164             plane[0].length = plane[0].bytesused = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_SIZE);
3165             buf.m.planes = plane;
3166             buf.length = num_input_planes;
3167 
3168             usage = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_USAGE);
3169             usage = usage > 0 ? usage : 0;
3170 
3171             extra_idx = EXTRADATA_IDX(num_input_planes);
3172 
3173             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
3174                 plane[extra_idx].bytesused = input_extradata_info.buffer_size;
3175                 plane[extra_idx].length = input_extradata_info.buffer_size;
3176                 plane[extra_idx].m.userptr = (unsigned long)input_extradata_info.ion[v4l2Id].uaddr;
3177                 plane[extra_idx].reserved[MSM_VIDC_BUFFER_FD] = input_extradata_info.ion[v4l2Id].data_fd;
3178                 plane[extra_idx].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3179                 plane[extra_idx].data_offset = 0;
3180             } else if (extra_idx >= VIDEO_MAX_PLANES) {
3181                 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
3182                 return false;
3183             }
3184 
3185             if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
3186                 buf.flags |= V4L2_BUF_FLAG_EOS;
3187 
3188             // timestamp differences from camera are in nano-seconds
3189             bufTimeStamp = bufhdr->nTimeStamp + MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_TIMESTAMP) / 1000;
3190 
3191             DEBUG_PRINT_LOW(" Q Batch [%d of %d] : buf=%p fd=%d len=%d TS=%lld",
3192                 i, numBufs, bufhdr, plane[0].reserved[MSM_VIDC_BUFFER_FD], plane[0].length, bufTimeStamp);
3193             buf.timestamp.tv_sec = bufTimeStamp / 1000000;
3194             buf.timestamp.tv_usec = (bufTimeStamp % 1000000);
3195 
3196             if (!handle_input_extradata(buf)) {
3197                 DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
3198                 return false;
3199             }
3200 
3201             if (!handle_dynamic_config(bufhdr)) {
3202                 DEBUG_PRINT_ERROR("%s Failed to set dynamic configs", __func__);
3203                 return false;
3204             }
3205 
3206             VIDC_TRACE_INT_LOW("ETB-TS", bufTimeStamp / 1000);
3207 
3208             print_v4l2_buffer("QBUF-ETB", &buf);
3209             rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
3210             if (rc) {
3211                 DEBUG_PRINT_ERROR("%s: Failed to qbuf (etb) to driver", __func__);
3212                 return false;
3213             }
3214 
3215             etb++;
3216         }
3217     }
3218 
3219     if (status && !streaming[OUTPUT_PORT]) {
3220         enum v4l2_buf_type buf_type;
3221         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3222         int ret;
3223 
3224         if (!downscalar_enabled) {
3225             OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
3226 
3227             if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
3228                 return false;
3229             }
3230 
3231             if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
3232                 return false;
3233             }
3234 
3235             if (inp_width * inp_height != out_width * out_height) {
3236                 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
3237                 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
3238                 return false;
3239             }
3240         }
3241 
3242         ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
3243         if (ret) {
3244             DEBUG_PRINT_ERROR("Failed to call streamon");
3245             if (errno == EBUSY) {
3246                 hw_overload = true;
3247             }
3248             status = false;
3249         } else {
3250             streaming[OUTPUT_PORT] = true;
3251         }
3252     }
3253 
3254     return status;
3255 }
3256 
venc_fill_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)3257 bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd)
3258 {
3259     struct pmem *temp_buffer = NULL;
3260     struct venc_buffer  frameinfo;
3261     struct v4l2_buffer buf;
3262     struct v4l2_plane plane[VIDEO_MAX_PLANES];
3263     int rc = 0;
3264     unsigned int extra_idx;
3265     struct OMX_BUFFERHEADERTYPE *bufhdr;
3266 
3267     if (buffer == NULL)
3268         return false;
3269 
3270     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
3271 
3272     if (pmem_data_buf) {
3273         DEBUG_PRINT_LOW("Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf);
3274         plane[0].m.userptr = (unsigned long)pmem_data_buf;
3275     } else {
3276         DEBUG_PRINT_LOW("Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
3277         plane[0].m.userptr = (unsigned long)bufhdr->pBuffer;
3278     }
3279 
3280     memset(&buf, 0, sizeof(buf));
3281     memset(&plane, 0, sizeof(plane));
3282 
3283     buf.index = index;
3284     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3285     buf.memory = V4L2_MEMORY_USERPTR;
3286     plane[0].length = bufhdr->nAllocLen;
3287     plane[0].bytesused = bufhdr->nFilledLen;
3288     plane[0].reserved[MSM_VIDC_BUFFER_FD] = fd;
3289     plane[0].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3290     plane[0].data_offset = bufhdr->nOffset;
3291     buf.m.planes = plane;
3292     buf.length = num_output_planes;
3293     buf.flags = 0;
3294 
3295     if (venc_handle->is_secure_session()) {
3296         if (venc_handle->allocate_native_handle) {
3297             native_handle_t *handle_t = (native_handle_t *)(bufhdr->pBuffer);
3298             plane[0].length = handle_t->data[3];
3299         } else {
3300             output_metabuffer *meta_buf = (output_metabuffer *)(bufhdr->pBuffer);
3301             native_handle_t *handle_t = meta_buf->nh;
3302             plane[0].length = handle_t->data[3];
3303         }
3304     }
3305 
3306     extra_idx = EXTRADATA_IDX(num_output_planes);
3307 
3308     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
3309         plane[extra_idx].bytesused = output_extradata_info.buffer_size;
3310         plane[extra_idx].length = output_extradata_info.buffer_size;
3311         plane[extra_idx].m.userptr = (unsigned long)output_extradata_info.ion[index].uaddr;
3312 #ifdef USE_ION
3313         plane[extra_idx].reserved[MSM_VIDC_BUFFER_FD] = output_extradata_info.ion[index].data_fd;
3314 #endif
3315         plane[extra_idx].reserved[MSM_VIDC_DATA_OFFSET] = 0;
3316         plane[extra_idx].data_offset = 0;
3317     } else if (extra_idx >= VIDEO_MAX_PLANES) {
3318         DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx);
3319         return false;
3320     }
3321 
3322     print_v4l2_buffer("QBUF-FTB", &buf);
3323     rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
3324 
3325     if (rc) {
3326         DEBUG_PRINT_ERROR("Failed to qbuf (ftb) to driver");
3327         return false;
3328     }
3329 
3330     ftb++;
3331     return true;
3332 }
3333 
venc_set_colorspace(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer_chars,OMX_U32 matrix_coeffs)3334 bool venc_dev::venc_set_colorspace(OMX_U32 primaries, OMX_U32 range,
3335     OMX_U32 transfer_chars, OMX_U32 matrix_coeffs)
3336 {
3337     int rc;
3338     struct v4l2_control control;
3339 
3340     DEBUG_PRINT_LOW("Setting color space : Primaries = %d, Range = %d, Trans = %d, Matrix = %d",
3341         primaries, range, transfer_chars, matrix_coeffs);
3342 
3343     control.id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE;
3344     control.value = primaries;
3345 
3346     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3347     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3348 
3349     if (rc) {
3350         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE");
3351         return false;
3352     }
3353 
3354     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3355 
3356     color_space.primaries = control.value;
3357 
3358     control.id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE;
3359     control.value = range;
3360 
3361     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3362     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3363 
3364     if (rc) {
3365         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE");
3366         return false;
3367     }
3368 
3369     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3370 
3371     color_space.range = control.value;
3372 
3373     control.id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS;
3374     control.value = transfer_chars;
3375 
3376     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3377     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3378 
3379     if (rc) {
3380         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS");
3381         return false;
3382     }
3383 
3384     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3385 
3386     color_space.transfer_chars = control.value;
3387 
3388     control.id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS;
3389     control.value = matrix_coeffs;
3390 
3391     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3392     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3393 
3394     if (rc) {
3395         DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS");
3396         return false;
3397     }
3398 
3399     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3400 
3401     color_space.matrix_coeffs = control.value;
3402 
3403     return true;
3404 }
3405 
venc_set_qp(OMX_U32 i_frame_qp,OMX_U32 p_frame_qp,OMX_U32 b_frame_qp,OMX_U32 enable)3406 bool venc_dev::venc_set_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp, OMX_U32 enable)
3407 {
3408     int rc;
3409     struct v4l2_control control;
3410 
3411     OMX_U32 ids[3] = {
3412         V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
3413         V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
3414         V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP
3415     };
3416 
3417     OMX_U32 qp_values[3] = {
3418         i_frame_qp,
3419         p_frame_qp,
3420         b_frame_qp
3421     };
3422     unsigned long *session_qp_values[3] = {
3423         &session_qp.iframeqp,
3424         &session_qp.pframeqp,
3425         &session_qp.bframeqp
3426     };
3427     OMX_U32 qp_mask[3] = {
3428         ENABLE_I_QP,
3429         ENABLE_P_QP,
3430         ENABLE_B_QP
3431     };
3432 
3433     for(int i=0; i<3; i++) {
3434         if (enable & qp_mask[i]) {
3435             control.id = ids[i];
3436             control.value = qp_values[i];
3437 
3438             DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3439             rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3440 
3441             if (rc) {
3442                 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3443                 return false;
3444             }
3445             DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3446             *session_qp_values[i] = control.value;
3447         }
3448     }
3449 
3450     return true;
3451 }
3452 
set_nP_frames(unsigned long nPframes)3453 bool venc_dev::set_nP_frames(unsigned long nPframes)
3454 {
3455     struct v4l2_control control;
3456 
3457     control.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
3458     control.value = (nPframes > VENC_INFINITE_GOP) ? VENC_INFINITE_GOP : nPframes;
3459     int rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3460 
3461     if (rc) {
3462         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3463         return false;
3464     }
3465     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3466 
3467     return true;
3468 }
3469 
set_nB_frames(unsigned long nBframes)3470 bool venc_dev::set_nB_frames(unsigned long nBframes)
3471 {
3472     struct v4l2_control control;
3473 
3474     control.id = V4L2_CID_MPEG_VIDEO_B_FRAMES;
3475     control.value = (nBframes > VENC_INFINITE_GOP) ? VENC_INFINITE_GOP : nBframes;
3476     int rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3477 
3478     if (rc) {
3479         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3480         return false;
3481     }
3482     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3483 
3484     return true;
3485 }
3486 
set_native_recoder(bool enable)3487 bool venc_dev::set_native_recoder(bool enable)
3488 {
3489     struct v4l2_control control;
3490 
3491     control.id = V4L2_CID_MPEG_VIDC_VENC_NATIVE_RECORDER;
3492     control.value = enable;
3493     int rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3494 
3495     if (rc) {
3496         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3497         return false;
3498     }
3499     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3500 
3501     return true;
3502 }
3503 
venc_set_intra_refresh()3504 bool venc_dev::venc_set_intra_refresh()
3505 {
3506     int rc;
3507     struct v4l2_control control_mode;
3508 
3509     // Default is RANDOM mode
3510     control_mode.id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM;
3511     // Set intra refresh period (frame count) for Random mode
3512     control_mode.value  = intra_refresh.framecount;
3513 
3514     if (intra_refresh.irmode == OMX_VIDEO_IntraRefreshCyclic) {
3515         control_mode.id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB;
3516         control_mode.value  = intra_refresh.mbcount;
3517     }
3518 
3519     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%u, val=%d",
3520                     control_mode.id, control_mode.value);
3521     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_mode);
3522 
3523     if (rc) {
3524         DEBUG_PRINT_HIGH("Failed to set control, id %#x, value %d",
3525                          control_mode.id, control_mode.value);
3526         // This key is ignored if the video encoder does not support the intra refresh feature.
3527         // From android developer reference documentation.
3528     }
3529 
3530     return true;
3531 }
3532 
venc_set_target_bitrate(OMX_U32 nTargetBitrate)3533 bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate)
3534 {
3535     DEBUG_PRINT_LOW("venc_set_target_bitrate: bitrate = %u",
3536             (unsigned int)nTargetBitrate);
3537     struct v4l2_control control;
3538     int rc = 0;
3539     OMX_U32 ids[2] = {
3540         V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY,
3541         V4L2_CID_MPEG_VIDEO_BITRATE
3542     };
3543 
3544     control.id =  ids[!!(rate_ctrl.rcmode ^ V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)];
3545     control.value = nTargetBitrate;
3546 
3547     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3548     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3549     if (rc) {
3550         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3551         return false;
3552     }
3553 
3554     bitrate.target_bitrate = control.value;
3555     DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
3556 
3557     return true;
3558 }
3559 
venc_set_encode_framerate(OMX_U32 encode_framerate)3560 bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate)
3561 {
3562     int rc = 0;
3563     struct venc_framerate frame_rate_cfg;
3564     struct v4l2_control control;
3565 
3566     control.id =  V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
3567     control.value = encode_framerate;
3568 
3569     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
3570     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3571     if (rc) {
3572         DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
3573         return false;
3574     }
3575 
3576     Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator);
3577     m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator;
3578     m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator;
3579 
3580     return true;
3581 }
3582 
venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)3583 unsigned long venc_dev::venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)
3584 {
3585     unsigned long format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
3586 
3587     switch ((int)eColorFormat) {
3588     case OMX_COLOR_FormatYUV420SemiPlanar:
3589     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
3590         format = V4L2_PIX_FMT_NV12;
3591         break;
3592     case QOMX_COLOR_FormatYVU420SemiPlanar:
3593         format = V4L2_PIX_FMT_NV21;
3594         break;
3595     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
3596         format = V4L2_PIX_FMT_NV12_UBWC;
3597         break;
3598     case QOMX_COLOR_Format32bitRGBA8888:
3599         format = V4L2_PIX_FMT_RGB32;
3600         break;
3601     case QOMX_COLOR_Format32bitRGBA8888Compressed:
3602         format = V4L2_PIX_FMT_RGBA8888_UBWC;
3603         break;
3604     case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
3605         format = V4L2_PIX_FMT_NV12_TP10_UBWC;
3606         break;
3607     case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
3608         format = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
3609         break;
3610     default:
3611         DEBUG_PRINT_INFO("WARN: Unsupported eColorFormat %#x", eColorFormat);
3612         format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
3613         break;
3614     }
3615 
3616     if (m_codec == OMX_VIDEO_CodingImageHEIC)
3617         format = V4L2_PIX_FMT_NV12_512;
3618 
3619     return format;
3620 }
3621 
venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)3622 bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)
3623 {
3624     struct v4l2_format fmt;
3625     int color_space = 0;
3626     DEBUG_PRINT_LOW("venc_set_color_format: color_format = %u ", color_format);
3627 
3628     switch ((int)color_format) {
3629         case OMX_COLOR_FormatYUV420SemiPlanar:
3630         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
3631             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
3632             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
3633             break;
3634         case QOMX_COLOR_FormatYVU420SemiPlanar:
3635             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
3636             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
3637             break;
3638         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
3639             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
3640             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
3641             break;
3642         case QOMX_COLOR_Format32bitRGBA8888:
3643             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGB32;
3644             break;
3645         case QOMX_COLOR_Format32bitRGBA8888Compressed:
3646             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGBA8888_UBWC;
3647             break;
3648         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
3649             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_TP10_UBWC;
3650             break;
3651         case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
3652             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
3653             break;
3654         default:
3655             DEBUG_PRINT_HIGH("WARNING: Unsupported Color format [%d]", color_format);
3656             m_sVenc_cfg.inputformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
3657             color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
3658             DEBUG_PRINT_HIGH("Default color format NV12 UBWC is set");
3659             break;
3660     }
3661 
3662     if (m_codec == OMX_VIDEO_CodingImageHEIC)
3663         m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
3664 
3665     memset(&fmt, 0, sizeof(fmt));
3666     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3667     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
3668     fmt.fmt.pix_mp.colorspace = color_space;
3669     fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
3670     fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
3671 
3672     if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3673         DEBUG_PRINT_ERROR("Failed setting color format %x", color_format);
3674         return false;
3675     }
3676 
3677     return true;
3678 }
3679 
venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)3680 bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)
3681 {
3682     DEBUG_PRINT_LOW("venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh);
3683 
3684     if (intra_vop_refresh == OMX_TRUE) {
3685         struct v4l2_control control;
3686         int rc;
3687         control.id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME;
3688         control.value = 1;
3689 
3690         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3691         if (rc) {
3692             DEBUG_PRINT_ERROR("Failed to set Intra Frame Request control");
3693             return false;
3694         }
3695         DEBUG_PRINT_HIGH("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
3696     } else {
3697         DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect");
3698     }
3699 
3700     return true;
3701 }
3702 
venc_set_max_hierp_layer()3703 OMX_ERRORTYPE venc_dev::venc_set_max_hierp_layer()
3704 {
3705     DEBUG_PRINT_LOW("venc_set_max_hierp_layer");
3706     struct v4l2_control control;
3707 
3708     DEBUG_PRINT_LOW("Setting hierp max layer: %u",
3709                     temporal_layers_config.nMaxLayers);
3710 
3711     control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER;
3712     control.value = temporal_layers_config.nMaxLayers;
3713 
3714     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3715         DEBUG_PRINT_ERROR("Failed to set max HP layers: %u", control.value);
3716         return OMX_ErrorUnsupportedSetting;
3717     }
3718     return OMX_ErrorNone;
3719 }
3720 
venc_set_hierp_layer()3721 OMX_ERRORTYPE venc_dev::venc_set_hierp_layer()
3722 {
3723     DEBUG_PRINT_LOW("venc_set_hierp_layer");
3724     struct v4l2_control control;
3725 
3726     DEBUG_PRINT_LOW("Setting hierp layer: %u", temporal_layers_config.nPLayers);
3727 
3728     control.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER;
3729     control.value = temporal_layers_config.nPLayers;
3730 
3731     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3732         DEBUG_PRINT_ERROR("Failed to set HP layers: %u", control.value);
3733         return OMX_ErrorUnsupportedSetting;
3734     }
3735     return OMX_ErrorNone;
3736 }
3737 
venc_set_ltrcount(OMX_U32 count)3738 bool venc_dev::venc_set_ltrcount(OMX_U32 count)
3739 {
3740     DEBUG_PRINT_LOW("venc_set_ltrcount: count = %u", (unsigned int)count);
3741     struct v4l2_control control;
3742 
3743     control.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT;
3744     control.value = count;
3745 
3746     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3747         DEBUG_PRINT_ERROR("Failed to set LTR count: %u", control.value);
3748         return OMX_ErrorUnsupportedSetting;
3749     }
3750 
3751     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
3752                     control.id, control.value);
3753     return true;
3754 }
3755 
venc_set_useltr(OMX_U32 frameIdx)3756 bool venc_dev::venc_set_useltr(OMX_U32 frameIdx)
3757 {
3758     DEBUG_PRINT_LOW("venc_use_goldenframe");
3759     int rc = true;
3760     struct v4l2_control control;
3761 
3762     control.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME;
3763     control.value = frameIdx;
3764 
3765     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3766     if (rc) {
3767         DEBUG_PRINT_ERROR("Failed to set use_ltr %d", rc);
3768         return false;
3769     }
3770 
3771     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
3772                     control.id, control.value);
3773     return true;
3774 }
3775 
venc_set_markltr(OMX_U32 frameIdx)3776 bool venc_dev::venc_set_markltr(OMX_U32 frameIdx)
3777 {
3778     DEBUG_PRINT_LOW("venc_set_goldenframe");
3779     int rc = true;
3780     struct v4l2_control control;
3781 
3782     control.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME;
3783     control.value = frameIdx;
3784 
3785     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3786     if (rc) {
3787         DEBUG_PRINT_ERROR("Failed to set markltr %d", rc);
3788         return false;
3789     }
3790 
3791     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
3792                     control.id, control.value);
3793     return true;
3794 }
3795 
venc_set_mirror(OMX_MIRRORTYPE mirror)3796 bool venc_dev::venc_set_mirror(OMX_MIRRORTYPE mirror)
3797 {
3798     DEBUG_PRINT_LOW("venc_set_mirror");
3799     int rc = true;
3800     struct v4l2_control control[2];
3801 
3802     control[0].id = V4L2_CID_VFLIP;
3803     control[0].value = V4L2_MPEG_MSM_VIDC_DISABLE;
3804     control[1].id = V4L2_CID_HFLIP;
3805     control[1].value = V4L2_MPEG_MSM_VIDC_DISABLE;
3806 
3807     if (mirror == OMX_MirrorVertical || mirror == OMX_MirrorBoth) {
3808         control[0].value = V4L2_MPEG_MSM_VIDC_ENABLE;
3809     }
3810     if (mirror == OMX_MirrorHorizontal || mirror == OMX_MirrorBoth) {
3811         control[1].value = V4L2_MPEG_MSM_VIDC_ENABLE;
3812     }
3813 
3814     for(int i=0; i<2; i++) {
3815         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control[i]);
3816         if (rc) {
3817             DEBUG_PRINT_ERROR("Failed to set mirror %d", rc);
3818             return false;
3819         }
3820         DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
3821                         control[i].id, control[i].value);
3822     }
3823 
3824     return true;
3825 }
3826 
venc_set_vpe_rotation(OMX_S32 rotation_angle)3827 bool venc_dev::venc_set_vpe_rotation(OMX_S32 rotation_angle)
3828 {
3829     DEBUG_PRINT_LOW("venc_set_vpe_rotation: rotation angle = %d", (int)rotation_angle);
3830     struct v4l2_control control;
3831     int rc;
3832     struct v4l2_format fmt;
3833     struct v4l2_requestbuffers bufreq;
3834 
3835     if ((OMX_S32)m_rotation.rotation == rotation_angle) {
3836         DEBUG_PRINT_HIGH("venc_set_vpe_rotation: rotation (%d) not changed", rotation_angle);
3837         return true;
3838     }
3839 
3840     control.id = V4L2_CID_ROTATE;
3841     control.value = rotation_angle;
3842 
3843     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
3844     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3845     if (rc) {
3846         DEBUG_PRINT_HIGH("Failed to set VPE Rotation control");
3847         return false;
3848     }
3849     DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
3850 
3851     /* successfully set rotation_angle, save it */
3852     m_rotation.rotation = rotation_angle;
3853 
3854     return true;
3855 }
3856 
venc_prepare_c2d_rotation(OMX_S32 rotation_angle)3857 bool venc_dev::venc_prepare_c2d_rotation(OMX_S32 rotation_angle)
3858 {
3859    int rc;
3860    struct v4l2_format fmt;
3861    struct v4l2_requestbuffers bufreq;
3862    OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3863 
3864     DEBUG_PRINT_HIGH("venc_prepare_c2d_rotation angle = %d", (int)rotation_angle);
3865     if ((OMX_S32)m_rotation.rotation == rotation_angle) {
3866         DEBUG_PRINT_HIGH("venc_prepare_c2d_rotation: rotation (%d) not changed", rotation_angle);
3867         return true;
3868     }
3869 
3870     if (rotation_angle == 90 || rotation_angle == 270) {
3871         m_bDimensionsNeedFlip = true;
3872         portDefn = &venc_handle->m_sInPortDef;
3873         m_sVenc_cfg.input_height = portDefn->format.video.nFrameWidth;
3874         m_sVenc_cfg.input_width =  portDefn->format.video.nFrameHeight;
3875 
3876         memset(&fmt, 0, sizeof(fmt));
3877 
3878         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3879         if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
3880             DEBUG_PRINT_ERROR("Failed to get format on OUTPUT_MPLANE");
3881             return false;
3882         }
3883 
3884         fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
3885         fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
3886         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3887             DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d",
3888                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
3889                 hw_overload = errno == EBUSY;
3890                 return false;
3891         }
3892         m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
3893 
3894         portDefn = &venc_handle->m_sOutPortDef;
3895         m_sVenc_cfg.dvs_width  = portDefn->format.video.nFrameHeight;
3896         m_sVenc_cfg.dvs_height = portDefn->format.video.nFrameWidth;
3897 
3898         memset(&fmt, 0, sizeof(fmt));
3899 
3900         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3901         if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
3902             DEBUG_PRINT_ERROR("Failed to get format on CAPTURE_MPLANE");
3903             return false;
3904         }
3905 
3906         fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
3907         fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
3908         if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3909             DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed");
3910             hw_overload = errno == EBUSY;
3911             return false;
3912         }
3913 
3914         m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
3915     }
3916 
3917     /* successfully set rotation_angle, save it */
3918     m_rotation.rotation = rotation_angle;
3919 
3920     return true;
3921 }
3922 
venc_set_baselayerid(OMX_U32 baseid)3923 bool venc_dev::venc_set_baselayerid(OMX_U32 baseid)
3924 {
3925     struct v4l2_control control;
3926     if (temporal_layers_config.hier_mode == HIER_P) {
3927         control.id = V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID;
3928         control.value = baseid;
3929         DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
3930         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3931             DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
3932             return false;
3933         }
3934         return true;
3935     } else {
3936         DEBUG_PRINT_ERROR("Invalid mode set for V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID: %d",
3937                 temporal_layers_config.hier_mode);
3938         return false;
3939     }
3940 }
3941 
venc_set_priority(OMX_U32 priority)3942 bool venc_dev::venc_set_priority(OMX_U32 priority) {
3943     struct v4l2_control control;
3944 
3945     DEBUG_PRINT_LOW("venc_set_priority: %s", priority ? "NonRealTime" : "RealTime");
3946     control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
3947     if (priority == 0)
3948         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
3949     else
3950         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
3951 
3952     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3953         DEBUG_PRINT_ERROR("Failed to set V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_%s",
3954                 priority == 0 ? "ENABLE" : "DISABLE");
3955         return false;
3956     }
3957     return true;
3958 }
3959 
reconfigure_avc_param(OMX_VIDEO_PARAM_AVCTYPE * param)3960 bool venc_dev::reconfigure_avc_param(OMX_VIDEO_PARAM_AVCTYPE *param) {
3961     param->eProfile = (OMX_VIDEO_AVCPROFILETYPE)QOMX_VIDEO_AVCProfileMain;
3962 
3963     DEBUG_PRINT_LOW("reconfigure_avc_param");
3964 
3965     if (!venc_set_profile (param->eProfile)) {
3966         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
3967             param->eProfile);
3968         return false;
3969     }
3970     if (set_nP_frames(param->nPFrames) == false ||
3971         (param->nBFrames && set_nB_frames(param->nBFrames) == false)) {
3972             DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
3973             return false;
3974     }
3975     if (!venc_set_entropy_config (param->bEntropyCodingCABAC, param->nCabacInitIdc)) {
3976         DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed");
3977         return false;
3978     }
3979     if (!venc_set_inloop_filter (param->eLoopFilterMode)) {
3980         DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed");
3981         return false;
3982     }
3983     if (!venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB, param->nSliceHeaderSpacing)) {
3984         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config");
3985         return false;
3986     }
3987     if (!venc_h264_transform_8x8(param->bDirect8x8Inference)) {
3988         DEBUG_PRINT_ERROR("WARNING: Request for setting Transform8x8 failed");
3989         return false;
3990     }
3991 
3992     return true;
3993 }
3994 
venc_set_operatingrate(OMX_U32 rate)3995 bool venc_dev::venc_set_operatingrate(OMX_U32 rate) {
3996     struct v4l2_control control;
3997 
3998     control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
3999     control.value = rate;
4000 
4001     if (rate > INT_MAX)
4002         control.value = INT_MAX;
4003 
4004     DEBUG_PRINT_LOW("venc_set_operating_rate: %u fps", rate >> 16);
4005     DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%u", control.id, control.value);
4006 
4007     if (!strncmp(venc_handle->m_platform, "bengal", 6) &&
4008         (rate >> 16) > 30 && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 &&
4009         venc_handle->m_sParamAVC.eProfile ==
4010             (OMX_VIDEO_AVCPROFILETYPE)QOMX_VIDEO_AVCProfileHigh &&
4011         (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height >= 1920 * 1080)) {
4012         if (!reconfigure_avc_param(&venc_handle->m_sParamAVC)) {
4013             DEBUG_PRINT_ERROR("reconfigure avc param fails");
4014         }
4015     }
4016 
4017     if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4018         hw_overload = errno == EBUSY;
4019         DEBUG_PRINT_ERROR("Failed to set operating rate %d fps (%s)",
4020                 rate >> 16, hw_overload ? "HW overload" : strerror(errno));
4021         return false;
4022     }
4023 
4024     operating_rate = rate >> 16;
4025     DEBUG_PRINT_LOW("Operating Rate Set = %d fps",  rate >> 16);
4026 
4027     return true;
4028 }
4029 
venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO * roiInfo)4030 bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo)
4031 {
4032     struct roidata roi;
4033 
4034     if (!m_roi_enabled) {
4035         DEBUG_PRINT_ERROR("ROI info not enabled");
4036         return false;
4037     }
4038 
4039     if (!roiInfo) {
4040         DEBUG_PRINT_ERROR("No ROI info present");
4041         return false;
4042     }
4043     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
4044     m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
4045         DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
4046         return false;
4047     }
4048 
4049     memset(&roi, 0, sizeof(struct roidata));
4050 
4051     roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
4052     roi.info.nTimeStamp = roiInfo->nTimeStamp;
4053     memcpy(roi.info.pRoiMBInfo, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
4054 
4055     roi.dirty = true;
4056 
4057     pthread_mutex_lock(&m_roilock);
4058     DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
4059     m_roilist.push_back(roi);
4060     pthread_mutex_unlock(&m_roilock);
4061 
4062     return true;
4063 }
4064 
venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO * blurInfo)4065 bool venc_dev::venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO *blurInfo)
4066 {
4067     struct v4l2_control ctrl;
4068 
4069     ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS;
4070     ctrl.value = blurInfo->nBlurInfo;
4071 
4072     if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl)) {
4073         DEBUG_PRINT_ERROR("Failed to set blur resoltion");
4074         return false;
4075     }
4076 
4077     return true;
4078 }
4079 
venc_h264_transform_8x8(OMX_BOOL enable)4080 bool venc_dev::venc_h264_transform_8x8(OMX_BOOL enable)
4081 {
4082     struct v4l2_control control;
4083 
4084     control.id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM;
4085     if (enable)
4086         control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4087     else
4088         control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
4089 
4090     DEBUG_PRINT_LOW("Set h264_transform_8x8 mode: %d", control.value);
4091     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4092         DEBUG_PRINT_ERROR("set control: H264 transform 8x8 failed");
4093         return false;
4094     }
4095 
4096     return true;
4097 }
4098 
venc_get_temporal_layer_caps(OMX_U32 * nMaxLayers,OMX_U32 * nMaxBLayers,OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE * eSupportedPattern)4099 bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers,
4100         OMX_U32 *nMaxBLayers, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE *eSupportedPattern) {
4101 
4102     (void) nMaxBLayers;
4103     struct v4l2_queryctrl query_ctrl;
4104 
4105     if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC || m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
4106         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
4107     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
4108         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
4109     } else {
4110         *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone;
4111     }
4112 
4113     query_ctrl.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER;
4114 
4115     DEBUG_PRINT_LOW("TemporalLayer: Querying P layer caps");
4116     if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
4117         DEBUG_PRINT_ERROR("TemporalLayer: Query control P layer caps failed");
4118         return false;
4119     }
4120 
4121     //Return +1 as driver works on num max enhancement layers and OMX on num layers
4122     *nMaxLayers = query_ctrl.maximum + 1;
4123 
4124     return true;
4125 }
4126 
venc_set_bitrate_ratios()4127 OMX_ERRORTYPE venc_dev::venc_set_bitrate_ratios()
4128 {
4129     struct v4l2_control ctrl;
4130     int rc = 0;
4131     OMX_U32 ids[] = {
4132         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
4133         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
4134         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
4135         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
4136         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
4137         V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
4138     };
4139 
4140     DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio");
4141 
4142     // Set all bitrate ratios to kernel. If client hasn't set bitrate ratio
4143     // for a layer, 0 is passed on to kernel.
4144     for (OMX_U32 i = 0; i < (OMX_U32)(sizeof(ids)/sizeof(ids[0])); ++i) {
4145         ctrl.id = ids[i];
4146         ctrl.value = temporal_layers_config.nTemporalLayerBitrateRatio[i];
4147 
4148         rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl);
4149         if (rc) {
4150             DEBUG_PRINT_ERROR("Failed to set layerwise bitrate ratio. Id= %u, Value= %u, error %d",
4151                               ctrl.id, ctrl.value, rc);
4152             return OMX_ErrorUnsupportedSetting;
4153         }
4154         DEBUG_PRINT_LOW("Layerwise bitrate configured successfully for layer: %u, bitrate: %u",
4155                         i, temporal_layers_config.nTemporalLayerBitrateRatio[i]);
4156     }
4157 	return OMX_ErrorNone;
4158 }
4159 
venc_get_hevc_profile(OMX_U32 * profile)4160 bool venc_dev::venc_get_hevc_profile(OMX_U32* profile)
4161 {
4162     if (profile == nullptr) return false;
4163 
4164     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
4165         if(profile_level_converter::convert_v4l2_profile_to_omx(V4L2_PIX_FMT_HEVC, codec_profile.profile, (int*)profile)) {
4166             return true;
4167         } else return false;
4168     } else return false;
4169 }
4170 
venc_get_profile_level(OMX_U32 * eProfile,OMX_U32 * eLevel)4171 bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
4172 {
4173     bool status = true;
4174 
4175     if (eProfile == NULL || eLevel == NULL) {
4176         return false;
4177     }
4178 
4179     if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
4180         switch (codec_profile.profile) {
4181             case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
4182                 *eProfile = OMX_VIDEO_AVCProfileBaseline;
4183                 break;
4184             case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
4185                 *eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
4186                 break;
4187             case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
4188                 *eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
4189                 break;
4190             case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
4191                 *eProfile = OMX_VIDEO_AVCProfileMain;
4192                 break;
4193             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
4194                 *eProfile = OMX_VIDEO_AVCProfileHigh;
4195                 break;
4196             case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
4197                 *eProfile = OMX_VIDEO_AVCProfileExtended;
4198                 break;
4199             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
4200                 *eProfile = OMX_VIDEO_AVCProfileHigh10;
4201                 break;
4202             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
4203                 *eProfile = OMX_VIDEO_AVCProfileHigh422;
4204                 break;
4205             case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
4206                 *eProfile = OMX_VIDEO_AVCProfileHigh444;
4207                 break;
4208             default:
4209                 *eProfile = OMX_VIDEO_AVCProfileMax;
4210                 status = false;
4211                 break;
4212         }
4213 
4214         if (!status) {
4215             return status;
4216         }
4217 
4218         switch (profile_level.level) {
4219             case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
4220                 *eLevel = OMX_VIDEO_AVCLevel1;
4221                 break;
4222             case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
4223                 *eLevel = OMX_VIDEO_AVCLevel1b;
4224                 break;
4225             case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
4226                 *eLevel = OMX_VIDEO_AVCLevel11;
4227                 break;
4228             case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
4229                 *eLevel = OMX_VIDEO_AVCLevel12;
4230                 break;
4231             case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
4232                 *eLevel = OMX_VIDEO_AVCLevel13;
4233                 break;
4234             case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
4235                 *eLevel = OMX_VIDEO_AVCLevel2;
4236                 break;
4237             case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
4238                 *eLevel = OMX_VIDEO_AVCLevel21;
4239                 break;
4240             case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
4241                 *eLevel = OMX_VIDEO_AVCLevel22;
4242                 break;
4243             case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4244                 *eLevel = OMX_VIDEO_AVCLevel3;
4245                 break;
4246             case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4247                 *eLevel = OMX_VIDEO_AVCLevel31;
4248                 break;
4249             case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4250                 *eLevel = OMX_VIDEO_AVCLevel32;
4251                 break;
4252             case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4253                 *eLevel = OMX_VIDEO_AVCLevel4;
4254                 break;
4255             case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4256                 *eLevel = OMX_VIDEO_AVCLevel41;
4257                 break;
4258             case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4259                 *eLevel = OMX_VIDEO_AVCLevel42;
4260                 break;
4261             case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4262                 *eLevel = OMX_VIDEO_AVCLevel5;
4263                 break;
4264             case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4265                 *eLevel = OMX_VIDEO_AVCLevel51;
4266                 break;
4267             case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4268                 *eLevel = OMX_VIDEO_AVCLevel52;
4269                 break;
4270             default :
4271                 *eLevel = OMX_VIDEO_AVCLevelMax;
4272                 status = false;
4273                 break;
4274         }
4275     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
4276         switch (codec_profile.profile) {
4277             case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
4278                 *eProfile = OMX_VIDEO_VP8ProfileMain;
4279                 break;
4280             default:
4281                 *eProfile = OMX_VIDEO_VP8ProfileMax;
4282                 status = false;
4283                 break;
4284         }
4285         if (!status) {
4286             return status;
4287         }
4288 
4289         switch (profile_level.level) {
4290             case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
4291                 *eLevel = OMX_VIDEO_VP8Level_Version0;
4292                 break;
4293             case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
4294                 *eLevel = OMX_VIDEO_VP8Level_Version1;
4295                 break;
4296             default:
4297                 *eLevel = OMX_VIDEO_VP8LevelMax;
4298                 status = false;
4299                 break;
4300         }
4301     } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
4302         switch (codec_profile.profile) {
4303             case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
4304                 *eProfile = OMX_VIDEO_HEVCProfileMain;
4305                 break;
4306             case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10:
4307                 *eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
4308                 break;
4309             case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
4310                 *eProfile = OMX_VIDEO_HEVCProfileMainStill;
4311                 break;
4312             default:
4313                 *eProfile = OMX_VIDEO_HEVCProfileMax;
4314                 status = false;
4315                 break;
4316         }
4317         if (!status) {
4318             return status;
4319         }
4320 
4321         switch (profile_level.level) {
4322             case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
4323                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4324                                      OMX_VIDEO_HEVCMainTierLevel1:OMX_VIDEO_HEVCHighTierLevel1;
4325                 break;
4326             case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
4327                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4328                                      OMX_VIDEO_HEVCMainTierLevel2:OMX_VIDEO_HEVCHighTierLevel2;
4329                 break;
4330             case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
4331                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4332                                      OMX_VIDEO_HEVCMainTierLevel21:OMX_VIDEO_HEVCHighTierLevel21;
4333                 break;
4334             case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
4335                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4336                                      OMX_VIDEO_HEVCMainTierLevel3:OMX_VIDEO_HEVCHighTierLevel3;
4337                 break;
4338             case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
4339                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4340                                      OMX_VIDEO_HEVCMainTierLevel31:OMX_VIDEO_HEVCHighTierLevel31;
4341                 break;
4342             case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
4343                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4344                                      OMX_VIDEO_HEVCMainTierLevel4:OMX_VIDEO_HEVCHighTierLevel4;
4345                 break;
4346             case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
4347                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4348                                      OMX_VIDEO_HEVCMainTierLevel41:OMX_VIDEO_HEVCHighTierLevel41;
4349                 break;
4350             case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
4351                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4352                                      OMX_VIDEO_HEVCMainTierLevel5:OMX_VIDEO_HEVCHighTierLevel5;
4353                 break;
4354             case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
4355                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4356                                      OMX_VIDEO_HEVCMainTierLevel51:OMX_VIDEO_HEVCHighTierLevel51;
4357                 break;
4358             case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2:
4359                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4360                                      OMX_VIDEO_HEVCMainTierLevel52:OMX_VIDEO_HEVCHighTierLevel52;
4361                 break;
4362             case V4L2_MPEG_VIDEO_HEVC_LEVEL_6:
4363                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4364                                      OMX_VIDEO_HEVCMainTierLevel6:OMX_VIDEO_HEVCHighTierLevel6;
4365                 break;
4366             case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1:
4367                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4368                                      OMX_VIDEO_HEVCMainTierLevel61:OMX_VIDEO_HEVCHighTierLevel61;
4369                 break;
4370             case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2:
4371                 *eLevel = (profile_level.tier == V4L2_MPEG_VIDEO_HEVC_TIER_MAIN)?
4372                                      OMX_VIDEO_HEVCMainTierLevel62:OMX_VIDEO_HEVCHighTierLevel62;
4373                 break;
4374             default:
4375                 *eLevel = OMX_VIDEO_HEVCHighTiermax;
4376                 status = false;
4377                 break;
4378         }
4379     }
4380 
4381     return status;
4382 }
4383 
venc_set_nal_size(OMX_VIDEO_CONFIG_NALSIZE * nalSizeInfo)4384 bool venc_dev::venc_set_nal_size (OMX_VIDEO_CONFIG_NALSIZE *nalSizeInfo) {
4385     struct v4l2_control sControl;
4386 
4387     DEBUG_PRINT_HIGH("set video stream format - nal size - %u", nalSizeInfo->nNaluBytes);
4388 
4389     sControl.id = V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD;
4390     switch (nalSizeInfo->nNaluBytes) {
4391         case 0:
4392             sControl.value = V4L2_MPEG_VIDEO_HEVC_SIZE_0;
4393             break;
4394         case 4:
4395             sControl.value = V4L2_MPEG_VIDEO_HEVC_SIZE_4;
4396             break;
4397         default:
4398             return false;
4399     }
4400 
4401     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &sControl)) {
4402         DEBUG_PRINT_ERROR("set control: video stream format failed - %u",
4403                 (unsigned int)nalSizeInfo->nNaluBytes);
4404         return false;
4405     }
4406     return true;
4407 }
4408 
venc_superframe_enable(private_handle_t * handle)4409 bool venc_dev::venc_superframe_enable(private_handle_t *handle)
4410 {
4411     struct v4l2_control ctrl;
4412     OMX_U32 frame_size;
4413     unsigned long color_format;
4414 
4415     ctrl.id = V4L2_CID_MPEG_VIDC_SUPERFRAME;
4416     color_format = get_media_colorformat(m_sVenc_cfg.inputformat);
4417     frame_size = VENUS_BUFFER_SIZE(color_format, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
4418 
4419     /*
4420     * disable superframe if handle->size is not multiple of
4421     * frame_size or if it is a single frame.
4422     */
4423     if (handle->size % frame_size || handle->size == frame_size) {
4424         DEBUG_PRINT_ERROR("Invalid superframe handle size %d for frame size %d",
4425             handle->size, frame_size);
4426         return false;
4427     }
4428     ctrl.value = handle->size / frame_size;
4429     DEBUG_PRINT_HIGH("venc_superframe_enable: %d", ctrl.value);
4430     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl)) {
4431         DEBUG_PRINT_ERROR("Failed to enable superframe, errno %d", errno);
4432         return false;
4433     }
4434     return true;
4435 }
4436 
venc_cvp_enable(private_handle_t * handle)4437 bool venc_dev::venc_cvp_enable(private_handle_t *handle)
4438 {
4439     cvpMetadata.size = 0;
4440     if (temporal_layers_config.nMaxLayers > 1) {
4441         DEBUG_PRINT_INFO("venc_cvp_enable: disabling CVP as max layers %u", temporal_layers_config.nMaxLayers);
4442         return true;
4443     }
4444     if (getMetaData(handle, GET_CVP_METADATA, &cvpMetadata) == 0) {
4445         if (cvpMetadata.size == CVP_METADATA_SIZE) {
4446             struct v4l2_control control;
4447             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
4448             control.value = EXTRADATA_ENC_INPUT_CVP;
4449             if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4450                 DEBUG_PRINT_ERROR("ERROR: Setting CVP metadata extradata control failed");
4451                 return false;
4452             }
4453             m_cvp_meta_enabled = true;
4454             m_cvp_first_metadata = true;
4455             DEBUG_PRINT_HIGH("CVP metadata enabled");
4456             if (!venc_set_cvp_skipratio_controls())
4457                 return false;
4458         } else {
4459             DEBUG_PRINT_ERROR("ERROR: External CVP mode disabled for this session and continue!");
4460             setMetaData(handle, SET_CVP_METADATA, 0);
4461         }
4462     } else {
4463         DEBUG_PRINT_INFO("venc_cvp_enable: cvp metadata not available");
4464     }
4465     return true;
4466 }
4467 
venc_set_cvp_skipratio_controls()4468 bool venc_dev::venc_set_cvp_skipratio_controls()
4469 {
4470     struct v4l2_control ctrl;
4471 
4472     if (!cvpMetadata.cvp_frame_rate || !cvpMetadata.capture_frame_rate) {
4473         DEBUG_PRINT_ERROR("ERROR: Invalid cvp frame rate received");
4474         return true;
4475     }
4476     DEBUG_PRINT_HIGH("cvpMetadata: frame_rate %u capture rate %u", cvpMetadata.cvp_frame_rate, cvpMetadata.capture_frame_rate);
4477 
4478     ctrl.id = V4L2_CID_MPEG_VIDC_CAPTURE_FRAME_RATE;
4479     ctrl.value = cvpMetadata.capture_frame_rate;
4480     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl)) {
4481         DEBUG_PRINT_ERROR("ERROR: Setting capture frame rate control failed");
4482         return false;
4483     }
4484 
4485     ctrl.id = V4L2_CID_MPEG_VIDC_CVP_FRAME_RATE;
4486     ctrl.value = cvpMetadata.cvp_frame_rate;
4487     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl)) {
4488         DEBUG_PRINT_ERROR("ERROR: Setting cvp frame rate control failed");
4489         return false;
4490     }
4491     return true;
4492 }
4493 
venc_get_cvp_metadata(private_handle_t * handle,struct v4l2_buffer * buf)4494 bool venc_dev::venc_get_cvp_metadata(private_handle_t *handle, struct v4l2_buffer *buf)
4495 {
4496     if (!m_cvp_meta_enabled)
4497         return true;
4498 
4499     unsigned int capture_rate = cvpMetadata.capture_frame_rate;
4500     unsigned int cvp_rate = cvpMetadata.cvp_frame_rate;
4501 
4502     buf->flags &= ~V4L2_BUF_FLAG_CVPMETADATA_SKIP;
4503     cvpMetadata.size = 0;
4504     if (getMetaData(handle, GET_CVP_METADATA, &cvpMetadata) == 0) {
4505         setMetaData(handle, SET_CVP_METADATA, 0);
4506         if (cvpMetadata.size != CVP_METADATA_SIZE) {
4507             DEBUG_PRINT_ERROR("ERROR: Invalid CVP metadata size %d",
4508                 cvpMetadata.size);
4509             cvpMetadata.size = 0;
4510             /* If camera sends metadata of size not matching to CVP_METADATA_SIZE,
4511                it is considered as an error case. So, do not add skip flag */
4512             return false;
4513         }
4514         DEBUG_PRINT_LOW("CVP metadata size %d", cvpMetadata.size);
4515         if (m_debug.cvp_log) {
4516             venc_cvp_log_buffers("CVP", cvpMetadata.size, cvpMetadata.payload);
4517         }
4518     } else {
4519         DEBUG_PRINT_ERROR("ERROR: CVP metadata not available");
4520         return false;
4521     }
4522 
4523     if (m_cvp_first_metadata) {
4524         m_cvp_first_metadata = false;
4525     } else if (cvpMetadata.flags & CVP_METADATA_FLAG_REPEAT) {
4526         buf->flags |= V4L2_BUF_FLAG_CVPMETADATA_SKIP;
4527         DEBUG_PRINT_LOW("venc_empty_buf: V4L2_BUF_FLAG_CVPMETADATA_SKIP is set");
4528     }
4529 
4530     if ((cvpMetadata.capture_frame_rate != capture_rate) ||
4531         (cvpMetadata.cvp_frame_rate != cvp_rate)) {
4532         if(!venc_set_cvp_skipratio_controls())
4533             return false;
4534     }
4535     return true;
4536 }
4537 
venc_config_bitrate(OMX_VIDEO_CONFIG_BITRATETYPE * bit_rate)4538 bool venc_dev::venc_config_bitrate(OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate)
4539 {
4540     OMX_U32 bitrate = bit_rate->nEncodeBitrate;
4541     if (bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
4542         // If quality boost is eligible, also increase bitrate by 15% in dynamic change case
4543         if (mQualityBoostEligible && bitrate < VENC_QUALITY_BOOST_BITRATE_THRESHOLD) {
4544             bitrate += bitrate * 15 / 100;
4545         }
4546         if (venc_set_target_bitrate(bitrate) == false) {
4547             DEBUG_PRINT_ERROR("ERROR: Setting Target Bit rate failed");
4548             return false;
4549         }
4550     } else {
4551         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate");
4552         return false;
4553     }
4554     return true;
4555 }
4556 
venc_config_framerate(OMX_CONFIG_FRAMERATETYPE * frame_rate)4557 bool venc_dev::venc_config_framerate(OMX_CONFIG_FRAMERATETYPE *frame_rate)
4558 {
4559     if (frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
4560         if (venc_set_encode_framerate(frame_rate->xEncodeFramerate) == false) {
4561             DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
4562             return false;
4563         }
4564     } else {
4565         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
4566         return false;
4567     }
4568     return true;
4569 }
4570 
venc_config_intravoprefresh(OMX_CONFIG_INTRAREFRESHVOPTYPE * intra_vop_refresh)4571 bool venc_dev::venc_config_intravoprefresh(OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh)
4572 {
4573     if (intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
4574         if (venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) {
4575             DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
4576             return false;
4577         }
4578     } else {
4579         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
4580         return false;
4581     }
4582 
4583     return true;
4584 }
4585 
venc_config_markLTR(OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE * markltr)4586 bool venc_dev::venc_config_markLTR(OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE *markltr)
4587 {
4588     if (markltr->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
4589         if(venc_set_markltr(markltr->nID) == false) {
4590             DEBUG_PRINT_ERROR("ERROR: Mark LTR failed");
4591             return false;
4592         }
4593     }  else {
4594         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRMark");
4595         return false;
4596     }
4597     return true;
4598 }
4599 
venc_config_useLTR(OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE * useltr)4600 bool venc_dev::venc_config_useLTR(OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE *useltr)
4601 {
4602     if (useltr->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
4603         if(venc_set_useltr(useltr->nID) == false) {
4604             DEBUG_PRINT_ERROR("ERROR: Use LTR failed");
4605             return false;
4606         }
4607     } else {
4608         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRUse");
4609         return false;
4610     }
4611     return true;
4612 }
4613 
venc_config_qp(OMX_SKYPE_VIDEO_CONFIG_QP * configqp)4614 bool venc_dev::venc_config_qp(OMX_SKYPE_VIDEO_CONFIG_QP *configqp)
4615 {
4616     if (venc_set_qp(configqp->nQP,
4617                     configqp->nQP,
4618                     configqp->nQP,
4619                     ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP ) == false) {
4620         DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigQp failed");
4621         return false;
4622     }
4623     return true;
4624 }
4625 
venc_config_vp8refframe(OMX_VIDEO_VP8REFERENCEFRAMETYPE * vp8refframe)4626 bool venc_dev::venc_config_vp8refframe(OMX_VIDEO_VP8REFERENCEFRAMETYPE *vp8refframe)
4627 {
4628     if ((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
4629             (vp8refframe->bUseGoldenFrame)) {
4630         if(venc_set_useltr(0x1) == false) {
4631             DEBUG_PRINT_ERROR("ERROR: use goldenframe failed");
4632             return false;
4633         }
4634     } else if((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
4635             (vp8refframe->bGoldenFrameRefresh)) {
4636         if(venc_set_markltr(0x1) == false) {
4637             DEBUG_PRINT_ERROR("ERROR: Setting goldenframe failed");
4638             return false;
4639         }
4640     } else {
4641         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoVp8ReferenceFrame");
4642         return false;
4643     }
4644     return true;
4645 }
4646 
4647 #ifdef _ANDROID_ICS_
venc_set_meta_mode(bool mode)4648 bool venc_dev::venc_set_meta_mode(bool mode)
4649 {
4650     metadatamode = mode;
4651     return true;
4652 }
4653 #endif
4654 
venc_is_video_session_supported(unsigned long width,unsigned long height)4655 bool venc_dev::venc_is_video_session_supported(unsigned long width,
4656         unsigned long height)
4657 {
4658     if ((width * height < capability.min_width *  capability.min_height) ||
4659             (width * height > capability.max_width *  capability.max_height)) {
4660         DEBUG_PRINT_ERROR(
4661                 "Unsupported video resolution WxH = (%lu)x(%lu) supported range = min (%d)x(%d) - max (%d)x(%d)",
4662                 width, height, capability.min_width, capability.min_height,
4663                 capability.max_width, capability.max_height);
4664         return false;
4665     }
4666 
4667     DEBUG_PRINT_LOW("video session supported");
4668     return true;
4669 }
4670 
BatchInfo()4671 venc_dev::BatchInfo::BatchInfo()
4672     : mNumPending(0) {
4673     pthread_mutex_init(&mLock, NULL);
4674     for (int i = 0; i < kMaxBufs; ++i) {
4675         mBufMap[i] = kBufIDFree;
4676     }
4677 }
4678 
registerBuffer(int bufferId)4679 int venc_dev::BatchInfo::registerBuffer(int bufferId) {
4680     pthread_mutex_lock(&mLock);
4681     int availId = 0;
4682     for( ; availId < kMaxBufs && mBufMap[availId] != kBufIDFree; ++availId);
4683     if (availId >= kMaxBufs) {
4684         DEBUG_PRINT_ERROR("Failed to find free entry !");
4685         pthread_mutex_unlock(&mLock);
4686         return -1;
4687     }
4688     mBufMap[availId] = bufferId;
4689     mNumPending++;
4690     pthread_mutex_unlock(&mLock);
4691     return availId;
4692 }
4693 
retrieveBufferAt(int v4l2Id)4694 int venc_dev::BatchInfo::retrieveBufferAt(int v4l2Id) {
4695     pthread_mutex_lock(&mLock);
4696     if (v4l2Id >= kMaxBufs || v4l2Id < 0) {
4697         DEBUG_PRINT_ERROR("Batch: invalid index %d", v4l2Id);
4698         pthread_mutex_unlock(&mLock);
4699         return -1;
4700     }
4701     if (mBufMap[v4l2Id] == kBufIDFree) {
4702         DEBUG_PRINT_ERROR("Batch: buffer @ %d was not registered !", v4l2Id);
4703         pthread_mutex_unlock(&mLock);
4704         return -1;
4705     }
4706     int bufferId = mBufMap[v4l2Id];
4707     mBufMap[v4l2Id] = kBufIDFree;
4708     mNumPending--;
4709     pthread_mutex_unlock(&mLock);
4710     return bufferId;
4711 }
4712 
isPending(int bufferId)4713 bool venc_dev::BatchInfo::isPending(int bufferId) {
4714     pthread_mutex_lock(&mLock);
4715     int existsId = 0;
4716     for(; existsId < kMaxBufs && mBufMap[existsId] != bufferId; ++existsId);
4717     pthread_mutex_unlock(&mLock);
4718     return existsId < kMaxBufs;
4719 }
4720 
venc_set_hdr_info(const MasteringDisplay & mastering_disp_info,const ContentLightLevel & content_light_level_info)4721 bool venc_dev::venc_set_hdr_info(const MasteringDisplay& mastering_disp_info,
4722                             const ContentLightLevel& content_light_level_info)
4723 {
4724     struct v4l2_control ctrl = {0, 0};
4725     const unsigned int hdr_info[] = {
4726         MSM_VIDC_RGB_PRIMARY_00,
4727         MSM_VIDC_RGB_PRIMARY_01,
4728         MSM_VIDC_RGB_PRIMARY_10,
4729         MSM_VIDC_RGB_PRIMARY_11,
4730         MSM_VIDC_RGB_PRIMARY_20,
4731         MSM_VIDC_RGB_PRIMARY_21,
4732         MSM_VIDC_WHITEPOINT_X,
4733         MSM_VIDC_WHITEPOINT_Y,
4734         MSM_VIDC_MAX_DISP_LUM,
4735         MSM_VIDC_MIN_DISP_LUM,
4736         MSM_VIDC_RGB_MAX_CLL,
4737         MSM_VIDC_RGB_MAX_FLL
4738     };
4739 
4740     unsigned int values[] = {
4741         mastering_disp_info.primaries.rgbPrimaries[0][0],
4742         mastering_disp_info.primaries.rgbPrimaries[0][1],
4743         mastering_disp_info.primaries.rgbPrimaries[1][0],
4744         mastering_disp_info.primaries.rgbPrimaries[1][1],
4745         mastering_disp_info.primaries.rgbPrimaries[2][0],
4746         mastering_disp_info.primaries.rgbPrimaries[2][1],
4747         mastering_disp_info.primaries.whitePoint[0],
4748         mastering_disp_info.primaries.whitePoint[1],
4749         // maxDisplayLuminance is in cd/m^2 scale. But the standard requires this field
4750         // to be in 0.0001 cd/m^2 scale. So, multiply with LUMINANCE_MULTIPLICATION_FACTOR
4751         // and give to be driver
4752         mastering_disp_info.maxDisplayLuminance * LUMINANCE_MULTIPLICATION_FACTOR,
4753         mastering_disp_info.minDisplayLuminance,
4754         content_light_level_info.maxContentLightLevel,
4755         content_light_level_info.minPicAverageLightLevel
4756     };
4757 
4758     ctrl.id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO;
4759 
4760     for (unsigned int i = 0; i < (sizeof(hdr_info)/sizeof(hdr_info[0])); i++) {
4761         ctrl.value = (unsigned int) ((values[i] & 0xFFFFFFF ) | (hdr_info[i] << 28));
4762         if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &ctrl)) {
4763             DEBUG_PRINT_ERROR("VIDIOC_S_CTRL failed for HDR Info : (%u) value %#X : %#X",
4764                               i, hdr_info[i], values[i]);
4765             return false;
4766         }
4767     }
4768 
4769     return true;
4770 }
4771 
4772 /*=================================================================================
4773  * Function:   venc_set_roi_region_qp_info
4774  * @brief      set the config of OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO and store
4775  *             the info in the list
4776  * Parameters:
4777  * @param      OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo:
4778  *             the config to be set
4779  * Return value:
4780  *             bool: return true if the config is set successfully
4781 *==================================================================================*/
venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO * roiRegionInfo)4782 bool venc_dev::venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo)
4783 {
4784     if (!m_roi_enabled || m_roi_type == ROI_NONE) {
4785         DEBUG_PRINT_ERROR("ROI-Region: roi info not enabled (%d) or unknown roi type (%u)",
4786             m_roi_enabled, m_roi_type);
4787         return false;
4788     }
4789     if (!roiRegionInfo) {
4790         DEBUG_PRINT_ERROR("ROI-Region: no region info present");
4791         return false;
4792     }
4793     if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
4794             m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
4795         DEBUG_PRINT_ERROR("ROI-Region: is not supported for %d codec",
4796                 (OMX_U32) m_sVenc_cfg.codectype);
4797         return false;
4798     }
4799 
4800     pthread_mutex_lock(&m_roilock);
4801     DEBUG_PRINT_LOW("ROI-Region: add region with timestamp %lld us.", roiRegionInfo->nTimeStamp);
4802     mRoiRegionList.push_back(*roiRegionInfo);
4803     pthread_mutex_unlock(&m_roilock);
4804     return true;
4805 }
4806 
4807 /*=================================================================================
4808  * Function:   append_extradata_roi_region_qp_info
4809  * @brief      fill the roi info in the extradata of input Buffer
4810  * Parameters:
4811  * @param      OMX_OTHER_EXTRADATATYPE *data: the address of the extradata buffer
4812  *             OMX_TICKS timestamp:  the timestamp of the input Buffer
4813  *             OMX_U32: the available size of the extradata buffer
4814  * Return value:
4815  *             OMX_U32: the filled size
4816 *==================================================================================*/
append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE * data,OMX_TICKS timestamp,OMX_U32 freeSize)4817 OMX_U32 venc_dev::append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE *data,
4818         OMX_TICKS timestamp, OMX_U32 freeSize)
4819 {
4820     bool found = false;
4821     pthread_mutex_lock(&m_roilock);
4822     if (mRoiRegionList.size() == 0) {
4823         pthread_mutex_unlock(&m_roilock);
4824         return 0;
4825     }
4826     std::list<OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO>::iterator it =
4827             mRoiRegionList.begin();
4828     while (it != mRoiRegionList.end()) {
4829         if (it->nTimeStamp < timestamp) {
4830             it = mRoiRegionList.erase(it);
4831             continue;
4832         } else if (it->nTimeStamp == timestamp) {
4833             found = true;
4834             break;
4835         }
4836         it++;
4837     }
4838     pthread_mutex_unlock(&m_roilock);
4839     if (!found) {
4840         DEBUG_PRINT_LOW("ROI-Region: no region roi data was found");
4841         return 0;
4842     }
4843     OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO regionInfo = *it;
4844     bool isHevc = m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC ? true:false;
4845     OMX_U32 height = m_sVenc_cfg.dvs_height;
4846     OMX_U32 width = m_sVenc_cfg.dvs_width;
4847     OMX_U32 mbAlign = isHevc ? 32 : 16;
4848     OMX_U8 mbBit = isHevc ? 5 : 4;
4849     OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
4850     OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
4851     OMX_U32 numBytes, mbLeft, mbTop, mbRight, mbBottom = 0;
4852     OMX_S8 deltaQP = 0;
4853     DEBUG_PRINT_LOW("ROI-Region: clip(%ux%u: %s), mb(%ux%u), region(num:%u, ts:%lld)",
4854             width, height, isHevc ? "hevc" : "avc", mbRow, mbCol, regionInfo.nRegionNum,
4855             regionInfo.nTimeStamp);
4856 
4857     if (m_roi_type == ROI_2BYTE) {
4858         OMX_U32 mbRowAligned = ALIGN(mbRow, 8);
4859         numBytes = mbRowAligned * mbCol * 2;
4860         OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
4861 
4862         data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload), 256)
4863                             + numBytesAligned;
4864         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
4865         if (data->nSize > freeSize) {
4866             DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
4867                      freeSize, data->nSize);
4868             data->nDataSize = 0;
4869             data->nSize = 0;
4870             return 0;
4871         }
4872 
4873         data->nVersion.nVersion = OMX_SPEC_VERSION;
4874         data->nPortIndex = 0;
4875         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
4876         struct msm_vidc_roi_deltaqp_payload *roiData =
4877                 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
4878         roiData->b_roi_info = true;
4879         roiData->mbi_info_size = numBytesAligned;
4880         roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256)
4881                 - (unsigned long)roiData->data);
4882         OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);
4883         OMX_U32 mb = 0;
4884         OMX_U16 *pData = NULL;
4885 
4886         for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
4887             mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
4888             mbTop = regionInfo.nRegions[i].nTop >> mbBit;
4889             mbRight = regionInfo.nRegions[i].nRight >> mbBit;
4890             mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
4891             deltaQP = regionInfo.nRegions[i].nDeltaQP;
4892             if (mbLeft >= mbRow || mbRight >= mbRow
4893                     || mbTop >= mbCol || mbBottom >= mbCol) {
4894                 continue;
4895             }
4896             for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
4897                 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
4898                     mb = row * mbRowAligned + col;
4899                     pData = exDataBuf + mb;
4900                    *pData = (1 << 11) | ((deltaQP & 0x3F) << 4);
4901                 }
4902             }
4903         }
4904         DEBUG_PRINT_LOW("ROI-Region(2Byte): set roi: raw size: %u", numBytesAligned);
4905     } else if (m_roi_type == ROI_2BIT) {
4906         numBytes = (mbRow * mbCol * 2 + 7) >> 3;
4907         data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload) + numBytes;
4908         data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
4909 
4910         if (data->nSize > freeSize) {
4911             DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
4912                     freeSize, data->nSize);
4913             data->nDataSize = 0;
4914             data->nSize = 0;
4915             return 0;
4916         }
4917 
4918         data->nVersion.nVersion = OMX_SPEC_VERSION;
4919         data->nPortIndex = 0;
4920         data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
4921         struct msm_vidc_roi_qp_payload *roiData =
4922                 (struct msm_vidc_roi_qp_payload *)(data->data);
4923         roiData->b_roi_info = true;
4924         roiData->mbi_info_size = numBytes;
4925         roiData->lower_qp_offset = 0;
4926         roiData->upper_qp_offset = 0;
4927         OMX_U8 flag = 0x1;
4928         OMX_U32 mb, mb_byte = 0;
4929         OMX_U8 mb_bit = 0;
4930         OMX_U8 *pData = NULL;
4931 
4932         for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
4933             mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
4934             mbTop = regionInfo.nRegions[i].nTop >> mbBit;
4935             mbRight = regionInfo.nRegions[i].nRight >> mbBit;
4936             mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
4937             deltaQP = regionInfo.nRegions[i].nDeltaQP;
4938             if (mbLeft >= mbRow || mbRight >= mbRow
4939                     || mbTop >= mbCol || mbBottom >= mbCol
4940                     || deltaQP == 0) {
4941                 continue;
4942             }
4943             // choose the minimum absolute value for lower and upper offset
4944             if (deltaQP < 0) {
4945                 if (roiData->lower_qp_offset == 0) {
4946                     roiData->lower_qp_offset = deltaQP;
4947                 } else if (roiData->lower_qp_offset < deltaQP) {
4948                     roiData->lower_qp_offset = deltaQP;
4949                 }
4950                 flag = 0x1;
4951             } else {
4952                 if (roiData->upper_qp_offset == 0) {
4953                     roiData->upper_qp_offset = deltaQP;
4954                 } else if (roiData->upper_qp_offset > deltaQP) {
4955                     roiData->upper_qp_offset = deltaQP;
4956                 }
4957                 flag = 0x2;
4958             }
4959             for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
4960                 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
4961                     mb = row * mbRow + col;
4962                     mb_byte = mb >> 2;
4963                     mb_bit = (3 - (mb & 0x3)) << 1;
4964                     pData = (OMX_U8 *)roiData->data + mb_byte;
4965                     *pData |= (flag << mb_bit);
4966                 }
4967             }
4968         }
4969         DEBUG_PRINT_LOW("ROI-Region(2Bit):set roi low:%d,up:%d", roiData->lower_qp_offset, roiData->upper_qp_offset);
4970     } else {
4971         DEBUG_PRINT_ERROR("Invalied roi type : %u", m_roi_type);
4972         return 0;
4973     }
4974     return data->nSize;
4975 }
4976 
venc_set_quality_boost(OMX_BOOL c2d_enable)4977 void venc_dev::venc_set_quality_boost(OMX_BOOL c2d_enable)
4978 {
4979     OMX_U32 initial_qp;
4980     OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE qp_range;
4981     OMX_QTI_VIDEO_CONFIG_BLURINFO blurinfo;
4982 
4983     // Conditions to enable encoder quality boost,
4984     // 1. Codec is AVC
4985     // 2. RCMode is VBR
4986     // 3. Input is RGBA/RGBA_UBWC (C2D enabled)
4987     // 4. width <= 960 and height <= 960
4988     // 5. width >= 400 and height >= 400
4989     // 6. FPS <= 30
4990     // 7. bitrate < 2Mbps
4991 
4992     if (mQualityBoostRequested && c2d_enable &&
4993         m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 &&
4994         rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
4995         m_sVenc_cfg.dvs_width <= 960 && m_sVenc_cfg.dvs_height <= 960 &&
4996         m_sVenc_cfg.dvs_width >= 400 && m_sVenc_cfg.dvs_height >= 400 &&
4997         (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) <= 30 &&
4998         bitrate.target_bitrate < VENC_QUALITY_BOOST_BITRATE_THRESHOLD) {
4999         mQualityBoostEligible = true;
5000         DEBUG_PRINT_HIGH("Quality boost eligible encoder session");
5001     } else {
5002         return;
5003     }
5004 
5005     if (bitrate.target_bitrate <= 64000)
5006         venc_set_level(OMX_VIDEO_AVCLevel1);
5007 
5008     // Set below configurations to boost quality
5009     // 1. Increase bitrate by 15%
5010     bitrate.target_bitrate += bitrate.target_bitrate * 15 / 100;
5011     venc_set_target_bitrate(bitrate.target_bitrate);
5012 
5013     // 2. Set initial QP=30
5014     initial_qp = 30;
5015     venc_set_qp(initial_qp, initial_qp, initial_qp, 7);
5016 
5017     // 3. Set QP range [10,40]
5018     qp_range.minIQP = qp_range.minPQP = qp_range.minBQP = 10;
5019     qp_range.maxIQP = qp_range.maxPQP = qp_range.maxBQP = 40;
5020     venc_set_session_qp_range(&qp_range);
5021 
5022     // 4. Disable blur (both external and internal)
5023     blurinfo.nBlurInfo = 2;
5024     venc_set_blur_resolution(&blurinfo);
5025 
5026     // 5. Disable bitrate savings (CAC)
5027     venc_set_bitrate_savings_mode(0);
5028 }
5029