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