Commit | Line | Data |
---|---|---|
97fb5e8d | 1 | // SPDX-License-Identifier: GPL-2.0-only |
aaaa93ed SV |
2 | /* |
3 | * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. | |
4 | * Copyright (C) 2017 Linaro Ltd. | |
aaaa93ed SV |
5 | */ |
6 | #include <linux/types.h> | |
7 | #include <media/v4l2-ctrls.h> | |
8 | ||
9 | #include "core.h" | |
10 | #include "venc.h" | |
11 | ||
12 | #define BITRATE_MIN 32000 | |
13 | #define BITRATE_MAX 160000000 | |
14 | #define BITRATE_DEFAULT 1000000 | |
15 | #define BITRATE_DEFAULT_PEAK (BITRATE_DEFAULT * 2) | |
16 | #define BITRATE_STEP 100 | |
17 | #define SLICE_BYTE_SIZE_MAX 1024 | |
18 | #define SLICE_BYTE_SIZE_MIN 1024 | |
19 | #define SLICE_MB_SIZE_MAX 300 | |
20 | #define INTRA_REFRESH_MBS_MAX 300 | |
21 | #define AT_SLICE_BOUNDARY \ | |
22 | V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY | |
23 | ||
8fc58186 SV |
24 | static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf) |
25 | { | |
26 | u32 half = (gop_size - 1) >> 1; | |
27 | u32 b, p, ratio; | |
28 | bool found = false; | |
29 | ||
30 | if (!gop_size) | |
31 | return -EINVAL; | |
32 | ||
33 | *bf = *pf = 0; | |
34 | ||
35 | if (!conseq_b) { | |
36 | *pf = gop_size - 1; | |
37 | return 0; | |
38 | } | |
39 | ||
40 | b = p = half; | |
41 | ||
42 | for (; b <= gop_size - 1; b++, p--) { | |
43 | if (b % p) | |
44 | continue; | |
45 | ||
46 | ratio = b / p; | |
47 | ||
48 | if (ratio == conseq_b) { | |
49 | found = true; | |
50 | break; | |
51 | } | |
52 | ||
53 | if (ratio > conseq_b) | |
54 | break; | |
55 | } | |
56 | ||
57 | if (!found) | |
58 | return -EINVAL; | |
59 | ||
60 | if (b + p + 1 != gop_size) | |
61 | return -EINVAL; | |
62 | ||
63 | *bf = b; | |
64 | *pf = p; | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
aaaa93ed SV |
69 | static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) |
70 | { | |
71 | struct venus_inst *inst = ctrl_to_inst(ctrl); | |
72 | struct venc_controls *ctr = &inst->controls.enc; | |
c35f0b16 | 73 | struct hfi_enable en = { .enable = 1 }; |
61df5aa3 | 74 | struct hfi_bitrate brate; |
8fc58186 | 75 | u32 bframes; |
61df5aa3 | 76 | u32 ptype; |
8fc58186 | 77 | int ret; |
aaaa93ed SV |
78 | |
79 | switch (ctrl->id) { | |
80 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | |
81 | ctr->bitrate_mode = ctrl->val; | |
82 | break; | |
83 | case V4L2_CID_MPEG_VIDEO_BITRATE: | |
84 | ctr->bitrate = ctrl->val; | |
61df5aa3 MG |
85 | mutex_lock(&inst->lock); |
86 | if (inst->streamon_out && inst->streamon_cap) { | |
87 | ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; | |
88 | brate.bitrate = ctr->bitrate; | |
89 | brate.layer_id = 0; | |
90 | ||
91 | ret = hfi_session_set_property(inst, ptype, &brate); | |
92 | if (ret) { | |
93 | mutex_unlock(&inst->lock); | |
94 | return ret; | |
95 | } | |
96 | } | |
97 | mutex_unlock(&inst->lock); | |
aaaa93ed SV |
98 | break; |
99 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | |
100 | ctr->bitrate_peak = ctrl->val; | |
101 | break; | |
102 | case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: | |
103 | ctr->h264_entropy_mode = ctrl->val; | |
104 | break; | |
105 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | |
106 | ctr->profile.mpeg4 = ctrl->val; | |
107 | break; | |
108 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: | |
109 | ctr->profile.h264 = ctrl->val; | |
110 | break; | |
cd396c8c KL |
111 | case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: |
112 | ctr->profile.hevc = ctrl->val; | |
113 | break; | |
5520b946 | 114 | case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: |
aaaa93ed SV |
115 | ctr->profile.vpx = ctrl->val; |
116 | break; | |
117 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: | |
118 | ctr->level.mpeg4 = ctrl->val; | |
119 | break; | |
120 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: | |
121 | ctr->level.h264 = ctrl->val; | |
122 | break; | |
cd396c8c KL |
123 | case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: |
124 | ctr->level.hevc = ctrl->val; | |
125 | break; | |
aaaa93ed SV |
126 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: |
127 | ctr->h264_i_qp = ctrl->val; | |
128 | break; | |
129 | case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: | |
130 | ctr->h264_p_qp = ctrl->val; | |
131 | break; | |
132 | case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: | |
133 | ctr->h264_b_qp = ctrl->val; | |
134 | break; | |
135 | case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: | |
136 | ctr->h264_min_qp = ctrl->val; | |
137 | break; | |
138 | case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: | |
139 | ctr->h264_max_qp = ctrl->val; | |
140 | break; | |
141 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: | |
142 | ctr->multi_slice_mode = ctrl->val; | |
143 | break; | |
144 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: | |
145 | ctr->multi_slice_max_bytes = ctrl->val; | |
146 | break; | |
147 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: | |
148 | ctr->multi_slice_max_mb = ctrl->val; | |
149 | break; | |
150 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: | |
151 | ctr->h264_loop_filter_alpha = ctrl->val; | |
152 | break; | |
153 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: | |
154 | ctr->h264_loop_filter_beta = ctrl->val; | |
155 | break; | |
156 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: | |
157 | ctr->h264_loop_filter_mode = ctrl->val; | |
158 | break; | |
159 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: | |
160 | ctr->header_mode = ctrl->val; | |
161 | break; | |
162 | case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: | |
163 | break; | |
164 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | |
8fc58186 SV |
165 | ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes, |
166 | &ctr->num_p_frames); | |
167 | if (ret) | |
168 | return ret; | |
169 | ||
aaaa93ed SV |
170 | ctr->gop_size = ctrl->val; |
171 | break; | |
172 | case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: | |
173 | ctr->h264_i_period = ctrl->val; | |
174 | break; | |
175 | case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP: | |
176 | ctr->vp8_min_qp = ctrl->val; | |
177 | break; | |
178 | case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP: | |
179 | ctr->vp8_max_qp = ctrl->val; | |
180 | break; | |
181 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | |
8fc58186 SV |
182 | ret = venc_calc_bpframes(ctr->gop_size, ctrl->val, &bframes, |
183 | &ctr->num_p_frames); | |
184 | if (ret) | |
185 | return ret; | |
186 | ||
187 | ctr->num_b_frames = bframes; | |
aaaa93ed | 188 | break; |
c35f0b16 MG |
189 | case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: |
190 | mutex_lock(&inst->lock); | |
191 | if (inst->streamon_out && inst->streamon_cap) { | |
192 | ptype = HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME; | |
193 | ret = hfi_session_set_property(inst, ptype, &en); | |
194 | ||
195 | if (ret) { | |
196 | mutex_unlock(&inst->lock); | |
197 | return ret; | |
198 | } | |
199 | } | |
200 | mutex_unlock(&inst->lock); | |
201 | break; | |
6f704b2f JK |
202 | case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: |
203 | ctr->rc_enable = ctrl->val; | |
204 | break; | |
aaaa93ed SV |
205 | default: |
206 | return -EINVAL; | |
207 | } | |
208 | ||
209 | return 0; | |
210 | } | |
211 | ||
212 | static const struct v4l2_ctrl_ops venc_ctrl_ops = { | |
213 | .s_ctrl = venc_op_s_ctrl, | |
214 | }; | |
215 | ||
216 | int venc_ctrl_init(struct venus_inst *inst) | |
217 | { | |
218 | int ret; | |
219 | ||
6f704b2f | 220 | ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 31); |
aaaa93ed SV |
221 | if (ret) |
222 | return ret; | |
223 | ||
224 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
225 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | |
226 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, | |
227 | ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | | |
228 | (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)), | |
229 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | |
230 | ||
231 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
232 | V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, | |
233 | V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, | |
234 | 0, V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC); | |
235 | ||
236 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
237 | V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, | |
238 | V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY, | |
239 | ~((1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) | | |
240 | (1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE)), | |
241 | V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE); | |
242 | ||
243 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
244 | V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, | |
245 | V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, | |
246 | 0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0); | |
247 | ||
cd396c8c KL |
248 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, |
249 | V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, | |
250 | V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, | |
251 | ~((1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | | |
252 | (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | | |
253 | (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)), | |
254 | V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN); | |
255 | ||
256 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
257 | V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, | |
258 | V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, | |
259 | 0, V4L2_MPEG_VIDEO_HEVC_LEVEL_1); | |
260 | ||
aaaa93ed SV |
261 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, |
262 | V4L2_CID_MPEG_VIDEO_H264_PROFILE, | |
263 | V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, | |
264 | ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | | |
265 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | | |
266 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | | |
267 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | | |
268 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) | | |
269 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH)), | |
270 | V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); | |
271 | ||
272 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
273 | V4L2_CID_MPEG_VIDEO_H264_LEVEL, | |
274 | V4L2_MPEG_VIDEO_H264_LEVEL_5_1, | |
275 | 0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0); | |
276 | ||
277 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
278 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, | |
279 | AT_SLICE_BOUNDARY, | |
280 | 0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED); | |
281 | ||
282 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
283 | V4L2_CID_MPEG_VIDEO_HEADER_MODE, | |
284 | V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, | |
285 | 1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, | |
286 | V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE); | |
287 | ||
288 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, | |
289 | V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, | |
4914425e | 290 | V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES, |
aaaa93ed SV |
291 | 0, V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE); |
292 | ||
5520b946 KW |
293 | v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, |
294 | V4L2_CID_MPEG_VIDEO_VP8_PROFILE, | |
295 | V4L2_MPEG_VIDEO_VP8_PROFILE_3, | |
296 | 0, V4L2_MPEG_VIDEO_VP8_PROFILE_0); | |
297 | ||
aaaa93ed SV |
298 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, |
299 | V4L2_CID_MPEG_VIDEO_BITRATE, BITRATE_MIN, BITRATE_MAX, | |
300 | BITRATE_STEP, BITRATE_DEFAULT); | |
301 | ||
302 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
303 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, BITRATE_MIN, BITRATE_MAX, | |
304 | BITRATE_STEP, BITRATE_DEFAULT_PEAK); | |
305 | ||
306 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
aaaa93ed SV |
307 | V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 26); |
308 | ||
309 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
310 | V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 28); | |
311 | ||
312 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
313 | V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, 1, 51, 1, 30); | |
314 | ||
315 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
316 | V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 1, 51, 1, 1); | |
317 | ||
318 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
319 | V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 1, 51, 1, 51); | |
320 | ||
321 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
322 | V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, SLICE_BYTE_SIZE_MIN, | |
323 | SLICE_BYTE_SIZE_MAX, 1, SLICE_BYTE_SIZE_MIN); | |
324 | ||
325 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
326 | V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, | |
327 | SLICE_MB_SIZE_MAX, 1, 1); | |
328 | ||
329 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
330 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0); | |
331 | ||
332 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
333 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0); | |
334 | ||
335 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
336 | V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, | |
337 | 0, INTRA_REFRESH_MBS_MAX, 1, 0); | |
338 | ||
339 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
f8e5b2f3 | 340 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30); |
aaaa93ed SV |
341 | |
342 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
343 | V4L2_CID_MPEG_VIDEO_VPX_MIN_QP, 1, 128, 1, 1); | |
344 | ||
345 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
346 | V4L2_CID_MPEG_VIDEO_VPX_MAX_QP, 1, 128, 1, 128); | |
347 | ||
348 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
349 | V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 4, 1, 0); | |
350 | ||
351 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, | |
352 | V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, 0, (1 << 16) - 1, 1, 0); | |
353 | ||
c35f0b16 MG |
354 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, |
355 | V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, 0, 0, 0, 0); | |
356 | ||
6f704b2f JK |
357 | v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, |
358 | V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1); | |
359 | ||
aaaa93ed SV |
360 | ret = inst->ctrl_handler.error; |
361 | if (ret) | |
362 | goto err; | |
363 | ||
364 | ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler); | |
365 | if (ret) | |
366 | goto err; | |
367 | ||
368 | return 0; | |
369 | err: | |
370 | v4l2_ctrl_handler_free(&inst->ctrl_handler); | |
371 | return ret; | |
372 | } | |
373 | ||
374 | void venc_ctrl_deinit(struct venus_inst *inst) | |
375 | { | |
376 | v4l2_ctrl_handler_free(&inst->ctrl_handler); | |
377 | } |