1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010-2018, 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 HYPERVISOR
39 #include "hypv_intercept.h"
40 #endif
41 #ifdef USE_ION
42 #include <linux/msm_ion.h>
43 #endif
44 #include<linux/v4l2-controls.h>
45
46 #include <math.h>
47 #include <media/msm_media_info.h>
48 #include <cutils/properties.h>
49 #include <media/hardware/HardwareAPI.h>
50
51 #ifdef _ANDROID_
52 #include <media/hardware/HardwareAPI.h>
53 #include <gralloc_priv.h>
54 #endif
55
56 #ifdef _USE_GLIB_
57 #include <glib.h>
58 #define strlcpy g_strlcpy
59 #endif
60
61 #include <qdMetaData.h>
62 #include <color_metadata.h>
63 #include "PlatformConfig.h"
64
65 #define ATRACE_TAG ATRACE_TAG_VIDEO
66 #include <utils/Trace.h>
67
68 #define YUV_STATS_LIBRARY_NAME "libgpustats.so" // UBWC case: use GPU library
69
70 #ifdef HYPERVISOR
71 #define ioctl(x, y, z) hypv_ioctl(x, y, z)
72 #define poll(x, y, z) hypv_poll(x, y, z)
73 #endif
74
75 #undef ALIGN
76 #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
77 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
78 #define MAXDPB 16
79 #ifndef MIN
80 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
81 #endif
82 #ifndef MAX
83 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
84 #endif
85
86 #define ROUND(__sz, __align) (((__sz) + ((__align>>1))) & (~(__align-1)))
87 #define MAX_PROFILE_PARAMS 6
88 #define HEVC_MAIN_START 0
89 #define HEVC_MAIN10_START (HEVC_MAIN_START + 13)
90 #define POLL_TIMEOUT 1000
91 #define MAX_SUPPORTED_SLICES_PER_FRAME 28 /* Max supported slices with 32 output buffers */
92
93 #define SZ_4K 0x1000
94 #define SZ_1M 0x100000
95
96
97 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
98 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
99
100 #define BUFFER_LOG_LOC "/data/vendor/media"
101
102 #define OMX_VIDEO_LEVEL_UNKNOWN 0
103
104 #define VENC_BFRAME_MAX_COUNT 1
105 #define VENC_BFRAME_MAX_FPS 60
106 #define VENC_BFRAME_MAX_WIDTH 1920
107 #define VENC_BFRAME_MAX_HEIGHT 1088
108 #define VENC_INFINITE_GOP 0xFFFFFFF
109
110 /* TODO: Use sanctioned vendor bits for HEIF
111 * once end to end 64-bit support is available.
112 */
113 #define GRALLOC_USAGE_PRIVATE_HEIF_VIDEO (UINT32_C(1) << 27)
114 #define GRALLOC_USAGE_PRIVATE_10BIT_VIDEO (UINT32_C(1) << 30)
115
116 #define REQUEST_LINEAR_COLOR_8_BIT 0x1
117 #define REQUEST_LINEAR_COLOR_10_BIT 0x2
118 #define REQUEST_LINEAR_COLOR_ALL (REQUEST_LINEAR_COLOR_8_BIT | REQUEST_LINEAR_COLOR_10_BIT)
119
120 #undef LOG_TAG
121 #define LOG_TAG "OMX-VENC: venc_dev"
122
123 #define LUMINANCE_MULTIPLICATION_FACTOR 10000
124
125 //constructor
venc_dev(class omx_venc * venc_class)126 venc_dev::venc_dev(class omx_venc *venc_class)
127 {
128 //nothing to do
129 int i = 0;
130 venc_handle = venc_class;
131 etb = ebd = ftb = fbd = 0;
132 m_poll_efd = -1;
133
134 struct v4l2_control control;
135 for (i = 0; i < MAX_PORT; i++)
136 streaming[i] = false;
137
138 stopped = 1;
139 paused = false;
140 async_thread_created = false;
141 async_thread_force_stop = false;
142 color_format = 0;
143 hw_overload = false;
144 mBatchSize = 0;
145 deinterlace_enabled = false;
146 m_roi_enabled = false;
147 m_roi_type = 0;
148 low_latency_mode = false;
149 pthread_mutex_init(&m_roilock, NULL);
150 pthread_mutex_init(&pause_resume_mlock, NULL);
151 pthread_cond_init(&pause_resume_cond, NULL);
152 memset(&input_extradata_info, 0, sizeof(input_extradata_info));
153 input_extradata_info.ion.data_fd = -1;
154 memset(&output_extradata_info, 0, sizeof(output_extradata_info));
155 output_extradata_info.ion.data_fd = -1;
156 memset(&idrperiod, 0, sizeof(idrperiod));
157 memset(&multislice, 0, sizeof(multislice));
158 memset (&slice_mode, 0 , sizeof(slice_mode));
159 memset(&m_sVenc_cfg, 0, sizeof(m_sVenc_cfg));
160 memset(&rate_ctrl, 0, sizeof(rate_ctrl));
161 memset(&bitrate, 0, sizeof(bitrate));
162 memset(&intra_period, 0, sizeof(intra_period));
163 memset(&codec_profile, 0, sizeof(codec_profile));
164 memset(&set_param, 0, sizeof(set_param));
165 memset(&time_inc, 0, sizeof(time_inc));
166 memset(&m_sInput_buff_property, 0, sizeof(m_sInput_buff_property));
167 memset(&m_sOutput_buff_property, 0, sizeof(m_sOutput_buff_property));
168 memset(&session_qp, 0, sizeof(session_qp));
169 memset(&session_ipb_qp_values, 0, sizeof(session_ipb_qp_values));
170 memset(&entropy, 0, sizeof(entropy));
171 memset(&dbkfilter, 0, sizeof(dbkfilter));
172 memset(&intra_refresh, 0, sizeof(intra_refresh));
173 memset(&hec, 0, sizeof(hec));
174 memset(&voptimecfg, 0, sizeof(voptimecfg));
175 memset(&capability, 0, sizeof(capability));
176 memset(&m_debug,0,sizeof(m_debug));
177 is_searchrange_set = false;
178 enable_mv_narrow_searchrange = false;
179 supported_rc_modes = RC_ALL;
180 memset(&vqzip_sei_info, 0, sizeof(vqzip_sei_info));
181 memset(<rinfo, 0, sizeof(ltrinfo));
182 memset(&fd_list, 0, sizeof(fd_list));
183 sess_priority.priority = 1;
184 operating_rate = 30;
185 memset(&color_space, 0x0, sizeof(color_space));
186 memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
187 client_req_disable_bframe = false;
188 bframe_implicitly_enabled = false;
189 client_req_disable_temporal_layers = false;
190 client_req_turbo_mode = false;
191 intra_period.num_pframes = 29;
192 intra_period.num_bframes = 0;
193 mIsNativeRecorder = false;
194 m_hdr10meta_enabled = false;
195 hdr10metadata_supported = false;
196
197 Platform::Config::getInt32(Platform::vidc_enc_log_in,
198 (int32_t *)&m_debug.in_buffer_log, 0);
199 Platform::Config::getInt32(Platform::vidc_enc_log_out,
200 (int32_t *)&m_debug.out_buffer_log, 0);
201 Platform::Config::getInt32(Platform::vidc_enc_csc_custom_matrix,
202 (int32_t *)&is_csc_custom_matrix_enabled, 0);
203
204 char property_value[PROPERTY_VALUE_MAX] = {0};
205
206 property_get("vendor.vidc.enc.log.in", property_value, "0");
207 m_debug.in_buffer_log |= atoi(property_value);
208
209 property_value[0] = '\0';
210 property_get("vendor.vidc.enc.log.out", property_value, "0");
211 m_debug.out_buffer_log |= atoi(property_value);
212
213 property_get("vendor.vidc.enc.log.extradata", property_value, "0");
214 m_debug.extradata_log = atoi(property_value);
215
216 #ifdef _UBWC_
217 property_get("vendor.gralloc.disable_ubwc", property_value, "0");
218 if(!(strncmp(property_value, "1", PROPERTY_VALUE_MAX)) ||
219 !(strncmp(property_value, "true", PROPERTY_VALUE_MAX))) {
220 is_gralloc_source_ubwc = 0;
221 } else {
222 is_gralloc_source_ubwc = 1;
223 }
224 #else
225 is_gralloc_source_ubwc = 0;
226 #endif
227
228 property_value[0] = '\0';
229 property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
230 if (*property_value)
231 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
232
233 mUseAVTimerTimestamps = false;
234 mIsGridset = false;
235 Platform::Config::getInt32(Platform::vidc_enc_linear_color_format,
236 (int32_t *)&mUseLinearColorFormat, 0);
237 Platform::Config::getInt32(Platform::vidc_enc_bitrate_savings_enable,
238 (int32_t *)&mBitrateSavingsEnable, 0);
239
240 profile_level_converter::init();
241 }
242
~venc_dev()243 venc_dev::~venc_dev()
244 {
245 if (m_roi_enabled) {
246 std::list<roidata>::iterator iter;
247 pthread_mutex_lock(&m_roilock);
248 for (iter = m_roilist.begin(); iter != m_roilist.end(); iter++) {
249 DEBUG_PRINT_HIGH("roidata with timestamp (%lld) should have been removed already",
250 iter->info.nTimeStamp);
251 }
252 m_roilist.clear();
253 mRoiRegionList.clear();
254 pthread_mutex_unlock(&m_roilock);
255 }
256 pthread_mutex_destroy(&m_roilock);
257 }
258
async_venc_message_thread(void * input)259 void* venc_dev::async_venc_message_thread (void *input)
260 {
261 struct venc_msg venc_msg;
262 omx_video* omx_venc_base = NULL;
263 omx_venc *omx = reinterpret_cast<omx_venc*>(input);
264 omx_venc_base = reinterpret_cast<omx_video*>(input);
265 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
266
267 prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0);
268 struct v4l2_plane plane[VIDEO_MAX_PLANES];
269 struct pollfd pfds[2];
270 struct v4l2_buffer v4l2_buf;
271 struct v4l2_event dqevent;
272 struct statistics stats;
273 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
274 pfds[1].events = POLLIN | POLLERR;
275 pfds[0].fd = omx->handle->m_nDriver_fd;
276 pfds[1].fd = omx->handle->m_poll_efd;
277 int error_code = 0,rc=0;
278
279 memset(&stats, 0, sizeof(statistics));
280 memset(&v4l2_buf, 0, sizeof(v4l2_buf));
281
282 while (!omx->handle->async_thread_force_stop) {
283 pthread_mutex_lock(&omx->handle->pause_resume_mlock);
284
285 if (omx->handle->paused) {
286 venc_msg.msgcode = VEN_MSG_PAUSE;
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 pause msg");
291 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
292 break;
293 }
294
295 /* Block here until the IL client resumes us again */
296 pthread_cond_wait(&omx->handle->pause_resume_cond,
297 &omx->handle->pause_resume_mlock);
298
299 venc_msg.msgcode = VEN_MSG_RESUME;
300 venc_msg.statuscode = VEN_S_SUCCESS;
301
302 if (omx->async_message_process(input, &venc_msg) < 0) {
303 DEBUG_PRINT_ERROR("ERROR: Failed to process resume msg");
304 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
305 break;
306 }
307 memset(&stats, 0, sizeof(statistics));
308 }
309
310 pthread_mutex_unlock(&omx->handle->pause_resume_mlock);
311
312 rc = poll(pfds, 2, POLL_TIMEOUT);
313
314 if (!rc) {
315 DEBUG_PRINT_HIGH("Poll timedout, pipeline stalled due to client/firmware ETB: %d, EBD: %d, FTB: %d, FBD: %d",
316 omx->handle->etb, omx->handle->ebd, omx->handle->ftb, omx->handle->fbd);
317 continue;
318 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
319 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
320 break;
321 }
322
323 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
324 DEBUG_PRINT_ERROR("async_venc_message_thread interrupted to be exited");
325 break;
326 }
327
328 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
329 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
330 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
331 v4l2_buf.length = omx->handle->num_output_planes;
332 v4l2_buf.m.planes = plane;
333
334 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
335 venc_msg.msgcode=VEN_MSG_OUTPUT_BUFFER_DONE;
336 venc_msg.statuscode=VEN_S_SUCCESS;
337 omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf.index;
338 venc_msg.buf.len= v4l2_buf.m.planes->bytesused;
339 venc_msg.buf.offset = v4l2_buf.m.planes->data_offset;
340 venc_msg.buf.flags = 0;
341 venc_msg.buf.ptrbuffer = (OMX_U8 *)omx_venc_base->m_pOutput_pmem[v4l2_buf.index].buffer;
342 venc_msg.buf.clientdata=(void*)omxhdr;
343 venc_msg.buf.timestamp = (uint64_t) v4l2_buf.timestamp.tv_sec * (uint64_t) 1000000 + (uint64_t) v4l2_buf.timestamp.tv_usec;
344
345 /* TODO: ideally report other types of frames as well
346 * for now it doesn't look like IL client cares about
347 * other types
348 */
349 if (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
350 venc_msg.buf.flags |= QOMX_VIDEO_PictureTypeIDR;
351 venc_msg.buf.flags |= OMX_BUFFERFLAG_SYNCFRAME;
352 }
353 if (v4l2_buf.flags & V4L2_BUF_FLAG_PFRAME) {
354 venc_msg.buf.flags |= OMX_VIDEO_PictureTypeP;
355 } else if (v4l2_buf.flags & V4L2_BUF_FLAG_BFRAME) {
356 venc_msg.buf.flags |= OMX_VIDEO_PictureTypeB;
357 }
358
359 if (v4l2_buf.flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
360 venc_msg.buf.flags |= OMX_BUFFERFLAG_CODECCONFIG;
361
362 if (v4l2_buf.flags & V4L2_QCOM_BUF_FLAG_EOS)
363 venc_msg.buf.flags |= OMX_BUFFERFLAG_EOS;
364
365 if (omx->handle->num_output_planes > 1 && v4l2_buf.m.planes->bytesused)
366 venc_msg.buf.flags |= OMX_BUFFERFLAG_EXTRADATA;
367
368 if (omxhdr->nFilledLen)
369 venc_msg.buf.flags |= OMX_BUFFERFLAG_ENDOFFRAME;
370
371 omx->handle->fbd++;
372 stats.bytes_generated += venc_msg.buf.len;
373
374 if (omx->async_message_process(input,&venc_msg) < 0) {
375 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
376 break;
377 }
378 }
379 }
380
381 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
382 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
383 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
384 v4l2_buf.m.planes = plane;
385 v4l2_buf.length = omx->handle->num_input_planes;
386
387 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
388 venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE;
389 venc_msg.statuscode=VEN_S_SUCCESS;
390 omx->handle->ebd++;
391
392 if (omx->handle->mBatchSize) {
393 int bufIndex = omx->handle->mBatchInfo.retrieveBufferAt(v4l2_buf.index);
394 if (bufIndex < 0) {
395 DEBUG_PRINT_ERROR("Retrieved invalid buffer %d", v4l2_buf.index);
396 break;
397 }
398 if (omx->handle->mBatchInfo.isPending(bufIndex)) {
399 DEBUG_PRINT_LOW(" EBD for %d [v4l2-id=%d].. batch still pending",
400 bufIndex, v4l2_buf.index);
401 //do not return to client yet
402 continue;
403 }
404 v4l2_buf.index = bufIndex;
405 }
406 if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion)
407 omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf.index];
408 else
409 omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index];
410
411 venc_msg.buf.clientdata=(void*)omxhdr;
412
413 DEBUG_PRINT_LOW("sending EBD %p [id=%d]", omxhdr, v4l2_buf.index);
414 if (omx->async_message_process(input,&venc_msg) < 0) {
415 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
416 break;
417 }
418 }
419 }
420
421 if (pfds[0].revents & POLLPRI) {
422 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
423
424 if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
425 venc_msg.msgcode = VEN_MSG_FLUSH_INPUT_DONE;
426 venc_msg.statuscode = VEN_S_SUCCESS;
427
428 if (omx->async_message_process(input,&venc_msg) < 0) {
429 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
430 break;
431 }
432
433 venc_msg.msgcode = VEN_MSG_FLUSH_OUPUT_DONE;
434 venc_msg.statuscode = VEN_S_SUCCESS;
435
436 if (omx->async_message_process(input,&venc_msg) < 0) {
437 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
438 break;
439 }
440 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
441 DEBUG_PRINT_ERROR("HW Overload received");
442 venc_msg.statuscode = VEN_S_EFAIL;
443 venc_msg.msgcode = VEN_MSG_HW_OVERLOAD;
444
445 if (omx->async_message_process(input,&venc_msg) < 0) {
446 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
447 break;
448 }
449 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR){
450 DEBUG_PRINT_ERROR("ERROR: Encoder is in bad state");
451 venc_msg.msgcode = VEN_MSG_INDICATION;
452 venc_msg.statuscode=VEN_S_EFAIL;
453
454 if (omx->async_message_process(input,&venc_msg) < 0) {
455 DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
456 break;
457 }
458 }
459 }
460
461 /* calc avg. fps, bitrate */
462 struct timeval tv;
463 gettimeofday(&tv,NULL);
464 OMX_U64 time_diff = (OMX_U32)((tv.tv_sec * 1000000 + tv.tv_usec) -
465 (stats.prev_tv.tv_sec * 1000000 + stats.prev_tv.tv_usec));
466 if (time_diff >= 5000000) {
467 OMX_U32 num_fbd = omx->handle->fbd - stats.prev_fbd;
468 if (stats.prev_tv.tv_sec && num_fbd && time_diff) {
469 float framerate = num_fbd * 1000000/(float)time_diff;
470 OMX_U32 bitrate = (stats.bytes_generated * 8 / num_fbd) * framerate;
471 DEBUG_PRINT_INFO("stats: avg. fps %0.2f, bitrate %d",
472 framerate, bitrate);
473 }
474 stats.prev_tv = tv;
475 stats.bytes_generated = 0;
476 stats.prev_fbd = omx->handle->fbd;
477 }
478
479 }
480
481 DEBUG_PRINT_HIGH("omx_venc: Async Thread exit");
482 return NULL;
483 }
484
485 static const int event_type[] = {
486 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
487 V4L2_EVENT_MSM_VIDC_SYS_ERROR
488 };
489
subscribe_to_events(int fd)490 static OMX_ERRORTYPE subscribe_to_events(int fd)
491 {
492 OMX_ERRORTYPE eRet = OMX_ErrorNone;
493 struct v4l2_event_subscription sub;
494 int array_sz = sizeof(event_type)/sizeof(int);
495 int i,rc;
496 memset(&sub, 0, sizeof(sub));
497
498 if (fd < 0) {
499 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
500 return OMX_ErrorBadParameter;
501 }
502
503 for (i = 0; i < array_sz; ++i) {
504 memset(&sub, 0, sizeof(sub));
505 sub.type = event_type[i];
506 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
507
508 if (rc) {
509 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
510 break;
511 }
512 }
513
514 if (i < array_sz) {
515 for (--i; i >=0 ; i--) {
516 memset(&sub, 0, sizeof(sub));
517 sub.type = event_type[i];
518 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
519
520 if (rc)
521 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
522 }
523
524 eRet = OMX_ErrorNotImplemented;
525 }
526
527 return eRet;
528 }
529
venc_query_cap(struct v4l2_queryctrl & cap)530 bool venc_dev::venc_query_cap(struct v4l2_queryctrl &cap) {
531
532 if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &cap)) {
533 DEBUG_PRINT_ERROR("Query caps for id = %u failed", cap.id);
534 return false;
535 }
536 return true;
537 }
538
venc_validate_range(OMX_S32 id,OMX_S32 val)539 bool inline venc_dev::venc_validate_range(OMX_S32 id, OMX_S32 val) {
540
541 struct v4l2_queryctrl cap;
542 memset(&cap, 0, sizeof(struct v4l2_queryctrl));
543
544 cap.id = id;
545 if (venc_query_cap(cap)) {
546 if (val >= cap.minimum && val <= cap.maximum) {
547 return true;
548 } else {
549 DEBUG_PRINT_INFO("id = %u, value = %u, min = %u, max = %u",
550 cap.id, val, cap.minimum, cap.maximum);
551 }
552 }
553 return false;
554 }
555
get_roi_for_timestamp(struct roidata & roi,OMX_TICKS timestamp)556 void venc_dev::get_roi_for_timestamp(struct roidata &roi, OMX_TICKS timestamp)
557 {
558 std::list<roidata>::iterator iter;
559 bool found = false;
560
561 memset(&roi, 0, sizeof(struct roidata));
562 roi.dirty = false;
563
564 pthread_mutex_lock(&m_roilock);
565 iter = m_roilist.begin();
566 while (iter != m_roilist.end()) {
567 if (iter->info.nTimeStamp < timestamp) {
568 /* remove previous roi data */
569 iter = m_roilist.erase(iter);
570 /* iter++ is not required as erase would do it */
571 continue;
572 } else if (iter->info.nTimeStamp == timestamp){
573 found = true;
574 roi = *iter;
575 break;
576 }
577 iter++;
578 }
579 if (found) {
580 DEBUG_PRINT_LOW("found roidata with timestamp %lld us", roi.info.nTimeStamp);
581 }
582 pthread_mutex_unlock(&m_roilock);
583 }
584
append_mbi_extradata(void * dst,struct msm_vidc_extradata_header * src)585 int venc_dev::append_mbi_extradata(void *dst, struct msm_vidc_extradata_header* src)
586 {
587 OMX_QCOM_EXTRADATA_MBINFO *mbi = (OMX_QCOM_EXTRADATA_MBINFO *)dst;
588
589 if (!dst || !src)
590 return 0;
591
592 /* TODO: Once Venus 3XX target names are known, nFormat should 2 for those
593 * targets, since the payload format will be different */
594 mbi->nFormat = 2;
595 mbi->nDataSize = src->data_size;
596 memcpy(&mbi->data, &src->data, src->data_size);
597
598 return mbi->nDataSize + sizeof(*mbi);
599 }
600
get_yuv_size(unsigned long fmt,int width,int height)601 inline int get_yuv_size(unsigned long fmt, int width, int height) {
602 unsigned int y_stride, uv_stride, y_sclines,
603 uv_sclines, y_plane, uv_plane;
604 unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0;
605 unsigned size = 0;
606
607 y_stride = VENUS_Y_STRIDE(fmt, width);
608 uv_stride = VENUS_UV_STRIDE(fmt, width);
609 y_sclines = VENUS_Y_SCANLINES(fmt, height);
610 uv_sclines = VENUS_UV_SCANLINES(fmt, height);
611
612 switch (fmt) {
613 case COLOR_FMT_NV12:
614 y_plane = y_stride * y_sclines;
615 uv_plane = uv_stride * uv_sclines;
616 size = MSM_MEDIA_ALIGN(y_plane + uv_plane, 4096);
617 break;
618 default:
619 break;
620 }
621 return size;
622 }
623
append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE * p_extra,struct msm_vidc_extradata_header * p_extradata)624 void venc_dev::append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE *p_extra,
625 struct msm_vidc_extradata_header *p_extradata)
626 {
627 OMX_U32 payloadSize = append_mbi_extradata(&p_extra->data, p_extradata);
628 p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + payloadSize - sizeof(unsigned int), 4);
629 p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
630 p_extra->nPortIndex = OMX_DirOutput;
631 p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoEncoderMBInfo;
632 p_extra->nDataSize = payloadSize;
633
634 }
635
append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE * p_extra,struct msm_vidc_extradata_header * p_extradata)636 void venc_dev::append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE *p_extra,
637 struct msm_vidc_extradata_header *p_extradata)
638 {
639 p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size - sizeof(unsigned int), 4);
640 p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
641 p_extra->nPortIndex = OMX_DirOutput;
642 p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
643 p_extra->nDataSize = p_extradata->data_size;
644 memcpy(p_extra->data, p_extradata->data, p_extradata->data_size);
645 }
646
append_extradata_none(OMX_OTHER_EXTRADATATYPE * p_extra)647 void venc_dev::append_extradata_none(OMX_OTHER_EXTRADATATYPE *p_extra)
648 {
649 p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4);
650 p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
651 p_extra->nPortIndex = OMX_DirOutput;
652 p_extra->eType = OMX_ExtraDataNone;
653 p_extra->nDataSize = 0;
654 }
655
handle_input_extradata(struct v4l2_buffer buf)656 bool venc_dev::handle_input_extradata(struct v4l2_buffer buf)
657 {
658 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
659 unsigned int consumed_len = 0, filled_len = 0;
660 unsigned int yuv_size = 0, index = 0;
661 int enable = 0, i = 0, size = 0;
662 unsigned char *pVirt = NULL;
663 int height = m_sVenc_cfg.input_height;
664 int width = m_sVenc_cfg.input_width;
665 OMX_TICKS nTimeStamp = buf.timestamp.tv_sec * 1000000 + buf.timestamp.tv_usec;
666 int fd = buf.m.planes[0].reserved[0];
667 bool vqzip_sei_found = false;
668 char *p_extradata = NULL;
669 OMX_OTHER_EXTRADATATYPE *data = NULL;
670 struct roidata roi;
671 bool status = true;
672 OMX_U32 packet_size = 0;
673 OMX_U32 payload_size = 0;
674
675 if (!EXTRADATA_IDX(num_input_planes)) {
676 DEBUG_PRINT_LOW("Input extradata not enabled");
677 return true;
678 }
679
680 if (!input_extradata_info.uaddr) {
681 DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
682 return true;
683 }
684
685 DEBUG_PRINT_HIGH("Processing Extradata for Buffer = %lld", nTimeStamp); // Useful for debugging
686 #ifdef USE_ION
687 venc_handle->do_cache_operations(input_extradata_info.ion.data_fd);
688 #endif
689 if (m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV12 || m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV21) {
690 size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
691 yuv_size = get_yuv_size(COLOR_FMT_NV12, width, height);
692 pVirt = (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
693 if (pVirt == MAP_FAILED) {
694 DEBUG_PRINT_ERROR("%s Failed to mmap",__func__);
695 status = false;
696 goto bailout;
697 }
698 p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + yuv_size + 3)&(~3));
699 }
700
701 if (!venc_get_index_from_fd(fd, &index)) {
702 status = false;
703 goto bailout;
704 }
705 p_extradata = input_extradata_info.uaddr + index * input_extradata_info.buffer_size;
706 data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
707 memset((void *)(data), 0, (input_extradata_info.buffer_size)); // clear stale data in current buffer
708
709 while (p_extra && (consumed_len + sizeof(OMX_OTHER_EXTRADATATYPE)) <= (size - yuv_size)
710 && (consumed_len + p_extra->nSize) <= (size - yuv_size)
711 && (filled_len + sizeof(OMX_OTHER_EXTRADATATYPE) <= input_extradata_info.buffer_size)
712 && (filled_len + p_extra->nSize <= input_extradata_info.buffer_size)
713 && (p_extra->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
714
715 DEBUG_PRINT_LOW("Extradata Type = 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
716 switch ((OMX_QCOM_EXTRADATATYPE)p_extra->eType) {
717 case OMX_ExtraDataFrameDimension:
718 {
719 struct msm_vidc_extradata_index *payload;
720 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *framedimension_format;
721 data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_extradata_index) + 3)&(~3);
722 data->nVersion.nVersion = OMX_SPEC_VERSION;
723 data->nPortIndex = 0;
724 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_INDEX;
725 data->nDataSize = sizeof(struct msm_vidc_input_crop_payload);
726 framedimension_format = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)p_extra->data;
727 payload = (struct msm_vidc_extradata_index *)(data->data);
728 payload->type = MSM_VIDC_EXTRADATA_INPUT_CROP;
729 payload->input_crop.left = framedimension_format->nDecWidth;
730 payload->input_crop.top = framedimension_format->nDecHeight;
731 payload->input_crop.width = framedimension_format->nActualWidth;
732 payload->input_crop.height = framedimension_format->nActualHeight;
733 DEBUG_PRINT_LOW("Height = %d Width = %d Actual Height = %d Actual Width = %d",
734 framedimension_format->nDecWidth, framedimension_format->nDecHeight,
735 framedimension_format->nActualWidth, framedimension_format->nActualHeight);
736 filled_len += data->nSize;
737 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
738 break;
739 }
740 case OMX_ExtraDataQP:
741 {
742 OMX_QCOM_EXTRADATA_QP * qp_payload = NULL;
743 struct msm_vidc_frame_qp_payload *payload;
744 data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_frame_qp_payload) + 3)&(~3);
745 data->nVersion.nVersion = OMX_SPEC_VERSION;
746 data->nPortIndex = 0;
747 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_FRAME_QP;
748 data->nDataSize = sizeof(struct msm_vidc_frame_qp_payload);
749 qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data;
750 payload = (struct msm_vidc_frame_qp_payload *)(data->data);
751 payload->frame_qp = qp_payload->nQP;
752 DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp);
753 filled_len += data->nSize;
754 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
755 break;
756 }
757 case OMX_ExtraDataVQZipSEI:
758 DEBUG_PRINT_LOW("VQZIP SEI Found ");
759 input_extradata_info.vqzip_sei_found = true;
760 break;
761 case OMX_ExtraDataFrameInfo:
762 {
763 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
764 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(p_extra->data);
765 if (frame_info->ePicType == OMX_VIDEO_PictureTypeI) {
766 if (venc_set_intra_vop_refresh((OMX_BOOL)true) == false)
767 DEBUG_PRINT_ERROR("%s Error in requesting I Frame ", __func__);
768 }
769 break;
770 }
771 default:
772 DEBUG_PRINT_HIGH("Unknown Extradata 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
773 break;
774 }
775
776 consumed_len += p_extra->nSize;
777 p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
778 }
779
780 /*
781 * Below code is based on these points.
782 * 1) As _PQ_ not defined in Napali :
783 * a) Send data to Venus as ROI.
784 * b) ROI enabled : Processed under unlocked context.
785 * c) ROI disabled : Nothing to fill.
786 * d) pq enabled : Not possible.
787 * 2) Normal ROI handling.
788 * By this time if client sets next ROI, then we shouldn't process new ROI here.
789 */
790
791 memset(&roi, 0, sizeof(struct roidata));
792 roi.dirty = false;
793 if (m_roi_enabled) {
794 get_roi_for_timestamp(roi, nTimeStamp);
795 }
796
797 if (roi.dirty) {
798 OMX_U32 mbAlign = 16;
799 if (m_codec == OMX_VIDEO_CodingHEVC) {
800 mbAlign = 32;
801 }
802 OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
803 OMX_U32 mbRowAligned = ((mbRow + 7) >> 3) << 3;
804 OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
805 OMX_U32 numBytes = mbRowAligned * mbCol * 2;
806 OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
807
808 data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload),256)
809 + numBytesAligned;
810 data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
811 if (data->nSize > input_extradata_info.buffer_size - filled_len) {
812 DEBUG_PRINT_ERROR("Buffer size (%lu) is less than ROI extradata size (%u)",
813 (input_extradata_info.buffer_size - filled_len) ,data->nSize);
814 status = false;
815 goto bailout;
816 }
817
818 data->nVersion.nVersion = OMX_SPEC_VERSION;
819 data->nPortIndex = 0;
820 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
821 struct msm_vidc_roi_deltaqp_payload *roiData =
822 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
823 roiData->b_roi_info = true;
824 roiData->mbi_info_size = numBytesAligned;
825 /* Video hardware expects ROI QP data to be aligned to 256,
826 * And its offset should be available in roiData->data[0].
827 * -----------------
828 * | unsigned int b_roi_info; |
829 * | int mbi_info_size; |
830 * ----------------------------
831 * | data[0] = n | => Contains Offset value to 256 aligned address
832 * | . |
833 * | . |
834 * | . |
835 * | data+n <ROI data start> | => 256 aligned address
836 * ----------------------------
837 */
838 roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256) - (unsigned long)roiData->data);
839
840 OMX_U8* tempBuf = (OMX_U8*)roi.info.pRoiMBInfo;
841 OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);;
842 OMX_U16* pBuf;
843 OMX_U8 clientROI;
844
845 /* Convert input extradata format to HW compatible format
846 * Input : 1byte per MB
847 * HW Format : 2bytes per MB. (1 << 11) | ((clientROI & 0x3F)<< 4)
848 * MB Row must be aligned to 8
849 */
850 for (OMX_U32 j = 0;j < mbCol; j++)
851 {
852 pBuf = exDataBuf + j*mbRowAligned;
853 for (OMX_U32 i = 0;i < mbRow; i++)
854 {
855 clientROI = *tempBuf++;
856 *pBuf++ = (1 << 11) | ((clientROI & 0x3F)<< 4);
857 }
858 }
859 filled_len += data->nSize;
860 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
861 } else {
862 // m_roilist didn't contain any ROI info with OMX_IndexConfigVideoRoiInfo.
863 // then we can check mRoiRegionList which may contain the roi from vendor extension.
864 OMX_U32 freeSize = input_extradata_info.buffer_size - filled_len;
865 OMX_U32 appendSize = append_extradata_roi_region_qp_info(data, nTimeStamp, freeSize);
866 filled_len += appendSize;
867 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + appendSize);
868 }
869
870 if (m_roi_enabled) {
871 if (roi.dirty) {
872 DEBUG_PRINT_LOW("free roidata with timestamp %lld us", roi.info.nTimeStamp);
873 roi.dirty = false;
874 }
875 }
876
877 /* HDR10Plus MetaData information. Enabled by Default. */
878 payload_size = sizeof(struct msm_vidc_hdr10plus_metadata_payload) - sizeof(unsigned int)
879 + colorData.dynamicMetaDataLen;
880 packet_size = (sizeof(OMX_OTHER_EXTRADATATYPE) + payload_size + 3)&(~3);
881
882 if (m_hdr10meta_enabled && (filled_len + packet_size <= input_extradata_info.buffer_size) && colorData.dynamicMetaDataLen > 0) {
883 struct msm_vidc_hdr10plus_metadata_payload *payload;
884
885 data->nSize = packet_size;
886 data->nVersion.nVersion = OMX_SPEC_VERSION;
887 data->nPortIndex = 0;
888 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_HDR10PLUS_METADATA;
889 data->nDataSize = payload_size;
890
891 payload = (struct msm_vidc_hdr10plus_metadata_payload *)(data->data);
892 payload->size = colorData.dynamicMetaDataLen;
893 memcpy(payload->data, colorData.dynamicMetaDataPayload, colorData.dynamicMetaDataLen);
894
895 filled_len += data->nSize;
896 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
897 } else if (colorData.dynamicMetaDataLen == 0) {
898 DEBUG_PRINT_HIGH("DynamicMetaDataLength == 0 Skip writing metadata.");
899 } else {
900 if (m_hdr10meta_enabled) {
901 DEBUG_PRINT_HIGH("Insufficient size for HDR10Metadata: Required %u Available %lu",
902 packet_size, (input_extradata_info.buffer_size - filled_len));
903 }
904 }
905
906 #ifdef _VQZIP_
907 if (vqzip_sei_info.enabled && !input_extradata_info.vqzip_sei_found) {
908 DEBUG_PRINT_ERROR("VQZIP is enabled, But no VQZIP SEI found. Rejecting the session");
909 if (pVirt)
910 munmap(pVirt, size);
911 status = false;
912 goto bailout; //This should be treated as fatal error
913 }
914 if (vqzip_sei_info.enabled && pVirt) {
915 data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct VQZipStats) + 3)&(~3);
916 data->nVersion.nVersion = OMX_SPEC_VERSION;
917 data->nPortIndex = 0;
918 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_YUVSTATS_INFO;
919 data->nDataSize = sizeof(struct VQZipStats);
920 vqzip.fill_stats_data((void*)pVirt, (void*) data->data);
921 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
922 }
923 #endif
924 data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
925 data->nVersion.nVersion = OMX_SPEC_VERSION;
926 data->eType = OMX_ExtraDataNone;
927 data->nDataSize = 0;
928 data->data[0] = 0;
929
930 if (pVirt)
931 munmap(pVirt, size);
932
933 bailout:
934 #ifdef USE_ION
935 venc_handle->do_cache_operations(input_extradata_info.ion.data_fd);
936 #endif
937 return status;
938 }
939
venc_handle_client_input_extradata(void * buffer)940 bool venc_dev::venc_handle_client_input_extradata(void *buffer)
941 {
942 OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
943 OMX_OTHER_EXTRADATATYPE *p_extra = (OMX_OTHER_EXTRADATATYPE*)p_bufhdr->pBuffer;
944 while(p_extra->eType != OMX_ExtraDataNone) {
945 switch((int)p_extra->eType) {
946 case OMX_ExtraDataInputROIInfo:
947 {
948 OMX_QTI_VIDEO_CONFIG_ROIINFO* roiInfo = reinterpret_cast<OMX_QTI_VIDEO_CONFIG_ROIINFO*>(p_extra->data);
949 struct roidata roi;
950 if (!m_roi_enabled) {
951 DEBUG_PRINT_ERROR("ROI info not enabled");
952 return false;
953 }
954
955 if (!roiInfo) {
956 DEBUG_PRINT_ERROR("No ROI info present");
957 return false;
958 }
959 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
960 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
961 DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
962 return false;
963 }
964
965 memset(&roi, 0, sizeof(struct roidata));
966
967 roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
968 roi.info.nTimeStamp = roiInfo->nTimeStamp;
969 memcpy(roi.info.pRoiMBInfo, &roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
970
971 roi.dirty = true;
972
973 pthread_mutex_lock(&m_roilock);
974 DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
975 m_roilist.push_back(roi);
976 pthread_mutex_unlock(&m_roilock);
977 break;
978 }
979 }
980 p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
981 }
982 return true;
983 }
984
handle_output_extradata(void * buffer,int index)985 bool venc_dev::handle_output_extradata(void *buffer, int index)
986 {
987 OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer;
988 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
989 OMX_OTHER_EXTRADATATYPE *p_clientextra = NULL;
990 OMX_U32 remaining_extradata_size = 0;
991 OMX_U32 remaining_client_extradata_size = 0;
992 OMX_U32 remaining_fw_extradata_size = 0;
993
994 if(venc_handle->m_client_output_extradata_mem_ptr && venc_handle->m_sExtraData
995 && venc_handle->m_client_out_extradata_info.getSize() >=
996 output_extradata_info.buffer_size) {
997 p_clientextra = (OMX_OTHER_EXTRADATATYPE * )
998 ((venc_handle->m_client_output_extradata_mem_ptr + index) ->pBuffer);
999 }
1000 if (p_clientextra == NULL) {
1001 DEBUG_PRINT_ERROR("Client Extradata buffers not allocated\n");
1002 }
1003
1004 if (!output_extradata_info.uaddr) {
1005 DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
1006 return false;
1007 }
1008
1009 p_extra = (OMX_OTHER_EXTRADATATYPE *)ALIGN(p_bufhdr->pBuffer +
1010 p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4);
1011
1012 if (output_extradata_info.buffer_size >
1013 p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4)) {
1014 DEBUG_PRINT_ERROR("Insufficient buffer size for extradata");
1015 p_extra = NULL;
1016 return false;
1017 } else if (sizeof(msm_vidc_extradata_header) != sizeof(OMX_OTHER_EXTRADATATYPE)) {
1018 /* A lot of the code below assumes this condition, so error out if it's not met */
1019 DEBUG_PRINT_ERROR("Extradata ABI mismatch");
1020 return false;
1021 }
1022 remaining_extradata_size = p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset +
1023 p_bufhdr->nFilledLen, 4);
1024 if(p_clientextra){
1025 remaining_client_extradata_size = (venc_handle->m_client_output_extradata_mem_ptr +
1026 index)->nAllocLen;
1027 }
1028 remaining_fw_extradata_size = output_extradata_info.buffer_size;
1029
1030 struct msm_vidc_extradata_header *p_extradata = NULL;
1031 do {
1032 DEBUG_PRINT_LOW("Remaining size for: extradata= %d client= %d fw= %d ",\
1033 remaining_extradata_size,remaining_client_extradata_size,\
1034 remaining_fw_extradata_size);
1035
1036 if (remaining_fw_extradata_size < sizeof(OMX_OTHER_EXTRADATATYPE)) {
1037 DEBUG_PRINT_ERROR("Insufficient space for extradata");
1038 break;
1039 }
1040 p_extradata = (struct msm_vidc_extradata_header *) (p_extradata ?
1041 ((char *)p_extradata) + p_extradata->size :
1042 output_extradata_info.uaddr + index * output_extradata_info.buffer_size);
1043
1044 if ((remaining_fw_extradata_size < p_extradata->size)) {
1045 DEBUG_PRINT_ERROR("Corrupt extradata");
1046 break;
1047 }
1048 remaining_fw_extradata_size -= p_extradata->size;
1049
1050 if (remaining_extradata_size < p_extradata->size){
1051 DEBUG_PRINT_ERROR("insufficient size available in extradata port buffer");
1052 break;
1053 }
1054
1055 if(p_clientextra){
1056 if (remaining_client_extradata_size < p_extradata->size) {
1057 DEBUG_PRINT_ERROR("insufficient size available in client buffer");
1058 break;
1059 }
1060 }
1061
1062 switch (p_extradata->type) {
1063 case MSM_VIDC_EXTRADATA_METADATA_MBI:
1064 {
1065 append_extradata_mbidata(p_extra, p_extradata);
1066 if(p_clientextra) {
1067 append_extradata_mbidata(p_clientextra, p_extradata);
1068 }
1069 DEBUG_PRINT_LOW("MBI Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
1070 break;
1071 }
1072 case MSM_VIDC_EXTRADATA_METADATA_LTR:
1073 {
1074 append_extradata_ltrinfo(p_extra, p_extradata);
1075 if(p_clientextra) {
1076 append_extradata_ltrinfo(p_clientextra, p_extradata);
1077 }
1078 DEBUG_PRINT_LOW("LTRInfo Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
1079 break;
1080 }
1081 case MSM_VIDC_EXTRADATA_NONE:
1082 append_extradata_none(p_extra);
1083 if(p_clientextra) {
1084 append_extradata_none(p_clientextra);
1085 }
1086 break;
1087 default:
1088 /* No idea what this stuff is, just skip over it */
1089 DEBUG_PRINT_HIGH("Found an unrecognised extradata (%x) ignoring it",
1090 p_extradata->type);
1091 continue;
1092 }
1093
1094 remaining_extradata_size-= p_extra->nSize;
1095 if(p_clientextra) {
1096 remaining_client_extradata_size -= p_clientextra->nSize;
1097 DEBUG_PRINT_LOW("Client Extradata Size= %u",p_clientextra->nSize);
1098 }
1099
1100 DEBUG_PRINT_LOW("Extradata Size= %u FW= %d",\
1101 p_extra->nSize,p_extradata->size);
1102
1103 p_extra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_extra) + p_extra->nSize);
1104 if(p_clientextra) {
1105 p_clientextra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_clientextra) + p_clientextra->nSize);
1106 }
1107 } while (p_extradata->type != MSM_VIDC_EXTRADATA_NONE);
1108
1109 /* Just for debugging: Traverse the list of extra datas and spit it out onto log */
1110 p_extra = (OMX_OTHER_EXTRADATATYPE *)ALIGN(p_bufhdr->pBuffer +
1111 p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4);
1112 remaining_extradata_size = p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset +
1113 p_bufhdr->nFilledLen, 4);
1114 while(p_extra->eType != OMX_ExtraDataNone)
1115 {
1116 DEBUG_PRINT_LOW("Remaining size for: extradata= %d",remaining_extradata_size);
1117 if (remaining_extradata_size < p_extra->nSize){
1118 DEBUG_PRINT_ERROR("insufficient size available in extradata port buffer");
1119 break;
1120 }
1121
1122 DEBUG_PRINT_LOW("[%p/%u] found extradata type %x of size %u (%u) at %p",
1123 p_bufhdr->pBuffer, (unsigned int)p_bufhdr->nFilledLen, p_extra->eType,
1124 (unsigned int)p_extra->nSize, (unsigned int)p_extra->nDataSize, p_extra);
1125
1126 remaining_extradata_size-= p_extra->nSize;
1127
1128 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) +
1129 p_extra->nSize);
1130 }
1131
1132 return true;
1133 }
1134
venc_set_format(int format)1135 int venc_dev::venc_set_format(int format)
1136 {
1137 int rc = true;
1138
1139 if (format) {
1140 color_format = format;
1141
1142 switch (color_format) {
1143 case NV12_128m:
1144 case NV12_512:
1145 return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m);
1146 case NV12_UBWC:
1147 return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed);
1148 case YCbCr420_VENUS_P010:
1149 return venc_set_color_format((OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
1150 default:
1151 return false;
1152 }
1153
1154 } else {
1155 color_format = 0;
1156 rc = false;
1157 }
1158
1159 return rc;
1160 }
1161
venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)1162 OMX_ERRORTYPE venc_dev::venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
1163 {
1164 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1165 struct v4l2_queryctrl profile_cap, level_cap;
1166 int v4l2_profile;
1167 int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
1168 QOMX_VIDEO_AVCProfileBaseline,
1169 QOMX_VIDEO_AVCProfileMain,
1170 QOMX_VIDEO_AVCProfileConstrainedHigh,
1171 QOMX_VIDEO_AVCProfileHigh };
1172 int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain,
1173 OMX_VIDEO_HEVCProfileMain10HDR10,
1174 OMX_VIDEO_HEVCProfileMainStill };
1175
1176 if (!profileLevelType)
1177 return OMX_ErrorBadParameter;
1178
1179 memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
1180 memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
1181
1182 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1183 level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
1184 profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
1185 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1186 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
1187 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1188 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
1189 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
1190 } else {
1191 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
1192 return OMX_ErrorInvalidComponent;
1193 }
1194
1195 if (profile_cap.id) {
1196 if(!venc_query_cap(profile_cap)) {
1197 DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
1198 return OMX_ErrorHardware;
1199 }
1200 }
1201
1202 if (level_cap.id) {
1203 if(!venc_query_cap(level_cap)) {
1204 DEBUG_PRINT_ERROR("Getting capabilities for level failed");
1205 return OMX_ErrorHardware;
1206 }
1207 }
1208
1209 /* Get the corresponding omx level from v4l2 level */
1210 if (!profile_level_converter::convert_v4l2_level_to_omx(m_sVenc_cfg.codectype, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
1211 DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
1212 return OMX_ErrorHardware;
1213 }
1214
1215 /* For given profile index get corresponding profile that needs to be supported */
1216 if (profileLevelType->nPortIndex != 1) {
1217 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on output port only %u",
1218 (unsigned int)profileLevelType->nPortIndex);
1219 return OMX_ErrorBadPortIndex;
1220 }
1221
1222 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1223 if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
1224 profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
1225 } else {
1226 DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1227 (unsigned int)profileLevelType->nProfileIndex);
1228 return OMX_ErrorNoMore;
1229 }
1230 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1231 if (profileLevelType->nProfileIndex == 0) {
1232 profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
1233 } else {
1234 DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1235 (unsigned int)profileLevelType->nProfileIndex);
1236 return OMX_ErrorNoMore;
1237 }
1238 /* Driver has no notion of VP8 profile and there is only one profile supported. Hence return here */
1239 return OMX_ErrorNone;
1240 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1241 if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
1242 profileLevelType->eProfile = hevc_profiles[profileLevelType->nProfileIndex];
1243 } else {
1244 DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
1245 (unsigned int)profileLevelType->nProfileIndex);
1246 return OMX_ErrorNoMore;
1247 }
1248 }
1249
1250 /* Check if the profile is supported by driver or not */
1251 /* During query caps of profile driver sends a mask of */
1252 /* of all v4l2 profiles supported(in the flags field) */
1253 if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, profileLevelType->eProfile, &v4l2_profile)) {
1254 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
1255 return OMX_ErrorHardware;
1256 }
1257
1258 DEBUG_PRINT_INFO("v4l2 profile : %d flags : %d ", v4l2_profile, profile_cap.flags);
1259 if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
1260 DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
1261 eRet = OMX_ErrorNoMore;
1262 }
1263
1264 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
1265 (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
1266 return eRet;
1267 }
1268
venc_get_supported_color_format(unsigned index,OMX_U32 * colorFormat)1269 bool venc_dev::venc_get_supported_color_format(unsigned index, OMX_U32 *colorFormat) {
1270 #ifdef _UBWC_
1271 //we support following formats
1272 //index 0 - Compressed (UBWC) Venus flavour of YUV420SP
1273 //index 1 - Venus flavour of YUV420SP
1274 //index 2 - Compressed (UBWC) TP10 (10bit packed)
1275 //index 3 - Compressed (UBWC) Venus flavour of RGBA8888
1276 //index 4 - Venus flavour of RGBA8888
1277 //index 5 - opaque which internally maps to YUV420SP.
1278 //index 6 - vannilla YUV420SP
1279 //this can be extended in the future
1280 int supportedFormats[] = {
1281 [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed,
1282 [1] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1283 [2] = QOMX_COLOR_FormatYVU420SemiPlanar,
1284 [3] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed,
1285 [4] = QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus,
1286 [5] = QOMX_COLOR_Format32bitRGBA8888Compressed,
1287 [6] = QOMX_COLOR_Format32bitRGBA8888,
1288 [7] = QOMX_COLOR_FormatAndroidOpaque,
1289 [8] = OMX_COLOR_FormatYUV420SemiPlanar,
1290 };
1291 #else
1292 //we support two formats
1293 //index 0 - Venus flavour of YUV420SP
1294 //index 1 - opaque which internally maps to YUV420SP.
1295 //index 2 - vannilla YUV420SP
1296 //this can be extended in the future
1297 int supportedFormats[] = {
1298 [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
1299 [1] = QOMX_COLOR_FormatYVU420SemiPlanar,
1300 [2] = QOMX_COLOR_FormatAndroidOpaque,
1301 [3] = OMX_COLOR_FormatYUV420SemiPlanar,
1302 };
1303 #endif
1304 if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1))
1305 return false;
1306 *colorFormat = supportedFormats[index];
1307 return true;
1308 }
1309
allocate_extradata(struct extradata_buffer_info * extradata_info,int flags)1310 OMX_ERRORTYPE venc_dev::allocate_extradata(struct extradata_buffer_info *extradata_info, int flags)
1311 {
1312 if (extradata_info->allocated) {
1313 DEBUG_PRINT_HIGH("2nd allocation return for port = %d",extradata_info->port_index);
1314 return OMX_ErrorNone;
1315 }
1316
1317 #ifdef USE_ION
1318
1319 if (extradata_info->buffer_size) {
1320 if (extradata_info->ion.data_fd != -1) {
1321 venc_handle->ion_unmap(extradata_info->ion.data_fd, (void *)extradata_info->uaddr, extradata_info->size);
1322 venc_handle->free_ion_memory(&extradata_info->ion);
1323 }
1324 extradata_info->size = (extradata_info->size + 4095) & (~4095);
1325
1326 // ION_IOC_MAP defined @ bionic/libc/kernel/uapi/linux/ion.h not in kernel,
1327 // and this ioctl uses "struct ion_fd_data" with handle member
1328 // Refer alloc_map_ion_memory definition @omx_video_base.cpp
1329 bool status = venc_handle->alloc_map_ion_memory(
1330 extradata_info->size, &extradata_info->ion, flags);
1331
1332 if (status == false) {
1333 DEBUG_PRINT_ERROR("Failed to alloc extradata memory\n");
1334 return OMX_ErrorInsufficientResources;
1335 }
1336
1337 extradata_info->uaddr = (char *)venc_handle->ion_map(extradata_info->ion.data_fd,
1338 extradata_info->size);
1339
1340 if (extradata_info->uaddr == MAP_FAILED) {
1341 DEBUG_PRINT_ERROR("Failed to map extradata memory\n");
1342 venc_handle->free_ion_memory(&extradata_info->ion);
1343 return OMX_ErrorInsufficientResources;
1344 }
1345 }
1346 #else
1347 (void)flags;
1348 #endif
1349 extradata_info->allocated = OMX_TRUE;
1350 return OMX_ErrorNone;
1351 }
1352
free_extradata(struct extradata_buffer_info * extradata_info)1353 void venc_dev::free_extradata(struct extradata_buffer_info *extradata_info)
1354 {
1355 #ifdef USE_ION
1356
1357 if (extradata_info == NULL) {
1358 return;
1359 }
1360
1361 if (extradata_info->uaddr) {
1362 venc_handle->ion_unmap(extradata_info->ion.data_fd, (void *)extradata_info->uaddr, extradata_info->size);
1363 extradata_info->uaddr = NULL;
1364 venc_handle->free_ion_memory(&extradata_info->ion);
1365 }
1366
1367 memset(extradata_info, 0, sizeof(*extradata_info));
1368 extradata_info->ion.data_fd = -1;
1369 extradata_info->allocated = OMX_FALSE;
1370 #else
1371 (void)extradata_info;
1372 #endif // USE_ION
1373 }
1374
free_extradata_all()1375 void venc_dev::free_extradata_all()
1376 {
1377 free_extradata(&output_extradata_info);
1378 free_extradata(&input_extradata_info);
1379 }
1380
venc_get_output_log_flag()1381 bool venc_dev::venc_get_output_log_flag()
1382 {
1383 return (m_debug.out_buffer_log == 1);
1384 }
1385
venc_output_log_buffers(const char * buffer_addr,int buffer_len,uint64_t timestamp)1386 int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len, uint64_t timestamp)
1387 {
1388 if (venc_handle->is_secure_session()) {
1389 DEBUG_PRINT_ERROR("logging secure output buffers is not allowed!");
1390 return -1;
1391 }
1392
1393 if (!m_debug.outfile) {
1394 int size = 0;
1395 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1396 size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.264",
1397 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1398 } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1399 size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%ld_%ld_%p.265",
1400 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1401 } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1402 size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.ivf",
1403 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1404 } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
1405 size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.tme",
1406 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1407 }
1408 if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1409 DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1410 m_debug.outfile_name, size);
1411 }
1412 m_debug.outfile = fopen(m_debug.outfile_name, "ab");
1413 if (!m_debug.outfile) {
1414 DEBUG_PRINT_ERROR("Failed to open output file: %s for logging errno:%d",
1415 m_debug.outfile_name, errno);
1416 m_debug.outfile_name[0] = '\0';
1417 return -1;
1418 }
1419 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1420 int fps = m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
1421 IvfFileHeader ivfFileHeader(false, m_sVenc_cfg.input_width,
1422 m_sVenc_cfg.input_height, fps, 1, 0);
1423 fwrite(&ivfFileHeader, sizeof(ivfFileHeader), 1, m_debug.outfile);
1424 }
1425 }
1426 if (m_debug.outfile && buffer_len) {
1427 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1428 IvfFrameHeader ivfFrameHeader(buffer_len, timestamp);
1429 fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.outfile);
1430 }
1431 DEBUG_PRINT_LOW("%s buffer_len:%d", __func__, buffer_len);
1432 fwrite(buffer_addr, buffer_len, 1, m_debug.outfile);
1433 }
1434 return 0;
1435 }
1436
venc_extradata_log_buffers(char * buffer_addr,bool input)1437 int venc_dev::venc_extradata_log_buffers(char *buffer_addr, bool input)
1438 {
1439 int fd;
1440
1441 if (input)
1442 fd = input_extradata_info.ion.data_fd;
1443 else
1444 fd = output_extradata_info.ion.data_fd;
1445
1446 #ifdef USE_ION
1447 venc_handle->do_cache_operations(fd);
1448 #endif
1449 if (!m_debug.extradatafile && m_debug.extradata_log) {
1450 int size = 0;
1451
1452 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
1453 size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1454 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1455 } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
1456 size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1457 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1458 } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1459 size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.bin",
1460 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1461 }
1462 if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1463 DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging size:%d",
1464 m_debug.extradatafile_name, size);
1465 }
1466
1467 m_debug.extradatafile = fopen(m_debug.extradatafile_name, "ab");
1468 if (!m_debug.extradatafile) {
1469 DEBUG_PRINT_ERROR("Failed to open extradata file: %s for logging errno:%d",
1470 m_debug.extradatafile_name, errno);
1471 m_debug.extradatafile_name[0] = '\0';
1472 #ifdef USE_ION
1473 venc_handle->do_cache_operations(fd);
1474 #endif
1475 return -1;
1476 }
1477 }
1478
1479 if (m_debug.extradatafile && buffer_addr) {
1480 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
1481 do {
1482 p_extra = (OMX_OTHER_EXTRADATATYPE *)(!p_extra ? buffer_addr :
1483 ((char *)p_extra) + p_extra->nSize);
1484 fwrite(p_extra, p_extra->nSize, 1, m_debug.extradatafile);
1485 } while (p_extra->eType != OMX_ExtraDataNone);
1486 }
1487 #ifdef USE_ION
1488 venc_handle->do_cache_operations(fd);
1489 #endif
1490 return 0;
1491 }
1492
venc_input_log_buffers(OMX_BUFFERHEADERTYPE * pbuffer,int fd,int plane_offset,unsigned long inputformat,bool interlaced)1493 int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset,
1494 unsigned long inputformat, bool interlaced) {
1495 int status = 0;
1496 if (venc_handle->is_secure_session()) {
1497 DEBUG_PRINT_ERROR("logging secure input buffers is not allowed!");
1498 return -1;
1499 }
1500
1501 #ifdef USE_ION
1502 venc_handle->do_cache_operations(fd);
1503 #endif
1504 if (!m_debug.infile) {
1505 int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%lu_%lu_%p.yuv",
1506 m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
1507 if ((size > PROPERTY_VALUE_MAX) && (size < 0)) {
1508 DEBUG_PRINT_ERROR("Failed to open output file: %s for logging size:%d",
1509 m_debug.infile_name, size);
1510 }
1511 m_debug.infile = fopen (m_debug.infile_name, "ab");
1512 if (!m_debug.infile) {
1513 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1514 m_debug.infile_name[0] = '\0';
1515 status = -1;
1516 goto bailout;
1517 }
1518 }
1519
1520 if (m_debug.infile && pbuffer && pbuffer->nFilledLen) {
1521 unsigned long stride, scanlines;
1522 unsigned long color_format;
1523 unsigned long i, msize;
1524 unsigned char *pvirt = NULL, *ptemp = NULL;
1525 unsigned char *temp = (unsigned char *)pbuffer->pBuffer;
1526
1527 switch (inputformat) {
1528 case V4L2_PIX_FMT_NV12:
1529 color_format = COLOR_FMT_NV12;
1530 break;
1531 case V4L2_PIX_FMT_NV12_512:
1532 color_format = COLOR_FMT_NV12_512;
1533 break;
1534 case V4L2_PIX_FMT_NV12_UBWC:
1535 color_format = COLOR_FMT_NV12_UBWC;
1536 break;
1537 case V4L2_PIX_FMT_RGB32:
1538 color_format = COLOR_FMT_RGBA8888;
1539 break;
1540 case V4L2_PIX_FMT_RGBA8888_UBWC:
1541 color_format = COLOR_FMT_RGBA8888_UBWC;
1542 break;
1543 case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS:
1544 color_format = COLOR_FMT_P010;
1545 break;
1546 case V4L2_PIX_FMT_NV12_TP10_UBWC:
1547 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1548 break;
1549 default:
1550 color_format = COLOR_FMT_NV12;
1551 DEBUG_PRINT_LOW("Default format NV12 is set for logging [%lu]", inputformat);
1552 break;
1553 }
1554
1555 msize = VENUS_BUFFER_SIZE_USED(color_format, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,interlaced);
1556 const unsigned int extra_size = VENUS_EXTRADATA_SIZE(m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
1557
1558 if (metadatamode == 1) {
1559 pvirt= (unsigned char *)mmap(NULL, msize, PROT_READ|PROT_WRITE,MAP_SHARED, fd, plane_offset);
1560 if (pvirt == MAP_FAILED) {
1561 DEBUG_PRINT_ERROR("%s mmap failed", __func__);
1562 status = -1;
1563 goto bailout;
1564 }
1565 ptemp = pvirt;
1566 } else {
1567 ptemp = temp;
1568 }
1569
1570 if (color_format == COLOR_FMT_NV12) {
1571 stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1572 scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1573
1574 for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1575 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1576 ptemp += stride;
1577 }
1578 if (metadatamode == 1) {
1579 ptemp = pvirt + (stride * scanlines);
1580 } else {
1581 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1582 }
1583 for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1584 fwrite(ptemp, m_sVenc_cfg.input_width, 1, m_debug.infile);
1585 ptemp += stride;
1586 }
1587 } else if (color_format == COLOR_FMT_NV12_512) {
1588 stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1589 scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1590
1591 for (i = 0; i < scanlines; i++) {
1592 fwrite(ptemp, stride, 1, m_debug.infile);
1593 ptemp += stride;
1594 }
1595 if (metadatamode == 1) {
1596 ptemp = pvirt + (stride * scanlines);
1597 } else {
1598 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1599 }
1600 for (i = 0; i < scanlines/2; i++) {
1601 fwrite(ptemp, stride, 1, m_debug.infile);
1602 ptemp += stride;
1603 }
1604 } else if (color_format == COLOR_FMT_RGBA8888) {
1605 stride = VENUS_RGB_STRIDE(color_format, m_sVenc_cfg.input_width);
1606 scanlines = VENUS_RGB_SCANLINES(color_format, m_sVenc_cfg.input_height);
1607
1608 for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1609 fwrite(ptemp, m_sVenc_cfg.input_width * 4, 1, m_debug.infile);
1610 ptemp += stride;
1611 }
1612 } else if (color_format == COLOR_FMT_NV12_UBWC || color_format == COLOR_FMT_NV12_BPP10_UBWC || color_format == COLOR_FMT_RGBA8888_UBWC) {
1613 fwrite(ptemp, msize, 1, m_debug.infile);
1614 } else if(color_format == COLOR_FMT_P010) {
1615 stride = VENUS_Y_STRIDE(color_format, m_sVenc_cfg.input_width);
1616 scanlines = VENUS_Y_SCANLINES(color_format, m_sVenc_cfg.input_height);
1617
1618 for (i = 0; i < m_sVenc_cfg.input_height; i++) {
1619 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1620 ptemp += stride;
1621 }
1622 if (metadatamode == 1) {
1623 ptemp = pvirt + (stride * scanlines);
1624 } else {
1625 ptemp = (unsigned char *)pbuffer->pBuffer + (stride * scanlines);
1626 }
1627 for (i = 0; i < m_sVenc_cfg.input_height/2; i++) {
1628 fwrite(ptemp, m_sVenc_cfg.input_width*2, 1, m_debug.infile);
1629 ptemp += stride;
1630 }
1631 }
1632
1633 if (metadatamode == 1 && pvirt) {
1634 munmap(pvirt, msize);
1635 }
1636 }
1637 bailout:
1638 #ifdef USE_ION
1639 venc_handle->do_cache_operations(fd);
1640 #endif
1641 return status;
1642 }
1643
venc_open(OMX_U32 codec)1644 bool venc_dev::venc_open(OMX_U32 codec)
1645 {
1646 int r, minqp = 0, maxqp = 127;
1647 unsigned int alignment = 0,buffer_size = 0, temp =0;
1648 struct v4l2_control control;
1649 OMX_STRING device_name = (OMX_STRING)"/dev/video33";
1650 char property_value[PROPERTY_VALUE_MAX] = {0};
1651 FILE *soc_file = NULL;
1652 char buffer[10];
1653
1654 property_get("ro.board.platform", m_platform_name, "0");
1655
1656 if (!strncmp(m_platform_name, "msm8610", 7)) {
1657 device_name = (OMX_STRING)"/dev/video/q6_enc";
1658 supported_rc_modes = (RC_ALL & ~RC_CBR_CFR);
1659 }
1660
1661 if (!strcmp(m_platform_name, "sm6150") || !strcmp(m_platform_name, "atoll") || !strcmp(m_platform_name, "trinket"))
1662 {
1663 hdr10metadata_supported = false;
1664 }
1665 else {
1666 hdr10metadata_supported = true;
1667 }
1668
1669 #ifdef HYPERVISOR
1670 m_nDriver_fd = hypv_open(device_name, O_RDWR);
1671 #else
1672 m_nDriver_fd = open(device_name, O_RDWR);
1673 #endif
1674
1675 if ((int)m_nDriver_fd < 0) {
1676 DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure");
1677 return false;
1678 }
1679 m_poll_efd = eventfd(0, 0);
1680 if (m_poll_efd < 0) {
1681 DEBUG_PRINT_ERROR("Failed to open event fd(%s)", strerror(errno));
1682 return false;
1683 }
1684 DEBUG_PRINT_LOW("m_nDriver_fd = %u", (unsigned int)m_nDriver_fd);
1685
1686 // set the basic configuration of the video encoder driver
1687 m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH;
1688 m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT;
1689 m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH;
1690 m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT;
1691 m_sVenc_cfg.fps_num = 30;
1692 m_sVenc_cfg.fps_den = 1;
1693 m_sVenc_cfg.targetbitrate = 64000;
1694 m_sVenc_cfg.inputformat= V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1695 m_rotation.rotation = 0;
1696 m_codec = codec;
1697 downscalar_enabled = OMX_FALSE;
1698
1699 if (codec == OMX_VIDEO_CodingAVC) {
1700 m_sVenc_cfg.codectype = V4L2_PIX_FMT_H264;
1701 codec_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1702 profile_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1703 idrperiod.idrperiod = 1;
1704 minqp = 0;
1705 maxqp = 51;
1706 } else if (codec == OMX_VIDEO_CodingVP8) {
1707 m_sVenc_cfg.codectype = V4L2_PIX_FMT_VP8;
1708 codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
1709 profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
1710 minqp = 0;
1711 maxqp = 127;
1712 } else if (codec == OMX_VIDEO_CodingHEVC || codec == OMX_VIDEO_CodingImageHEIC) {
1713 m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC;
1714 idrperiod.idrperiod = 1;
1715 minqp = 0;
1716 maxqp = 51;
1717 if (codec == OMX_VIDEO_CodingImageHEIC) {
1718 m_sVenc_cfg.input_width = DEFAULT_TILE_DIMENSION;
1719 m_sVenc_cfg.input_height = DEFAULT_TILE_DIMENSION;
1720 m_sVenc_cfg.dvs_width = DEFAULT_TILE_DIMENSION;
1721 m_sVenc_cfg.dvs_height = DEFAULT_TILE_DIMENSION;
1722 codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC;
1723 }
1724 else
1725 codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
1726 profile_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
1727 } else if (codec == QOMX_VIDEO_CodingTME) {
1728 m_sVenc_cfg.codectype = V4L2_PIX_FMT_TME;
1729 }
1730 session_ipb_qp_values.min_i_qp = minqp;
1731 session_ipb_qp_values.max_i_qp = maxqp;
1732 session_ipb_qp_values.min_p_qp = minqp;
1733 session_ipb_qp_values.max_p_qp = maxqp;
1734 session_ipb_qp_values.min_b_qp = minqp;
1735 session_ipb_qp_values.max_b_qp = maxqp;
1736
1737 int ret;
1738 ret = subscribe_to_events(m_nDriver_fd);
1739
1740 if (ret) {
1741 DEBUG_PRINT_ERROR("Subscribe Event Failed");
1742 return false;
1743 }
1744
1745 struct v4l2_fmtdesc fdesc;
1746 struct v4l2_format fmt;
1747 struct v4l2_requestbuffers bufreq;
1748 struct v4l2_capability cap;
1749
1750 ret = ioctl(m_nDriver_fd, VIDIOC_QUERYCAP, &cap);
1751
1752 if (ret) {
1753 DEBUG_PRINT_ERROR("Failed to query capabilities");
1754 } else {
1755 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1756 " version = %d, capabilities = %x", cap.driver, cap.card,
1757 cap.bus_info, cap.version, cap.capabilities);
1758 }
1759
1760 ret=0;
1761 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1762 fdesc.index=0;
1763
1764 while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1765 DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1766 fdesc.pixelformat, fdesc.flags);
1767 fdesc.index++;
1768 }
1769
1770 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1771 fdesc.index=0;
1772
1773 while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1774 DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1775 fdesc.pixelformat, fdesc.flags);
1776 fdesc.index++;
1777 }
1778
1779 if (venc_handle->is_secure_session()) {
1780 m_sOutput_buff_property.alignment = SZ_1M;
1781 m_sInput_buff_property.alignment = SZ_1M;
1782 } else {
1783 m_sOutput_buff_property.alignment = SZ_4K;
1784 m_sInput_buff_property.alignment = SZ_4K;
1785 }
1786
1787 memset(&fmt, 0, sizeof(fmt));
1788 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1789 fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
1790 fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
1791 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
1792
1793 /*TODO: Return values not handled properly in this function anywhere.
1794 * Need to handle those.*/
1795 ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1796
1797 if (ret) {
1798 DEBUG_PRINT_ERROR("Failed to set format on capture port");
1799 return false;
1800 }
1801
1802 m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1803
1804 memset(&fmt, 0, sizeof(fmt));
1805 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1806 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
1807 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
1808 fmt.fmt.pix_mp.pixelformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
1809 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
1810
1811 ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
1812 m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1813
1814 if (m_codec == OMX_VIDEO_CodingImageHEIC) {
1815 if (!venc_set_grid_enable()) {
1816 DEBUG_PRINT_ERROR("Failed to enable grid");
1817 return false;
1818 }
1819
1820 if (!venc_set_ratectrl_cfg(OMX_Video_ControlRateConstantQuality)) {
1821 DEBUG_PRINT_ERROR("Failed to set rate control:CQ");
1822 return false;
1823 }
1824 }
1825
1826 bufreq.memory = V4L2_MEMORY_USERPTR;
1827 bufreq.count = 2;
1828
1829 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1830 ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1831 m_sInput_buff_property.mincount = m_sInput_buff_property.actualcount = bufreq.count;
1832
1833 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1834 bufreq.count = 2;
1835 ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
1836 m_sOutput_buff_property.mincount = m_sOutput_buff_property.actualcount = bufreq.count;
1837
1838 if(venc_handle->is_secure_session()) {
1839 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1840 control.value = 1;
1841 DEBUG_PRINT_HIGH("ioctl: open secure device");
1842 ret=ioctl(m_nDriver_fd, VIDIOC_S_CTRL,&control);
1843 if (ret) {
1844 DEBUG_PRINT_ERROR("ioctl: open secure dev fail, rc %d", ret);
1845 return false;
1846 }
1847 }
1848
1849 resume_in_stopped = 0;
1850 metadatamode = 0;
1851
1852 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_TME) {
1853 control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
1854 control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
1855
1856 DEBUG_PRINT_LOW("Calling IOCTL to disable seq_hdr in sync_frame id=%d, val=%d", control.id, control.value);
1857
1858 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1859 DEBUG_PRINT_ERROR("Failed to set control");
1860 }
1861
1862 struct v4l2_frmsizeenum frmsize;
1863
1864 //Get the hardware capabilities
1865 memset((void *)&frmsize,0,sizeof(frmsize));
1866 frmsize.index = 0;
1867 frmsize.pixel_format = m_sVenc_cfg.codectype;
1868 ret = ioctl(m_nDriver_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize);
1869
1870 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
1871 DEBUG_PRINT_ERROR("Failed to get framesizes");
1872 return false;
1873 }
1874
1875 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1876 capability.min_width = frmsize.stepwise.min_width;
1877 capability.max_width = frmsize.stepwise.max_width;
1878 capability.min_height = frmsize.stepwise.min_height;
1879 capability.max_height = frmsize.stepwise.max_height;
1880 }
1881
1882 //Initialize non-default parameters
1883 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
1884 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
1885 control.value = 0x7fffffff;
1886 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control))
1887 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAME\n");
1888 }
1889
1890
1891 /* Enable Low power mode by default for better power */
1892
1893 input_extradata_info.port_index = OUTPUT_PORT;
1894 output_extradata_info.port_index = CAPTURE_PORT;
1895
1896 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
1897 control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_PAYLOAD_VERSION;
1898 ret = ioctl(m_nDriver_fd, VIDIOC_G_CTRL,&control);
1899
1900 if (ret) {
1901 DEBUG_PRINT_ERROR("Failed to read TME version");
1902 return false;
1903 }
1904 venc_handle->tme_payload_version = control.value;
1905 DEBUG_PRINT_HIGH("TME version is 0x%x", control.value);
1906 }
1907 return true;
1908 }
1909
unsubscribe_to_events(int fd)1910 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
1911 {
1912 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1913 struct v4l2_event_subscription sub;
1914 int array_sz = sizeof(event_type)/sizeof(int);
1915 int i,rc;
1916
1917 if (fd < 0) {
1918 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
1919 return OMX_ErrorBadParameter;
1920 }
1921
1922 for (i = 0; i < array_sz; ++i) {
1923 memset(&sub, 0, sizeof(sub));
1924 sub.type = event_type[i];
1925 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1926
1927 if (rc) {
1928 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
1929 break;
1930 }
1931 }
1932
1933 return eRet;
1934 }
1935
venc_close()1936 void venc_dev::venc_close()
1937 {
1938 DEBUG_PRINT_LOW("venc_close: fd = %u", (unsigned int)m_nDriver_fd);
1939
1940 if ((int)m_nDriver_fd >= 0) {
1941 DEBUG_PRINT_HIGH("venc_close E");
1942
1943 if(eventfd_write(m_poll_efd, 1)) {
1944 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
1945 async_thread_force_stop = true;
1946 }
1947
1948 if (async_thread_created)
1949 pthread_join(m_tid,NULL);
1950
1951 if (venc_handle->msg_thread_created) {
1952 venc_handle->msg_thread_created = false;
1953 venc_handle->msg_thread_stop = true;
1954 post_message(venc_handle, omx_video::OMX_COMPONENT_CLOSE_MSG);
1955 DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
1956 pthread_join(venc_handle->msg_thread_id, NULL);
1957 }
1958 DEBUG_PRINT_HIGH("venc_close X");
1959 unsubscribe_to_events(m_nDriver_fd);
1960 close(m_poll_efd);
1961 #ifdef HYPERVISOR
1962 hypv_close(m_nDriver_fd);
1963 #else
1964 close(m_nDriver_fd);
1965 #endif
1966 m_nDriver_fd = -1;
1967 }
1968
1969 #ifdef _VQZIP_
1970 vqzip.deinit();
1971 #endif
1972
1973 if (m_debug.infile) {
1974 fclose(m_debug.infile);
1975 m_debug.infile = NULL;
1976 }
1977
1978 if (m_debug.outfile) {
1979 fclose(m_debug.outfile);
1980 m_debug.outfile = NULL;
1981 }
1982
1983 if (m_debug.extradatafile) {
1984 fclose(m_debug.extradatafile);
1985 m_debug.extradatafile = NULL;
1986 }
1987 }
1988
venc_set_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)1989 bool venc_dev::venc_set_buf_req(OMX_U32 *min_buff_count,
1990 OMX_U32 *actual_buff_count,
1991 OMX_U32 *buff_size,
1992 OMX_U32 port)
1993 {
1994 (void)min_buff_count, (void)buff_size;
1995 unsigned long temp_count = 0;
1996
1997 if (port == 0) {
1998 if (*actual_buff_count > m_sInput_buff_property.mincount) {
1999 temp_count = m_sInput_buff_property.actualcount;
2000 m_sInput_buff_property.actualcount = *actual_buff_count;
2001 DEBUG_PRINT_LOW("I/P Count set to %u", (unsigned int)*actual_buff_count);
2002 }
2003 } else {
2004 if (*actual_buff_count > m_sOutput_buff_property.mincount) {
2005 temp_count = m_sOutput_buff_property.actualcount;
2006 m_sOutput_buff_property.actualcount = *actual_buff_count;
2007 DEBUG_PRINT_LOW("O/P Count set to %u", (unsigned int)*actual_buff_count);
2008 }
2009 }
2010
2011 return true;
2012
2013 }
2014
venc_loaded_start()2015 bool venc_dev::venc_loaded_start()
2016 {
2017 return true;
2018 }
2019
venc_loaded_stop()2020 bool venc_dev::venc_loaded_stop()
2021 {
2022 return true;
2023 }
2024
venc_loaded_start_done()2025 bool venc_dev::venc_loaded_start_done()
2026 {
2027 return true;
2028 }
2029
venc_loaded_stop_done()2030 bool venc_dev::venc_loaded_stop_done()
2031 {
2032 return true;
2033 }
2034
venc_get_seq_hdr(void * buffer,unsigned buffer_size,unsigned * header_len)2035 bool venc_dev::venc_get_seq_hdr(void *buffer,
2036 unsigned buffer_size, unsigned *header_len)
2037 {
2038 (void) buffer, (void) buffer_size, (void) header_len;
2039 return true;
2040 }
2041
venc_get_dimensions(OMX_U32 portIndex,OMX_U32 * w,OMX_U32 * h)2042 bool venc_dev::venc_get_dimensions(OMX_U32 portIndex, OMX_U32 *w, OMX_U32 *h) {
2043 struct v4l2_format fmt;
2044 memset(&fmt, 0, sizeof(fmt));
2045 fmt.type = portIndex == PORT_INDEX_OUT ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
2046 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2047
2048 if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
2049 DEBUG_PRINT_ERROR("Failed to get format on %s port",
2050 portIndex == PORT_INDEX_OUT ? "capture" : "output");
2051 return false;
2052 }
2053 *w = fmt.fmt.pix_mp.width;
2054 *h = fmt.fmt.pix_mp.height;
2055 return true;
2056 }
2057
venc_get_buf_req(OMX_U32 * min_buff_count,OMX_U32 * actual_buff_count,OMX_U32 * buff_size,OMX_U32 port)2058 bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
2059 OMX_U32 *actual_buff_count,
2060 OMX_U32 *buff_size,
2061 OMX_U32 port)
2062 {
2063 struct v4l2_format fmt;
2064 unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
2065 int ret;
2066 int extra_idx = 0;
2067 struct v4l2_control control;
2068 unsigned int minCount = 0;
2069
2070 memset(&control, 0, sizeof(control));
2071 memset(&fmt, 0, sizeof(fmt));
2072
2073 if (port == 0) {
2074 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2075 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2076 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2077 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2078 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
2079 ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2080 if (ret) {
2081 DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x, colorspace %d\n",
2082 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2083 fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
2084 return false;
2085 }
2086 m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2087
2088 control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
2089 ret = ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control);
2090 if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
2091 DEBUG_PRINT_ERROR("Driver returned invalid data, port = %d ret = %d Count = %d",
2092 port, ret, (unsigned int)control.value);
2093 return false;
2094 }
2095
2096 // Increase buffer-header count for metadata-mode on input port
2097 // to improve buffering and reduce bottlenecks in clients
2098 if (metadatamode) {
2099 DEBUG_PRINT_LOW("FW returned buffer count = %d , overwriting with 9",
2100 control.value);
2101 minCount = 9;
2102 }
2103
2104 if (m_sVenc_cfg.input_height * m_sVenc_cfg.input_width >= 3840*2160) {
2105 DEBUG_PRINT_LOW("Increasing buffer count = %d to 11", minCount);
2106 minCount = 11;
2107 }
2108
2109 /* Need more buffers for HFR usecase */
2110 if (operating_rate >= 120 || (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) >= 120) {
2111 minCount = MAX(minCount, 16);
2112 DEBUG_PRINT_HIGH("fps %d, operating rate %d, input min count %d",
2113 (int)(m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den), operating_rate, minCount);
2114 }
2115
2116 // Request MAX_V4L2_BUFS from V4L2 in batch mode.
2117 // Keep the original count for the client
2118 if (metadatamode && mBatchSize) {
2119 minCount = MAX_V4L2_BUFS;
2120 DEBUG_PRINT_LOW("Set buffer count = %d as metadata mode and batchmode enabled", minCount);
2121 }
2122
2123 // reset min count to 4 for HEIC cases
2124 if (mIsGridset) {
2125 minCount = 4;
2126 DEBUG_PRINT_LOW("Set buffer count = %d for HEIC", minCount);
2127 }
2128
2129 minCount = MAX((unsigned int)control.value, minCount);
2130 m_sInput_buff_property.mincount = minCount;
2131
2132 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2133 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2134 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2135 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2136 ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2137 if (ret) {
2138 DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
2139 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2140 fmt.fmt.pix_mp.pixelformat);
2141 return false;
2142 }
2143 m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2144
2145 if (m_sInput_buff_property.actualcount < m_sInput_buff_property.mincount)
2146 m_sInput_buff_property.actualcount = m_sInput_buff_property.mincount;
2147
2148 *min_buff_count = m_sInput_buff_property.mincount;
2149 *actual_buff_count = m_sInput_buff_property.actualcount;
2150 #ifdef USE_ION
2151 // For ION memory allocations of the allocated buffer size
2152 // must be 4k aligned, hence aligning the input buffer
2153 // size to 4k.
2154 m_sInput_buff_property.datasize = ALIGN(m_sInput_buff_property.datasize, SZ_4K);
2155 #endif
2156 *buff_size = m_sInput_buff_property.datasize;
2157 num_input_planes = fmt.fmt.pix_mp.num_planes;
2158 extra_idx = EXTRADATA_IDX(num_input_planes);
2159
2160 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
2161 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
2162 } else if (extra_idx >= VIDEO_MAX_PLANES) {
2163 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx);
2164 return false;
2165 }
2166 input_extradata_info.buffer_size = ALIGN(extra_data_size, SZ_4K);
2167 input_extradata_info.count = MAX_V4L2_BUFS;
2168 input_extradata_info.size = input_extradata_info.buffer_size * input_extradata_info.count;
2169 venc_handle->m_client_in_extradata_info.set_extradata_info(input_extradata_info.buffer_size,m_sInput_buff_property.actualcount);
2170 } else {
2171 unsigned int extra_idx = 0;
2172 memset(&fmt, 0, sizeof(fmt));
2173 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2174 fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2175 fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2176 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2177
2178 ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt);
2179 if (ret) {
2180 DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, format %#x\n",
2181 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2182 fmt.fmt.pix_mp.pixelformat);
2183 return false;
2184 }
2185
2186 m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2187 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2188 fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2189 fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2190 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2191
2192 ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt);
2193 if (ret) {
2194 DEBUG_PRINT_ERROR("get format failed, type %d, wxh %dx%d, format %#x\n",
2195 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2196 fmt.fmt.pix_mp.pixelformat);
2197 return false;
2198 }
2199 m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2200
2201 control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
2202
2203 ret = ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control);
2204 if (ret || (unsigned int)control.value > MAX_V4L2_BUFS) {
2205 DEBUG_PRINT_ERROR("Driver returned invalid data port = %d ret = %d Count = %d",
2206 port, ret, (unsigned int)control.value);
2207 return false;
2208 }
2209 minCount = control.value;
2210
2211 if (mBatchSize) {
2212 // If we're in batch mode, we'd like to end up in a situation where
2213 // driver is able to own mBatchSize buffers and we'd also own atleast
2214 // mBatchSize buffers
2215 minCount = MAX((unsigned int)control.value, mBatchSize) + mBatchSize;
2216 DEBUG_PRINT_LOW("set min count %d as mBatchSize %d", minCount, mBatchSize);
2217 }
2218
2219 /* Need more buffers for HFR usecase */
2220 if (operating_rate >= 120 || (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) >= 120) {
2221 minCount = MAX(minCount, 16);
2222 DEBUG_PRINT_HIGH("fps %d, operating rate %d, output min count %d",
2223 (int)(m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den), operating_rate, minCount);
2224 }
2225
2226 m_sOutput_buff_property.mincount = minCount;
2227
2228 if (m_sOutput_buff_property.actualcount < m_sOutput_buff_property.mincount)
2229 m_sOutput_buff_property.actualcount = m_sOutput_buff_property.mincount;
2230
2231 *min_buff_count = m_sOutput_buff_property.mincount;
2232 *actual_buff_count = m_sOutput_buff_property.actualcount;
2233 *buff_size = m_sOutput_buff_property.datasize;
2234 num_output_planes = fmt.fmt.pix_mp.num_planes;
2235 extra_idx = EXTRADATA_IDX(num_output_planes);
2236
2237 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
2238 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
2239 } else if (extra_idx >= VIDEO_MAX_PLANES) {
2240 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
2241 return false;
2242 }
2243
2244 output_extradata_info.buffer_size = ALIGN(extra_data_size, SZ_4K);
2245 output_extradata_info.count = m_sOutput_buff_property.actualcount;
2246 output_extradata_info.size = output_extradata_info.buffer_size * output_extradata_info.count;
2247 venc_handle->m_client_out_extradata_info.set_extradata_info(output_extradata_info.buffer_size,output_extradata_info.count);
2248 }
2249
2250 DEBUG_PRINT_HIGH("venc_get_buf_req: port %d, wxh %dx%d, format %#x, driver min count %d, "
2251 "updated min count %d, act count %d, size %d, num planes %d",
2252 port, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.pixelformat,
2253 control.value, *min_buff_count, *actual_buff_count, *buff_size, fmt.fmt.pix_mp.num_planes);
2254
2255 return true;
2256 }
2257
venc_set_param(void * paramData,OMX_INDEXTYPE index)2258 bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index)
2259 {
2260 DEBUG_PRINT_LOW("venc_set_param index 0x%x", index);
2261 struct v4l2_format fmt;
2262 struct v4l2_requestbuffers bufreq;
2263 int ret;
2264 bool isCBR;
2265
2266 switch ((int)index) {
2267 case OMX_IndexParamPortDefinition:
2268 {
2269 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2270 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2271
2272 if (portDefn->nPortIndex == PORT_INDEX_IN) {
2273 if (!venc_set_encode_framerate(portDefn->format.video.xFramerate)) {
2274 return false;
2275 }
2276
2277 if (enable_mv_narrow_searchrange &&
2278 (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height) >=
2279 (OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT)) {
2280 if (venc_set_searchrange() == false) {
2281 DEBUG_PRINT_ERROR("ERROR: Failed to set search range");
2282 }
2283 }
2284
2285 unsigned long inputformat = venc_get_color_format(portDefn->format.video.eColorFormat);
2286
2287 if (m_sVenc_cfg.input_height != portDefn->format.video.nFrameHeight ||
2288 m_sVenc_cfg.input_width != portDefn->format.video.nFrameWidth ||
2289 m_sInput_buff_property.actualcount != portDefn->nBufferCountActual ||
2290 m_sVenc_cfg.inputformat != inputformat) {
2291
2292 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
2293 portDefn->nPortIndex, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
2294 portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
2295 m_sInput_buff_property.actualcount, portDefn->nBufferCountActual,
2296 m_sVenc_cfg.inputformat, inputformat);
2297
2298 if (portDefn->nBufferCountActual < m_sInput_buff_property.mincount) {
2299 DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
2300 portDefn->nBufferCountActual, m_sInput_buff_property.mincount, portDefn->nPortIndex);
2301 return false;
2302 }
2303
2304 m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight;
2305 m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth;
2306 m_sVenc_cfg.inputformat = inputformat;
2307 m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
2308
2309 memset(&fmt, 0, sizeof(fmt));
2310 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2311 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
2312 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
2313 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
2314 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
2315 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2316 DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x, colorspace %#x",
2317 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2318 fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
2319 hw_overload = errno == EBUSY;
2320 return false;
2321 }
2322 m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2323
2324 bufreq.memory = V4L2_MEMORY_USERPTR;
2325 bufreq.count = portDefn->nBufferCountActual;
2326 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2327 if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2328 DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
2329 return false;
2330 }
2331
2332 if (num_input_planes > 1)
2333 input_extradata_info.count = m_sInput_buff_property.actualcount + 1;
2334
2335 if (!downscalar_enabled) {
2336 m_sVenc_cfg.dvs_height = portDefn->format.video.nFrameHeight;
2337 m_sVenc_cfg.dvs_width = portDefn->format.video.nFrameWidth;
2338 }
2339 memset(&fmt, 0, sizeof(fmt));
2340 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2341 fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2342 fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2343 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2344
2345 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2346 DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed");
2347 hw_overload = errno == EBUSY;
2348 return false;
2349 }
2350
2351 m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2352
2353 } else {
2354 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
2355 portDefn->nPortIndex);
2356 }
2357 } else if (portDefn->nPortIndex == PORT_INDEX_OUT) {
2358
2359 unsigned long codectype = venc_get_codectype(portDefn->format.video.eCompressionFormat);
2360
2361 //Don't worry about width/height if downscalar is enabled.
2362 if (((m_sVenc_cfg.dvs_height != portDefn->format.video.nFrameHeight ||
2363 m_sVenc_cfg.dvs_width != portDefn->format.video.nFrameWidth) && !downscalar_enabled) ||
2364 m_sOutput_buff_property.actualcount != portDefn->nBufferCountActual ||
2365 m_sVenc_cfg.codectype != codectype) {
2366
2367 if (portDefn->nBufferCountActual < m_sOutput_buff_property.mincount) {
2368 DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
2369 portDefn->nBufferCountActual, m_sOutput_buff_property.mincount, portDefn->nPortIndex);
2370 return false;
2371 }
2372
2373 //If downscalar is enabled. Correct width/height is populated no need to replace with port def width/height
2374 if (!downscalar_enabled) {
2375 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
2376 portDefn->nPortIndex, m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
2377 portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
2378 m_sOutput_buff_property.actualcount, portDefn->nBufferCountActual,
2379 m_sVenc_cfg.codectype, codectype);
2380 m_sVenc_cfg.dvs_height = portDefn->format.video.nFrameHeight;
2381 m_sVenc_cfg.dvs_width = portDefn->format.video.nFrameWidth;
2382 }
2383
2384 m_sVenc_cfg.codectype = codectype;
2385 m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual;
2386
2387 memset(&fmt, 0, sizeof(fmt));
2388 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2389 fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
2390 fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
2391 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
2392 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
2393 DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x",
2394 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
2395 fmt.fmt.pix_mp.pixelformat);
2396 hw_overload = errno == EBUSY;
2397 return false;
2398 }
2399 m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
2400
2401 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_TME) {
2402 if (!venc_set_target_bitrate(portDefn->format.video.nBitrate)) {
2403 return false;
2404 }
2405 }
2406
2407 bufreq.memory = V4L2_MEMORY_USERPTR;
2408 bufreq.count = portDefn->nBufferCountActual;
2409 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2410 if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
2411 DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
2412 return false;
2413 }
2414
2415 if (num_output_planes > 1)
2416 output_extradata_info.count = m_sOutput_buff_property.actualcount;
2417 } else {
2418 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
2419 portDefn->nPortIndex);
2420 }
2421 } else {
2422 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index (%d) for OMX_IndexParamPortDefinition", portDefn->nPortIndex);
2423 }
2424 }
2425 break;
2426 case OMX_IndexParamVideoPortFormat:
2427 {
2428 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt;
2429 portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2430 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat");
2431
2432 if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
2433 if (!venc_set_color_format(portFmt->eColorFormat)) {
2434 return false;
2435 }
2436 } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2437 if (!venc_set_encode_framerate(portFmt->xFramerate)) {
2438 return false;
2439 }
2440 } else {
2441 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat");
2442 }
2443 break;
2444 }
2445 case OMX_IndexParamVideoBitrate:
2446 {
2447 OMX_VIDEO_PARAM_BITRATETYPE* pParam;
2448 pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
2449 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate");
2450
2451 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2452 if (!venc_set_ratectrl_cfg(pParam->eControlRate)) {
2453 DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed");
2454 return false;
2455 }
2456
2457 if (!venc_set_target_bitrate(pParam->nTargetBitrate)) {
2458 DEBUG_PRINT_ERROR("ERROR: Target Bit Rate setting failed");
2459 return false;
2460 }
2461 } else {
2462 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate");
2463 }
2464
2465 break;
2466 }
2467 case OMX_IndexParamVideoAvc:
2468 {
2469 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc");
2470 OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
2471 OMX_U32 bFrames = 0;
2472
2473 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2474 DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d",
2475 pParam->eProfile,pParam->eLevel);
2476
2477 if (!venc_set_profile (pParam->eProfile)) {
2478 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2479 pParam->eProfile);
2480 return false;
2481 } else {
2482 if ((pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) &&
2483 (pParam->eProfile != (OMX_VIDEO_AVCPROFILETYPE) QOMX_VIDEO_AVCProfileConstrainedBaseline)) {
2484 if (pParam->nBFrames) {
2485 bFrames = pParam->nBFrames;
2486 }
2487 } else {
2488 if (pParam->nBFrames) {
2489 DEBUG_PRINT_ERROR("Warning: B frames not supported");
2490 bFrames = 0;
2491 }
2492 }
2493 }
2494
2495 if(!venc_set_level(OMX_VIDEO_LEVEL_UNKNOWN)) {
2496 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2497 return false;
2498 }
2499
2500 if (!venc_set_intra_period (pParam->nPFrames, bFrames)) {
2501 DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2502 return false;
2503 }
2504 if (!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) {
2505 DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed");
2506 return false;
2507 }
2508 if (!venc_set_inloop_filter (pParam->eLoopFilterMode)) {
2509 DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed");
2510 return false;
2511 }
2512
2513 if (!venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB, pParam->nSliceHeaderSpacing)) {
2514 DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config");
2515 return false;
2516 }
2517 } else {
2518 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAvc");
2519 }
2520
2521 //TBD, lot of other variables to be updated, yet to decide
2522 break;
2523 }
2524 case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
2525 {
2526 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoVp8");
2527 OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
2528
2529 //TODO: Set VP8 level/profile currently based on driver change
2530 if (!venc_set_profile (pParam->eProfile)) {
2531 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2532 pParam->eProfile);
2533 return false;
2534 }
2535 if (!venc_set_level (OMX_VIDEO_LEVEL_UNKNOWN)) {
2536 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2537 return false;
2538 }
2539 if(venc_set_vpx_error_resilience(pParam->bErrorResilientMode) == false) {
2540 DEBUG_PRINT_ERROR("ERROR: Failed to set vpx error resilience");
2541 return false;
2542 }
2543 break;
2544 }
2545 case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
2546 {
2547 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoHevc");
2548 OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
2549
2550 if (!venc_set_profile (pParam->eProfile)) {
2551 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2552 pParam->eProfile);
2553 return false;
2554 }
2555 if (!venc_set_level (OMX_VIDEO_LEVEL_UNKNOWN)) {
2556 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level to unknown");
2557 return false;
2558 }
2559 if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable))
2560 DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder");
2561
2562 OMX_U32 fps = m_sVenc_cfg.fps_den ? m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den : 30;
2563 OMX_U32 nPFrames = pParam->nKeyFrameInterval > 0 ? pParam->nKeyFrameInterval - 1 : fps - 1;
2564 if (!venc_set_intra_period (nPFrames, 0 /* nBFrames */)) {
2565 DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2566 return false;
2567 }
2568 break;
2569 }
2570 case (OMX_INDEXTYPE)OMX_IndexParamVideoTme:
2571 {
2572 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoTme");
2573 QOMX_VIDEO_PARAM_TMETYPE * pParam = (QOMX_VIDEO_PARAM_TMETYPE*)paramData;
2574
2575 if (!venc_set_profile(pParam->eProfile)) {
2576 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
2577 pParam->eProfile);
2578 return false;
2579 }
2580 if (!venc_set_level(pParam->eLevel)) {
2581 DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating level %d",
2582 pParam->eLevel);
2583 return false;
2584 }
2585 break;
2586 }
2587 case (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid:
2588 {
2589 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidImageGrid. Ignore!");
2590 break;
2591 }
2592 case OMX_IndexParamVideoIntraRefresh:
2593 {
2594 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh");
2595 OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh_param =
2596 (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData;
2597
2598 if (intra_refresh_param->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2599 intra_refresh.irmode = intra_refresh_param->eRefreshMode;
2600 intra_refresh.mbcount = intra_refresh_param->nCirMBs;
2601 intra_refresh.framecount = 0;
2602 } else {
2603 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh");
2604 }
2605
2606 break;
2607 }
2608 case OMX_IndexParamVideoAndroidVp8Encoder:
2609 {
2610 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidVp8Encoder");
2611 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8EncodeParams =
2612 (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)paramData;
2613
2614 if (vp8EncodeParams->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2615 int pFrames = vp8EncodeParams->nKeyFrameInterval - 1;
2616 if (venc_set_intra_period(pFrames, 0) == false) {
2617 DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2618 return false;
2619 }
2620
2621 } else {
2622 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAndroidVp8Encoder");
2623 }
2624 break;
2625 }
2626 case OMX_IndexParamVideoErrorCorrection:
2627 {
2628 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection");
2629 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience =
2630 (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData;
2631
2632 if (error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2633 if (venc_set_error_resilience(error_resilience) == false) {
2634 DEBUG_PRINT_ERROR("ERROR: Setting Error Correction failed");
2635 return false;
2636 }
2637 } else {
2638 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection");
2639 }
2640
2641 break;
2642 }
2643 case OMX_QcomIndexParamVideoSliceSpacing:
2644 {
2645 DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoSliceSpacing");
2646 QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE *slice_spacing =
2647 (QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE*)paramData;
2648
2649 if (slice_spacing->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2650 if (!venc_set_multislice_cfg(slice_spacing->eSliceMode, slice_spacing->nSliceSize)) {
2651 DEBUG_PRINT_ERROR("ERROR: Setting Slice Spacing failed");
2652 return false;
2653 }
2654 } else {
2655 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexParamVideoSliceSpacing");
2656 }
2657
2658 break;
2659 }
2660 case OMX_IndexParamVideoProfileLevelCurrent:
2661 {
2662 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent");
2663 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level =
2664 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
2665
2666 if (profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2667 if (!venc_set_profile(profile_level->eProfile)) {
2668 DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating Profile");
2669 return false;
2670 }
2671 if (!venc_set_level(profile_level->eLevel)) {
2672 DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating level");
2673 return false;
2674 }
2675 } else {
2676 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent");
2677 }
2678
2679 break;
2680 }
2681 case OMX_IndexParamVideoQuantization:
2682 {
2683 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization");
2684 OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp =
2685 (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData;
2686 if (session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2687 if (venc_set_qp(session_qp->nQpI,
2688 session_qp->nQpP,
2689 session_qp->nQpB,
2690 ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP) == false) {
2691 DEBUG_PRINT_ERROR("ERROR: Setting Session QP failed");
2692 return false;
2693 }
2694 } else {
2695 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoQuantization");
2696 }
2697
2698 break;
2699 }
2700 case QOMX_IndexParamVideoInitialQp:
2701 {
2702 DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexParamVideoInitialQp");
2703 QOMX_EXTNINDEX_VIDEO_INITIALQP *initial_qp =
2704 (QOMX_EXTNINDEX_VIDEO_INITIALQP *)paramData;
2705 if (initial_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
2706 if (venc_set_qp(initial_qp->nQpI,
2707 initial_qp->nQpP,
2708 initial_qp->nQpB,
2709 initial_qp->bEnableInitQp) == false) {
2710 DEBUG_PRINT_ERROR("ERROR: Setting Initial QP failed");
2711 return false;
2712 }
2713 } else {
2714 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for QOMX_IndexParamVideoInitialQp");
2715 }
2716
2717 break;
2718 }
2719 case OMX_QcomIndexParamVideoIPBQPRange:
2720 {
2721 DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoIPBQPRange");
2722 OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *session_qp_range =
2723 (OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *)paramData;
2724 if(session_qp_range->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
2725 if ( venc_set_session_qp_range (session_qp_range) == false) {
2726 DEBUG_PRINT_ERROR("ERROR: Setting QP range failed");
2727 return false;
2728 }
2729 }
2730
2731 break;
2732 }
2733 case OMX_QcomIndexEnableSliceDeliveryMode:
2734 {
2735 QOMX_EXTNINDEX_PARAMTYPE* pParam =
2736 (QOMX_EXTNINDEX_PARAMTYPE*)paramData;
2737
2738 if (pParam->nPortIndex == PORT_INDEX_OUT) {
2739 if (venc_set_slice_delivery_mode(pParam->bEnable) == false) {
2740 DEBUG_PRINT_ERROR("Setting slice delivery mode failed");
2741 return false;
2742 }
2743 } else {
2744 DEBUG_PRINT_ERROR("OMX_QcomIndexEnableSliceDeliveryMode "
2745 "called on wrong port(%u)", (unsigned int)pParam->nPortIndex);
2746 return false;
2747 }
2748
2749 break;
2750 }
2751 case OMX_ExtraDataFrameDimension:
2752 {
2753 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataFrameDimension");
2754 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2755
2756 if (venc_set_extradata(OMX_ExtraDataFrameDimension, extra_data) == false) {
2757 DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataFrameDimension failed");
2758 return false;
2759 }
2760
2761 extradata = true;
2762 break;
2763 }
2764 case OMX_ExtraDataVideoEncoderSliceInfo:
2765 {
2766 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderSliceInfo");
2767 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2768
2769 if (venc_set_extradata(OMX_ExtraDataVideoEncoderSliceInfo, extra_data) == false) {
2770 DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoEncoderSliceInfo failed");
2771 return false;
2772 }
2773
2774 extradata = true;
2775 break;
2776 }
2777 case OMX_ExtraDataVideoEncoderMBInfo:
2778 {
2779 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderMBInfo");
2780 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2781
2782 if (venc_set_extradata(OMX_ExtraDataVideoEncoderMBInfo, extra_data) == false) {
2783 DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoEncoderMBInfo failed");
2784 return false;
2785 }
2786
2787 extradata = true;
2788 break;
2789 }
2790 case OMX_ExtraDataVideoLTRInfo:
2791 {
2792 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoLTRInfo");
2793 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2794 if (venc_set_extradata(OMX_ExtraDataVideoLTRInfo, extra_data) == false) {
2795 DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoLTRInfo failed");
2796 return false;
2797 }
2798 extradata = true;
2799 break;
2800 }
2801 case OMX_QcomIndexParamSequenceHeaderWithIDR:
2802 {
2803 PrependSPSPPSToIDRFramesParams * pParam =
2804 (PrependSPSPPSToIDRFramesParams *)paramData;
2805
2806 DEBUG_PRINT_LOW("set inband sps/pps: %d", pParam->bEnable);
2807 if(venc_set_inband_video_header(pParam->bEnable) == false) {
2808 DEBUG_PRINT_ERROR("ERROR: set inband sps/pps failed");
2809 return false;
2810 }
2811
2812 break;
2813 }
2814 case OMX_QcomIndexParamAUDelimiter:
2815 {
2816 OMX_QCOM_VIDEO_CONFIG_AUD * pParam =
2817 (OMX_QCOM_VIDEO_CONFIG_AUD *)paramData;
2818
2819 DEBUG_PRINT_LOW("set AU Delimiters: %d", pParam->bEnable);
2820 if(venc_set_au_delimiter(pParam->bEnable) == false) {
2821 DEBUG_PRINT_ERROR("ERROR: set AU delimiter failed");
2822 return false;
2823 }
2824
2825 break;
2826 }
2827 case OMX_QcomIndexConfigH264EntropyCodingCabac:
2828 {
2829 QOMX_VIDEO_H264ENTROPYCODINGTYPE * pParam =
2830 (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)paramData;
2831
2832 DEBUG_PRINT_LOW("set Entropy info : %d", pParam->bCabac);
2833 if(venc_set_entropy_config (pParam->bCabac, 0) == false) {
2834 DEBUG_PRINT_ERROR("ERROR: set Entropy failed");
2835 return false;
2836 }
2837
2838 break;
2839 }
2840 case OMX_QcomIndexParamH264VUITimingInfo:
2841 {
2842 OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
2843 (OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *)paramData;
2844 DEBUG_PRINT_LOW("Set VUI timing info: %d", pParam->bEnable);
2845 if(venc_set_vui_timing_info(pParam->bEnable) == false) {
2846 DEBUG_PRINT_ERROR("ERROR: Failed to set vui timing info to %d", pParam->bEnable);
2847 return false;
2848 } else {
2849 vui_timing_info.enabled = (unsigned int) pParam->bEnable;
2850 }
2851 break;
2852 }
2853 case OMX_QcomIndexParamPeakBitrate:
2854 {
2855 OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam =
2856 (OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *)paramData;
2857 DEBUG_PRINT_LOW("Set peak bitrate: %u", (unsigned int)pParam->nPeakBitrate);
2858 if(venc_set_peak_bitrate(pParam->nPeakBitrate) == false) {
2859 DEBUG_PRINT_ERROR("ERROR: Failed to set peak bitrate to %u", (unsigned int)pParam->nPeakBitrate);
2860 return false;
2861 } else {
2862 peak_bitrate.peakbitrate = (unsigned int) pParam->nPeakBitrate;
2863 }
2864 break;
2865 }
2866 case OMX_QcomIndexParamSetMVSearchrange:
2867 {
2868 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexParamSetMVSearchrange");
2869 is_searchrange_set = true;
2870 if (!venc_set_searchrange()) {
2871 DEBUG_PRINT_ERROR("ERROR: Failed to set search range");
2872 return false;
2873 }
2874 }
2875 break;
2876 case OMX_QcomIndexParamVideoLTRCount:
2877 {
2878 DEBUG_PRINT_LOW("venc_set_param: OMX_QcomIndexParamVideoLTRCount");
2879 OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE* pParam =
2880 (OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData;
2881 if (pParam->nCount > 0) {
2882 if (venc_set_ltrmode(1, pParam->nCount) == false) {
2883 DEBUG_PRINT_ERROR("ERROR: Enable LTR mode failed");
2884 return false;
2885 }
2886 } else {
2887 if (venc_set_ltrmode(0, 0) == false) {
2888 DEBUG_PRINT_ERROR("ERROR: Disable LTR mode failed");
2889 return false;
2890 }
2891 }
2892 break;
2893 }
2894 case OMX_QcomIndexParamBatchSize:
2895 {
2896 OMX_PARAM_U32TYPE* pParam =
2897 (OMX_PARAM_U32TYPE*)paramData;
2898
2899 if (pParam->nPortIndex == PORT_INDEX_OUT) {
2900 DEBUG_PRINT_ERROR("For the moment, client-driven batching not supported"
2901 " on output port");
2902 return false;
2903 }
2904 break;
2905 }
2906 case OMX_QcomIndexParamVencAspectRatio:
2907 {
2908 if (!venc_set_aspectratio(paramData)) {
2909 DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexParamVencAspectRatio failed");
2910 return false;
2911 }
2912 break;
2913 }
2914 case OMX_QTIIndexParamVideoEnableRoiInfo:
2915 {
2916 struct v4l2_control control;
2917 OMX_BOOL extra_data = *(OMX_BOOL *)(paramData);
2918 if (extra_data == OMX_FALSE) {
2919 DEBUG_PRINT_INFO("OMX_QTIIndexParamVideoEnableRoiInfo: bEnableRoiInfo is false");
2920 break;
2921 }
2922 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
2923 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
2924 DEBUG_PRINT_ERROR("OMX_QTIIndexParamVideoEnableRoiInfo is not supported for %lu codec", m_sVenc_cfg.codectype);
2925 return false;
2926 }
2927 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
2928 control.value = V4L2_MPEG_VIDC_EXTRADATA_ROI_QP;
2929 DEBUG_PRINT_LOW("Setting param OMX_QTIIndexParamVideoEnableRoiInfo");
2930 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
2931 DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableRoiInfo failed");
2932 return false;
2933 }
2934 m_roi_enabled = true;
2935 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE;
2936 if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control)) {
2937 DEBUG_PRINT_ERROR("ERROR: Getting V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE failed");
2938 } else {
2939 DEBUG_PRINT_LOW("ROI type: %d", control.value);
2940 m_roi_type = control.value;
2941 }
2942 break;
2943 }
2944 case OMX_QTIIndexParamLowLatencyMode:
2945 {
2946 QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE *pParam =
2947 (QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
2948
2949 if (!venc_set_lowlatency_mode(pParam->bEnableLowLatencyMode)) {
2950 DEBUG_PRINT_ERROR("Setting low latency mode failed");
2951 return false;
2952 }
2953 break;
2954 }
2955 case OMX_IndexParamAndroidVideoTemporalLayering:
2956 {
2957 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE hierData;
2958 memcpy(&hierData, paramData, sizeof(hierData));
2959
2960 if (!venc_validate_temporal_extn(hierData)) {
2961 DEBUG_PRINT_ERROR("set_param: Failed to validate temporal settings");
2962 return false;
2963 }
2964
2965 venc_copy_temporal_settings(hierData);
2966
2967 break;
2968 }
2969 case OMX_QTIIndexParamDisablePQ:
2970 {
2971 QOMX_DISABLETYPE * pParam = (QOMX_DISABLETYPE *)paramData;
2972 DEBUG_PRINT_LOW("venc_set_param: OMX_QTIIndexParamDisablePQ: %d", pParam->bDisable);
2973 break;
2974 }
2975 case OMX_QTIIndexParamIframeSizeType:
2976 {
2977 QOMX_VIDEO_IFRAMESIZE* pParam =
2978 (QOMX_VIDEO_IFRAMESIZE *)paramData;
2979 isCBR = rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR ||
2980 rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
2981 if (!isCBR) {
2982 DEBUG_PRINT_ERROR("venc_set_param: OMX_QTIIndexParamIframeSizeType not allowed for this configuration isCBR(%d)",
2983 isCBR);
2984 return false;
2985 }
2986 if (!venc_set_iframesize_type(pParam->eType)) {
2987 DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamIframeSizeType failed");
2988 return false;
2989 }
2990 break;
2991 }
2992 case OMX_QTIIndexParamEnableAVTimerTimestamps:
2993 {
2994 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
2995 mUseAVTimerTimestamps = pParam->bEnable == OMX_TRUE;
2996 DEBUG_PRINT_INFO("AVTimer timestamps enabled");
2997 break;
2998 }
2999 case OMX_QcomIndexParamVideoDownScalar:
3000 {
3001 QOMX_INDEXDOWNSCALAR *pParam = (QOMX_INDEXDOWNSCALAR *)paramData;
3002 downscalar_enabled = pParam->bEnable;
3003
3004 DEBUG_PRINT_INFO("Downscalar settings: Enabled : %d Width : %u Height %u",
3005 pParam->bEnable, pParam->nOutputWidth, pParam->nOutputHeight);
3006 if (downscalar_enabled) {
3007 m_sVenc_cfg.dvs_width = pParam->nOutputWidth;
3008 m_sVenc_cfg.dvs_height = pParam->nOutputHeight;
3009
3010 memset(&fmt, 0, sizeof(fmt));
3011 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3012 fmt.fmt.pix_mp.width = pParam->nOutputWidth;
3013 fmt.fmt.pix_mp.height = pParam->nOutputHeight;
3014 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
3015 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3016 DEBUG_PRINT_ERROR("Failed to set format on capture port");
3017 return false;
3018 }
3019 m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
3020 }
3021 break;
3022 }
3023 case OMX_QTIIndexParamColorSpaceConversion:
3024 {
3025 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3026 csc_enable = pParam->bEnable;
3027 DEBUG_PRINT_INFO("CSC settings: Enabled : %d ", pParam->bEnable);
3028 break;
3029 }
3030 case OMX_QTIIndexParamEnableLinearColorFormat:
3031 {
3032 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3033 mUseLinearColorFormat = pParam->bEnable ? REQUEST_LINEAR_COLOR_ALL : 0;
3034 DEBUG_PRINT_INFO("Linear Color Format Enabled : %d ", pParam->bEnable);
3035 break;
3036 }
3037 case OMX_QTIIndexParamVideoEnableBlur:
3038 {
3039 OMX_QTI_VIDEO_CONFIG_BLURINFO *pParam = (OMX_QTI_VIDEO_CONFIG_BLURINFO *)paramData;
3040 if (!venc_set_blur_resolution(pParam)) {
3041 DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableBlur failed");
3042 return false;
3043 }
3044 break;
3045 }
3046 case OMX_QTIIndexParamNativeRecorder:
3047 {
3048 QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
3049 mIsNativeRecorder = pParam->bEnable == OMX_TRUE;
3050 DEBUG_PRINT_INFO("Native recorder encode session %d", pParam->bEnable);
3051 break;
3052 }
3053 default:
3054 DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
3055 index);
3056 break;
3057 }
3058
3059 return true;
3060 }
3061
venc_set_config(void * configData,OMX_INDEXTYPE index)3062 bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
3063 {
3064
3065 DEBUG_PRINT_LOW("Inside venc_set_config");
3066
3067 switch ((int)index) {
3068 case OMX_IndexConfigVideoBitrate:
3069 {
3070 OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *)
3071 configData;
3072 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoBitrate");
3073
3074 if (bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3075 if (venc_set_target_bitrate(bit_rate->nEncodeBitrate) == false) {
3076 DEBUG_PRINT_ERROR("ERROR: Setting Target Bit rate failed");
3077 return false;
3078 }
3079 } else {
3080 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate");
3081 }
3082
3083 break;
3084 }
3085 case OMX_IndexConfigVideoFramerate:
3086 {
3087 OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *)
3088 configData;
3089 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoFramerate");
3090
3091 if (frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3092 if (venc_set_encode_framerate(frame_rate->xEncodeFramerate) == false) {
3093 DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
3094 return false;
3095 }
3096 } else {
3097 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
3098 }
3099
3100 break;
3101 }
3102 case QOMX_IndexConfigVideoIntraperiod:
3103 {
3104 DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod");
3105 QOMX_VIDEO_INTRAPERIODTYPE *intraperiod =
3106 (QOMX_VIDEO_INTRAPERIODTYPE *)configData;
3107
3108 if (intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
3109 if (venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) {
3110 DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
3111 return false;
3112 }
3113
3114 if (venc_set_idr_period(intraperiod->nIDRPeriod) == false) {
3115 DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
3116 return false;
3117 }
3118 client_req_disable_bframe = (intraperiod->nBFrames == 0) ? true : false;
3119 }
3120
3121 break;
3122 }
3123 case OMX_IndexConfigVideoIntraVOPRefresh:
3124 {
3125 OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)
3126 configData;
3127 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh");
3128
3129 if (intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
3130 if (venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) {
3131 DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
3132 return false;
3133 }
3134 } else {
3135 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
3136 }
3137
3138 break;
3139 }
3140 case OMX_IndexConfigCommonMirror:
3141 {
3142 OMX_CONFIG_MIRRORTYPE *mirror = (OMX_CONFIG_MIRRORTYPE*) configData;
3143 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigCommonMirror");
3144
3145 if (venc_set_mirror(mirror->eMirror) == false) {
3146 DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigCommonMirror failed");
3147 return false;
3148 }
3149 break;
3150 }
3151 case OMX_IndexConfigCommonRotate:
3152 {
3153 OMX_CONFIG_ROTATIONTYPE *config_rotation =
3154 reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
3155 OMX_U32 nFrameWidth;
3156 if (!config_rotation) {
3157 return false;
3158 }
3159 if (true == deinterlace_enabled) {
3160 DEBUG_PRINT_ERROR("ERROR: Rotation is not supported with deinterlacing");
3161 return false;
3162 }
3163 if(venc_set_vpe_rotation(config_rotation->nRotation) == false) {
3164 DEBUG_PRINT_ERROR("ERROR: Dimension Change for Rotation failed");
3165 return false;
3166 }
3167
3168 break;
3169 }
3170 case OMX_IndexConfigVideoAVCIntraPeriod:
3171 {
3172 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *avc_iperiod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD*) configData;
3173 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigVideoAVCIntraPeriod");
3174
3175 if (venc_set_intra_period(avc_iperiod->nPFrames, intra_period.num_bframes) == false) {
3176 DEBUG_PRINT_ERROR("ERROR: Setting intra period failed");
3177 return false;
3178 }
3179 if (venc_set_idr_period(avc_iperiod->nIDRPeriod) == false) {
3180 DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
3181 return false;
3182 }
3183 break;
3184 }
3185 case OMX_IndexConfigVideoVp8ReferenceFrame:
3186 {
3187 OMX_VIDEO_VP8REFERENCEFRAMETYPE* vp8refframe = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) configData;
3188 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoVp8ReferenceFrame");
3189 if ((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
3190 (vp8refframe->bUseGoldenFrame)) {
3191 if(venc_set_useltr(0x1) == false) {
3192 DEBUG_PRINT_ERROR("ERROR: use goldenframe failed");
3193 return false;
3194 }
3195 } else if((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
3196 (vp8refframe->bGoldenFrameRefresh)) {
3197 if(venc_set_markltr(0x1) == false) {
3198 DEBUG_PRINT_ERROR("ERROR: Setting goldenframe failed");
3199 return false;
3200 }
3201 } else {
3202 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoVp8ReferenceFrame");
3203 }
3204 break;
3205 }
3206 case OMX_QcomIndexConfigVideoLTRUse:
3207 {
3208 OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE*)configData;
3209 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRUse");
3210 if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3211 if (venc_set_useltr(pParam->nID) == false) {
3212 DEBUG_PRINT_ERROR("ERROR: Use LTR failed");
3213 return false;
3214 }
3215 } else {
3216 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRUse");
3217 }
3218 break;
3219 }
3220 case OMX_QcomIndexConfigVideoLTRMark:
3221 {
3222 OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE*)configData;
3223 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRMark");
3224 if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3225 if (venc_set_markltr(pParam->nID) == false) {
3226 DEBUG_PRINT_ERROR("ERROR: Mark LTR failed");
3227 return false;
3228 }
3229 } else {
3230 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRMark");
3231 }
3232 break;
3233 }
3234 case OMX_IndexConfigAndroidVideoTemporalLayering:
3235 {
3236 OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pParam =
3237 (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *) configData;
3238 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE temporalParams;
3239
3240 memset(&temporalParams, 0x0, sizeof(temporalParams));
3241 temporalParams.nPLayerCountActual = pParam->nPLayerCountActual;
3242 temporalParams.bBitrateRatiosSpecified = pParam->bBitrateRatiosSpecified;
3243 temporalParams.ePattern = pParam->ePattern;
3244 temporalParams.nLayerCountMax = temporal_layers_config.nMaxLayers;
3245
3246 if (temporalParams.bBitrateRatiosSpecified == OMX_TRUE) {
3247 for (OMX_U32 i = 0; i < temporalParams.nPLayerCountActual; ++i) {
3248 temporalParams.nBitrateRatios[i] = pParam->nBitrateRatios[i];
3249 }
3250 }
3251
3252 if (!venc_validate_temporal_extn(temporalParams)) {
3253 DEBUG_PRINT_ERROR("set_param: Failed to validate temporal settings");
3254 return false;
3255 }
3256
3257 venc_copy_temporal_settings(temporalParams);
3258
3259 // Set temporal layers with these settings
3260 if (!venc_reconfigure_temporal_settings()) {
3261 DEBUG_PRINT_ERROR("Reconfiguring temporal settings failed");
3262 return false;
3263 }
3264
3265 break;
3266 }
3267 case OMX_QcomIndexConfigBaseLayerId:
3268 {
3269 OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID* pParam =
3270 (OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID*) configData;
3271 if (venc_set_baselayerid(pParam->nPID) == false) {
3272 DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigBaseLayerId failed");
3273 return false;
3274 }
3275 break;
3276 }
3277 case OMX_IndexParamAndroidVideoTemporalLayering:
3278 {
3279 DEBUG_PRINT_ERROR("TemporalLayer: Changing layer-configuration dynamically is not supported!");
3280 return false;
3281 }
3282 case OMX_QcomIndexConfigQp:
3283 {
3284 OMX_QCOM_VIDEO_CONFIG_QP* pParam =
3285 (OMX_QCOM_VIDEO_CONFIG_QP*) configData;
3286 DEBUG_PRINT_LOW("Set_config: nQP %d", pParam->nQP);
3287 if (venc_set_qp(pParam->nQP,
3288 pParam->nQP,
3289 pParam->nQP,
3290 ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP ) == false) {
3291 DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigQp failed");
3292 return false;
3293 }
3294 break;
3295 }
3296 case OMX_IndexConfigPriority:
3297 {
3298 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
3299 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
3300 if (!venc_set_priority(priority->nU32)) {
3301 DEBUG_PRINT_ERROR("Failed to set priority");
3302 return false;
3303 }
3304 sess_priority.priority = priority->nU32;
3305 break;
3306 }
3307 case OMX_IndexConfigOperatingRate:
3308 {
3309 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
3310 DEBUG_PRINT_LOW("Set_config: operating rate %u", rate->nU32);
3311 if (!venc_set_operatingrate(rate->nU32)) {
3312 DEBUG_PRINT_ERROR("Failed to set operating rate");
3313 return false;
3314 }
3315 break;
3316 }
3317 case OMX_IndexConfigAndroidIntraRefresh:
3318 {
3319 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intra_refresh_period = (OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)configData;
3320 DEBUG_PRINT_LOW("OMX_IndexConfigAndroidIntraRefresh : num frames = %d", intra_refresh_period->nRefreshPeriod);
3321
3322 if (intra_refresh_period->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
3323 intra_refresh.framecount = intra_refresh_period->nRefreshPeriod;
3324 intra_refresh.irmode = OMX_VIDEO_IntraRefreshMax;
3325 intra_refresh.mbcount = 0;
3326 } else {
3327 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoIntraRefreshType");
3328 }
3329 break;
3330 }
3331 case OMX_QTIIndexConfigVideoBlurResolution:
3332 {
3333 OMX_QTI_VIDEO_CONFIG_BLURINFO *blur = (OMX_QTI_VIDEO_CONFIG_BLURINFO *)configData;
3334 if (blur->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
3335 DEBUG_PRINT_LOW("Set_config: blur resolution: %u", blur->nBlurInfo);
3336 if(!venc_set_blur_resolution(blur)) {
3337 DEBUG_PRINT_ERROR("Failed to set Blur Resolution");
3338 return false;
3339 }
3340 } else {
3341 DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QTIIndexConfigVideoBlurResolution");
3342 return false;
3343 }
3344 break;
3345 }
3346 case OMX_QcomIndexConfigH264Transform8x8:
3347 {
3348 OMX_CONFIG_BOOLEANTYPE *pEnable = (OMX_CONFIG_BOOLEANTYPE *) configData;
3349 DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigH264Transform8x8");
3350 if (venc_h264_transform_8x8(pEnable->bEnabled) == false) {
3351 DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigH264Transform8x8");
3352 return false;
3353 }
3354 break;
3355 }
3356 case OMX_QTIIndexConfigDescribeColorAspects:
3357 {
3358 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
3359
3360 OMX_U32 color_space = MSM_VIDC_BT601_6_625;
3361 OMX_U32 full_range = 0;
3362 OMX_U32 matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
3363 OMX_U32 transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
3364
3365 switch((ColorAspects::Primaries)(params->sAspects.mPrimaries)) {
3366 case ColorAspects::PrimariesBT709_5:
3367 color_space = MSM_VIDC_BT709_5;
3368 break;
3369 case ColorAspects::PrimariesBT470_6M:
3370 color_space = MSM_VIDC_BT470_6_M;
3371 break;
3372 case ColorAspects::PrimariesBT601_6_625:
3373 color_space = MSM_VIDC_BT601_6_625;
3374 break;
3375 case ColorAspects::PrimariesBT601_6_525:
3376 color_space = MSM_VIDC_BT601_6_525;
3377 break;
3378 case ColorAspects::PrimariesGenericFilm:
3379 color_space = MSM_VIDC_GENERIC_FILM;
3380 break;
3381 case ColorAspects::PrimariesBT2020:
3382 color_space = MSM_VIDC_BT2020;
3383 break;
3384 default:
3385 color_space = MSM_VIDC_BT601_6_625;
3386 //params->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
3387 break;
3388 }
3389 switch((ColorAspects::Range)params->sAspects.mRange) {
3390 case ColorAspects::RangeFull:
3391 full_range = 1;
3392 break;
3393 case ColorAspects::RangeLimited:
3394 full_range = 0;
3395 break;
3396 default:
3397 break;
3398 }
3399 switch((ColorAspects::Transfer)params->sAspects.mTransfer) {
3400 case ColorAspects::TransferSMPTE170M:
3401 transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
3402 break;
3403 case ColorAspects::TransferUnspecified:
3404 transfer_chars = MSM_VIDC_TRANSFER_UNSPECIFIED;
3405 break;
3406 case ColorAspects::TransferGamma22:
3407 transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_M;
3408 break;
3409 case ColorAspects::TransferGamma28:
3410 transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_BG;
3411 break;
3412 case ColorAspects::TransferSMPTE240M:
3413 transfer_chars = MSM_VIDC_TRANSFER_SMPTE_240M;
3414 break;
3415 case ColorAspects::TransferLinear:
3416 transfer_chars = MSM_VIDC_TRANSFER_LINEAR;
3417 break;
3418 case ColorAspects::TransferXvYCC:
3419 transfer_chars = MSM_VIDC_TRANSFER_IEC_61966;
3420 break;
3421 case ColorAspects::TransferBT1361:
3422 transfer_chars = MSM_VIDC_TRANSFER_BT_1361;
3423 break;
3424 case ColorAspects::TransferSRGB:
3425 transfer_chars = MSM_VIDC_TRANSFER_SRGB;
3426 break;
3427 default:
3428 //params->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
3429 transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
3430 break;
3431 }
3432 switch((ColorAspects::MatrixCoeffs)params->sAspects.mMatrixCoeffs) {
3433 case ColorAspects::MatrixUnspecified:
3434 matrix_coeffs = MSM_VIDC_MATRIX_UNSPECIFIED;
3435 break;
3436 case ColorAspects::MatrixBT709_5:
3437 matrix_coeffs = MSM_VIDC_MATRIX_BT_709_5;
3438 break;
3439 case ColorAspects::MatrixBT470_6M:
3440 matrix_coeffs = MSM_VIDC_MATRIX_FCC_47;
3441 break;
3442 case ColorAspects::MatrixBT601_6:
3443 matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
3444 break;
3445 case ColorAspects::MatrixSMPTE240M:
3446 matrix_coeffs = MSM_VIDC_MATRIX_SMPTE_240M;
3447 break;
3448 case ColorAspects::MatrixBT2020:
3449 matrix_coeffs = MSM_VIDC_MATRIX_BT_2020;
3450 break;
3451 case ColorAspects::MatrixBT2020Constant:
3452 matrix_coeffs = MSM_VIDC_MATRIX_BT_2020_CONST;
3453 break;
3454 default:
3455 //params->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
3456 matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
3457 break;
3458 }
3459 if (!venc_set_colorspace(color_space, full_range,
3460 transfer_chars, matrix_coeffs)) {
3461
3462 DEBUG_PRINT_ERROR("Failed to set operating rate");
3463 return false;
3464 }
3465 break;
3466 }
3467 case OMX_QTIIndexConfigVideoRoiInfo:
3468 {
3469 if(!venc_set_roi_qp_info((OMX_QTI_VIDEO_CONFIG_ROIINFO *)configData)) {
3470 DEBUG_PRINT_ERROR("Failed to set ROI QP info");
3471 return false;
3472 }
3473 break;
3474 }
3475 case OMX_IndexConfigVideoNalSize:
3476 {
3477 if(!venc_set_nal_size((OMX_VIDEO_CONFIG_NALSIZE *)configData)) {
3478 DEBUG_PRINT_LOW("Failed to set Nal size info");
3479 return false;
3480 }
3481 break;
3482 }
3483 case OMX_QTIIndexConfigVideoRoiRectRegionInfo:
3484 {
3485 if(!venc_set_roi_region_qp_info((OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *)configData)) {
3486 DEBUG_PRINT_ERROR("Failed to set ROI Region QP info");
3487 return false;
3488 }
3489 break;
3490 }
3491 default:
3492 DEBUG_PRINT_ERROR("Unsupported config index = %u", index);
3493 break;
3494 }
3495
3496 return true;
3497 }
3498
venc_handle_empty_eos_buffer(void)3499 bool venc_dev::venc_handle_empty_eos_buffer( void)
3500 {
3501 struct v4l2_encoder_cmd enc;
3502 int rc = 0;
3503
3504 if (!streaming[OUTPUT_PORT]) {
3505 enum v4l2_buf_type buf_type;
3506 struct v4l2_control control;
3507 int ret = 0;
3508
3509 /* If first ETB is an EOS with 0 filled length there is a limitation */
3510 /* for which we need to combine sequence header with 1st frame */
3511 control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
3512 control.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME;
3513 DEBUG_PRINT_LOW("Combining sequence header with 1st frame ");
3514 ret = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3515 if (ret) {
3516 DEBUG_PRINT_ERROR("Failed to set header mode");
3517 return false;
3518 }
3519
3520 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3521
3522 DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
3523 ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
3524 if (ret) {
3525 DEBUG_PRINT_ERROR("Failed to call streamon");
3526 if (errno == EBUSY) {
3527 hw_overload = true;
3528 }
3529 return false;
3530 } else {
3531 streaming[OUTPUT_PORT] = true;
3532 }
3533 }
3534
3535 memset(&enc, 0, sizeof(enc));
3536 enc.cmd = V4L2_ENC_CMD_STOP;
3537 DEBUG_PRINT_LOW("Sending : Encoder STOP comamnd");
3538 rc = ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc);
3539 if (rc) {
3540 DEBUG_PRINT_ERROR("Failed : Encoder STOP comamnd");
3541 return false;
3542 }
3543 return true;
3544 }
3545
venc_stop(void)3546 unsigned venc_dev::venc_stop( void)
3547 {
3548 struct venc_msg venc_msg;
3549 struct v4l2_requestbuffers bufreq;
3550 int rc = 0, ret = 0;
3551
3552 if (!stopped) {
3553 enum v4l2_buf_type cap_type;
3554
3555 if (streaming[OUTPUT_PORT]) {
3556 cap_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3557 rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
3558
3559 if (rc) {
3560 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
3561 cap_type, rc);
3562 } else
3563 streaming[OUTPUT_PORT] = false;
3564
3565 DEBUG_PRINT_LOW("Releasing registered buffers from driver on o/p port");
3566 bufreq.memory = V4L2_MEMORY_USERPTR;
3567 bufreq.count = 0;
3568 bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3569 ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
3570
3571 if (ret) {
3572 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS OUTPUT MPLANE Failed");
3573 return false;
3574 }
3575 }
3576
3577 if (!rc && streaming[CAPTURE_PORT]) {
3578 cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3579 rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &cap_type);
3580
3581 if (rc) {
3582 DEBUG_PRINT_ERROR("Failed to call streamoff on driver: capability: %d, %d",
3583 cap_type, rc);
3584 } else
3585 streaming[CAPTURE_PORT] = false;
3586
3587 DEBUG_PRINT_LOW("Releasing registered buffers from driver on capture port");
3588 bufreq.memory = V4L2_MEMORY_USERPTR;
3589 bufreq.count = 0;
3590 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3591 ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq);
3592
3593 if (ret) {
3594 DEBUG_PRINT_ERROR("ERROR: VIDIOC_REQBUFS CAPTURE MPLANE Failed");
3595 return false;
3596 }
3597 }
3598
3599 if (!rc && !ret) {
3600 venc_stop_done();
3601 stopped = 1;
3602 /*set flag to re-configure when started again*/
3603 resume_in_stopped = 1;
3604 }
3605 }
3606
3607 return rc;
3608 }
3609
is_streamon_done(OMX_U32 port)3610 bool venc_dev::is_streamon_done(OMX_U32 port)
3611 {
3612 return streaming[port];
3613 }
3614
venc_pause(void)3615 unsigned venc_dev::venc_pause(void)
3616 {
3617 pthread_mutex_lock(&pause_resume_mlock);
3618 paused = true;
3619 pthread_mutex_unlock(&pause_resume_mlock);
3620 return 0;
3621 }
3622
venc_resume(void)3623 unsigned venc_dev::venc_resume(void)
3624 {
3625 pthread_mutex_lock(&pause_resume_mlock);
3626 paused = false;
3627 pthread_mutex_unlock(&pause_resume_mlock);
3628
3629 return pthread_cond_signal(&pause_resume_cond);
3630 }
3631
venc_start_done(void)3632 unsigned venc_dev::venc_start_done(void)
3633 {
3634 struct venc_msg venc_msg;
3635 venc_msg.msgcode = VEN_MSG_START;
3636 venc_msg.statuscode = VEN_S_SUCCESS;
3637 venc_handle->async_message_process(venc_handle,&venc_msg);
3638 return 0;
3639 }
3640
venc_stop_done(void)3641 unsigned venc_dev::venc_stop_done(void)
3642 {
3643 struct venc_msg venc_msg;
3644 free_extradata_all();
3645 venc_msg.msgcode=VEN_MSG_STOP;
3646 venc_msg.statuscode=VEN_S_SUCCESS;
3647 venc_handle->async_message_process(venc_handle,&venc_msg);
3648 return 0;
3649 }
3650
venc_set_message_thread_id(pthread_t tid)3651 unsigned venc_dev::venc_set_message_thread_id(pthread_t tid)
3652 {
3653 async_thread_created = true;
3654 m_tid=tid;
3655 return 0;
3656 }
3657
venc_set_vqzip_defaults()3658 bool venc_dev::venc_set_vqzip_defaults()
3659 {
3660 struct v4l2_control control;
3661 int rc = 0, num_mbs_per_frame;
3662
3663 num_mbs_per_frame = m_sVenc_cfg.input_height * m_sVenc_cfg.input_width;
3664
3665 switch (num_mbs_per_frame) {
3666 case OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT:
3667 case OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT:
3668 case OMX_CORE_4KUHD_WIDTH * OMX_CORE_4KUHD_HEIGHT:
3669 case OMX_CORE_4KDCI_WIDTH * OMX_CORE_4KDCI_HEIGHT:
3670 break;
3671 default:
3672 DEBUG_PRINT_ERROR("VQZIP is not supported for this resoultion : %lu X %lu",
3673 m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
3674 return false;
3675 }
3676
3677 control.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
3678 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF;
3679 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3680 if (rc)
3681 DEBUG_PRINT_ERROR("Failed to set Rate Control OFF for VQZIP");
3682
3683 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
3684 control.value = INT_MAX;
3685
3686 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3687 if (rc)
3688 DEBUG_PRINT_ERROR("Failed to set P frame period for VQZIP");
3689
3690 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
3691 control.value = 0;
3692
3693 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3694 if (rc)
3695 DEBUG_PRINT_ERROR("Failed to set B frame period for VQZIP");
3696
3697 control.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
3698 control.value = 1;
3699
3700 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
3701 if (rc)
3702 DEBUG_PRINT_ERROR("Failed to set IDR period for VQZIP");
3703
3704 return true;
3705 }
venc_set_extradata_hdr10metadata()3706 bool venc_dev::venc_set_extradata_hdr10metadata()
3707 {
3708 struct v4l2_control control;
3709
3710 /* HDR10 Metadata is enabled by default for HEVC Main10 profile. */
3711 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC &&
3712 codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) {
3713
3714 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
3715 control.value = V4L2_MPEG_VIDC_EXTRADATA_HDR10PLUS_METADATA;
3716
3717 DEBUG_PRINT_HIGH("venc_set_extradata:: HDR10PLUS_METADATA");
3718
3719 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
3720 DEBUG_PRINT_ERROR("ERROR: Set extradata HDR10PLUS_METADATA failed %d", errno);
3721 return false;
3722 }
3723 m_hdr10meta_enabled = true;
3724 extradata = true;
3725
3726 //Get upated buffer requirement as enable extradata leads to two buffer planes
3727 venc_get_buf_req (&venc_handle->m_sInPortDef.nBufferCountMin,
3728 &venc_handle->m_sInPortDef.nBufferCountActual,
3729 &venc_handle->m_sInPortDef.nBufferSize,
3730 venc_handle->m_sInPortDef.nPortIndex);
3731 }
3732
3733 return true;
3734 }
3735
venc_start(void)3736 unsigned venc_dev::venc_start(void)
3737 {
3738 enum v4l2_buf_type buf_type;
3739 int ret, r;
3740 struct v4l2_control control;
3741
3742 memset(&control, 0, sizeof(control));
3743
3744 if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults())
3745 return 1;
3746
3747 if (!venc_set_priority(sess_priority.priority)) {
3748 DEBUG_PRINT_ERROR("Failed to set priority");
3749 return 1;
3750 }
3751 // Client can set intra refresh period in terms of frames.
3752 // This requires reconfiguration on port redefinition as
3753 // mbcount for IR depends on encode resolution.
3754 if (!venc_reconfigure_intra_refresh_period()) {
3755 DEBUG_PRINT_ERROR("Reconfiguring intra refresh period failed");
3756 return 1;
3757 }
3758
3759 if (!venc_reconfigure_intra_period()) {
3760 DEBUG_PRINT_ERROR("Reconfiguring intra period failed");
3761 return 1;
3762 }
3763
3764 // re-configure the temporal layers as RC-mode and key-frame interval
3765 // might have changed since the client last configured the layers.
3766 if (!venc_reconfigure_temporal_settings()) {
3767 DEBUG_PRINT_ERROR("Reconfiguring temporal settings failed");
3768 return 1;
3769 }
3770
3771 // Note HP settings could change GOP structure
3772 if (!venc_set_intra_period(intra_period.num_pframes, intra_period.num_bframes)) {
3773 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set nPframes/nBframes");
3774 return OMX_ErrorUndefined;
3775 }
3776
3777 // If Hybrid HP is enable, LTR needs to be reset
3778 if (!venc_reconfigure_ltrmode()) {
3779 DEBUG_PRINT_ERROR("Reconfiguring LTR mode failed");
3780 return 1;
3781 }
3782
3783 if (hdr10metadata_supported == true) {
3784 venc_set_extradata_hdr10metadata();
3785 }
3786
3787 venc_config_print();
3788
3789 /* set buffercount before start */
3790 venc_reconfig_reqbufs();
3791 resume_in_stopped = 0;
3792
3793 /* Check if slice_delivery mode is enabled & max slices is sufficient for encoding complete frame */
3794 if (slice_mode.enable && multislice.mslice_size &&
3795 (m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)/(256 * multislice.mslice_size) >= MAX_SUPPORTED_SLICES_PER_FRAME) {
3796 DEBUG_PRINT_ERROR("slice_mode: %lu, max slices (%lu) should be less than (%d)", slice_mode.enable,
3797 (m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)/(256 * multislice.mslice_size),
3798 MAX_SUPPORTED_SLICES_PER_FRAME);
3799 return 1;
3800 }
3801
3802 if (m_codec == OMX_VIDEO_CodingImageHEIC && mIsGridset) {
3803 struct v4l2_format fmt;
3804 memset(&fmt, 0, sizeof(fmt));
3805 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3806 fmt.fmt.pix_mp.height = DEFAULT_TILE_DIMENSION;
3807 fmt.fmt.pix_mp.width = DEFAULT_TILE_DIMENSION;
3808 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
3809 DEBUG_PRINT_INFO("set format type %d, wxh %dx%d, pixelformat %#x",
3810 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
3811 fmt.fmt.pix_mp.pixelformat);
3812 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
3813 DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x",
3814 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
3815 fmt.fmt.pix_mp.pixelformat);
3816 hw_overload = errno == EBUSY;
3817 return false;
3818 }
3819 }
3820
3821 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3822 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
3823 ret=ioctl(m_nDriver_fd, VIDIOC_STREAMON,&buf_type);
3824
3825 if (ret)
3826 return 1;
3827
3828 streaming[CAPTURE_PORT] = true;
3829
3830 stopped = 0;
3831 return 0;
3832 }
3833
hiermode_string(int val)3834 inline const char* hiermode_string(int val)
3835 {
3836 switch(val)
3837 {
3838 case HIER_NONE:
3839 return "No Hier";
3840 case HIER_P:
3841 return "Hier-P";
3842 case HIER_B:
3843 return "Hier-B";
3844 case HIER_P_HYBRID:
3845 return "Hybrid Hier-P";
3846 default:
3847 return "No hier";
3848 }
3849 }
3850
bitrate_type_string(int val)3851 inline const char* bitrate_type_string(int val)
3852 {
3853 switch(val)
3854 {
3855 case V4L2_MPEG_MSM_VIDC_DISABLE:
3856 return "CUMULATIVE";
3857 case V4L2_MPEG_MSM_VIDC_ENABLE:
3858 return "LAYER WISE";
3859 default:
3860 return "Unknown Bitrate Type";
3861 }
3862 }
3863
codec_as_string(unsigned long codec)3864 static const char *codec_as_string(unsigned long codec) {
3865 switch (codec) {
3866 case V4L2_PIX_FMT_H264:
3867 return "H264";
3868 case V4L2_PIX_FMT_HEVC:
3869 return "HEVC";
3870 case V4L2_PIX_FMT_VP8:
3871 return "VP8";
3872 default:
3873 return "UNKOWN";
3874 }
3875 }
3876
venc_config_print()3877 void venc_dev::venc_config_print()
3878 {
3879
3880 DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %s, Profile %ld, level : %ld",
3881 codec_as_string(m_sVenc_cfg.codectype), codec_profile.profile, profile_level.level);
3882
3883 DEBUG_PRINT_HIGH("ENC_CONFIG: Input Width: %ld, Height:%ld, Fps: %ld",
3884 m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
3885 m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
3886
3887 DEBUG_PRINT_HIGH("ENC_CONFIG: Output Width: %ld, Height:%ld, Fps: %ld",
3888 m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
3889 m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
3890
3891 DEBUG_PRINT_HIGH("ENC_CONFIG: Color Space: Primaries = %u, Range = %u, Transfer Chars = %u, Matrix Coeffs = %u",
3892 color_space.primaries, color_space.range, color_space.transfer_chars, color_space.matrix_coeffs);
3893
3894 DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld",
3895 bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes);
3896
3897 DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %ld, qpP: %ld, qpb: %ld enableqp : %ld",
3898 session_qp.iframeqp, session_qp.pframeqp, session_qp.bframeqp, session_qp.enableqp);
3899
3900 DEBUG_PRINT_HIGH("ENC_CONFIG: minIQP: %lu, maxIQP: %lu minPQP : %lu maxPQP : %lu minBQP : %lu maxBQP : %lu",
3901 session_ipb_qp_values.min_i_qp, session_ipb_qp_values.max_i_qp,
3902 session_ipb_qp_values.min_p_qp, session_ipb_qp_values.max_p_qp,
3903 session_ipb_qp_values.min_b_qp, session_ipb_qp_values.max_b_qp);
3904
3905 DEBUG_PRINT_HIGH("ENC_CONFIG: VOP_Resolution: %ld, Slice-Mode: %ld, Slize_Size: %ld",
3906 voptimecfg.voptime_resolution, multislice.mslice_mode,
3907 multislice.mslice_size);
3908
3909 DEBUG_PRINT_HIGH("ENC_CONFIG: EntropyMode: %d, CabacModel: %ld",
3910 entropy.longentropysel, entropy.cabacmodel);
3911
3912 DEBUG_PRINT_HIGH("ENC_CONFIG: DB-Mode: %ld, alpha: %ld, Beta: %ld",
3913 dbkfilter.db_mode, dbkfilter.slicealpha_offset,
3914 dbkfilter.slicebeta_offset);
3915
3916 DEBUG_PRINT_HIGH("ENC_CONFIG: HEC: %ld, IDR Period: %ld",
3917 hec.header_extension, idrperiod.idrperiod);
3918
3919 DEBUG_PRINT_HIGH("ENC_CONFIG: LTR Enabled: %d, Count: %d",
3920 ltrinfo.enabled, ltrinfo.count);
3921
3922 if (temporal_layers_config.nPLayers) {
3923 DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: P-layers: %u, B-layers: %u, Adjusted I-frame-interval: %lu",
3924 temporal_layers_config.nPLayers, temporal_layers_config.nBLayers,
3925 intra_period.num_pframes + intra_period.num_bframes + 1);
3926
3927 for (OMX_U32 l = 0; temporal_layers_config.bIsBitrateRatioValid
3928 && (l < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers); ++l) {
3929 DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: layer[%d] bitrate %% = %u%%",
3930 l, temporal_layers_config.nTemporalLayerBitrateFraction[l]);
3931 }
3932 } else {
3933
3934 DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d",
3935 temporal_layers_config.nPLayers, hiermode_string(temporal_layers_config.hier_mode), vpx_err_resilience.enable);
3936
3937 DEBUG_PRINT_HIGH("ENC_CONFIG: Hier params: Frame Interval : %d, MinQP: %d, Max_QP: %d",
3938 temporal_layers_config.nKeyFrameInterval, temporal_layers_config.nMinQuantizer, temporal_layers_config.nMaxQuantizer);
3939
3940 DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layer0: %d, Layer1: %d, Later2: %d, Layer3: %d, Layer4: %d, Layer5: %d",
3941 temporal_layers_config.nTemporalLayerBitrateRatio[0], temporal_layers_config.nTemporalLayerBitrateRatio[1],
3942 temporal_layers_config.nTemporalLayerBitrateRatio[2], temporal_layers_config.nTemporalLayerBitrateRatio[3],
3943 temporal_layers_config.nTemporalLayerBitrateRatio[4], temporal_layers_config.nTemporalLayerBitrateRatio[5]);
3944 }
3945
3946 DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled);
3947
3948 DEBUG_PRINT_HIGH("ENC_CONFIG: Peak bitrate: %d", peak_bitrate.peakbitrate);
3949
3950 DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %s", sess_priority.priority ? "NonRealTime" : "RealTime");
3951
3952 DEBUG_PRINT_HIGH("ENC_CONFIG: ROI : %u", m_roi_enabled);
3953
3954 DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate);
3955 }
3956
venc_reconfig_reqbufs()3957 bool venc_dev::venc_reconfig_reqbufs()
3958 {
3959 struct v4l2_requestbuffers bufreq;
3960
3961 DEBUG_PRINT_HIGH("venc_reconfig_reqbufs: output_mplane %lu, capture_mplane %lu",
3962 m_sInput_buff_property.actualcount, m_sOutput_buff_property.actualcount);
3963
3964 bufreq.memory = V4L2_MEMORY_USERPTR;
3965 bufreq.count = m_sInput_buff_property.actualcount;
3966 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3967 if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
3968 DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: OUTPUT_MPLANE (count %d) failed", bufreq.count);
3969 return false;
3970 }
3971
3972 bufreq.memory = V4L2_MEMORY_USERPTR;
3973 bufreq.count = m_sOutput_buff_property.actualcount;
3974 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3975 if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
3976 DEBUG_PRINT_ERROR("VIDIOC_REQBUFS: CAPTURE_MPLANE (count %d) failed", bufreq.count);
3977 return false;
3978 }
3979 return true;
3980 }
3981
venc_flush(unsigned port)3982 unsigned venc_dev::venc_flush( unsigned port)
3983 {
3984 struct v4l2_encoder_cmd enc;
3985 DEBUG_PRINT_LOW("in %s", __func__);
3986
3987 for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
3988 fd_list[i] = 0;
3989 }
3990
3991 enc.cmd = V4L2_QCOM_CMD_FLUSH;
3992 enc.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT | V4L2_QCOM_CMD_FLUSH_CAPTURE;
3993
3994 if (ioctl(m_nDriver_fd, VIDIOC_ENCODER_CMD, &enc)) {
3995 DEBUG_PRINT_ERROR("Flush Port (%d) Failed ", port);
3996 return -1;
3997 }
3998
3999 return 0;
4000 }
4001
4002 //allocating I/P memory from pmem and register with the device
allocate_extradata(unsigned port)4003 bool venc_dev::allocate_extradata(unsigned port)
4004 {
4005 int rc = 0;
4006 unsigned int extra_idx = 0;
4007
4008 // PORT_INDEX_IN = 0
4009 // PORT_INDEX_OUT = 1
4010 struct port_info_s {
4011 int num_planes;
4012 struct extradata_buffer_info *extradata_info;
4013 int flag;
4014 }port_info[2] = {
4015 {
4016 .num_planes = num_input_planes,
4017 .extradata_info = &input_extradata_info,
4018 .flag = 0
4019 },
4020 {
4021 .num_planes = num_output_planes,
4022 .extradata_info = &output_extradata_info,
4023 .flag = 0
4024 }
4025 };
4026
4027 if (port != PORT_INDEX_IN && port != PORT_INDEX_OUT) {
4028 DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index ");
4029 return false;
4030 }
4031
4032 extra_idx = EXTRADATA_IDX(port_info[port].num_planes);
4033 if ((port_info[port].num_planes > 1) && (extra_idx)) {
4034 rc = allocate_extradata(port_info[port].extradata_info,
4035 port_info[port].flag);
4036 if (rc) {
4037 DEBUG_PRINT_ERROR("Failed to allocate extradata: %d\n", rc);
4038 return false;
4039 }
4040 }
4041
4042 return true;
4043 }
4044
venc_free_buf(void * buf_addr,unsigned port)4045 bool venc_dev::venc_free_buf(void *buf_addr, unsigned port)
4046 {
4047 struct pmem *pmem_tmp;
4048 struct venc_bufferpayload dev_buffer;
4049
4050 memset(&dev_buffer, 0, sizeof(dev_buffer));
4051 pmem_tmp = (struct pmem *)buf_addr;
4052
4053 if (port == PORT_INDEX_IN) {
4054 dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
4055 dev_buffer.fd = pmem_tmp->fd;
4056 dev_buffer.maped_size = pmem_tmp->size;
4057 dev_buffer.sz = pmem_tmp->size;
4058 dev_buffer.offset = pmem_tmp->offset;
4059 DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
4060 dev_buffer.pbuffer, \
4061 dev_buffer.fd, \
4062 dev_buffer.offset, \
4063 dev_buffer.maped_size);
4064
4065 } else if (port == PORT_INDEX_OUT) {
4066 dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
4067 dev_buffer.fd = pmem_tmp->fd;
4068 dev_buffer.sz = pmem_tmp->size;
4069 dev_buffer.maped_size = pmem_tmp->size;
4070 dev_buffer.offset = pmem_tmp->offset;
4071
4072 DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %p,fd = %x, offset = %d, maped_size = %d", \
4073 dev_buffer.pbuffer, \
4074 dev_buffer.fd, \
4075 dev_buffer.offset, \
4076 dev_buffer.maped_size);
4077 } else {
4078 DEBUG_PRINT_ERROR("ERROR: venc_free_buf:Invalid Port Index ");
4079 return false;
4080 }
4081
4082 return true;
4083 }
4084
venc_color_align(OMX_BUFFERHEADERTYPE * buffer,OMX_U32 width,OMX_U32 height)4085 bool venc_dev::venc_color_align(OMX_BUFFERHEADERTYPE *buffer,
4086 OMX_U32 width, OMX_U32 height)
4087 {
4088 OMX_U32 y_stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width),
4089 y_scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height),
4090 uv_stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, width),
4091 uv_scanlines = VENUS_UV_SCANLINES(COLOR_FMT_NV12, height),
4092 src_chroma_offset = width * height;
4093
4094 if (buffer->nAllocLen >= VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height)) {
4095 OMX_U8* src_buf = buffer->pBuffer, *dst_buf = buffer->pBuffer;
4096 //Do chroma first, so that we can convert it in-place
4097 src_buf += width * height;
4098 dst_buf += y_stride * y_scanlines;
4099 for (int line = height / 2 - 1; line >= 0; --line) {
4100 /* Align the length to 16 for better memove performance. */
4101 memmove(dst_buf + line * uv_stride,
4102 src_buf + line * width,
4103 ALIGN(width, 16));
4104 }
4105
4106 dst_buf = src_buf = buffer->pBuffer;
4107 //Copy the Y next
4108 for (int line = height - 1; line > 0; --line) {
4109 /* Align the length to 16 for better memove performance. */
4110 memmove(dst_buf + line * y_stride,
4111 src_buf + line * width,
4112 ALIGN(width, 16));
4113 }
4114 /* Inform driver to do cache flush on total buffer */
4115 buffer->nFilledLen = buffer->nAllocLen;
4116 } else {
4117 DEBUG_PRINT_ERROR("Failed to align Chroma. from %u to %u : \
4118 Insufficient bufferLen=%u v/s Required=%u",
4119 (unsigned int)(width*height), (unsigned int)src_chroma_offset, (unsigned int)buffer->nAllocLen,
4120 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height));
4121 return false;
4122 }
4123
4124 return true;
4125 }
4126
venc_get_vui_timing_info(OMX_U32 * enabled)4127 bool venc_dev::venc_get_vui_timing_info(OMX_U32 *enabled)
4128 {
4129 if (!enabled) {
4130 DEBUG_PRINT_ERROR("Null pointer error");
4131 return false;
4132 } else {
4133 *enabled = vui_timing_info.enabled;
4134 return true;
4135 }
4136 }
4137
venc_get_vqzip_sei_info(OMX_U32 * enabled)4138 bool venc_dev::venc_get_vqzip_sei_info(OMX_U32 *enabled)
4139 {
4140 if (!enabled) {
4141 DEBUG_PRINT_ERROR("Null pointer error");
4142 return false;
4143 } else {
4144 *enabled = vqzip_sei_info.enabled;
4145 return true;
4146 }
4147 }
4148
venc_get_peak_bitrate(OMX_U32 * peakbitrate)4149 bool venc_dev::venc_get_peak_bitrate(OMX_U32 *peakbitrate)
4150 {
4151 if (!peakbitrate) {
4152 DEBUG_PRINT_ERROR("Null pointer error");
4153 return false;
4154 } else {
4155 *peakbitrate = peak_bitrate.peakbitrate;
4156 return true;
4157 }
4158 }
4159
venc_get_batch_size(OMX_U32 * size)4160 bool venc_dev::venc_get_batch_size(OMX_U32 *size)
4161 {
4162 if (!size) {
4163 DEBUG_PRINT_ERROR("Null pointer error");
4164 return false;
4165 } else {
4166 *size = mBatchSize;
4167 return true;
4168 }
4169 }
4170
4171
venc_empty_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)4172 bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, unsigned fd)
4173 {
4174 struct pmem *temp_buffer;
4175 struct v4l2_buffer buf;
4176 struct v4l2_requestbuffers bufreq;
4177 struct v4l2_plane plane[VIDEO_MAX_PLANES];
4178 int rc = 0, extra_idx, c2d_enabled = 0;
4179 bool interlace_flag = false;
4180 struct OMX_BUFFERHEADERTYPE *bufhdr;
4181 LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
4182 temp_buffer = (struct pmem *)buffer;
4183
4184 memset (&buf, 0, sizeof(buf));
4185 memset (&plane, 0, sizeof(plane));
4186
4187 if (buffer == NULL) {
4188 DEBUG_PRINT_ERROR("ERROR: venc_etb: buffer is NULL");
4189 return false;
4190 }
4191
4192 bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
4193 bufreq.memory = V4L2_MEMORY_USERPTR;
4194 bufreq.count = m_sInput_buff_property.actualcount;
4195 bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4196
4197 DEBUG_PRINT_LOW("Input buffer length %u, Timestamp = %lld", (unsigned int)bufhdr->nFilledLen, bufhdr->nTimeStamp);
4198
4199 if (pmem_data_buf) {
4200 DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
4201 plane[0].m.userptr = (unsigned long)pmem_data_buf;
4202 plane[0].data_offset = bufhdr->nOffset;
4203 plane[0].length = bufhdr->nAllocLen;
4204 plane[0].bytesused = bufhdr->nFilledLen;
4205 } else {
4206 // --------------------------------------------------------------------------------------
4207 // [Usage] [metadatamode] [Type] [color_format] [Where is buffer info]
4208 // ---------------------------------------------------------------------------------------
4209 // Camera-2 1 CameraSource 0 meta-handle
4210 // Camera-3 1 GrallocSource 0 gralloc-private-handle
4211 // surface encode (RBG) 1 GrallocSource 1 bufhdr (color-converted)
4212 // CPU (Eg: MediaCodec) 0 -- 0 bufhdr
4213 // ---------------------------------------------------------------------------------------
4214 if (metadatamode) {
4215 plane[0].m.userptr = index;
4216 meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
4217
4218 if (!meta_buf) {
4219 if (!bufhdr->nFilledLen) {
4220 if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS) {
4221 DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
4222 DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
4223 return false;
4224 }
4225 DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
4226 return false;
4227 }
4228 } else if (!color_format) { // Metadata mode
4229
4230 if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
4231 native_handle_t *hnd = (native_handle_t*)meta_buf->meta_handle;
4232 if (!hnd) {
4233 DEBUG_PRINT_ERROR("ERROR: venc_etb: handle is NULL");
4234 return false;
4235 }
4236 int usage = 0;
4237 usage = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_USAGE);
4238 usage = usage > 0 ? usage : 0;
4239
4240 if (!streaming[OUTPUT_PORT] && !(m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGB32 ||
4241 m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGBA8888_UBWC)) {
4242
4243 unsigned int is_csc_enabled = 0;
4244 struct v4l2_format fmt;
4245 OMX_COLOR_FORMATTYPE color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
4246
4247 color_format = (OMX_COLOR_FORMATTYPE)MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_COLORFORMAT);
4248
4249 memset(&fmt, 0, sizeof(fmt));
4250 if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709 ||
4251 usage & private_handle_t::PRIV_FLAGS_ITU_R_601) {
4252 DEBUG_PRINT_ERROR("Camera buffer color format is not 601_FR.");
4253 DEBUG_PRINT_ERROR(" This leads to unknown color space");
4254 }
4255 if (usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) {
4256 if (is_csc_enabled) {
4257 struct v4l2_control control;
4258 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
4259 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4260 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4261 DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC for 601_to_709");
4262 } else {
4263 DEBUG_PRINT_INFO("venc_empty_buf: Will convert 601-FR to 709");
4264 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
4265 venc_set_colorspace(MSM_VIDC_BT709_5, 0,
4266 MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
4267 }
4268 } else {
4269 venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
4270 MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
4271 fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
4272 }
4273 }
4274 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4275 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
4276 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
4277 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
4278 if (usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
4279 usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) {
4280 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
4281 }
4282
4283 if (color_format > 0 && !venc_set_color_format(color_format)) {
4284 DEBUG_PRINT_ERROR("Failed setting color format in Camerasource %lx", m_sVenc_cfg.inputformat);
4285 return false;
4286 }
4287
4288 if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
4289 DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
4290 return false;
4291 }
4292 }
4293
4294 // Setting batch mode is sticky. We do not expect camera to change
4295 // between batch and normal modes at runtime.
4296 if (mBatchSize) {
4297 if ((unsigned int)MetaBufferUtil::getBatchSize(hnd) != mBatchSize) {
4298 DEBUG_PRINT_ERROR("Don't support dynamic batch sizes (changed from %d->%d)",
4299 mBatchSize, MetaBufferUtil::getBatchSize(hnd));
4300 return false;
4301 }
4302
4303 return venc_empty_batch ((OMX_BUFFERHEADERTYPE*)buffer, index);
4304 }
4305
4306 int offset = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_OFFSET);
4307 int length = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_SIZE);
4308 if (offset < 0 || length < 0) {
4309 DEBUG_PRINT_ERROR("Invalid meta buffer handle!");
4310 return false;
4311 }
4312 plane[0].data_offset = offset;
4313 plane[0].length = length;
4314 plane[0].bytesused = length;
4315 DEBUG_PRINT_LOW("venc_empty_buf: camera buf: fd = %d filled %d of %d flag 0x%x format 0x%lx",
4316 fd, plane[0].bytesused, plane[0].length, buf.flags, m_sVenc_cfg.inputformat);
4317 } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
4318 VideoGrallocMetadata *meta_buf = (VideoGrallocMetadata *)bufhdr->pBuffer;
4319 private_handle_t *handle = (private_handle_t *)meta_buf->pHandle;
4320
4321 if (!handle) {
4322 DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
4323 return false;
4324 }
4325 interlace_flag = is_ubwc_interlaced(handle);
4326
4327 if (mUseAVTimerTimestamps) {
4328 uint64_t avTimerTimestampNs = bufhdr->nTimeStamp * 1000;
4329 if (getMetaData(handle, GET_VT_TIMESTAMP, &avTimerTimestampNs) == 0
4330 && avTimerTimestampNs > 0) {
4331 bufhdr->nTimeStamp = avTimerTimestampNs / 1000;
4332 DEBUG_PRINT_LOW("AVTimer TS : %llu us", (unsigned long long)bufhdr->nTimeStamp);
4333 }
4334 }
4335
4336 if (!streaming[OUTPUT_PORT]) {
4337 // Moment of truth... actual colorspace is known here..
4338 if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
4339 DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData colorPrimaries=%d colorRange=%d "
4340 "transfer=%d matrixcoefficients=%d"
4341 "dynamicMetaDataValid %u dynamicMetaDataLen %u",
4342 colorData.colorPrimaries, colorData.range,
4343 colorData.transfer, colorData.matrixCoefficients,
4344 colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
4345 }
4346
4347 struct v4l2_format fmt;
4348 memset(&fmt, 0, sizeof(fmt));
4349 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4350
4351 bool isUBWC = ((handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
4352 handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) &&
4353 is_gralloc_source_ubwc);
4354
4355 char grallocFormatStr[200];
4356 get_gralloc_format_as_string(grallocFormatStr, sizeof(grallocFormatStr), handle->format);
4357 DEBUG_PRINT_LOW("gralloc format 0x%x (%s) (%s)",
4358 handle->format, grallocFormatStr, isUBWC ? "UBWC" : "Linear");
4359
4360 if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) {
4361 m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_NV12_UBWC : V4L2_PIX_FMT_NV12;
4362 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 %s", isUBWC ? "UBWC" : "Linear");
4363 } else if (handle->format == HAL_PIXEL_FORMAT_NV12_HEIF) {
4364 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
4365 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_512");
4366 } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC) {
4367 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
4368 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12_UBWC");
4369 } else if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) {
4370 // In case of RGB, conversion to YUV is handled within encoder.
4371 // Disregard the Colorspace in gralloc-handle in case of RGB and use
4372 // [a] 601 for non-UBWC case : C2D output is (apparently) 601-LR
4373 // [b] 601 for UBWC case : Venus can convert to 601-LR or FR. use LR for now.
4374 //set colormetadata corresponding to ITU_R_601;
4375 colorData.colorPrimaries = ColorPrimaries_BT601_6_525;
4376 colorData.range = Range_Limited;
4377 colorData.transfer = Transfer_SMPTE_170M;
4378 colorData.matrixCoefficients = MatrixCoEff_BT601_6_525;
4379 m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_RGBA8888_UBWC : V4L2_PIX_FMT_RGB32;
4380 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = RGBA8888 %s", isUBWC ? "UBWC" : "Linear");
4381 } else if (handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
4382 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
4383 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 Linear");
4384 } else if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC ||
4385 handle->format == HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS) {
4386 if ((m_codec == OMX_VIDEO_CodingHEVC) &&
4387 (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10)) {
4388 m_sVenc_cfg.inputformat =
4389 (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC)?
4390 V4L2_PIX_FMT_NV12_TP10_UBWC :
4391 V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
4392 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = 10bit");
4393 } else {
4394 DEBUG_PRINT_ERROR("ENC_CONFIG: 10bit colorformat not supported for this codec and profile");
4395 return false;
4396 }
4397
4398 if(colorData.masteringDisplayInfo.colorVolumeSEIEnabled ||
4399 colorData.contentLightLevel.lightLevelSEIEnabled) {
4400 if (!venc_set_hdr_info(colorData.masteringDisplayInfo, colorData.contentLightLevel)) {
4401 DEBUG_PRINT_ERROR("HDR10-PQ Info Setting failed");
4402 return false;
4403 } else {
4404 DEBUG_PRINT_INFO("Encoding in HDR10-PQ mode");
4405 }
4406 } else {
4407 DEBUG_PRINT_INFO("Encoding in HLG mode");
4408 }
4409 } else if (handle->format == QOMX_COLOR_FormatYVU420SemiPlanar) {
4410 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
4411 DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV21 Linear");
4412 } else {
4413 DEBUG_PRINT_ERROR("Color format is not recoganized. Format 0x%X", handle->format);
4414 return false;
4415 }
4416
4417 DEBUG_PRINT_INFO("color_space.primaries %d colorData.colorPrimaries %d, is_csc_custom_matrix_enabled=%d",
4418 color_space.primaries, colorData.colorPrimaries, is_csc_custom_matrix_enabled);
4419
4420 if (csc_enable) {
4421 struct v4l2_control control;
4422
4423 /* Set Camera Color Space. When we set CSC, this will be passed to
4424 fimrware as the InputPrimaries */
4425 venc_set_colorspace(colorData.colorPrimaries, colorData.range,
4426 colorData.transfer, colorData.matrixCoefficients);
4427
4428 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
4429 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4430 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4431 DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC");
4432 }
4433 else {
4434 if (is_csc_custom_matrix_enabled) {
4435 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX;
4436 control.value = 1;
4437 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
4438 DEBUG_PRINT_ERROR("venc_empty_buf: Failed to enable VPE CSC custom matrix");
4439 } else {
4440 DEBUG_PRINT_INFO("venc_empty_buf: Enabled VPE CSC custom matrix");
4441 }
4442 }
4443 /* Change Colorspace to 709*/
4444 colorData.colorPrimaries = ColorPrimaries_BT709_5;
4445 colorData.range = Range_Limited;
4446 colorData.transfer = Transfer_sRGB;
4447 colorData.matrixCoefficients = MatrixCoEff_BT709_5;
4448 }
4449 }
4450
4451 /* Enum values from gralloc ColorMetaData matches with the driver values
4452 as it is standard compliant */
4453 venc_set_colorspace(colorData.colorPrimaries, colorData.range,
4454 colorData.transfer, colorData.matrixCoefficients);
4455
4456 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
4457 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
4458 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
4459 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
4460 DEBUG_PRINT_ERROR("Failed setting color format in Grallocsource %lx", m_sVenc_cfg.inputformat);
4461 return false;
4462 }
4463 if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
4464 DEBUG_PRINT_ERROR("VIDIOC_REQBUFS OUTPUT_MPLANE Failed");
4465 return false;
4466 }
4467 } else {
4468 if (m_hdr10meta_enabled) {
4469 if (getMetaData(handle, GET_COLOR_METADATA, &colorData) == 0) {
4470 DEBUG_PRINT_INFO("ENC_CONFIG: gralloc Color MetaData dynamicMetaDataValid=%u dynamicMetaDataLen=%u",
4471 colorData.dynamicMetaDataValid, colorData.dynamicMetaDataLen);
4472 }
4473 }
4474 } // Check OUTPUT Streaming
4475
4476 struct UBWCStats cam_ubwc_stats[2];
4477 unsigned long long int compression_ratio = 1 << 16;
4478
4479 if (getMetaData(handle, GET_UBWC_CR_STATS_INFO, (void *)cam_ubwc_stats) == 0) {
4480 if (cam_ubwc_stats[0].bDataValid) {
4481 switch (cam_ubwc_stats[0].version) {
4482 case UBWC_1_0:
4483 {
4484 // Camera hw doesn't support UBWC stats in trinket and sends
4485 // a hardcoded compression factor in nCRStatsTile32
4486 compression_ratio = cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32;
4487 }
4488 break;
4489 case UBWC_2_0:
4490 case UBWC_3_0:
4491 {
4492 unsigned long long int sum = 0, weighted_sum = 0;
4493
4494 DEBUG_PRINT_HIGH("Field 0 : 32 Tile = %d 64 Tile = %d 96 Tile = %d "
4495 "128 Tile = %d 160 Tile = %d 192 Tile = %d 256 Tile = %d\n",
4496 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32,
4497 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64,
4498 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96,
4499 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128,
4500 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160,
4501 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192,
4502 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256);
4503
4504 weighted_sum =
4505 32 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
4506 64 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
4507 96 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
4508 128 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
4509 160 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
4510 192 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
4511 256 * cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
4512
4513 sum =
4514 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile32 +
4515 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile64 +
4516 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile96 +
4517 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile128 +
4518 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile160 +
4519 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile192 +
4520 cam_ubwc_stats[0].ubwc_stats.nCRStatsTile256;
4521
4522 compression_ratio = (weighted_sum && sum) ?
4523 ((256 * sum) << 16) / weighted_sum : compression_ratio;
4524 }
4525 break;
4526 default:
4527 break;
4528 }
4529 }
4530 }
4531
4532 uint32_t encodePerfMode = 0;
4533 if (getMetaData(handle, GET_VIDEO_PERF_MODE, &encodePerfMode) == 0) {
4534 if (encodePerfMode == OMX_TRUE) {
4535 buf.flags |= V4L2_QCOM_BUF_FLAG_PERF_MODE;
4536 }
4537 // Clear SET_VIDEO_PERF_MODE in buffer handle
4538 setMetaData(handle, SET_VIDEO_PERF_MODE, 0);
4539 }
4540 fd = handle->fd;
4541 plane[0].data_offset = 0;
4542 plane[0].length = handle->size;
4543 plane[0].bytesused = handle->size;
4544 plane[0].reserved[2] = (unsigned long int)compression_ratio;
4545 char v4l2ColorFormatStr[200];
4546 get_v4l2_color_format_as_string(v4l2ColorFormatStr, sizeof(v4l2ColorFormatStr), m_sVenc_cfg.inputformat);
4547 DEBUG_PRINT_LOW("venc_empty_buf: Opaque camera buf: fd = %d "
4548 ": filled %d of %d format 0x%lx (%s) CR %d", fd, plane[0].bytesused,
4549 plane[0].length, m_sVenc_cfg.inputformat, v4l2ColorFormatStr, plane[0].reserved[2]);
4550 }
4551 } else {
4552 // Metadata mode
4553 // color_format == 1 ==> RGBA to YUV Color-converted buffer
4554 // Buffers color-converted via C2D have 601-Limited color
4555 if (!streaming[OUTPUT_PORT]) {
4556 c2d_enabled = 1;
4557 DEBUG_PRINT_HIGH("Setting colorspace 601-L for Color-converted buffer");
4558 venc_set_colorspace(MSM_VIDC_BT601_6_625, 0 /*range-limited*/,
4559 MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
4560 }
4561 plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
4562 plane[0].data_offset = bufhdr->nOffset;
4563 plane[0].length = bufhdr->nAllocLen;
4564 plane[0].bytesused = bufhdr->nFilledLen;
4565 DEBUG_PRINT_LOW("venc_empty_buf: Opaque non-camera buf: fd = %d filled %d of %d",
4566 fd, plane[0].bytesused, plane[0].length);
4567 }
4568 } else { // Not Metadata mode
4569 plane[0].m.userptr = (unsigned long) bufhdr->pBuffer;
4570 plane[0].data_offset = bufhdr->nOffset;
4571 plane[0].length = bufhdr->nAllocLen;
4572 plane[0].bytesused = bufhdr->nFilledLen;
4573 DEBUG_PRINT_LOW("venc_empty_buf: non-camera buf: fd = %d filled %d of %d",
4574 fd, plane[0].bytesused, plane[0].length);
4575 }
4576 }
4577
4578 if (!streaming[OUTPUT_PORT] && (c2d_enabled ||
4579 (m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_TP10_UBWC &&
4580 m_sVenc_cfg.inputformat != V4L2_PIX_FMT_NV12_UBWC))) {
4581 if (bframe_implicitly_enabled) {
4582 DEBUG_PRINT_HIGH("Disabling implicitly enabled B-frames");
4583 intra_period.num_pframes = nPframes_cache;
4584 if (!_venc_set_intra_period(intra_period.num_pframes, 0)) {
4585 DEBUG_PRINT_ERROR("Failed to set nPframes/nBframes");
4586 return OMX_ErrorUndefined;
4587 }
4588 }
4589 }
4590
4591 extra_idx = EXTRADATA_IDX(num_input_planes);
4592
4593 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4594 OMX_U32 extradata_index;
4595 if (!venc_get_index_from_fd(fd, &extradata_index)) {
4596 return false;
4597 }
4598
4599 plane[extra_idx].bytesused = 0;
4600 plane[extra_idx].length = input_extradata_info.size;
4601 plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size);
4602 #ifdef USE_ION
4603 plane[extra_idx].reserved[0] = input_extradata_info.ion.data_fd;
4604 #endif
4605 plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index;
4606 plane[extra_idx].reserved[2] = input_extradata_info.size;
4607 plane[extra_idx].data_offset = 0;
4608 } else if (extra_idx >= VIDEO_MAX_PLANES) {
4609 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
4610 return false;
4611 }
4612
4613 buf.index = index;
4614 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4615 buf.memory = V4L2_MEMORY_USERPTR;
4616 plane[0].reserved[0] = fd;
4617 plane[0].reserved[1] = 0;
4618 buf.m.planes = plane;
4619 buf.length = num_input_planes;
4620 buf.timestamp.tv_sec = bufhdr->nTimeStamp / 1000000;
4621 buf.timestamp.tv_usec = (bufhdr->nTimeStamp % 1000000);
4622
4623 if (!handle_input_extradata(buf)) {
4624 DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
4625 return false;
4626 }
4627 VIDC_TRACE_INT_LOW("ETB-TS", bufhdr->nTimeStamp / 1000);
4628
4629 if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
4630 buf.flags |= V4L2_QCOM_BUF_FLAG_EOS;
4631
4632 if (!plane[0].bytesused) {
4633 if (buf.flags & V4L2_QCOM_BUF_FLAG_EOS) {
4634 DEBUG_PRINT_ERROR("venc_empty_buf: Zero length EOS buffers are not valid");
4635 DEBUG_PRINT_ERROR("Use this function instead : venc_handle_empty_eos_buffer");
4636 return false;
4637 }
4638 DEBUG_PRINT_ERROR("venc_empty_buf: Zero length buffers are not valid");
4639 return false;
4640 }
4641
4642 if (m_debug.in_buffer_log) {
4643 venc_input_log_buffers(bufhdr, fd, plane[0].data_offset, m_sVenc_cfg.inputformat, interlace_flag);
4644 }
4645 if (m_debug.extradata_log && extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4646 DEBUG_PRINT_ERROR("Extradata Addr 0x%llx, Buffer Addr = 0x%x", (OMX_U64)input_extradata_info.uaddr, (unsigned int)plane[extra_idx].m.userptr);
4647 venc_extradata_log_buffers((char *)plane[extra_idx].m.userptr, true);
4648 }
4649 rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4650
4651 if (rc) {
4652 DEBUG_PRINT_ERROR("Failed to qbuf (etb) to driver");
4653 return false;
4654 }
4655
4656 etb++;
4657
4658 if (!streaming[OUTPUT_PORT]) {
4659 enum v4l2_buf_type buf_type;
4660 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4661 int ret;
4662
4663 if (!downscalar_enabled) {
4664 OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
4665
4666 if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
4667 return false;
4668 }
4669
4670 if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
4671 return false;
4672 }
4673
4674 // Tiling in HEIC requires output WxH to be Tile size; difference is permitted
4675 if (!(m_codec == OMX_VIDEO_CodingImageHEIC) &&
4676 inp_width * inp_height != out_width * out_height) {
4677 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
4678 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
4679 return false;
4680 }
4681 }
4682
4683 ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
4684
4685 if (ret) {
4686 DEBUG_PRINT_ERROR("Failed to call streamon");
4687 if (errno == EBUSY) {
4688 hw_overload = true;
4689 }
4690 return false;
4691 } else {
4692 streaming[OUTPUT_PORT] = true;
4693 }
4694 }
4695
4696 return true;
4697 }
4698
venc_empty_batch(OMX_BUFFERHEADERTYPE * bufhdr,unsigned index)4699 bool venc_dev::venc_empty_batch(OMX_BUFFERHEADERTYPE *bufhdr, unsigned index)
4700 {
4701 struct v4l2_buffer buf;
4702 struct v4l2_plane plane[VIDEO_MAX_PLANES];
4703 int rc = 0, extra_idx, numBufs;
4704 struct v4l2_control control;
4705 LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;
4706 native_handle_t *hnd = NULL;
4707
4708 if (bufhdr == NULL) {
4709 DEBUG_PRINT_ERROR("ERROR: %s: buffer is NULL", __func__);
4710 return false;
4711 }
4712
4713 bool status = true;
4714 if (metadatamode) {
4715 plane[0].m.userptr = index;
4716 meta_buf = (LEGACY_CAM_METADATA_TYPE *)bufhdr->pBuffer;
4717
4718 if (!color_format) {
4719 if (meta_buf->buffer_type == LEGACY_CAM_SOURCE) {
4720 hnd = (native_handle_t*)meta_buf->meta_handle;
4721 if (!hnd) {
4722 DEBUG_PRINT_ERROR("venc_empty_batch: invalid handle !");
4723 return false;
4724 } else if (MetaBufferUtil::getBatchSize(hnd) > kMaxBuffersInBatch) {
4725 DEBUG_PRINT_ERROR("venc_empty_batch: Too many buffers (%d) in batch. "
4726 "Max = %d", MetaBufferUtil::getBatchSize(hnd), kMaxBuffersInBatch);
4727 status = false;
4728 }
4729 DEBUG_PRINT_LOW("venc_empty_batch: Batch of %d bufs", MetaBufferUtil::getBatchSize(hnd));
4730 } else {
4731 DEBUG_PRINT_ERROR("Batch supported for CameraSource buffers only !");
4732 status = false;
4733 }
4734 } else {
4735 DEBUG_PRINT_ERROR("Batch supported for Camera buffers only !");
4736 status = false;
4737 }
4738 } else {
4739 DEBUG_PRINT_ERROR("Batch supported for metabuffer mode only !");
4740 status = false;
4741 }
4742
4743 if (status) {
4744 OMX_TICKS bufTimeStamp = 0ll;
4745 int numBufs = MetaBufferUtil::getBatchSize(hnd);
4746 int v4l2Ids[kMaxBuffersInBatch] = {-1};
4747 for (int i = 0; i < numBufs; ++i) {
4748 v4l2Ids[i] = mBatchInfo.registerBuffer(index);
4749 if (v4l2Ids[i] < 0) {
4750 DEBUG_PRINT_ERROR("Failed to register buffer");
4751 // TODO: cleanup the map and purge all slots of current index
4752 status = false;
4753 break;
4754 }
4755 }
4756 for (int i = 0; i < numBufs; ++i) {
4757 int v4l2Id = v4l2Ids[i];
4758 int usage = 0;
4759
4760 memset(&buf, 0, sizeof(buf));
4761 memset(&plane, 0, sizeof(plane));
4762
4763 DEBUG_PRINT_LOW("Batch: registering %d as %d", index, v4l2Id);
4764 buf.index = (unsigned)v4l2Id;
4765 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4766 buf.memory = V4L2_MEMORY_USERPTR;
4767 plane[0].reserved[0] = MetaBufferUtil::getFdAt(hnd, i);
4768 plane[0].reserved[1] = 0;
4769 plane[0].data_offset = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_OFFSET);
4770 plane[0].m.userptr = (unsigned long)meta_buf;
4771 plane[0].length = plane[0].bytesused = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_SIZE);
4772 buf.m.planes = plane;
4773 buf.length = num_input_planes;
4774
4775 usage = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_USAGE);
4776 usage = usage > 0 ? usage : 0;
4777
4778 extra_idx = EXTRADATA_IDX(num_input_planes);
4779
4780 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4781 int fd = plane[0].reserved[0];
4782 OMX_U32 extradata_index;
4783 if (!venc_get_index_from_fd(fd, &extradata_index)) {
4784 return false;
4785 }
4786
4787 plane[extra_idx].bytesused = 0;
4788 plane[extra_idx].length = input_extradata_info.size;
4789 plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size);
4790 plane[extra_idx].reserved[0] = input_extradata_info.ion.data_fd;
4791 plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index;
4792 plane[extra_idx].reserved[2] = input_extradata_info.size;
4793 plane[extra_idx].data_offset = 0;
4794 } else if (extra_idx >= VIDEO_MAX_PLANES) {
4795 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
4796 return false;
4797 }
4798
4799 if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
4800 buf.flags |= V4L2_QCOM_BUF_FLAG_EOS;
4801 #if NEED_TO_REVISIT
4802 if (i != numBufs - 1) {
4803 buf.flags |= V4L2_MSM_BUF_FLAG_DEFER;
4804 DEBUG_PRINT_LOW("for buffer %d (etb #%d) in batch of %d, marking as defer",
4805 i, etb + 1, numBufs);
4806 }
4807 #endif
4808 // timestamp differences from camera are in nano-seconds
4809 bufTimeStamp = bufhdr->nTimeStamp + MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_TIMESTAMP) / 1000;
4810
4811 DEBUG_PRINT_LOW(" Q Batch [%d of %d] : buf=%p fd=%d len=%d TS=%lld",
4812 i, numBufs, bufhdr, plane[0].reserved[0], plane[0].length, bufTimeStamp);
4813 buf.timestamp.tv_sec = bufTimeStamp / 1000000;
4814 buf.timestamp.tv_usec = (bufTimeStamp % 1000000);
4815
4816 if (!handle_input_extradata(buf)) {
4817 DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
4818 return false;
4819 }
4820 VIDC_TRACE_INT_LOW("ETB-TS", bufTimeStamp / 1000);
4821
4822 rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4823 if (rc) {
4824 DEBUG_PRINT_ERROR("%s: Failed to qbuf (etb) to driver", __func__);
4825 return false;
4826 }
4827
4828 etb++;
4829 }
4830 }
4831
4832 if (status && !streaming[OUTPUT_PORT]) {
4833 enum v4l2_buf_type buf_type;
4834 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4835 int ret;
4836
4837 if (!downscalar_enabled) {
4838 OMX_U32 inp_width = 0, inp_height = 0, out_width = 0, out_height = 0;
4839
4840 if (!venc_get_dimensions(PORT_INDEX_IN, &inp_width, &inp_height)) {
4841 return false;
4842 }
4843
4844 if (!venc_get_dimensions(PORT_INDEX_OUT, &out_width, &out_height)) {
4845 return false;
4846 }
4847
4848 if (inp_width * inp_height != out_width * out_height) {
4849 DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match");
4850 DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height);
4851 return false;
4852 }
4853 }
4854
4855 ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type);
4856 if (ret) {
4857 DEBUG_PRINT_ERROR("Failed to call streamon");
4858 if (errno == EBUSY) {
4859 hw_overload = true;
4860 }
4861 status = false;
4862 } else {
4863 streaming[OUTPUT_PORT] = true;
4864 }
4865 }
4866
4867 return status;
4868 }
4869
venc_fill_buf(void * buffer,void * pmem_data_buf,unsigned index,unsigned fd)4870 bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd)
4871 {
4872 struct pmem *temp_buffer = NULL;
4873 struct venc_buffer frameinfo;
4874 struct v4l2_buffer buf;
4875 struct v4l2_plane plane[VIDEO_MAX_PLANES];
4876 int rc = 0;
4877 unsigned int extra_idx;
4878 struct OMX_BUFFERHEADERTYPE *bufhdr;
4879
4880 if (buffer == NULL)
4881 return false;
4882
4883 bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
4884
4885 if (pmem_data_buf) {
4886 DEBUG_PRINT_LOW("Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf);
4887 plane[0].m.userptr = (unsigned long)pmem_data_buf;
4888 } else {
4889 DEBUG_PRINT_LOW("Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
4890 plane[0].m.userptr = (unsigned long)bufhdr->pBuffer;
4891 }
4892
4893 memset(&buf, 0, sizeof(buf));
4894 memset(&plane, 0, sizeof(plane));
4895
4896 buf.index = index;
4897 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4898 buf.memory = V4L2_MEMORY_USERPTR;
4899 plane[0].length = bufhdr->nAllocLen;
4900 plane[0].bytesused = bufhdr->nFilledLen;
4901 plane[0].reserved[0] = fd;
4902 plane[0].reserved[1] = 0;
4903 plane[0].data_offset = bufhdr->nOffset;
4904 buf.m.planes = plane;
4905 buf.length = num_output_planes;
4906 buf.flags = 0;
4907
4908 if (venc_handle->is_secure_session()) {
4909 if (venc_handle->allocate_native_handle) {
4910 native_handle_t *handle_t = (native_handle_t *)(bufhdr->pBuffer);
4911 plane[0].length = handle_t->data[3];
4912 } else {
4913 output_metabuffer *meta_buf = (output_metabuffer *)(bufhdr->pBuffer);
4914 native_handle_t *handle_t = meta_buf->nh;
4915 plane[0].length = handle_t->data[3];
4916 }
4917 }
4918
4919 if (mBatchSize) {
4920 // Should always mark first buffer as DEFER, since 0 % anything is 0, just offset by 1
4921 // This results in the first batch being of size mBatchSize + 1, but thats good because
4922 // we need an extra FTB for the codec specific data.
4923 #if NEED_TO_REVISIT
4924 if (!ftb || ftb % mBatchSize) {
4925 buf.flags |= V4L2_MSM_BUF_FLAG_DEFER;
4926 DEBUG_PRINT_LOW("for ftb buffer %d marking as defer", ftb + 1);
4927 }
4928 #endif
4929 }
4930
4931 extra_idx = EXTRADATA_IDX(num_output_planes);
4932
4933 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4934 plane[extra_idx].bytesused = 0;
4935 plane[extra_idx].length = output_extradata_info.buffer_size;
4936 plane[extra_idx].m.userptr = (unsigned long) (output_extradata_info.uaddr + index * output_extradata_info.buffer_size);
4937 #ifdef USE_ION
4938 plane[extra_idx].reserved[0] = output_extradata_info.ion.data_fd;
4939 #endif
4940 plane[extra_idx].reserved[1] = output_extradata_info.buffer_size * index;
4941 plane[extra_idx].data_offset = 0;
4942 } else if (extra_idx >= VIDEO_MAX_PLANES) {
4943 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx);
4944 return false;
4945 }
4946
4947 rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
4948
4949 if (rc) {
4950 DEBUG_PRINT_ERROR("Failed to qbuf (ftb) to driver");
4951 return false;
4952 }
4953
4954 ftb++;
4955 return true;
4956 }
4957
venc_set_inband_video_header(OMX_BOOL enable)4958 bool venc_dev::venc_set_inband_video_header(OMX_BOOL enable)
4959 {
4960 struct v4l2_control control;
4961
4962 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
4963 return false;
4964 }
4965
4966 control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
4967 if(enable) {
4968 control.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME;
4969 } else {
4970 control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
4971 }
4972
4973 DEBUG_PRINT_HIGH("Set inband sps/pps: %d", enable);
4974 if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
4975 DEBUG_PRINT_ERROR("Request for inband sps/pps failed");
4976 return false;
4977 }
4978 return true;
4979 }
4980
venc_set_au_delimiter(OMX_BOOL enable)4981 bool venc_dev::venc_set_au_delimiter(OMX_BOOL enable)
4982 {
4983 struct v4l2_control control;
4984
4985 control.id = V4L2_CID_MPEG_VIDC_VIDEO_AU_DELIMITER;
4986 if(enable) {
4987 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4988 } else {
4989 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
4990 }
4991
4992 DEBUG_PRINT_HIGH("Set AU delimiters: %d", enable);
4993 if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
4994 DEBUG_PRINT_ERROR("Request for AU delimiters failed");
4995 return false;
4996 }
4997 return true;
4998 }
4999
venc_get_index_from_fd(OMX_U32 buffer_fd,OMX_U32 * index)5000 bool venc_dev::venc_get_index_from_fd(OMX_U32 buffer_fd, OMX_U32 *index)
5001 {
5002 for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
5003 if (fd_list[i] == buffer_fd) {
5004 DEBUG_PRINT_HIGH("FD : %d found at index = %d", buffer_fd, i);
5005 *index = i;
5006 return true;
5007 }
5008 }
5009
5010 for (unsigned int i = 0; i < (sizeof(fd_list)/sizeof(fd_list[0])); i++) {
5011 if (fd_list[i] == 0) {
5012 DEBUG_PRINT_HIGH("FD : %d added at index = %d", buffer_fd, i);
5013 fd_list[i] = buffer_fd;
5014 *index = i;
5015 return true;
5016 }
5017 }
5018 DEBUG_PRINT_ERROR("Couldn't get index from fd : %d",buffer_fd);
5019 return false;
5020 }
5021
venc_set_extradata(OMX_U32 extra_data,OMX_BOOL enable)5022 bool venc_dev::venc_set_extradata(OMX_U32 extra_data, OMX_BOOL enable)
5023 {
5024 struct v4l2_control control;
5025
5026 DEBUG_PRINT_HIGH("venc_set_extradata:: %x", (int) extra_data);
5027
5028 if (enable == OMX_FALSE) {
5029 /* No easy way to turn off extradata to the driver
5030 * at the moment */
5031 return false;
5032 }
5033
5034 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
5035 switch (extra_data) {
5036 case OMX_ExtraDataVideoLTRInfo:
5037 control.value = V4L2_MPEG_VIDC_EXTRADATA_LTR;
5038 break;
5039 #ifdef V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP
5040 case OMX_ExtraDataFrameDimension:
5041 control.value = V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP;
5042 break;
5043 #endif
5044 default:
5045 DEBUG_PRINT_ERROR("Unrecognized extradata index 0x%x", (unsigned int)extra_data);
5046 return false;
5047 }
5048
5049 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
5050 DEBUG_PRINT_ERROR("ERROR: Request for setting extradata (%x) failed %d",
5051 (unsigned int)extra_data, errno);
5052 return false;
5053 }
5054
5055 return true;
5056 }
5057
venc_set_slice_delivery_mode(OMX_U32 enable)5058 bool venc_dev::venc_set_slice_delivery_mode(OMX_U32 enable)
5059 {
5060 struct v4l2_control control;
5061
5062 if (enable) {
5063 control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE;
5064 control.value = 1;
5065 DEBUG_PRINT_LOW("Set slice_delivery_mode: %d", control.value);
5066
5067 if (multislice.mslice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5068 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
5069 DEBUG_PRINT_ERROR("Request for setting slice delivery mode failed");
5070 return false;
5071 } else {
5072 DEBUG_PRINT_LOW("Successfully set Slice delivery mode id: %d, value=%d", control.id, control.value);
5073 slice_mode.enable = 1;
5074 }
5075 } else {
5076 DEBUG_PRINT_ERROR("Failed to set slice delivery mode, slice_mode [%lu] "
5077 "is not MB BASED or [%lu] is not H264 codec ", multislice.mslice_mode,
5078 m_sVenc_cfg.codectype);
5079 }
5080 } else {
5081 DEBUG_PRINT_ERROR("Slice_DELIVERY_MODE not enabled");
5082 }
5083
5084 return true;
5085 }
5086
venc_set_colorspace(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer_chars,OMX_U32 matrix_coeffs)5087 bool venc_dev::venc_set_colorspace(OMX_U32 primaries, OMX_U32 range,
5088 OMX_U32 transfer_chars, OMX_U32 matrix_coeffs)
5089 {
5090 int rc;
5091 struct v4l2_control control;
5092
5093 DEBUG_PRINT_LOW("Setting color space : Primaries = %d, Range = %d, Trans = %d, Matrix = %d",
5094 primaries, range, transfer_chars, matrix_coeffs);
5095
5096 control.id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE;
5097 control.value = primaries;
5098
5099 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5100 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5101
5102 if (rc) {
5103 DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE");
5104 return false;
5105 }
5106
5107 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5108
5109 color_space.primaries = control.value;
5110
5111 control.id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE;
5112 control.value = range;
5113
5114 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5115 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5116
5117 if (rc) {
5118 DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE");
5119 return false;
5120 }
5121
5122 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5123
5124 color_space.range = control.value;
5125
5126 control.id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS;
5127 control.value = transfer_chars;
5128
5129 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5130 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5131
5132 if (rc) {
5133 DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS");
5134 return false;
5135 }
5136
5137 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5138
5139 color_space.transfer_chars = control.value;
5140
5141 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS;
5142 control.value = matrix_coeffs;
5143
5144 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5145 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5146
5147 if (rc) {
5148 DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS");
5149 return false;
5150 }
5151
5152 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5153
5154 color_space.matrix_coeffs = control.value;
5155
5156 return true;
5157 }
5158
venc_set_qp(OMX_U32 i_frame_qp,OMX_U32 p_frame_qp,OMX_U32 b_frame_qp,OMX_U32 enable)5159 bool venc_dev::venc_set_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp, OMX_U32 enable)
5160 {
5161 int rc;
5162 struct v4l2_control control;
5163
5164 control.id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP;
5165 control.value = i_frame_qp;
5166
5167 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5168 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5169
5170 if (rc) {
5171 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5172 return false;
5173 }
5174 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5175 session_qp.iframeqp = control.value;
5176
5177 control.id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP;
5178 control.value = p_frame_qp;
5179
5180 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5181 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5182
5183 if (rc) {
5184 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5185 return false;
5186 }
5187 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5188 session_qp.pframeqp = control.value;
5189
5190 control.id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP;
5191 control.value = b_frame_qp;
5192 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5193
5194 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5195 if (rc) {
5196 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5197 return false;
5198 }
5199 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5200 session_qp.bframeqp = control.value;
5201
5202 control.id = V4L2_CID_MPEG_VIDC_VIDEO_QP_MASK;
5203 control.value = enable;
5204
5205 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5206 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5207
5208 if (rc) {
5209 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5210 return false;
5211 }
5212 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5213 session_qp.enableqp = control.value;
5214
5215 return true;
5216 }
5217
venc_set_session_qp_range(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE * qp_range)5218 bool venc_dev::venc_set_session_qp_range(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE* qp_range)
5219 {
5220 int rc;
5221 struct v4l2_ext_control ctrl[7];
5222 struct v4l2_ext_controls controls;
5223
5224 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LAYER_ID;
5225 ctrl[0].value = MSM_VIDC_ALL_LAYER_ID;
5226
5227 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN;
5228 ctrl[1].value = qp_range->minIQP;
5229
5230 ctrl[2].id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX;
5231 ctrl[2].value = qp_range->maxIQP;
5232
5233 ctrl[3].id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN;
5234 ctrl[3].value = qp_range->minPQP;
5235
5236 ctrl[4].id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX;
5237 ctrl[4].value = qp_range->maxPQP;
5238
5239 ctrl[5].id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN;
5240 ctrl[5].value = qp_range->minBQP;
5241
5242 ctrl[6].id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX;
5243 ctrl[6].value = qp_range->maxBQP;
5244
5245 controls.count = 7;
5246 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
5247 controls.controls = ctrl;
5248
5249 if(ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
5250 DEBUG_PRINT_ERROR("Failed to set QP range");
5251 return false;
5252 }
5253
5254 session_ipb_qp_values.min_i_qp = qp_range->minIQP;
5255 session_ipb_qp_values.max_i_qp = qp_range->maxIQP;
5256 session_ipb_qp_values.min_p_qp = qp_range->minPQP;
5257 session_ipb_qp_values.max_p_qp = qp_range->maxPQP;
5258 session_ipb_qp_values.min_b_qp = qp_range->minBQP;
5259 session_ipb_qp_values.max_b_qp = qp_range->maxBQP;
5260 return true;
5261 }
5262
venc_set_profile(OMX_U32 eProfile)5263 bool venc_dev::venc_set_profile(OMX_U32 eProfile)
5264 {
5265 int rc;
5266 struct v4l2_control control;
5267
5268 DEBUG_PRINT_LOW("venc_set_profile:: eProfile = %u",
5269 (unsigned int)eProfile);
5270
5271 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5272 control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
5273 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
5274 //In driver VP8 profile is hardcoded. No need to set anything from here
5275 return true;
5276 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5277 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
5278 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
5279 control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_PROFILE;
5280 } else {
5281 DEBUG_PRINT_ERROR("Wrong CODEC");
5282 return false;
5283 }
5284
5285 if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, eProfile, &control.value)) {
5286 DEBUG_PRINT_ERROR("Cannot find v4l2 profile for OMX profile : %d Codec : %lu ",
5287 eProfile, m_sVenc_cfg.codectype);
5288 return false;
5289 }
5290
5291 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5292 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5293
5294 if (rc) {
5295 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5296 return false;
5297 }
5298 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5299
5300 codec_profile.profile = control.value;
5301
5302 if (hdr10metadata_supported == true) {
5303 if (venc_set_extradata_hdr10metadata() == false)
5304 {
5305 DEBUG_PRINT_ERROR("Failed to set extradata HDR10PLUS_METADATA");
5306 return false;
5307 }
5308 }
5309 return true;
5310 }
5311
venc_set_level(OMX_U32 eLevel)5312 bool venc_dev::venc_set_level(OMX_U32 eLevel)
5313 {
5314 int rc;
5315 struct v4l2_control control;
5316
5317 DEBUG_PRINT_LOW("venc_set_level:: eLevel = %u",
5318 (unsigned int)eLevel);
5319
5320 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
5321 control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
5322 control.value = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN;
5323 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
5324 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
5325 control.value = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
5326 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5327 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
5328 control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN;
5329 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_TME) {
5330 control.id = V4L2_CID_MPEG_VIDC_VIDEO_TME_LEVEL;
5331 control.value = V4L2_MPEG_VIDC_VIDEO_TME_LEVEL_INTEGER;
5332 } else {
5333 DEBUG_PRINT_ERROR("Wrong CODEC");
5334 return false;
5335 }
5336
5337 /* If OMX_VIDEO_LEVEL_UNKNOWN then set default values assigned above */
5338 if (eLevel != OMX_VIDEO_LEVEL_UNKNOWN) {
5339 if (!profile_level_converter::convert_omx_level_to_v4l2(m_sVenc_cfg.codectype, eLevel, &control.value)) {
5340 DEBUG_PRINT_LOW("Warning: Cannot find v4l2 level for OMX level : %d Codec : %lu Setting unknown level",
5341 eLevel, m_sVenc_cfg.codectype);
5342 }
5343 }
5344
5345 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5346 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5347 if (rc) {
5348 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5349 return false;
5350 }
5351
5352 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5353
5354 profile_level.level = control.value;
5355
5356 return true;
5357 }
5358
venc_set_voptiming_cfg(OMX_U32 TimeIncRes)5359 bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes)
5360 {
5361
5362 struct venc_voptimingcfg vop_timing_cfg;
5363
5364 DEBUG_PRINT_LOW("venc_set_voptiming_cfg: TimeRes = %u",
5365 (unsigned int)TimeIncRes);
5366
5367 vop_timing_cfg.voptime_resolution = TimeIncRes;
5368
5369 voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution;
5370 return true;
5371 }
5372
venc_reconfigure_intra_refresh_period()5373 bool venc_dev::venc_reconfigure_intra_refresh_period() {
5374
5375 DEBUG_PRINT_LOW("venc_reconfigure_intra_refresh_period");
5376 if (intra_refresh.framecount) {
5377 OMX_U32 mb_size = 16;
5378 // Firmware will re-calculate mbcount if codec is HEVC.
5379 OMX_U32 num_mbs_per_frame = (ALIGN(m_sVenc_cfg.dvs_height, mb_size)/mb_size) * (ALIGN(m_sVenc_cfg.dvs_width, mb_size)/mb_size);
5380 OMX_U32 num_intra_refresh_mbs = 0;
5381 num_intra_refresh_mbs = ceil(num_mbs_per_frame / intra_refresh.framecount);
5382
5383 intra_refresh.irmode = OMX_VIDEO_IntraRefreshRandom;
5384 intra_refresh.mbcount = num_intra_refresh_mbs;
5385 }
5386
5387 if (venc_set_intra_refresh() == false) {
5388 DEBUG_PRINT_ERROR("ERROR: Setting Intra refresh failed");
5389 return false;
5390 }
5391
5392 return true;
5393 }
5394
venc_reconfigure_intra_period()5395 bool venc_dev::venc_reconfigure_intra_period()
5396 {
5397 int rc;
5398 bool isValidCodec = false;
5399 bool isValidResolution = false;
5400 bool isValidFps = false;
5401 bool isValidOpRate = false;
5402 bool isValidLayerCount = false;
5403 bool enableBframes = false;
5404 bool isValidLtrSetting = false;
5405 bool isValidRcMode = false;
5406 struct v4l2_control control;
5407
5408 DEBUG_PRINT_LOW("venc_reconfigure_intra_period");
5409
5410 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 &&
5411 ((codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) ||
5412 (codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_HIGH))) {
5413 isValidCodec = true;
5414 }
5415
5416 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC &&
5417 ((codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) ||
5418 (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) ||
5419 (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC)) &&
5420 (m_codec != OMX_VIDEO_CodingImageHEIC)) {
5421 isValidCodec = true;
5422 }
5423
5424 if ((m_sVenc_cfg.input_width <= VENC_BFRAME_MAX_WIDTH && m_sVenc_cfg.input_height <= VENC_BFRAME_MAX_HEIGHT) ||
5425 (m_sVenc_cfg.input_width <= VENC_BFRAME_MAX_HEIGHT && m_sVenc_cfg.input_height <= VENC_BFRAME_MAX_WIDTH)) {
5426 isValidResolution = true;
5427 }
5428
5429 if ((m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) <= VENC_BFRAME_MAX_FPS) {
5430 isValidFps = true;
5431 }
5432
5433 if (operating_rate <= VENC_BFRAME_MAX_FPS) {
5434 isValidOpRate = true;
5435 }
5436
5437 if (temporal_layers_config.nPLayers <= 1) {
5438 isValidLayerCount = true;
5439 }
5440
5441 if (rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
5442 isValidRcMode = true;
5443 }
5444
5445 isValidLtrSetting = ltrinfo.enabled ? false : true;
5446
5447 enableBframes = isValidResolution &&
5448 isValidFps &&
5449 isValidOpRate &&
5450 isValidLayerCount &&
5451 isValidLtrSetting &&
5452 isValidRcMode &&
5453 isValidCodec &&
5454 !low_latency_mode &&
5455 !client_req_disable_bframe;
5456
5457 DEBUG_PRINT_LOW("B-frame enablement = %u; Conditions for Resolution = %u, FPS = %u,"
5458 "Operating rate = %u, Layer condition = %u, LTR = %u, RC = %u"
5459 "Codec/Profile = %u Client request to disable = %u LowLatency : %u \n isNativeRecorder : %u",
5460 enableBframes, isValidResolution, isValidFps, isValidOpRate,
5461 isValidLayerCount, isValidLtrSetting, isValidRcMode, isValidCodec, client_req_disable_bframe,
5462 low_latency_mode, mIsNativeRecorder);
5463
5464 if (enableBframes && intra_period.num_bframes == 0 && intra_period.num_pframes > VENC_BFRAME_MAX_COUNT
5465 && mIsNativeRecorder) {
5466 intra_period.num_bframes = VENC_BFRAME_MAX_COUNT;
5467 nPframes_cache = intra_period.num_pframes;
5468 intra_period.num_pframes = intra_period.num_pframes / (1 + intra_period.num_bframes);
5469 bframe_implicitly_enabled = true;
5470 } else if (!enableBframes && intra_period.num_bframes > 0) {
5471 intra_period.num_pframes = intra_period.num_pframes + (intra_period.num_pframes * intra_period.num_bframes);
5472 intra_period.num_bframes = 0;
5473 }
5474
5475 if (!venc_calibrate_gop())
5476 {
5477 DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
5478 return false;
5479 }
5480
5481 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
5482 control.value = intra_period.num_pframes;
5483
5484 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5485
5486 if (rc) {
5487 DEBUG_PRINT_ERROR("Failed to set control V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES");
5488 return false;
5489 }
5490
5491 DEBUG_PRINT_LOW("Success IOCTL set control for V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES value=%d", control.value);
5492
5493 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
5494 control.value = intra_period.num_bframes;
5495
5496 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5497
5498 if (rc) {
5499 DEBUG_PRINT_ERROR("Failed to set control V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES");
5500 return false;
5501 }
5502
5503 DEBUG_PRINT_LOW("Success IOCTL set control for V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES value=%lu", intra_period.num_bframes);
5504
5505 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 ||
5506 m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
5507 /*
5508 * This call is to ensure default idr period is set if client
5509 * did not set it using index OMX_IndexConfigVideoAVCIntraPeriod.
5510 */
5511 if (venc_set_idr_period(idrperiod.idrperiod) == false) {
5512 DEBUG_PRINT_ERROR("ERROR: Setting idr period failed");
5513 return false;
5514 }
5515 }
5516
5517 return true;
5518 }
5519
venc_set_grid_enable()5520 bool venc_dev::venc_set_grid_enable()
5521 {
5522 int rc;
5523 struct v4l2_control control;
5524
5525 DEBUG_PRINT_LOW("venc_set_grid_enable");
5526 control.id = V4L2_CID_MPEG_VIDC_IMG_GRID_ENABLE;
5527 control.value = 1;
5528 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5529
5530 if (rc) {
5531 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5532 return false;
5533 }
5534
5535 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5536 mIsGridset = true;
5537 return true;
5538 }
5539
venc_set_intra_period(OMX_U32 nPFrames,OMX_U32 nBFrames)5540 bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
5541 {
5542 DEBUG_PRINT_LOW("venc_set_intra_period: nPFrames = %u, nBFrames: %u", (unsigned int)nPFrames, (unsigned int)nBFrames);
5543
5544 if ((streaming[OUTPUT_PORT] || streaming[CAPTURE_PORT]) && (intra_period.num_bframes != nBFrames)) {
5545 DEBUG_PRINT_ERROR("Invalid settings, Cannot change B frame count dynamically");
5546 return false;
5547 }
5548 return _venc_set_intra_period(nPFrames, nBFrames);
5549 }
5550
_venc_set_intra_period(OMX_U32 nPFrames,OMX_U32 nBFrames)5551 bool venc_dev::_venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
5552 {
5553 int rc;
5554 struct v4l2_control control;
5555 char property_value[PROPERTY_VALUE_MAX] = {0};
5556
5557 if ((m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
5558 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) ||
5559 m_codec == OMX_VIDEO_CodingImageHEIC) {
5560 nBFrames = 0;
5561 }
5562
5563 if ((codec_profile.profile != V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) &&
5564 (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) &&
5565 (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) &&
5566 (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) &&
5567 (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC) &&
5568 (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) {
5569 nBFrames = 0;
5570 }
5571
5572 if (temporal_layers_config.nPLayers > 1 && nBFrames) {
5573 DEBUG_PRINT_ERROR("Invalid settings, bframes cannot be enabled with HP. Resetting it to 0");
5574 nBFrames = 0;
5575 }
5576
5577 if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES, nBFrames) || (nBFrames > VENC_BFRAME_MAX_COUNT)) {
5578 DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u bframes", nBFrames);
5579 return false;
5580 }
5581
5582 intra_period.num_pframes = nPFrames;
5583 intra_period.num_bframes = nBFrames;
5584
5585 if (!venc_calibrate_gop())
5586 {
5587 DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
5588 return false;
5589 }
5590
5591 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
5592 control.value = intra_period.num_pframes;
5593 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5594
5595 if (rc) {
5596 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5597 return false;
5598 }
5599 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5600
5601 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
5602 control.value = intra_period.num_bframes;
5603 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5604
5605 if (rc) {
5606 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5607 return false;
5608 }
5609 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5610
5611 return true;
5612 }
5613
venc_set_idr_period(OMX_U32 nIDRPeriod)5614 bool venc_dev::venc_set_idr_period(OMX_U32 nIDRPeriod)
5615 {
5616 int rc = 0;
5617 struct v4l2_control control;
5618
5619 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
5620 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
5621 // don't return error if idr period is zero even though invalid codectype
5622 if (!nIDRPeriod)
5623 return true;
5624
5625 DEBUG_PRINT_ERROR("venc_set_idr_period: invalid codedtype (%#lx)",
5626 m_sVenc_cfg.codectype);
5627 return false;
5628 }
5629
5630 DEBUG_PRINT_LOW("venc_set_idr_period: nIDRPeriod: %u", (unsigned int)nIDRPeriod);
5631 control.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
5632 control.value = nIDRPeriod;
5633 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5634 if (rc) {
5635 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5636 return false;
5637 }
5638 idrperiod.idrperiod = nIDRPeriod;
5639
5640 return true;
5641 }
5642
venc_set_entropy_config(OMX_BOOL enable,OMX_U32 i_cabac_level)5643 bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level)
5644 {
5645 int rc = 0;
5646 struct v4l2_control control;
5647
5648 DEBUG_PRINT_LOW("venc_set_entropy_config: CABAC = %u level: %u", enable, (unsigned int)i_cabac_level);
5649
5650 if (enable && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) &&
5651 (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE)) {
5652 control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
5653 } else if (!enable) {
5654 control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
5655 } else {
5656 DEBUG_PRINT_ERROR("Invalid Entropy mode for Baseline Profile");
5657 return false;
5658 }
5659
5660 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5661
5662 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5663 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5664
5665 if (rc) {
5666 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5667 return false;
5668 }
5669
5670 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5671 entropy.longentropysel = control.value;
5672
5673 return true;
5674 }
5675
venc_set_multislice_cfg(OMX_U32 nSlicemode,OMX_U32 nSlicesize)5676 bool venc_dev::venc_set_multislice_cfg(OMX_U32 nSlicemode, OMX_U32 nSlicesize)
5677 {
5678 int rc;
5679 int slice_id = 0;
5680 struct v4l2_control control;
5681 bool status = true;
5682
5683 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263 || nSlicesize == 0) {
5684 nSlicemode = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
5685 nSlicesize = 0;
5686 }
5687
5688 if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
5689 if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, nSlicesize)) {
5690 DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
5691 return false;
5692 }
5693 slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
5694
5695 } else if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
5696 if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, nSlicesize)) {
5697 DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
5698 return false;
5699 }
5700 slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
5701
5702 } else if (nSlicesize) {
5703 DEBUG_PRINT_ERROR("Invalid settings, unexpected slicemode = %u and slice size = %u", nSlicemode, nSlicesize);
5704 return false;
5705 }
5706
5707 control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
5708 control.value = nSlicemode;
5709
5710 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5711 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5712
5713 if (rc) {
5714 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5715 return false;
5716 }
5717
5718 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5719
5720 if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) {
5721 return status;
5722 }
5723
5724 control.id = slice_id;
5725 control.value = nSlicesize;
5726
5727 DEBUG_PRINT_LOW("Calling SLICE_MB IOCTL set control for id=%d, val=%d", control.id, control.value);
5728 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5729
5730 if (rc) {
5731 DEBUG_PRINT_ERROR("Failed to set control");
5732 return false;
5733 }
5734
5735 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5736
5737 multislice.mslice_mode = nSlicemode;
5738 multislice.mslice_size = nSlicesize;
5739
5740 return status;
5741 }
5742
venc_set_intra_refresh()5743 bool venc_dev::venc_set_intra_refresh()
5744 {
5745 bool status = true;
5746 int rc;
5747 struct v4l2_control control_mode;
5748 control_mode.id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE_CYCLIC;
5749 control_mode.value = 0;
5750 // There is no disabled mode. Disabled mode is indicated by a 0 count.
5751 if (intra_refresh.irmode == OMX_VIDEO_IntraRefreshMax || intra_refresh.mbcount == 0) {
5752 return status;
5753 } else if (intra_refresh.irmode == OMX_VIDEO_IntraRefreshCyclic ||
5754 intra_refresh.irmode == OMX_VIDEO_IntraRefreshRandom) {
5755 control_mode.value = intra_refresh.mbcount;
5756 } else {
5757 DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:"
5758 " mb mode:%lu", intra_refresh.irmode);
5759 return false;
5760 }
5761
5762 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%u, val=%d", control_mode.id, control_mode.value);
5763 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_mode);
5764
5765 if (rc) {
5766 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control_mode.id, control_mode.value);
5767 return false;
5768 }
5769
5770 return status;
5771 }
5772
venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE * error_resilience)5773 bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience)
5774 {
5775 bool status = true;
5776 struct venc_headerextension hec_cfg;
5777 struct venc_multiclicecfg multislice_cfg;
5778 int rc;
5779 OMX_U32 resynchMarkerSpacingBytes = 0;
5780 struct v4l2_control control;
5781
5782 memset(&control, 0, sizeof(control));
5783
5784 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) {
5785 if (error_resilience->bEnableHEC) {
5786 hec_cfg.header_extension = 1;
5787 } else {
5788 hec_cfg.header_extension = 0;
5789 }
5790
5791 hec.header_extension = error_resilience->bEnableHEC;
5792 }
5793
5794 if (error_resilience->bEnableRVLC) {
5795 DEBUG_PRINT_ERROR("RVLC is not Supported");
5796 return false;
5797 }
5798
5799 if (( m_sVenc_cfg.codectype != V4L2_PIX_FMT_H263) &&
5800 (error_resilience->bEnableDataPartitioning)) {
5801 DEBUG_PRINT_ERROR("DataPartioning are not Supported for MPEG4/H264");
5802 return false;
5803 }
5804
5805 if (error_resilience->nResynchMarkerSpacing) {
5806 resynchMarkerSpacingBytes = error_resilience->nResynchMarkerSpacing;
5807 resynchMarkerSpacingBytes = ALIGN(resynchMarkerSpacingBytes, 8) >> 3;
5808 }
5809
5810 status = venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, resynchMarkerSpacingBytes);
5811
5812 return status;
5813 }
5814
venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)5815 bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)
5816 {
5817 int rc;
5818 struct v4l2_control control;
5819 control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE;
5820 control.value=0;
5821
5822 if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable) {
5823 control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED;
5824 } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisable) {
5825 control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED;
5826 } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary) {
5827 control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY;
5828 }
5829
5830 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5831 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5832
5833 if (rc) {
5834 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5835 return false;
5836 }
5837
5838 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5839
5840 dbkfilter.db_mode=control.value;
5841
5842 control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA;
5843 control.value=0;
5844
5845 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5846 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5847
5848 if (rc) {
5849 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5850 return false;
5851 }
5852
5853 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5854 control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA;
5855 control.value=0;
5856 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5857 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5858
5859 if (rc) {
5860 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5861 return false;
5862 }
5863
5864 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5865
5866
5867 dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0;
5868 return true;
5869 }
5870
venc_set_target_bitrate(OMX_U32 nTargetBitrate)5871 bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate)
5872 {
5873 DEBUG_PRINT_LOW("venc_set_target_bitrate: bitrate = %u",
5874 (unsigned int)nTargetBitrate);
5875 struct v4l2_control control;
5876 int rc = 0;
5877
5878 if (vqzip_sei_info.enabled) {
5879 DEBUG_PRINT_HIGH("For VQZIP 1.0, Bitrate setting is not supported");
5880 return true;
5881 }
5882
5883 if (rate_ctrl.rcmode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
5884 control.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY;
5885 else
5886 control.id = V4L2_CID_MPEG_VIDEO_BITRATE;
5887 control.value = nTargetBitrate;
5888
5889 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
5890 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
5891 if (rc) {
5892 DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
5893 return false;
5894 }
5895
5896 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
5897
5898 if (control.id == V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY)
5899 return true;
5900
5901 m_sVenc_cfg.targetbitrate = control.value;
5902 bitrate.target_bitrate = control.value;
5903
5904 // Configure layer-wise bitrate if temporal layers are enabled and layer-wise distribution
5905 // has been specified
5906 if (temporal_layers_config.bIsBitrateRatioValid && temporal_layers_config.nPLayers) {
5907 OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0},
5908 numLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers;
5909
5910 DEBUG_PRINT_LOW("TemporalLayer: configuring layerwise bitrate");
5911 for (OMX_U32 i = 0; i < numLayers; ++i) {
5912 layerBitrates[i] =
5913 (temporal_layers_config.nTemporalLayerBitrateFraction[i] * bitrate.target_bitrate) / 100;
5914 DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)",
5915 i, temporal_layers_config.nTemporalLayerBitrateFraction[i],
5916 layerBitrates[i], bitrate.target_bitrate);
5917 }
5918 if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) {
5919 return false;
5920 }
5921 }
5922
5923 return true;
5924 }
5925
venc_set_encode_framerate(OMX_U32 encode_framerate)5926 bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate)
5927 {
5928 struct v4l2_streamparm parm;
5929 int rc = 0;
5930 struct venc_framerate frame_rate_cfg;
5931 Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator);
5932 parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5933 parm.parm.output.timeperframe.numerator = frame_rate_cfg.fps_denominator;
5934 parm.parm.output.timeperframe.denominator = frame_rate_cfg.fps_numerator;
5935
5936 if (vqzip_sei_info.enabled) {
5937 DEBUG_PRINT_HIGH("For VQZIP 1.0, Framerate setting is not supported");
5938 return true;
5939 }
5940
5941
5942 if (frame_rate_cfg.fps_numerator > 0)
5943 rc = ioctl(m_nDriver_fd, VIDIOC_S_PARM, &parm);
5944
5945 if (rc) {
5946 DEBUG_PRINT_ERROR("ERROR: Request for setting framerate failed");
5947 return false;
5948 }
5949
5950 m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator;
5951 m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator;
5952
5953 return true;
5954 }
5955
venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat)5956 unsigned long venc_dev::venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat)
5957 {
5958 unsigned long codectype = V4L2_PIX_FMT_H264;
5959
5960 switch ((int)eCompressionFormat) {
5961 case OMX_VIDEO_CodingAVC:
5962 codectype = V4L2_PIX_FMT_H264;
5963 break;
5964 case OMX_VIDEO_CodingVP8:
5965 codectype = V4L2_PIX_FMT_VP8;
5966 break;
5967 case OMX_VIDEO_CodingVP9:
5968 codectype = V4L2_PIX_FMT_VP9;
5969 break;
5970 case OMX_VIDEO_CodingHEVC:
5971 case OMX_VIDEO_CodingImageHEIC:
5972 codectype = V4L2_PIX_FMT_HEVC;
5973 break;
5974 case QOMX_VIDEO_CodingTME:
5975 codectype = V4L2_PIX_FMT_TME;
5976 break;
5977 default:
5978 DEBUG_PRINT_ERROR("Unsupported eCompressionFormat %#x", eCompressionFormat);
5979 codectype = V4L2_PIX_FMT_H264;
5980 break;
5981 }
5982
5983 return codectype;
5984 }
5985
venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)5986 unsigned long venc_dev::venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat)
5987 {
5988 unsigned long format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
5989
5990 switch ((int)eColorFormat) {
5991 case OMX_COLOR_FormatYUV420SemiPlanar:
5992 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
5993 format = V4L2_PIX_FMT_NV12;
5994 break;
5995 case QOMX_COLOR_FormatYVU420SemiPlanar:
5996 format = V4L2_PIX_FMT_NV21;
5997 break;
5998 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
5999 format = V4L2_PIX_FMT_NV12_UBWC;
6000 break;
6001 case QOMX_COLOR_Format32bitRGBA8888:
6002 format = V4L2_PIX_FMT_RGB32;
6003 break;
6004 case QOMX_COLOR_Format32bitRGBA8888Compressed:
6005 format = V4L2_PIX_FMT_RGBA8888_UBWC;
6006 break;
6007 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
6008 format = V4L2_PIX_FMT_NV12_TP10_UBWC;
6009 break;
6010 case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
6011 format = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
6012 break;
6013 default:
6014 DEBUG_PRINT_INFO("WARN: Unsupported eColorFormat %#x", eColorFormat);
6015 format = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
6016 break;
6017 }
6018
6019 if (m_codec == OMX_VIDEO_CodingImageHEIC)
6020 format = V4L2_PIX_FMT_NV12_512;
6021
6022 return format;
6023 }
6024
venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)6025 bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)
6026 {
6027 struct v4l2_format fmt;
6028 int color_space = 0;
6029 DEBUG_PRINT_LOW("venc_set_color_format: color_format = %u ", color_format);
6030
6031 switch ((int)color_format) {
6032 case OMX_COLOR_FormatYUV420SemiPlanar:
6033 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
6034 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
6035 color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6036 break;
6037 case QOMX_COLOR_FormatYVU420SemiPlanar:
6038 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21;
6039 color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6040 break;
6041 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed:
6042 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
6043 color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6044 break;
6045 case QOMX_COLOR_Format32bitRGBA8888:
6046 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGB32;
6047 break;
6048 case QOMX_COLOR_Format32bitRGBA8888Compressed:
6049 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGBA8888_UBWC;
6050 break;
6051 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed:
6052 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_TP10_UBWC;
6053 break;
6054 case QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus:
6055 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
6056 break;
6057 default:
6058 DEBUG_PRINT_HIGH("WARNING: Unsupported Color format [%d]", color_format);
6059 m_sVenc_cfg.inputformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT;
6060 color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
6061 DEBUG_PRINT_HIGH("Default color format NV12 UBWC is set");
6062 break;
6063 }
6064
6065 if (m_codec == OMX_VIDEO_CodingImageHEIC)
6066 m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_512;
6067
6068 memset(&fmt, 0, sizeof(fmt));
6069 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6070 fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
6071 fmt.fmt.pix_mp.colorspace = color_space;
6072 fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
6073 fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
6074
6075 if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
6076 DEBUG_PRINT_ERROR("Failed setting color format %x", color_format);
6077 return false;
6078 }
6079
6080 return true;
6081 }
6082
venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)6083 bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)
6084 {
6085 DEBUG_PRINT_LOW("venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh);
6086
6087 if (intra_vop_refresh == OMX_TRUE) {
6088 struct v4l2_control control;
6089 int rc;
6090 control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME;
6091 control.value = 1;
6092
6093 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6094 if (rc) {
6095 DEBUG_PRINT_ERROR("Failed to set Intra Frame Request control");
6096 return false;
6097 }
6098 DEBUG_PRINT_HIGH("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6099 } else {
6100 DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect");
6101 }
6102
6103 return true;
6104 }
6105
venc_calibrate_gop()6106 bool venc_dev::venc_calibrate_gop()
6107 {
6108 int ratio, sub_gop_size, gop_size, nPframes, nBframes, nLayers;
6109 int num_sub_gops_in_a_gop;
6110 nPframes = intra_period.num_pframes;
6111 nBframes = intra_period.num_bframes;
6112 nLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers;
6113
6114 if (!nPframes && nLayers) {
6115 DEBUG_PRINT_ERROR("nPframes should be non-zero when nLayers are present\n");
6116 return false;
6117 }
6118
6119 if (nBframes && !nPframes) {
6120 DEBUG_PRINT_ERROR("nPframes should be non-zero when nBframes is non-zero\n");
6121 return false;
6122 }
6123
6124 if (nLayers > 1) { /*Multi-layer encoding*/
6125 sub_gop_size = 1 << (nLayers - 1);
6126 /* Actual GOP definition is nPframes + nBframes + 1 but for the sake of
6127 * below calculations we are ignoring +1 . Ignoring +1 in below
6128 * calculations is not a mistake but intentional.
6129 */
6130 gop_size = MAX(sub_gop_size, ROUND(nPframes + (nPframes * nBframes), sub_gop_size));
6131 num_sub_gops_in_a_gop = gop_size/sub_gop_size;
6132 if (nBframes) { /*Hier-B case*/
6133 /*
6134 * Frame Type--> I B B B P B B B P I B B P ...
6135 * Layer --> 0 2 1 2 0 2 1 2 0 0 2 1 2 ...
6136 * nPframes = 2, nBframes = 3, nLayers = 3
6137 *
6138 * Intention is to keep the intraperiod as close as possible to what is desired
6139 * by the client while adjusting nPframes and nBframes to meet other constraints.
6140 * eg1: Input by client: nPframes = 9, nBframes = 14, nLayers = 2
6141 * Output of this fn: nPframes = 12, nBframes = 12, nLayers = 2
6142 *
6143 * eg2: Input by client: nPframes = 9, nBframes = 4, nLayers = 2
6144 * Output of this fn: nPframes = 7, nBframes = 7, nLayers = 2
6145 */
6146 nPframes = num_sub_gops_in_a_gop;
6147 nBframes = sub_gop_size - 1;
6148 } else { /*Hier-P case*/
6149 /*
6150 * Frame Type--> I P P P P P P P I P P P P ...
6151 * Layer--> 0 2 1 2 0 2 1 2 0 2 1 2 0 ...
6152 * nPframes = 7, nBframes = 0, nLayers = 3
6153 *
6154 * Intention is to keep the intraperiod as close as possible to what is desired
6155 * by the client while adjusting nPframes and nBframes to meet other constraints.
6156 * eg1: Input by client: nPframes = 9, nBframes = 0, nLayers = 3
6157 * Output of this fn: nPframes = 7, nBframes = 0, nLayers = 3
6158 *
6159 * eg2: Input by client: nPframes = 10, nBframes = 0, nLayers = 3
6160 * Output of this fn:nPframes = 12, nBframes = 0, nLayers = 3
6161 */
6162 nPframes = gop_size - 1;
6163 }
6164 } else { /*Single-layer encoding*/
6165 /*
6166 * No special handling needed for single layer
6167 */
6168 DEBUG_PRINT_LOW("Clip num of P and B frames, nPframes: %d nBframes: %d",
6169 nPframes,nBframes);
6170 if ((unsigned int)nPframes > VENC_INFINITE_GOP) {
6171 nPframes = VENC_INFINITE_GOP;
6172 }
6173 if ((unsigned int)nBframes > VENC_INFINITE_GOP) {
6174 nBframes = VENC_INFINITE_GOP;
6175 }
6176 }
6177
6178 DEBUG_PRINT_LOW("P/B Frames changed from: %ld/%ld to %d/%d",
6179 intra_period.num_pframes, intra_period.num_bframes, nPframes, nBframes);
6180 intra_period.num_pframes = nPframes;
6181 intra_period.num_bframes = nBframes;
6182 return true;
6183 }
6184
venc_set_bitrate_type(OMX_U32 type)6185 bool venc_dev::venc_set_bitrate_type(OMX_U32 type)
6186 {
6187 struct v4l2_control control;
6188 int rc = 0;
6189 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE;
6190 control.value = type;
6191 DEBUG_PRINT_LOW("Set Bitrate type to %s for %d \n", bitrate_type_string(type), type);
6192 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6193 if (rc) {
6194 DEBUG_PRINT_ERROR("Request to set Bitrate type to %s failed",
6195 bitrate_type_string(type));
6196 return false;
6197 }
6198 return true;
6199 }
6200
venc_set_layer_bitrates(OMX_U32 * layerBitrate,OMX_U32 numLayers)6201 bool venc_dev::venc_set_layer_bitrates(OMX_U32 *layerBitrate, OMX_U32 numLayers)
6202 {
6203 DEBUG_PRINT_LOW("venc_set_layer_bitrates");
6204 struct v4l2_ext_control ctrl[2];
6205 struct v4l2_ext_controls controls;
6206 int rc = 0;
6207 OMX_U32 i;
6208
6209 if (!venc_set_bitrate_type(V4L2_MPEG_MSM_VIDC_ENABLE)) {
6210 DEBUG_PRINT_ERROR("Failed to set layerwise bitrate type %d", rc);
6211 return false;
6212 }
6213
6214 for (OMX_U32 i = 0; i < numLayers && i < OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS; ++i) {
6215 if (!layerBitrate[i]) {
6216 DEBUG_PRINT_ERROR("Invalid bitrate settings for layer %d", i);
6217 return false;
6218 } else {
6219 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LAYER_ID;
6220 ctrl[0].value = i;
6221 ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE;
6222 ctrl[1].value = layerBitrate[i];
6223
6224 controls.count = 2;
6225 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6226 controls.controls = ctrl;
6227
6228 rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6229 if (rc) {
6230 DEBUG_PRINT_ERROR("Failed to set layerwise bitrate %d", rc);
6231 return false;
6232 }
6233
6234 DEBUG_PRINT_LOW("Layerwise bitrate configured successfully for layer : %u bitrate : %u ",i, layerBitrate[i]);
6235 }
6236 }
6237 return true;
6238 }
6239
6240
venc_set_ltrmode(OMX_U32 enable,OMX_U32 count)6241 bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
6242 {
6243 DEBUG_PRINT_LOW("venc_set_ltrmode: enable = %u", (unsigned int)enable);
6244 struct v4l2_ext_control ctrl[2];
6245 struct v4l2_ext_controls controls;
6246 int rc;
6247
6248 if (enable && temporal_layers_config.hier_mode == HIER_P_HYBRID) {
6249 DEBUG_PRINT_ERROR("Invalid settings, LTR is being enabled with HybridHP");
6250 return false;
6251 }
6252
6253 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT;
6254 if (enable && count > 0)
6255 ctrl[0].value = count;
6256 else if (enable)
6257 ctrl[0].value = 1;
6258 else
6259 ctrl[0].value = 0;
6260
6261 controls.count = 1;
6262 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6263 controls.controls = ctrl;
6264
6265 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d id=%x, val=%d",
6266 controls.controls[0].id, controls.controls[0].value,
6267 controls.controls[1].id, controls.controls[1].value);
6268
6269 rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6270 if (rc) {
6271 DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc);
6272 return false;
6273 }
6274 ltrinfo.enabled = enable;
6275 ltrinfo.count = count;
6276
6277 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d id=%x, val=%d",
6278 controls.controls[0].id, controls.controls[0].value,
6279 controls.controls[1].id, controls.controls[1].value);
6280 return true;
6281 }
6282
venc_set_useltr(OMX_U32 frameIdx)6283 bool venc_dev::venc_set_useltr(OMX_U32 frameIdx)
6284 {
6285 DEBUG_PRINT_LOW("venc_use_goldenframe");
6286 int rc = true;
6287 struct v4l2_control control;
6288
6289 control.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME;
6290 control.value = frameIdx;
6291
6292 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6293 if (rc) {
6294 DEBUG_PRINT_ERROR("Failed to set use_ltr %d", rc);
6295 return false;
6296 }
6297
6298 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6299 control.id, control.value);
6300 return true;
6301 }
6302
venc_set_markltr(OMX_U32 frameIdx)6303 bool venc_dev::venc_set_markltr(OMX_U32 frameIdx)
6304 {
6305 DEBUG_PRINT_LOW("venc_set_goldenframe");
6306 int rc = true;
6307 struct v4l2_control control;
6308
6309 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME;
6310 control.value = frameIdx;
6311
6312 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6313 if (rc) {
6314 DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc);
6315 return false;
6316 }
6317
6318 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6319 control.id, control.value);
6320 return true;
6321 }
6322
venc_set_mirror(OMX_U32 mirror)6323 bool venc_dev::venc_set_mirror(OMX_U32 mirror)
6324 {
6325 DEBUG_PRINT_LOW("venc_set_mirror");
6326 int rc = true;
6327 struct v4l2_control control;
6328
6329 control.id = V4L2_CID_MPEG_VIDC_VIDEO_FLIP;
6330 control.value = mirror;
6331
6332 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6333 if (rc) {
6334 DEBUG_PRINT_ERROR("Failed to set mirror %d", rc);
6335 return false;
6336 }
6337
6338 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
6339 control.id, control.value);
6340 return true;
6341 }
6342
venc_set_vpe_rotation(OMX_S32 rotation_angle)6343 bool venc_dev::venc_set_vpe_rotation(OMX_S32 rotation_angle)
6344 {
6345 DEBUG_PRINT_LOW("venc_set_vpe_rotation: rotation angle = %d", (int)rotation_angle);
6346 struct v4l2_control control;
6347 int rc;
6348 struct v4l2_format fmt;
6349 struct v4l2_requestbuffers bufreq;
6350
6351 if ((OMX_S32)m_rotation.rotation == rotation_angle) {
6352 DEBUG_PRINT_HIGH("venc_set_vpe_rotation: rotation (%d) not changed", rotation_angle);
6353 return true;
6354 }
6355
6356 control.id = V4L2_CID_ROTATE;
6357 control.value = rotation_angle;
6358
6359 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6360 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6361 if (rc) {
6362 DEBUG_PRINT_HIGH("Failed to set VPE Rotation control");
6363 return false;
6364 }
6365 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6366
6367 /* successfully set rotation_angle, save it */
6368 m_rotation.rotation = rotation_angle;
6369
6370 return true;
6371 }
6372
venc_set_searchrange()6373 bool venc_dev::venc_set_searchrange()
6374 {
6375 DEBUG_PRINT_LOW("venc_set_searchrange");
6376 struct v4l2_control control;
6377 struct v4l2_ext_control ctrl[6];
6378 struct v4l2_ext_controls controls;
6379 int rc;
6380
6381 if ((m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) ||
6382 (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8)) {
6383 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE;
6384 ctrl[0].value = 16;
6385 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_Y_RANGE;
6386 ctrl[1].value = 4;
6387 ctrl[2].id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_X_RANGE;
6388 ctrl[2].value = 16;
6389 ctrl[3].id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_Y_RANGE;
6390 ctrl[3].value = 4;
6391 ctrl[4].id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_X_RANGE;
6392 ctrl[4].value = 12;
6393 ctrl[5].id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_Y_RANGE;
6394 ctrl[5].value = 4;
6395 } else {
6396 DEBUG_PRINT_ERROR("Invalid codec type");
6397 return false;
6398 }
6399 controls.count = 6;
6400 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6401 controls.controls = ctrl;
6402
6403 DEBUG_PRINT_LOW(" Calling IOCTL set control for"
6404 "id=%x, val=%d id=%x, val=%d"
6405 "id=%x, val=%d id=%x, val=%d"
6406 "id=%x, val=%d id=%x, val=%d",
6407 controls.controls[0].id, controls.controls[0].value,
6408 controls.controls[1].id, controls.controls[1].value,
6409 controls.controls[2].id, controls.controls[2].value,
6410 controls.controls[3].id, controls.controls[3].value,
6411 controls.controls[4].id, controls.controls[4].value,
6412 controls.controls[5].id, controls.controls[5].value);
6413
6414 rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6415 if (rc) {
6416 DEBUG_PRINT_ERROR("Failed to set search range %d", rc);
6417 return false;
6418 }
6419 return true;
6420 }
6421
venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)6422 bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
6423 {
6424 bool status = true;
6425 struct v4l2_control control;
6426 int rc = 0;
6427 control.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
6428
6429 int temp = eControlRate;
6430 switch ((OMX_U32)eControlRate) {
6431 case OMX_Video_ControlRateDisable:
6432 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF;
6433 break;
6434 case OMX_Video_ControlRateVariableSkipFrames:
6435 (supported_rc_modes & RC_VBR_VFR) ?
6436 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR :
6437 status = false;
6438 break;
6439 case OMX_Video_ControlRateVariable:
6440 (supported_rc_modes & RC_VBR_CFR) ?
6441 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR :
6442 status = false;
6443 break;
6444 case OMX_Video_ControlRateConstantSkipFrames:
6445 (supported_rc_modes & RC_CBR_VFR) ?
6446 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR :
6447 status = false;
6448 break;
6449 case OMX_Video_ControlRateConstant:
6450 (supported_rc_modes & RC_CBR_CFR) ?
6451 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
6452 status = false;
6453 break;
6454 case QOMX_Video_ControlRateMaxBitrate:
6455 (supported_rc_modes & RC_MBR_CFR) ?
6456 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR:
6457 status = false;
6458 break;
6459 case QOMX_Video_ControlRateMaxBitrateSkipFrames:
6460 (supported_rc_modes & RC_MBR_VFR) ?
6461 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR:
6462 status = false;
6463 break;
6464 case OMX_Video_ControlRateConstantQuality:
6465 (supported_rc_modes & RC_CQ) ?
6466 control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CQ:
6467 status = false;
6468 break;
6469 default:
6470 status = false;
6471 break;
6472 }
6473
6474 if (status) {
6475
6476 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6477 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6478
6479 if (rc) {
6480 DEBUG_PRINT_ERROR("Failed to set control");
6481 return false;
6482 }
6483
6484 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6485
6486 rate_ctrl.rcmode = control.value;
6487 }
6488
6489 {
6490 DEBUG_PRINT_LOW("Set bitrate savings %d", mBitrateSavingsEnable);
6491 control.id = V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS;
6492 control.value = mBitrateSavingsEnable;
6493 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6494 if (rc) {
6495 DEBUG_PRINT_HIGH("Non-Fatal: Request to set bitrate savings failed");
6496 }
6497 }
6498
6499 #ifdef _VQZIP_
6500 if (eControlRate == OMX_Video_ControlRateVariable && (supported_rc_modes & RC_VBR_CFR)
6501 && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
6502 /* Enable VQZIP SEI by default for camcorder RC modes */
6503
6504 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI;
6505 control.value = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI_ENABLE;
6506 DEBUG_PRINT_HIGH("Set VQZIP SEI:");
6507 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
6508 DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed");
6509 }
6510 }
6511 #endif
6512
6513 return status;
6514 }
6515
venc_set_aspectratio(void * nSar)6516 bool venc_dev::venc_set_aspectratio(void *nSar)
6517 {
6518 int rc;
6519 struct v4l2_control control;
6520 struct v4l2_ext_control ctrl[2];
6521 struct v4l2_ext_controls controls;
6522 QOMX_EXTNINDEX_VIDEO_VENC_SAR *sar;
6523
6524 sar = (QOMX_EXTNINDEX_VIDEO_VENC_SAR *) nSar;
6525
6526 ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_WIDTH;
6527 ctrl[0].value = sar->nSARWidth;
6528 ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_HEIGHT;
6529 ctrl[1].value = sar->nSARHeight;
6530
6531 controls.count = 2;
6532 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6533 controls.controls = ctrl;
6534
6535 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x val=%d, id=%x val=%d",
6536 controls.controls[0].id, controls.controls[0].value,
6537 controls.controls[1].id, controls.controls[1].value);
6538
6539 rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
6540 if (rc) {
6541 DEBUG_PRINT_ERROR("Failed to set SAR %d", rc);
6542 return false;
6543 }
6544
6545 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x val=%d, id=%x val=%d",
6546 controls.controls[0].id, controls.controls[0].value,
6547 controls.controls[1].id, controls.controls[1].value);
6548 return true;
6549 }
6550
venc_set_lowlatency_mode(OMX_BOOL enable)6551 bool venc_dev::venc_set_lowlatency_mode(OMX_BOOL enable)
6552 {
6553 int rc = 0;
6554 struct v4l2_control control;
6555
6556 control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
6557 if (enable)
6558 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6559 else
6560 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6561
6562 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6563 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6564 if (rc) {
6565 DEBUG_PRINT_ERROR("Failed to set lowlatency control");
6566 return false;
6567 }
6568 low_latency_mode = enable;
6569 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6570
6571 return true;
6572 }
6573
venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type)6574 bool venc_dev::venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type)
6575 {
6576 struct v4l2_control control;
6577 control.id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE;
6578
6579 switch (type) {
6580 case QOMX_IFRAMESIZE_DEFAULT:
6581 control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
6582 break;
6583 case QOMX_IFRAMESIZE_MEDIUM:
6584 control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM;
6585 break;
6586 case QOMX_IFRAMESIZE_HUGE:
6587 control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE;
6588 break;
6589 case QOMX_IFRAMESIZE_UNLIMITED:
6590 control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED;
6591 break;
6592 default:
6593 DEBUG_PRINT_INFO("Unknown Iframe Size found setting it to default");
6594 control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
6595 }
6596
6597 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6598 DEBUG_PRINT_ERROR("Failed to set iframe size hint");
6599 return false;
6600 }
6601
6602 return true;
6603 }
6604
venc_set_baselayerid(OMX_U32 baseid)6605 bool venc_dev::venc_set_baselayerid(OMX_U32 baseid)
6606 {
6607 struct v4l2_control control;
6608 if (temporal_layers_config.hier_mode == HIER_P) {
6609 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID;
6610 control.value = baseid;
6611 DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
6612 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6613 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID");
6614 return false;
6615 }
6616 return true;
6617 } else {
6618 DEBUG_PRINT_ERROR("Invalid mode set for V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID: %d",
6619 temporal_layers_config.hier_mode);
6620 return false;
6621 }
6622 }
6623
venc_set_vui_timing_info(OMX_BOOL enable)6624 bool venc_dev::venc_set_vui_timing_info(OMX_BOOL enable)
6625 {
6626 struct v4l2_control control;
6627 int rc = 0;
6628 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO;
6629
6630 if (enable)
6631 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6632 else
6633 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6634
6635 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
6636 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6637 if (rc) {
6638 DEBUG_PRINT_ERROR("Failed to set VUI timing info control");
6639 return false;
6640 }
6641 DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
6642 return true;
6643 }
6644
venc_set_peak_bitrate(OMX_U32 nPeakBitrate)6645 bool venc_dev::venc_set_peak_bitrate(OMX_U32 nPeakBitrate)
6646 {
6647 struct v4l2_control control;
6648 int rc = 0;
6649 control.id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
6650 control.value = nPeakBitrate;
6651
6652 DEBUG_PRINT_LOW("venc_set_peak_bitrate: bitrate = %u", (unsigned int)nPeakBitrate);
6653
6654 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6655 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6656
6657 if (rc) {
6658 DEBUG_PRINT_ERROR("Failed to set peak bitrate control");
6659 return false;
6660 }
6661
6662 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6663
6664 return true;
6665 }
6666
venc_set_vpx_error_resilience(OMX_BOOL enable)6667 bool venc_dev::venc_set_vpx_error_resilience(OMX_BOOL enable)
6668 {
6669 struct v4l2_control control;
6670 int rc = 0;
6671 control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE;
6672
6673 if (enable)
6674 control.value = 1;
6675 else
6676 control.value = 0;
6677
6678 DEBUG_PRINT_LOW("venc_set_vpx_error_resilience: %d", control.value);
6679
6680 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
6681
6682 rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
6683 if (rc) {
6684 DEBUG_PRINT_ERROR("Failed to set VPX Error Resilience");
6685 return false;
6686 }
6687 vpx_err_resilience.enable = 1;
6688 DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
6689 return true;
6690 }
6691
venc_set_priority(OMX_U32 priority)6692 bool venc_dev::venc_set_priority(OMX_U32 priority) {
6693 struct v4l2_control control;
6694
6695 DEBUG_PRINT_LOW("venc_set_priority: %s", priority ? "NonRealTime" : "RealTime");
6696 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
6697 if (priority == 0)
6698 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6699 else
6700 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6701
6702 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6703 DEBUG_PRINT_ERROR("Failed to set V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_%s",
6704 priority == 0 ? "ENABLE" : "DISABLE");
6705 return false;
6706 }
6707 return true;
6708 }
6709
venc_set_operatingrate(OMX_U32 rate)6710 bool venc_dev::venc_set_operatingrate(OMX_U32 rate) {
6711 struct v4l2_control control;
6712
6713 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
6714 control.value = rate;
6715
6716 DEBUG_PRINT_LOW("venc_set_operating_rate: %u fps", rate >> 16);
6717 DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%u", control.id, control.value);
6718
6719 if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6720 hw_overload = errno == EBUSY;
6721 DEBUG_PRINT_ERROR("Failed to set operating rate %d fps (%s)",
6722 rate >> 16, hw_overload ? "HW overload" : strerror(errno));
6723 return false;
6724 }
6725 if (rate == QOMX_VIDEO_HIGH_PERF_OPERATING_MODE) {
6726 DEBUG_PRINT_LOW("Turbo mode requested");
6727 client_req_turbo_mode = true;
6728 } else {
6729 operating_rate = rate >> 16;
6730 client_req_turbo_mode = false;
6731 DEBUG_PRINT_LOW("Operating Rate Set = %d fps", rate >> 16);
6732 }
6733
6734 return true;
6735 }
6736
venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO * roiInfo)6737 bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo)
6738 {
6739 struct roidata roi;
6740
6741 if (!m_roi_enabled) {
6742 DEBUG_PRINT_ERROR("ROI info not enabled");
6743 return false;
6744 }
6745
6746 if (!roiInfo) {
6747 DEBUG_PRINT_ERROR("No ROI info present");
6748 return false;
6749 }
6750 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
6751 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
6752 DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", (OMX_U32) m_sVenc_cfg.codectype);
6753 return false;
6754 }
6755
6756 memset(&roi, 0, sizeof(struct roidata));
6757
6758 roi.info.nRoiMBInfoCount = roiInfo->nRoiMBInfoCount;
6759 roi.info.nTimeStamp = roiInfo->nTimeStamp;
6760 memcpy(roi.info.pRoiMBInfo, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoCount);
6761
6762 roi.dirty = true;
6763
6764 pthread_mutex_lock(&m_roilock);
6765 DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.info.nTimeStamp);
6766 m_roilist.push_back(roi);
6767 pthread_mutex_unlock(&m_roilock);
6768
6769 return true;
6770 }
6771
venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO * blurInfo)6772 bool venc_dev::venc_set_blur_resolution(OMX_QTI_VIDEO_CONFIG_BLURINFO *blurInfo)
6773 {
6774 struct v4l2_ext_control ctrl[2];
6775 struct v4l2_ext_controls controls;
6776
6777 int blur_width = 0, blur_height = 0;
6778
6779 switch (blurInfo->nBlurInfo) {
6780 case 0:
6781 blur_width = 0;
6782 blur_height = 0;
6783 [[fallthrough]];
6784 case 1:
6785 blur_width = 1;
6786 blur_height = 1;
6787 [[fallthrough]];
6788 default:
6789 blur_width = blurInfo->nBlurInfo >> 16;
6790 blur_height = blurInfo->nBlurInfo & 0xFFFF;
6791 DEBUG_PRINT_LOW("Custom blur resolution %ux%u", blur_width, blur_height);
6792 break;
6793 }
6794
6795 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH;
6796 ctrl[0].value = blur_width;
6797
6798 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT;
6799 ctrl[1].value = blur_height;
6800
6801 controls.count = 2;
6802 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
6803 controls.controls = ctrl;
6804
6805 if(ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
6806 DEBUG_PRINT_ERROR("Failed to set blur resoltion");
6807 return false;
6808 }
6809 DEBUG_PRINT_LOW("Blur resolution set = %u x %u", blur_width, blur_height);
6810 return true;
6811
6812 }
6813
venc_h264_transform_8x8(OMX_BOOL enable)6814 bool venc_dev::venc_h264_transform_8x8(OMX_BOOL enable)
6815 {
6816 struct v4l2_control control;
6817
6818 control.id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM;
6819 if (enable)
6820 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
6821 else
6822 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
6823
6824 DEBUG_PRINT_LOW("Set h264_transform_8x8 mode: %d", control.value);
6825 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6826 DEBUG_PRINT_ERROR("set control: H264 transform 8x8 failed");
6827 return false;
6828 }
6829
6830 return true;
6831 }
6832
venc_get_temporal_layer_caps(OMX_U32 * nMaxLayers,OMX_U32 * nMaxBLayers,OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE * eSupportedPattern)6833 bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers,
6834 OMX_U32 *nMaxBLayers, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE *eSupportedPattern) {
6835 struct v4l2_queryctrl query_ctrl;
6836
6837 if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC || m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
6838 *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
6839 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
6840 *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
6841 } else {
6842 *eSupportedPattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone;
6843 }
6844
6845 if(venc_check_for_hybrid_hp(*eSupportedPattern)) {
6846 query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6847 } else {
6848 query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
6849 }
6850
6851 DEBUG_PRINT_LOW("TemporalLayer: Querying P layer caps");
6852 if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
6853 DEBUG_PRINT_ERROR("TemporalLayer: Query control P layer caps failed");
6854 return false;
6855 }
6856
6857 //Return +1 as driver works on num max enhancement layers and OMX on num layers
6858 *nMaxLayers = query_ctrl.maximum + 1;
6859
6860 query_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS;
6861 DEBUG_PRINT_LOW("TemporalLayer: Querying B layer caps");
6862 if (ioctl(m_nDriver_fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
6863 DEBUG_PRINT_ERROR("TemporalLayer: Query control B layer caps faile");
6864 return false;
6865 }
6866
6867 *nMaxBLayers = query_ctrl.maximum;
6868 return true;
6869 }
6870
venc_check_for_hybrid_hp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern)6871 bool venc_dev::venc_check_for_hybrid_hp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern) {
6872 //Hybrid HP is only for H264 and VBR CFR
6873 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264) {
6874 DEBUG_PRINT_LOW("TemporalLayer: Hybrid HierP is not supported for non H264");
6875 return false;
6876 }
6877
6878 if (ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
6879 DEBUG_PRINT_LOW("TemporalLayer: The pattern must be Android for Hybrid HP");
6880 return false;
6881 }
6882 if (rate_ctrl.rcmode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
6883 DEBUG_PRINT_LOW("TemporalLayer: RC must be VBR CFR for HybridHP");
6884 return false;
6885 }
6886 return true;
6887 }
6888
venc_check_for_hierp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern)6889 bool venc_dev::venc_check_for_hierp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern) {
6890
6891 if (ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
6892 DEBUG_PRINT_LOW("TemporalLayer: Incorrect Pattern for H264/HEVC");
6893 return false;
6894 }
6895
6896 return true;
6897 }
6898
venc_find_hier_type(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6899 int venc_dev::venc_find_hier_type(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6900
6901 enum hier_type hier;
6902
6903 if (venc_check_for_hybrid_hp(temporal_settings.ePattern)) {
6904 hier = HIER_P_HYBRID;
6905 } else if (venc_check_for_hierp(temporal_settings.ePattern)) {
6906 hier = HIER_P;
6907 } else {
6908 hier = HIER_NONE;
6909 }
6910
6911 if (!venc_validate_temporal_extn(temporal_settings)) {
6912 hier = HIER_NONE;
6913 }
6914
6915 return hier;
6916 }
6917
venc_set_hp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6918 OMX_ERRORTYPE venc_dev::venc_set_hp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6919
6920 struct v4l2_control control;
6921 OMX_U32 maxLayerCount = 0;
6922
6923 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS;
6924 control.value = temporal_settings.nLayerCountMax - 1;
6925
6926 DEBUG_PRINT_LOW("TemporalLayer: Setting HP with max layers: %u num layers : %u",
6927 temporal_settings.nLayerCountMax - 1,
6928 temporal_settings.nPLayerCountActual - 1);
6929
6930 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6931 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set max HP layers to %u", control.value);
6932 return OMX_ErrorUnsupportedSetting;
6933 }
6934
6935 maxLayerCount = control.value + 1;
6936
6937 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
6938 control.value = temporal_settings.nPLayerCountActual - 1;
6939 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6940 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set hybrid hierp/hierp NumLayers : %u", control.value);
6941 return OMX_ErrorUnsupportedSetting;
6942 }
6943
6944 temporal_layers_config.ePattern = temporal_settings.ePattern;
6945 temporal_layers_config.hier_mode = HIER_P;
6946 temporal_layers_config.nPLayers = control.value + 1;
6947 temporal_layers_config.nMaxLayers = maxLayerCount;
6948 temporal_layers_config.nBLayers = 0;
6949 temporal_layers_config.nMaxBLayers = 0;
6950
6951 return OMX_ErrorNone;
6952 }
6953
venc_set_hhp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)6954 OMX_ERRORTYPE venc_dev::venc_set_hhp(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
6955
6956 struct v4l2_control control;
6957
6958 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6959 control.value = temporal_settings.nPLayerCountActual - 1;
6960
6961 DEBUG_PRINT_LOW("TemporalLayer: Setting HybridHP with num layers : %u", control.value);
6962
6963 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
6964 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set hybrid HP. Try HierP");
6965 return OMX_ErrorUnsupportedSetting;
6966 }
6967
6968 temporal_layers_config.ePattern = temporal_settings.ePattern;
6969 temporal_layers_config.hier_mode = HIER_P_HYBRID;
6970 temporal_layers_config.nPLayers = control.value + 1;
6971 temporal_layers_config.nMaxLayers = control.value + 1;
6972 temporal_layers_config.nBLayers = 0;
6973 temporal_layers_config.nMaxBLayers = 0;
6974 if (ltrinfo.enabled) {
6975 if (!venc_set_ltrmode(0, 0)) {
6976 DEBUG_PRINT_ERROR("TemporalLayer: Failed to disable LTR when HybridHP is enabled");
6977 return OMX_ErrorUndefined;
6978 }
6979 }
6980 return OMX_ErrorNone;
6981 }
venc_disable_hhp()6982 OMX_ERRORTYPE venc_dev::venc_disable_hhp() {
6983
6984 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264) {
6985 return OMX_ErrorNone;
6986 }
6987
6988 struct v4l2_control control;
6989
6990 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
6991 control.value = 0;
6992
6993 if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control)) {
6994 DEBUG_PRINT_ERROR("TemporalLayer: Failed to get hybrid HP");
6995 return OMX_ErrorUnsupportedSetting;
6996 }
6997
6998 if (control.value != 0) {
6999 control.value = 0;
7000
7001 DEBUG_PRINT_LOW("TemporalLayer: Disabling HybridHP");
7002
7003 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7004 DEBUG_PRINT_ERROR("TemporalLayer: Failed to disable hybrid HP");
7005 return OMX_ErrorUnsupportedSetting;
7006 }
7007 }
7008
7009 return OMX_ErrorNone;
7010 }
7011
venc_disable_hp()7012 OMX_ERRORTYPE venc_dev::venc_disable_hp() {
7013
7014 struct v4l2_control control;
7015
7016 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS;
7017 control.value = 0;
7018
7019 DEBUG_PRINT_LOW("TemporalLayer: Disabling HP");
7020
7021 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7022 DEBUG_PRINT_ERROR("TemporalLayer: Failed to reset max HP layers to %u", control.value);
7023 return OMX_ErrorUnsupportedSetting;
7024 }
7025
7026 control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
7027 control.value = 0;
7028
7029 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
7030 DEBUG_PRINT_ERROR("TemporalLayer: Failed to reset HP layers to %u", control.value);
7031 return OMX_ErrorUnsupportedSetting;
7032 }
7033
7034 return OMX_ErrorNone;
7035 }
7036
venc_set_bitrate_ratio(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7037 OMX_ERRORTYPE venc_dev::venc_set_bitrate_ratio(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7038
7039 OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0};
7040 OMX_U32 numLayers = temporal_settings.nPLayerCountActual + temporal_settings.nBLayerCountActual;
7041
7042 if (temporal_settings.bBitrateRatiosSpecified == OMX_FALSE) {
7043 DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio not specified. Will use cumulative");
7044
7045 if (!venc_set_bitrate_type(V4L2_MPEG_MSM_VIDC_DISABLE)) {
7046 return OMX_ErrorUnsupportedSetting;
7047 }
7048 return OMX_ErrorNone;
7049 }
7050
7051 DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio specified");
7052
7053 for (OMX_U32 i = 0; i < numLayers; ++i) {
7054 OMX_U32 previousLayersAccumulatedBitrateRatio = (i == 0) ? 0 : temporal_settings.nBitrateRatios[i-1];
7055 OMX_U32 currentLayerBitrateRatio = temporal_settings.nBitrateRatios[i] - previousLayersAccumulatedBitrateRatio;
7056 if (previousLayersAccumulatedBitrateRatio > temporal_settings.nBitrateRatios[i]) {
7057 DEBUG_PRINT_ERROR("TemporalLayer: invalid bitrate ratio for layer %d.. Will fallback to cumulative", i);
7058 return OMX_ErrorBadParameter;
7059 } else {
7060 layerBitrates[i] = (currentLayerBitrateRatio * bitrate.target_bitrate) / 100;
7061 temporal_layers_config.nTemporalLayerBitrateRatio[i] = temporal_settings.nBitrateRatios[i];
7062 temporal_layers_config.nTemporalLayerBitrateFraction[i] = currentLayerBitrateRatio;
7063 DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)",
7064 i, currentLayerBitrateRatio, layerBitrates[i], bitrate.target_bitrate);
7065 }
7066 }
7067
7068 temporal_layers_config.bIsBitrateRatioValid = OMX_TRUE;
7069
7070 // Setting layerwise bitrate makes sense only if target bitrate is configured, else defer until later
7071 if (bitrate.target_bitrate > 0) {
7072 if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) {
7073 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set layer bitrate");
7074 return OMX_ErrorUnsupportedSetting;
7075 }
7076 } else {
7077 DEBUG_PRINT_HIGH("TemporalLayer: Defer setting layerwise bitrate since target bitrate is not yet set");
7078 }
7079
7080 return OMX_ErrorNone;
7081 }
7082
venc_validate_temporal_settings()7083 bool venc_dev::venc_validate_temporal_settings() {
7084
7085 if (intra_period.num_bframes > 0 || intra_period.num_pframes == 0) {
7086 DEBUG_PRINT_HIGH("TemporalLayer: Invalid P-frame/B-frame settings for Hier layers");
7087 return false;
7088 }
7089 return true;
7090 }
7091
venc_validate_temporal_extn(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7092 bool venc_dev::venc_validate_temporal_extn(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7093
7094 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 && m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC &&
7095 temporal_settings.nPLayerCountActual > 1) {
7096 DEBUG_PRINT_LOW("TemporalLayer: Layer encoding supported for H264 & HEVC");
7097 return false;
7098 }
7099
7100 if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS, temporal_settings.nBLayerCountMax - 1) &&
7101 (temporal_settings.nBLayerCountMax > 0)) {
7102 DEBUG_PRINT_INFO("WARN: TemporalLayer: Invalid settings, hardware doesn't"
7103 " support %u HB layers", temporal_settings.nBLayerCountMax);
7104 return false;
7105 }
7106
7107 if (!venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS, temporal_settings.nLayerCountMax - 1) &&
7108 !venc_validate_range(V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE, temporal_settings.nLayerCountMax - 1)) {
7109 DEBUG_PRINT_INFO("WARN: TemporalLayer: Invalid settings, hardware doesn't"
7110 " support %u temporal layers", temporal_settings.nLayerCountMax);
7111 return false;
7112 }
7113
7114 if (temporal_settings.nPLayerCountActual > temporal_settings.nLayerCountMax) {
7115 DEBUG_PRINT_HIGH("TemporalLayer: Invalid num of max layers");
7116 return false;
7117 }
7118
7119 if (temporal_settings.ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
7120 DEBUG_PRINT_LOW("TemporalLayer: The pattern must be Android for Hybrid HP");
7121 return false;
7122 }
7123
7124 if ((streaming[CAPTURE_PORT] == true || streaming[OUTPUT_PORT] == true) && (temporal_layers_config.hier_mode == HIER_P_HYBRID)) {
7125 DEBUG_PRINT_HIGH("TemporalLayer: Cannot change Hybrid HP settings during streaming");
7126 return false;
7127 }
7128
7129 if ((streaming[CAPTURE_PORT] == true || streaming[OUTPUT_PORT] == true) &&
7130 ((temporal_settings.nPLayerCountActual > temporal_layers_config.nMaxLayers) ||
7131 (temporal_settings.nLayerCountMax != temporal_layers_config.nMaxLayers))) {
7132 DEBUG_PRINT_HIGH("TemporalLayer: Invalid value for Layer count during streaming");
7133 return false;
7134 }
7135
7136 return true;
7137 }
7138
venc_set_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporal_settings)7139 OMX_ERRORTYPE venc_dev::venc_set_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporal_settings) {
7140
7141 if (venc_find_hier_type(temporal_settings) == HIER_P) {
7142
7143 if (venc_disable_hhp() != OMX_ErrorNone) {
7144 return OMX_ErrorUnsupportedSetting;
7145 }
7146 if (venc_set_hp(temporal_settings) != OMX_ErrorNone) {
7147 return OMX_ErrorUnsupportedSetting;
7148 }
7149 if (venc_set_bitrate_ratio(temporal_settings) != OMX_ErrorNone) {
7150 return OMX_ErrorUnsupportedSetting;
7151 }
7152
7153
7154 } else if (venc_find_hier_type(temporal_settings) == HIER_P_HYBRID) {
7155
7156 if (venc_disable_hp() != OMX_ErrorNone) {
7157 return OMX_ErrorUnsupportedSetting;
7158 }
7159 if (venc_set_hhp(temporal_settings) != OMX_ErrorNone) {
7160 return OMX_ErrorUnsupportedSetting;
7161 }
7162 if (venc_set_bitrate_ratio(temporal_settings) != OMX_ErrorNone) {
7163 return OMX_ErrorUnsupportedSetting;
7164 }
7165
7166 } else {
7167
7168 if (venc_disable_hhp() != OMX_ErrorNone) {
7169 return OMX_ErrorUnsupportedSetting;
7170 }
7171 if (venc_disable_hp() != OMX_ErrorNone) {
7172 return OMX_ErrorUnsupportedSetting;
7173 }
7174 memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
7175 }
7176
7177 return OMX_ErrorNone;
7178 }
7179
venc_copy_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE & temporalParams)7180 void venc_dev::venc_copy_temporal_settings(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporalParams) {
7181
7182 OMX_U32 previousLayersAccumulatedBitrateRatio = 0;
7183 memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
7184
7185 temporal_layers_config.nMaxLayers = temporalParams.nLayerCountMax ;
7186 temporal_layers_config.nMaxBLayers = temporalParams.nBLayerCountMax ;
7187 temporal_layers_config.ePattern = temporalParams.ePattern;
7188 temporal_layers_config.nPLayers = temporalParams.nPLayerCountActual;
7189 temporal_layers_config.nBLayers = temporalParams.nBLayerCountActual;
7190 temporal_layers_config.bIsBitrateRatioValid = temporalParams.bBitrateRatiosSpecified;
7191
7192 if (temporalParams.bBitrateRatiosSpecified == OMX_TRUE) {
7193 for (OMX_U32 i = 0; i < temporalParams.nPLayerCountActual + temporalParams.nBLayerCountActual; ++i) {
7194 previousLayersAccumulatedBitrateRatio = (i == 0) ? 0 : temporalParams.nBitrateRatios[i-1];
7195 temporal_layers_config.nTemporalLayerBitrateRatio[i] = temporalParams.nBitrateRatios[i];
7196 temporal_layers_config.nTemporalLayerBitrateFraction[i] =
7197 temporalParams.nBitrateRatios[i] - previousLayersAccumulatedBitrateRatio;
7198 }
7199 }
7200
7201 if (temporalParams.nPLayerCountActual <= 1 ||
7202 temporalParams.ePattern == OMX_VIDEO_AndroidTemporalLayeringPatternNone) {
7203 client_req_disable_temporal_layers = true;
7204 } else {
7205 client_req_disable_temporal_layers = false;
7206 }
7207 }
7208
venc_reconfigure_temporal_settings()7209 bool venc_dev::venc_reconfigure_temporal_settings() {
7210
7211 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE temporalParams;
7212 memset(&temporalParams, 0x0, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE));
7213
7214 DEBUG_PRINT_HIGH("TemporalLayer: Reconfigure temporal layer settings");
7215
7216 if (!venc_validate_temporal_settings()) {
7217 DEBUG_PRINT_HIGH("TemporalLayer: Cannot enable temporal layers");
7218 return true;
7219 }
7220
7221 temporalParams.nLayerCountMax = temporal_layers_config.nMaxLayers;
7222 temporalParams.nBLayerCountMax = temporal_layers_config.nMaxBLayers;
7223 temporalParams.ePattern = temporal_layers_config.ePattern;
7224 temporalParams.nPLayerCountActual = temporal_layers_config.nPLayers;
7225 temporalParams.nBLayerCountActual = temporal_layers_config.nBLayers;
7226 temporalParams.bBitrateRatiosSpecified = temporal_layers_config.bIsBitrateRatioValid;
7227
7228 if (temporal_layers_config.bIsBitrateRatioValid == OMX_TRUE) {
7229 for (OMX_U32 i = 0; i < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers; ++i) {
7230 temporalParams.nBitrateRatios[i] =
7231 temporal_layers_config.nTemporalLayerBitrateRatio[i];
7232 }
7233 }
7234
7235 if (venc_set_temporal_settings(temporalParams) != OMX_ErrorNone) {
7236 DEBUG_PRINT_ERROR("TemporalLayer: Failed to set temporal settings");
7237 return false;
7238 }
7239
7240 return true;
7241 }
7242
venc_reconfigure_ltrmode()7243 bool venc_dev::venc_reconfigure_ltrmode() {
7244
7245 if ((ltrinfo.enabled == true) && (temporal_layers_config.hier_mode == HIER_P_HYBRID) &&
7246 (temporal_layers_config.nPLayers > 1)) {
7247
7248 if (!venc_set_ltrmode(0, 0)) {
7249 DEBUG_PRINT_ERROR("Failed to disable LTR when HybridHP is enabled");
7250 return false;
7251 }
7252 }
7253 return true;
7254 }
7255
venc_get_hevc_profile(OMX_U32 * profile)7256 bool venc_dev::venc_get_hevc_profile(OMX_U32* profile)
7257 {
7258 if (profile == nullptr) return false;
7259
7260 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
7261 if(profile_level_converter::convert_v4l2_profile_to_omx(V4L2_PIX_FMT_HEVC, codec_profile.profile, (int*)profile)) {
7262 return true;
7263 } else return false;
7264 } else return false;
7265 }
7266
venc_get_consumer_usage(OMX_U32 * usage)7267 void venc_dev::venc_get_consumer_usage(OMX_U32* usage) {
7268
7269 OMX_U32 eProfile = 0;
7270 bool hevc = venc_get_hevc_profile(&eProfile);
7271
7272 /* Initialize to zero & update as per required color format */
7273 *usage = 0;
7274
7275 if (hevc && eProfile == (OMX_U32)OMX_VIDEO_HEVCProfileMain10HDR10) {
7276 DEBUG_PRINT_INFO("Setting 10-bit consumer usage bits");
7277 *usage |= GRALLOC_USAGE_PRIVATE_10BIT_VIDEO;
7278 if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_10_BIT) {
7279 *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7280 DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 10-bit linear color requested");
7281 }
7282 } else if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_8_BIT) {
7283 *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7284 DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 8-bit linear color requested");
7285 }
7286
7287 if (m_codec == OMX_VIDEO_CodingImageHEIC) {
7288 DEBUG_PRINT_INFO("Clear UBWC and set HEIF consumer usage bit");
7289 *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7290 *usage |= GRALLOC_USAGE_PRIVATE_HEIF_VIDEO;
7291 }
7292
7293 if (!strncmp(m_platform_name, "trinket", 7)) {
7294 if (m_sVenc_cfg.input_width < 640 || m_sVenc_cfg.input_height < 480) {
7295 *usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
7296 }
7297 }
7298
7299 DEBUG_PRINT_INFO("venc_get_consumer_usage 0x%x", *usage);
7300 }
7301
venc_get_profile_level(OMX_U32 * eProfile,OMX_U32 * eLevel)7302 bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
7303 {
7304 bool status = true;
7305
7306 if (eProfile == NULL || eLevel == NULL) {
7307 return false;
7308 }
7309
7310 if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
7311 switch (codec_profile.profile) {
7312 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
7313 *eProfile = OMX_VIDEO_AVCProfileBaseline;
7314 break;
7315 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
7316 *eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
7317 break;
7318 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
7319 *eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
7320 break;
7321 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
7322 *eProfile = OMX_VIDEO_AVCProfileMain;
7323 break;
7324 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
7325 *eProfile = OMX_VIDEO_AVCProfileHigh;
7326 break;
7327 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
7328 *eProfile = OMX_VIDEO_AVCProfileExtended;
7329 break;
7330 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
7331 *eProfile = OMX_VIDEO_AVCProfileHigh10;
7332 break;
7333 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
7334 *eProfile = OMX_VIDEO_AVCProfileHigh422;
7335 break;
7336 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
7337 *eProfile = OMX_VIDEO_AVCProfileHigh444;
7338 break;
7339 default:
7340 *eProfile = OMX_VIDEO_AVCProfileMax;
7341 status = false;
7342 break;
7343 }
7344
7345 if (!status) {
7346 return status;
7347 }
7348
7349 switch (profile_level.level) {
7350 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
7351 *eLevel = OMX_VIDEO_AVCLevel1;
7352 break;
7353 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
7354 *eLevel = OMX_VIDEO_AVCLevel1b;
7355 break;
7356 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
7357 *eLevel = OMX_VIDEO_AVCLevel11;
7358 break;
7359 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
7360 *eLevel = OMX_VIDEO_AVCLevel12;
7361 break;
7362 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
7363 *eLevel = OMX_VIDEO_AVCLevel13;
7364 break;
7365 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
7366 *eLevel = OMX_VIDEO_AVCLevel2;
7367 break;
7368 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
7369 *eLevel = OMX_VIDEO_AVCLevel21;
7370 break;
7371 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
7372 *eLevel = OMX_VIDEO_AVCLevel22;
7373 break;
7374 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
7375 *eLevel = OMX_VIDEO_AVCLevel3;
7376 break;
7377 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
7378 *eLevel = OMX_VIDEO_AVCLevel31;
7379 break;
7380 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
7381 *eLevel = OMX_VIDEO_AVCLevel32;
7382 break;
7383 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
7384 *eLevel = OMX_VIDEO_AVCLevel4;
7385 break;
7386 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
7387 *eLevel = OMX_VIDEO_AVCLevel41;
7388 break;
7389 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
7390 *eLevel = OMX_VIDEO_AVCLevel42;
7391 break;
7392 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
7393 *eLevel = OMX_VIDEO_AVCLevel5;
7394 break;
7395 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
7396 *eLevel = OMX_VIDEO_AVCLevel51;
7397 break;
7398 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
7399 *eLevel = OMX_VIDEO_AVCLevel52;
7400 break;
7401 default :
7402 *eLevel = OMX_VIDEO_AVCLevelMax;
7403 status = false;
7404 break;
7405 }
7406 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
7407 switch (codec_profile.profile) {
7408 case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
7409 *eProfile = OMX_VIDEO_VP8ProfileMain;
7410 break;
7411 default:
7412 *eProfile = OMX_VIDEO_VP8ProfileMax;
7413 status = false;
7414 break;
7415 }
7416 if (!status) {
7417 return status;
7418 }
7419
7420 switch (profile_level.level) {
7421 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
7422 *eLevel = OMX_VIDEO_VP8Level_Version0;
7423 break;
7424 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
7425 *eLevel = OMX_VIDEO_VP8Level_Version1;
7426 break;
7427 default:
7428 *eLevel = OMX_VIDEO_VP8LevelMax;
7429 status = false;
7430 break;
7431 }
7432 } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
7433 switch (codec_profile.profile) {
7434 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
7435 *eProfile = OMX_VIDEO_HEVCProfileMain;
7436 break;
7437 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
7438 *eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
7439 break;
7440 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC:
7441 *eProfile = OMX_VIDEO_HEVCProfileMainStill;
7442 break;
7443 default:
7444 *eProfile = OMX_VIDEO_HEVCProfileMax;
7445 status = false;
7446 break;
7447 }
7448 if (!status) {
7449 return status;
7450 }
7451
7452 switch (profile_level.level) {
7453 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
7454 *eLevel = OMX_VIDEO_HEVCMainTierLevel1;
7455 break;
7456 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
7457 *eLevel = OMX_VIDEO_HEVCHighTierLevel1;
7458 break;
7459 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
7460 *eLevel = OMX_VIDEO_HEVCMainTierLevel2;
7461 break;
7462 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
7463 *eLevel = OMX_VIDEO_HEVCHighTierLevel2;
7464 break;
7465 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
7466 *eLevel = OMX_VIDEO_HEVCMainTierLevel21;
7467 break;
7468 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
7469 *eLevel = OMX_VIDEO_HEVCHighTierLevel21;
7470 break;
7471 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
7472 *eLevel = OMX_VIDEO_HEVCMainTierLevel3;
7473 break;
7474 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
7475 *eLevel = OMX_VIDEO_HEVCHighTierLevel3;
7476 break;
7477 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
7478 *eLevel = OMX_VIDEO_HEVCMainTierLevel31;
7479 break;
7480 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
7481 *eLevel = OMX_VIDEO_HEVCHighTierLevel31;
7482 break;
7483 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
7484 *eLevel = OMX_VIDEO_HEVCMainTierLevel4;
7485 break;
7486 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
7487 *eLevel = OMX_VIDEO_HEVCHighTierLevel4;
7488 break;
7489 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
7490 *eLevel = OMX_VIDEO_HEVCMainTierLevel41;
7491 break;
7492 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
7493 *eLevel = OMX_VIDEO_HEVCHighTierLevel41;
7494 break;
7495 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
7496 *eLevel = OMX_VIDEO_HEVCMainTierLevel5;
7497 break;
7498 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
7499 *eLevel = OMX_VIDEO_HEVCHighTierLevel5;
7500 break;
7501 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
7502 *eLevel = OMX_VIDEO_HEVCMainTierLevel51;
7503 break;
7504 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
7505 *eLevel = OMX_VIDEO_HEVCHighTierLevel51;
7506 break;
7507 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
7508 *eLevel = OMX_VIDEO_HEVCMainTierLevel52;
7509 break;
7510 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
7511 *eLevel = OMX_VIDEO_HEVCHighTierLevel52;
7512 break;
7513 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
7514 *eLevel = OMX_VIDEO_HEVCMainTierLevel6;
7515 break;
7516 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
7517 *eLevel = OMX_VIDEO_HEVCHighTierLevel6;
7518 break;
7519 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
7520 *eLevel = OMX_VIDEO_HEVCMainTierLevel61;
7521 break;
7522 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
7523 *eLevel = OMX_VIDEO_HEVCHighTierLevel61;
7524 break;
7525 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
7526 *eLevel = OMX_VIDEO_HEVCMainTierLevel62;
7527 break;
7528 default:
7529 *eLevel = OMX_VIDEO_HEVCHighTiermax;
7530 status = false;
7531 break;
7532 }
7533 }
7534
7535 return status;
7536 }
7537
venc_set_nal_size(OMX_VIDEO_CONFIG_NALSIZE * nalSizeInfo)7538 bool venc_dev::venc_set_nal_size (OMX_VIDEO_CONFIG_NALSIZE *nalSizeInfo) {
7539 struct v4l2_control gControl;
7540 struct v4l2_control sControl;
7541
7542 DEBUG_PRINT_HIGH("set video stream format - nal size - %u", nalSizeInfo->nNaluBytes);
7543 gControl.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
7544
7545 if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &gControl)) {
7546 DEBUG_PRINT_ERROR("get control: video stream format failed");
7547 return false;
7548 }
7549
7550 sControl.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
7551 switch (nalSizeInfo->nNaluBytes) {
7552 case 0:
7553 sControl.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
7554 break;
7555 case 4:
7556 sControl.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
7557 break;
7558 default:
7559 return false;
7560 }
7561
7562 if ((1 << sControl.value) & gControl.value) {
7563 if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &sControl)) {
7564 DEBUG_PRINT_ERROR("set control: video stream format failed - %u",
7565 (unsigned int)nalSizeInfo->nNaluBytes);
7566 return false;
7567 }
7568 return true;
7569 }
7570
7571 return false;
7572
7573 }
7574
7575 #ifdef _ANDROID_ICS_
venc_set_meta_mode(bool mode)7576 bool venc_dev::venc_set_meta_mode(bool mode)
7577 {
7578 metadatamode = mode;
7579 return true;
7580 }
7581 #endif
7582
venc_is_video_session_supported(unsigned long width,unsigned long height)7583 bool venc_dev::venc_is_video_session_supported(unsigned long width,
7584 unsigned long height)
7585 {
7586 if ((width * height < capability.min_width * capability.min_height) ||
7587 (width * height > capability.max_width * capability.max_height)) {
7588 DEBUG_PRINT_ERROR(
7589 "Unsupported video resolution WxH = (%lu)x(%lu) supported range = min (%d)x(%d) - max (%d)x(%d)",
7590 width, height, capability.min_width, capability.min_height,
7591 capability.max_width, capability.max_height);
7592 return false;
7593 }
7594
7595 DEBUG_PRINT_LOW("video session supported");
7596 return true;
7597 }
7598
BatchInfo()7599 venc_dev::BatchInfo::BatchInfo()
7600 : mNumPending(0) {
7601 pthread_mutex_init(&mLock, NULL);
7602 for (int i = 0; i < kMaxBufs; ++i) {
7603 mBufMap[i] = kBufIDFree;
7604 }
7605 }
7606
registerBuffer(int bufferId)7607 int venc_dev::BatchInfo::registerBuffer(int bufferId) {
7608 pthread_mutex_lock(&mLock);
7609 int availId = 0;
7610 for( ; availId < kMaxBufs && mBufMap[availId] != kBufIDFree; ++availId);
7611 if (availId >= kMaxBufs) {
7612 DEBUG_PRINT_ERROR("Failed to find free entry !");
7613 pthread_mutex_unlock(&mLock);
7614 return -1;
7615 }
7616 mBufMap[availId] = bufferId;
7617 mNumPending++;
7618 pthread_mutex_unlock(&mLock);
7619 return availId;
7620 }
7621
retrieveBufferAt(int v4l2Id)7622 int venc_dev::BatchInfo::retrieveBufferAt(int v4l2Id) {
7623 pthread_mutex_lock(&mLock);
7624 if (v4l2Id >= kMaxBufs || v4l2Id < 0) {
7625 DEBUG_PRINT_ERROR("Batch: invalid index %d", v4l2Id);
7626 pthread_mutex_unlock(&mLock);
7627 return -1;
7628 }
7629 if (mBufMap[v4l2Id] == kBufIDFree) {
7630 DEBUG_PRINT_ERROR("Batch: buffer @ %d was not registered !", v4l2Id);
7631 pthread_mutex_unlock(&mLock);
7632 return -1;
7633 }
7634 int bufferId = mBufMap[v4l2Id];
7635 mBufMap[v4l2Id] = kBufIDFree;
7636 mNumPending--;
7637 pthread_mutex_unlock(&mLock);
7638 return bufferId;
7639 }
7640
isPending(int bufferId)7641 bool venc_dev::BatchInfo::isPending(int bufferId) {
7642 pthread_mutex_lock(&mLock);
7643 int existsId = 0;
7644 for(; existsId < kMaxBufs && mBufMap[existsId] != bufferId; ++existsId);
7645 pthread_mutex_unlock(&mLock);
7646 return existsId < kMaxBufs;
7647 }
7648
venc_set_hdr_info(const MasteringDisplay & mastering_disp_info,const ContentLightLevel & content_light_level_info)7649 bool venc_dev::venc_set_hdr_info(const MasteringDisplay& mastering_disp_info,
7650 const ContentLightLevel& content_light_level_info)
7651 {
7652 struct v4l2_ext_control ctrl[13];
7653 struct v4l2_ext_controls controls;
7654 const unsigned int RGB_PRIMARY_TABLE[] = {
7655 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_00,
7656 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_01,
7657 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_10,
7658 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_11,
7659 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_20,
7660 V4L2_CID_MPEG_VIDC_VENC_RGB_PRIMARY_21,
7661 };
7662
7663 memset(&controls, 0, sizeof(controls));
7664 memset(ctrl, 0, sizeof(ctrl));
7665
7666 controls.count = 11;
7667 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
7668 controls.controls = ctrl;
7669
7670 ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO;
7671 ctrl[0].value = V4L2_MPEG_MSM_VIDC_ENABLE;
7672
7673 /* ctrl[1] - ctrl[6] */
7674 for (int i = 0; i < 3; i++) {
7675 int first_idx = 2*i+1;
7676 int second_idx = 2*i+2;
7677 ctrl[first_idx].id = RGB_PRIMARY_TABLE[first_idx-1];
7678 ctrl[first_idx].value = mastering_disp_info.primaries.rgbPrimaries[i][0];
7679
7680 ctrl[second_idx].id = RGB_PRIMARY_TABLE[second_idx-1];
7681 ctrl[second_idx].value = mastering_disp_info.primaries.rgbPrimaries[i][1];
7682 }
7683
7684 ctrl[7].id = V4L2_CID_MPEG_VIDC_VENC_WHITEPOINT_X;
7685 ctrl[7].value = mastering_disp_info.primaries.whitePoint[0];
7686
7687 ctrl[8].id = V4L2_CID_MPEG_VIDC_VENC_WHITEPOINT_Y;
7688 ctrl[8].value = mastering_disp_info.primaries.whitePoint[1];
7689
7690 ctrl[9].id = V4L2_CID_MPEG_VIDC_VENC_MAX_DISP_LUM;
7691 // maxDisplayLuminance is in cd/m^2 scale. But the standard requires this field
7692 // to be in 0.0001 cd/m^2 scale. So, multiply with LUMINANCE_MULTIPLICATION_FACTOR
7693 // and give to be driver
7694 ctrl[9].value = mastering_disp_info.maxDisplayLuminance * LUMINANCE_MULTIPLICATION_FACTOR;
7695
7696 ctrl[10].id = V4L2_CID_MPEG_VIDC_VENC_MIN_DISP_LUM;
7697 ctrl[10].value = mastering_disp_info.minDisplayLuminance;
7698
7699 if (ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
7700 DEBUG_PRINT_ERROR("VIDIOC_S_EXT_CTRLS failed for HDR Info : Disp SEI");
7701 return false;
7702 }
7703
7704 memset(&controls, 0, sizeof(controls));
7705 memset(ctrl, 0, sizeof(ctrl));
7706
7707 controls.count = 3;
7708 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
7709 controls.controls = ctrl;
7710
7711 ctrl[0].id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO;
7712 ctrl[0].value = V4L2_MPEG_MSM_VIDC_ENABLE;
7713
7714 ctrl[1].id = V4L2_CID_MPEG_VIDC_VENC_MAX_CLL;
7715 ctrl[1].value = content_light_level_info.maxContentLightLevel;
7716
7717 ctrl[2].id = V4L2_CID_MPEG_VIDC_VENC_MAX_FLL;
7718 ctrl[2].value = content_light_level_info.minPicAverageLightLevel;
7719
7720 if (ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls)) {
7721 DEBUG_PRINT_ERROR("VIDIOC_S_EXT_CTRLS failed for HDR Info : CLL SEI");
7722 return false;
7723 }
7724
7725 return true;
7726 }
7727
7728 #ifdef _VQZIP_
venc_dev_vqzip()7729 venc_dev::venc_dev_vqzip::venc_dev_vqzip()
7730 {
7731 mLibHandle = NULL;
7732 pthread_mutex_init(&lock, NULL);
7733 }
7734
init()7735 bool venc_dev::venc_dev_vqzip::init()
7736 {
7737 bool status = true;
7738 if (mLibHandle) {
7739 DEBUG_PRINT_ERROR("VQZIP init called twice");
7740 status = false;
7741 }
7742 if (status) {
7743 mLibHandle = dlopen("libvqzip.so", RTLD_NOW);
7744 if (mLibHandle) {
7745 mVQZIPInit = (vqzip_init_t)
7746 dlsym(mLibHandle,"VQZipInit");
7747 mVQZIPDeInit = (vqzip_deinit_t)
7748 dlsym(mLibHandle,"VQZipDeInit");
7749 mVQZIPComputeStats = (vqzip_compute_stats_t)
7750 dlsym(mLibHandle,"VQZipComputeStats");
7751 if (!mVQZIPInit || !mVQZIPDeInit || !mVQZIPComputeStats)
7752 status = false;
7753 } else {
7754 DEBUG_PRINT_ERROR("FATAL ERROR: could not dlopen libvqzip.so: %s", dlerror());
7755 status = false;
7756 }
7757 if (status) {
7758 mVQZIPHandle = mVQZIPInit();
7759 }
7760 }
7761 if (!status && mLibHandle) {
7762 dlclose(mLibHandle);
7763 mLibHandle = NULL;
7764 mVQZIPHandle = NULL;
7765 mVQZIPInit = NULL;
7766 mVQZIPDeInit = NULL;
7767 mVQZIPComputeStats = NULL;
7768 }
7769 return status;
7770 }
7771
fill_stats_data(void * pBuf,void * extraData)7772 int venc_dev::venc_dev_vqzip::fill_stats_data(void* pBuf, void* extraData)
7773 {
7774 VQZipStatus result;
7775 VQZipStats *pStats = (VQZipStats *)extraData;
7776 pConfig.pSEIPayload = NULL;
7777 unsigned long size;
7778
7779 if (!pBuf || !pStats || !mVQZIPHandle) {
7780 DEBUG_PRINT_ERROR("Invalid data passed to stats function");
7781 }
7782 result = mVQZIPComputeStats(mVQZIPHandle, (void* )pBuf, &pConfig, pStats);
7783 return result;
7784 }
7785
deinit()7786 void venc_dev::venc_dev_vqzip::deinit()
7787 {
7788 if (mLibHandle) {
7789 pthread_mutex_lock(&lock);
7790 dlclose(mLibHandle);
7791 mVQZIPDeInit(mVQZIPHandle);
7792 mLibHandle = NULL;
7793 mVQZIPHandle = NULL;
7794 mVQZIPInit = NULL;
7795 mVQZIPDeInit = NULL;
7796 mVQZIPComputeStats = NULL;
7797 pthread_mutex_unlock(&lock);
7798 }
7799 }
7800
~venc_dev_vqzip()7801 venc_dev::venc_dev_vqzip::~venc_dev_vqzip()
7802 {
7803 DEBUG_PRINT_HIGH("Destroy C2D instance");
7804 if (mLibHandle) {
7805 dlclose(mLibHandle);
7806 }
7807 mLibHandle = NULL;
7808 pthread_mutex_destroy(&lock);
7809 }
7810 #endif
7811
7812 /*=================================================================================
7813 * Function: venc_set_roi_region_qp_info
7814 * @brief set the config of OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO and store
7815 * the info in the list
7816 * Parameters:
7817 * @param OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo:
7818 * the config to be set
7819 * Return value:
7820 * bool: return true if the config is set successfully
7821 *==================================================================================*/
venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO * roiRegionInfo)7822 bool venc_dev::venc_set_roi_region_qp_info(OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *roiRegionInfo)
7823 {
7824 if (!m_roi_enabled || (m_roi_type == 0)) {
7825 DEBUG_PRINT_ERROR("ROI-Region: roi is invalid (enable:%u, type:%d)",
7826 m_roi_enabled, m_roi_type);
7827 return false;
7828 }
7829 if (!roiRegionInfo) {
7830 DEBUG_PRINT_ERROR("ROI-Region: no region info present");
7831 return false;
7832 }
7833 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
7834 m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
7835 DEBUG_PRINT_ERROR("ROI-Region: is not supported for %d codec",
7836 (OMX_U32) m_sVenc_cfg.codectype);
7837 return false;
7838 }
7839
7840 pthread_mutex_lock(&m_roilock);
7841 DEBUG_PRINT_LOW("ROI-Region: add region with timestamp %lld us.", roiRegionInfo->nTimeStamp);
7842 mRoiRegionList.push_back(*roiRegionInfo);
7843 pthread_mutex_unlock(&m_roilock);
7844 return true;
7845 }
7846
7847 /*=================================================================================
7848 * Function: append_extradata_roi_region_qp_info
7849 * @brief fill the roi info in the extradata of input Buffer
7850 * Parameters:
7851 * @param OMX_OTHER_EXTRADATATYPE *data: the address of the extradata buffer
7852 * OMX_TICKS timestamp: the timestamp of the input Buffer
7853 * OMX_U32: the available size of the extradata buffer
7854 * Return value:
7855 * OMX_U32: the filled size
7856 *==================================================================================*/
append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE * data,OMX_TICKS timestamp,OMX_U32 freeSize)7857 OMX_U32 venc_dev::append_extradata_roi_region_qp_info(OMX_OTHER_EXTRADATATYPE *data,
7858 OMX_TICKS timestamp, OMX_U32 freeSize)
7859 {
7860 bool found = false;
7861 pthread_mutex_lock(&m_roilock);
7862 if (mRoiRegionList.size() == 0) {
7863 pthread_mutex_unlock(&m_roilock);
7864 return 0;
7865 }
7866 std::list<OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO>::iterator it =
7867 mRoiRegionList.begin();
7868 while (it != mRoiRegionList.end()) {
7869 if (it->nTimeStamp < timestamp) {
7870 it = mRoiRegionList.erase(it);
7871 continue;
7872 } else if (it->nTimeStamp == timestamp) {
7873 found = true;
7874 break;
7875 }
7876 it++;
7877 }
7878 pthread_mutex_unlock(&m_roilock);
7879 if (!found) {
7880 DEBUG_PRINT_LOW("ROI-Region: no region roi data was found");
7881 return 0;
7882 }
7883 OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO regionInfo = *it;
7884 bool isHevc = m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC ? true:false;
7885 OMX_U32 height = m_sVenc_cfg.dvs_height;
7886 OMX_U32 width = m_sVenc_cfg.dvs_width;
7887 OMX_U32 mbAlign = isHevc ? 32 : 16;
7888 OMX_U8 mbBit = isHevc ? 5 : 4;
7889 OMX_U32 mbRow = ALIGN(width, mbAlign) / mbAlign;
7890 OMX_U32 mbCol = ALIGN(height, mbAlign) / mbAlign;
7891 OMX_U32 numBytes, mbLeft, mbTop, mbRight, mbBottom = 0;
7892 OMX_S8 deltaQP = 0;
7893 DEBUG_PRINT_LOW("ROI-Region: clip(%ux%u: %s), mb(%ux%u), region(num:%u, ts:%lld)",
7894 width, height, isHevc ? "hevc" : "avc",
7895 mbRow, mbCol, regionInfo.nRegionNum, regionInfo.nTimeStamp);
7896
7897 if (m_roi_type == V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BYTE) {
7898 OMX_U32 mbRowAligned = ALIGN(mbRow, 8);
7899 numBytes = mbRowAligned * mbCol * 2;
7900 OMX_U32 numBytesAligned = ALIGN(numBytes, 4);
7901
7902 data->nDataSize = ALIGN(sizeof(struct msm_vidc_roi_deltaqp_payload), 256)
7903 + numBytesAligned;
7904 data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
7905 if (data->nSize > freeSize) {
7906 DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
7907 freeSize, data->nSize);
7908 data->nDataSize = 0;
7909 data->nSize = 0;
7910 return 0;
7911 }
7912
7913 data->nVersion.nVersion = OMX_SPEC_VERSION;
7914 data->nPortIndex = 0;
7915 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
7916 struct msm_vidc_roi_deltaqp_payload *roiData =
7917 (struct msm_vidc_roi_deltaqp_payload *)(data->data);
7918 roiData->b_roi_info = true;
7919 roiData->mbi_info_size = numBytesAligned;
7920 roiData->data[0] = (unsigned int)(ALIGN(&roiData->data[1], 256)
7921 - (unsigned long)roiData->data);
7922 OMX_U16* exDataBuf = (OMX_U16*)((OMX_U8*)roiData->data + roiData->data[0]);
7923 OMX_U32 mb = 0;
7924 OMX_U16 *pData = NULL;
7925
7926 for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
7927 mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
7928 mbTop = regionInfo.nRegions[i].nTop >> mbBit;
7929 mbRight = regionInfo.nRegions[i].nRight >> mbBit;
7930 mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
7931 deltaQP = regionInfo.nRegions[i].nDeltaQP;
7932 if (mbLeft >= mbRow || mbRight >= mbRow
7933 || mbTop >= mbCol || mbBottom >= mbCol) {
7934 continue;
7935 }
7936 for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
7937 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
7938 mb = row * mbRowAligned + col;
7939 pData = exDataBuf + mb;
7940 *pData = (1 << 11) | ((deltaQP & 0x3F) << 4);
7941 }
7942 }
7943 }
7944 DEBUG_PRINT_LOW("ROI-Region(2Byte): set roi: raw size: %u", numBytesAligned);
7945 } else if (m_roi_type == V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BIT) {
7946 numBytes = (mbRow * mbCol * 2 + 7) >> 3;
7947 data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload) + numBytes;
7948 data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + data->nDataSize, 4);
7949
7950 if (data->nSize > freeSize) {
7951 DEBUG_PRINT_ERROR("ROI-Region: Buffer size(%u) is less than ROI extradata size(%u)",
7952 freeSize, data->nSize);
7953 data->nDataSize = 0;
7954 data->nSize = 0;
7955 return 0;
7956 }
7957
7958 data->nVersion.nVersion = OMX_SPEC_VERSION;
7959 data->nPortIndex = 0;
7960 data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
7961 struct msm_vidc_roi_qp_payload *roiData =
7962 (struct msm_vidc_roi_qp_payload *)(data->data);
7963 roiData->b_roi_info = true;
7964 roiData->mbi_info_size = numBytes;
7965 roiData->lower_qp_offset = 0;
7966 roiData->upper_qp_offset = 0;
7967 OMX_U8 flag = 0x1;
7968 OMX_U32 mb, mb_byte = 0;
7969 OMX_U8 mb_bit = 0;
7970 OMX_U8 *pData = NULL;
7971
7972 for (OMX_U8 i = 0; i < regionInfo.nRegionNum; i++) {
7973 mbLeft = regionInfo.nRegions[i].nLeft >> mbBit;
7974 mbTop = regionInfo.nRegions[i].nTop >> mbBit;
7975 mbRight = regionInfo.nRegions[i].nRight >> mbBit;
7976 mbBottom = regionInfo.nRegions[i].nBottom >> mbBit;
7977 deltaQP = regionInfo.nRegions[i].nDeltaQP;
7978 if (mbLeft >= mbRow || mbRight >= mbRow
7979 || mbTop >= mbCol || mbBottom >= mbCol
7980 || deltaQP == 0) {
7981 continue;
7982 }
7983 // choose the minimum absolute value for lower and upper offset
7984 if (deltaQP < 0) {
7985 if (roiData->lower_qp_offset == 0) {
7986 roiData->lower_qp_offset = deltaQP;
7987 } else if (roiData->lower_qp_offset < deltaQP) {
7988 roiData->lower_qp_offset = deltaQP;
7989 }
7990 flag = 0x1;
7991 } else {
7992 if (roiData->upper_qp_offset == 0) {
7993 roiData->upper_qp_offset = deltaQP;
7994 } else if (roiData->upper_qp_offset > deltaQP) {
7995 roiData->upper_qp_offset = deltaQP;
7996 }
7997 flag = 0x2;
7998 }
7999 for (OMX_U32 row = mbTop; row <= mbBottom; row++) {
8000 for (OMX_U32 col = mbLeft; col <= mbRight; col++) {
8001 mb = row * mbRow + col;
8002 mb_byte = mb >> 2;
8003 mb_bit = (3 - (mb & 0x3)) << 1;
8004 pData = (OMX_U8 *)roiData->data + mb_byte;
8005 *pData |= (flag << mb_bit);
8006 }
8007 }
8008 }
8009 DEBUG_PRINT_LOW("ROI-Region(2Bit):set roi low:%d,up:%d", roiData->lower_qp_offset, roiData->upper_qp_offset);
8010 }
8011 return data->nSize;
8012 }
8013
8014