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