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