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