1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2020-2021 NXP |
4 | */ |
5 | |
6 | #include <linux/init.h> |
7 | #include <linux/interconnect.h> |
8 | #include <linux/ioctl.h> |
9 | #include <linux/list.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/delay.h> |
13 | #include <linux/videodev2.h> |
14 | #include <linux/ktime.h> |
15 | #include <linux/rational.h> |
16 | #include <linux/vmalloc.h> |
17 | #include <media/v4l2-device.h> |
18 | #include <media/v4l2-event.h> |
19 | #include <media/v4l2-mem2mem.h> |
20 | #include <media/v4l2-ioctl.h> |
21 | #include <media/videobuf2-v4l2.h> |
22 | #include <media/videobuf2-dma-contig.h> |
23 | #include <media/videobuf2-vmalloc.h> |
24 | #include "vpu.h" |
25 | #include "vpu_defs.h" |
26 | #include "vpu_core.h" |
27 | #include "vpu_helpers.h" |
28 | #include "vpu_v4l2.h" |
29 | #include "vpu_cmds.h" |
30 | #include "vpu_rpc.h" |
31 | |
32 | #define VENC_OUTPUT_ENABLE BIT(0) |
33 | #define VENC_CAPTURE_ENABLE BIT(1) |
34 | #define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE) |
35 | #define VENC_MAX_BUF_CNT 8 |
36 | #define VENC_MIN_BUFFER_OUT 6 |
37 | #define VENC_MIN_BUFFER_CAP 6 |
38 | |
39 | struct venc_t { |
40 | struct vpu_encode_params params; |
41 | u32 request_key_frame; |
42 | u32 input_ready; |
43 | u32 cpb_size; |
44 | bool bitrate_change; |
45 | |
46 | struct vpu_buffer enc[VENC_MAX_BUF_CNT]; |
47 | struct vpu_buffer ref[VENC_MAX_BUF_CNT]; |
48 | struct vpu_buffer act[VENC_MAX_BUF_CNT]; |
49 | struct list_head frames; |
50 | u32 frame_count; |
51 | u32 encode_count; |
52 | u32 ready_count; |
53 | u32 enable; |
54 | u32 stopped; |
55 | |
56 | u32 skipped_count; |
57 | u32 skipped_bytes; |
58 | |
59 | wait_queue_head_t wq; |
60 | }; |
61 | |
62 | struct venc_frame_t { |
63 | struct list_head list; |
64 | struct vpu_enc_pic_info info; |
65 | u32 bytesused; |
66 | s64 timestamp; |
67 | }; |
68 | |
69 | static const struct vpu_format venc_formats[] = { |
70 | { |
71 | .pixfmt = V4L2_PIX_FMT_NV12M, |
72 | .mem_planes = 2, |
73 | .comp_planes = 2, |
74 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
75 | .sibling = V4L2_PIX_FMT_NV12, |
76 | }, |
77 | { |
78 | .pixfmt = V4L2_PIX_FMT_NV12, |
79 | .mem_planes = 1, |
80 | .comp_planes = 2, |
81 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
82 | .sibling = V4L2_PIX_FMT_NV12M, |
83 | }, |
84 | { |
85 | .pixfmt = V4L2_PIX_FMT_H264, |
86 | .mem_planes = 1, |
87 | .comp_planes = 1, |
88 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, |
89 | .flags = V4L2_FMT_FLAG_COMPRESSED |
90 | }, |
91 | {0, 0, 0, 0}, |
92 | }; |
93 | |
94 | static int venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) |
95 | { |
96 | strscpy(cap->driver, "amphion-vpu" , sizeof(cap->driver)); |
97 | strscpy(cap->card, "amphion vpu encoder" , sizeof(cap->card)); |
98 | strscpy(cap->bus_info, "platform: amphion-vpu" , sizeof(cap->bus_info)); |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) |
104 | { |
105 | struct vpu_inst *inst = to_inst(filp: file); |
106 | const struct vpu_format *fmt; |
107 | |
108 | memset(f->reserved, 0, sizeof(f->reserved)); |
109 | fmt = vpu_helper_enum_format(inst, type: f->type, index: f->index); |
110 | if (!fmt) |
111 | return -EINVAL; |
112 | |
113 | f->pixelformat = fmt->pixfmt; |
114 | f->flags = fmt->flags; |
115 | |
116 | return 0; |
117 | } |
118 | |
119 | static int venc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) |
120 | { |
121 | struct vpu_inst *inst = to_inst(filp: file); |
122 | const struct vpu_core_resources *res; |
123 | |
124 | if (!fsize || fsize->index) |
125 | return -EINVAL; |
126 | |
127 | if (!vpu_helper_find_format(inst, type: 0, pixelfmt: fsize->pixel_format)) |
128 | return -EINVAL; |
129 | |
130 | res = vpu_get_resource(inst); |
131 | if (!res) |
132 | return -EINVAL; |
133 | fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; |
134 | fsize->stepwise.max_width = res->max_width; |
135 | fsize->stepwise.max_height = res->max_height; |
136 | fsize->stepwise.min_width = res->min_width; |
137 | fsize->stepwise.min_height = res->min_height; |
138 | fsize->stepwise.step_width = res->step_width; |
139 | fsize->stepwise.step_height = res->step_height; |
140 | |
141 | return 0; |
142 | } |
143 | |
144 | static int venc_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *fival) |
145 | { |
146 | struct vpu_inst *inst = to_inst(filp: file); |
147 | const struct vpu_core_resources *res; |
148 | |
149 | if (!fival || fival->index) |
150 | return -EINVAL; |
151 | |
152 | if (!vpu_helper_find_format(inst, type: 0, pixelfmt: fival->pixel_format)) |
153 | return -EINVAL; |
154 | |
155 | if (!fival->width || !fival->height) |
156 | return -EINVAL; |
157 | |
158 | res = vpu_get_resource(inst); |
159 | if (!res) |
160 | return -EINVAL; |
161 | if (fival->width < res->min_width || fival->width > res->max_width || |
162 | fival->height < res->min_height || fival->height > res->max_height) |
163 | return -EINVAL; |
164 | |
165 | fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; |
166 | fival->stepwise.min.numerator = 1; |
167 | fival->stepwise.min.denominator = USHRT_MAX; |
168 | fival->stepwise.max.numerator = USHRT_MAX; |
169 | fival->stepwise.max.denominator = 1; |
170 | fival->stepwise.step.numerator = 1; |
171 | fival->stepwise.step.denominator = 1; |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) |
177 | { |
178 | struct vpu_inst *inst = to_inst(filp: file); |
179 | struct venc_t *venc = inst->priv; |
180 | struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; |
181 | struct vpu_format *cur_fmt; |
182 | int i; |
183 | |
184 | cur_fmt = vpu_get_format(inst, type: f->type); |
185 | |
186 | pixmp->pixelformat = cur_fmt->pixfmt; |
187 | pixmp->num_planes = cur_fmt->mem_planes; |
188 | pixmp->width = cur_fmt->width; |
189 | pixmp->height = cur_fmt->height; |
190 | pixmp->field = cur_fmt->field; |
191 | pixmp->flags = cur_fmt->flags; |
192 | for (i = 0; i < pixmp->num_planes; i++) { |
193 | pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; |
194 | pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(fmt: cur_fmt, plane_no: i); |
195 | } |
196 | |
197 | f->fmt.pix_mp.colorspace = venc->params.color.primaries; |
198 | f->fmt.pix_mp.xfer_func = venc->params.color.transfer; |
199 | f->fmt.pix_mp.ycbcr_enc = venc->params.color.matrix; |
200 | f->fmt.pix_mp.quantization = venc->params.color.full_range; |
201 | |
202 | return 0; |
203 | } |
204 | |
205 | static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f) |
206 | { |
207 | struct vpu_inst *inst = to_inst(filp: file); |
208 | struct vpu_format fmt; |
209 | |
210 | vpu_try_fmt_common(inst, f, fmt: &fmt); |
211 | |
212 | return 0; |
213 | } |
214 | |
215 | static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) |
216 | { |
217 | struct vpu_inst *inst = to_inst(filp: file); |
218 | struct vpu_format fmt; |
219 | struct vpu_format *cur_fmt; |
220 | struct vb2_queue *q; |
221 | struct venc_t *venc = inst->priv; |
222 | struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; |
223 | |
224 | q = v4l2_m2m_get_vq(m2m_ctx: inst->fh.m2m_ctx, type: f->type); |
225 | if (!q) |
226 | return -EINVAL; |
227 | if (vb2_is_busy(q)) |
228 | return -EBUSY; |
229 | |
230 | if (vpu_try_fmt_common(inst, f, fmt: &fmt)) |
231 | return -EINVAL; |
232 | |
233 | cur_fmt = vpu_get_format(inst, type: f->type); |
234 | |
235 | memcpy(cur_fmt, &fmt, sizeof(*cur_fmt)); |
236 | |
237 | if (V4L2_TYPE_IS_OUTPUT(f->type)) { |
238 | venc->params.input_format = cur_fmt->pixfmt; |
239 | venc->params.src_stride = cur_fmt->bytesperline[0]; |
240 | venc->params.src_width = cur_fmt->width; |
241 | venc->params.src_height = cur_fmt->height; |
242 | venc->params.crop.left = 0; |
243 | venc->params.crop.top = 0; |
244 | venc->params.crop.width = cur_fmt->width; |
245 | venc->params.crop.height = cur_fmt->height; |
246 | } else { |
247 | venc->params.codec_format = cur_fmt->pixfmt; |
248 | venc->params.out_width = cur_fmt->width; |
249 | venc->params.out_height = cur_fmt->height; |
250 | } |
251 | |
252 | if (V4L2_TYPE_IS_OUTPUT(f->type)) { |
253 | venc->params.color.primaries = pix_mp->colorspace; |
254 | venc->params.color.transfer = pix_mp->xfer_func; |
255 | venc->params.color.matrix = pix_mp->ycbcr_enc; |
256 | venc->params.color.full_range = pix_mp->quantization; |
257 | } |
258 | |
259 | pix_mp->colorspace = venc->params.color.primaries; |
260 | pix_mp->xfer_func = venc->params.color.transfer; |
261 | pix_mp->ycbcr_enc = venc->params.color.matrix; |
262 | pix_mp->quantization = venc->params.color.full_range; |
263 | |
264 | return 0; |
265 | } |
266 | |
267 | static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) |
268 | { |
269 | struct vpu_inst *inst = to_inst(filp: file); |
270 | struct venc_t *venc = inst->priv; |
271 | struct v4l2_fract *timeperframe; |
272 | |
273 | if (!parm) |
274 | return -EINVAL; |
275 | |
276 | if (!V4L2_TYPE_IS_OUTPUT(parm->type)) |
277 | return -EINVAL; |
278 | |
279 | if (!vpu_helper_check_type(inst, type: parm->type)) |
280 | return -EINVAL; |
281 | |
282 | timeperframe = &parm->parm.capture.timeperframe; |
283 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
284 | parm->parm.capture.readbuffers = 0; |
285 | timeperframe->numerator = venc->params.frame_rate.numerator; |
286 | timeperframe->denominator = venc->params.frame_rate.denominator; |
287 | |
288 | return 0; |
289 | } |
290 | |
291 | static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) |
292 | { |
293 | struct vpu_inst *inst = to_inst(filp: file); |
294 | struct venc_t *venc = inst->priv; |
295 | struct v4l2_fract *timeperframe; |
296 | unsigned long n, d; |
297 | |
298 | if (!parm) |
299 | return -EINVAL; |
300 | |
301 | if (!V4L2_TYPE_IS_OUTPUT(parm->type)) |
302 | return -EINVAL; |
303 | |
304 | if (!vpu_helper_check_type(inst, type: parm->type)) |
305 | return -EINVAL; |
306 | |
307 | timeperframe = &parm->parm.capture.timeperframe; |
308 | if (!timeperframe->numerator) |
309 | timeperframe->numerator = venc->params.frame_rate.numerator; |
310 | if (!timeperframe->denominator) |
311 | timeperframe->denominator = venc->params.frame_rate.denominator; |
312 | |
313 | venc->params.frame_rate.numerator = timeperframe->numerator; |
314 | venc->params.frame_rate.denominator = timeperframe->denominator; |
315 | |
316 | rational_best_approximation(given_numerator: venc->params.frame_rate.numerator, |
317 | given_denominator: venc->params.frame_rate.denominator, |
318 | max_numerator: venc->params.frame_rate.numerator, |
319 | max_denominator: venc->params.frame_rate.denominator, |
320 | best_numerator: &n, best_denominator: &d); |
321 | venc->params.frame_rate.numerator = n; |
322 | venc->params.frame_rate.denominator = d; |
323 | |
324 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
325 | memset(parm->parm.capture.reserved, 0, sizeof(parm->parm.capture.reserved)); |
326 | |
327 | return 0; |
328 | } |
329 | |
330 | static int venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) |
331 | { |
332 | struct vpu_inst *inst = to_inst(filp: file); |
333 | struct venc_t *venc = inst->priv; |
334 | |
335 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
336 | return -EINVAL; |
337 | |
338 | switch (s->target) { |
339 | case V4L2_SEL_TGT_CROP_DEFAULT: |
340 | case V4L2_SEL_TGT_CROP_BOUNDS: |
341 | s->r.left = 0; |
342 | s->r.top = 0; |
343 | s->r.width = inst->out_format.width; |
344 | s->r.height = inst->out_format.height; |
345 | break; |
346 | case V4L2_SEL_TGT_CROP: |
347 | s->r = venc->params.crop; |
348 | break; |
349 | default: |
350 | return -EINVAL; |
351 | } |
352 | |
353 | return 0; |
354 | } |
355 | |
356 | static int venc_valid_crop(struct venc_t *venc, const struct vpu_core_resources *res) |
357 | { |
358 | struct v4l2_rect *rect = NULL; |
359 | u32 min_width; |
360 | u32 min_height; |
361 | u32 src_width; |
362 | u32 src_height; |
363 | |
364 | rect = &venc->params.crop; |
365 | min_width = res->min_width; |
366 | min_height = res->min_height; |
367 | src_width = venc->params.src_width; |
368 | src_height = venc->params.src_height; |
369 | |
370 | if (rect->width == 0 || rect->height == 0) |
371 | return -EINVAL; |
372 | if (rect->left > src_width - min_width || rect->top > src_height - min_height) |
373 | return -EINVAL; |
374 | |
375 | rect->width = min(rect->width, src_width - rect->left); |
376 | rect->width = max_t(u32, rect->width, min_width); |
377 | |
378 | rect->height = min(rect->height, src_height - rect->top); |
379 | rect->height = max_t(u32, rect->height, min_height); |
380 | |
381 | return 0; |
382 | } |
383 | |
384 | static int venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) |
385 | { |
386 | struct vpu_inst *inst = to_inst(filp: file); |
387 | const struct vpu_core_resources *res; |
388 | struct venc_t *venc = inst->priv; |
389 | |
390 | res = vpu_get_resource(inst); |
391 | if (!res) |
392 | return -EINVAL; |
393 | |
394 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
395 | return -EINVAL; |
396 | if (s->target != V4L2_SEL_TGT_CROP) |
397 | return -EINVAL; |
398 | |
399 | venc->params.crop.left = ALIGN(s->r.left, res->step_width); |
400 | venc->params.crop.top = ALIGN(s->r.top, res->step_height); |
401 | venc->params.crop.width = ALIGN(s->r.width, res->step_width); |
402 | venc->params.crop.height = ALIGN(s->r.height, res->step_height); |
403 | if (venc_valid_crop(venc, res)) { |
404 | venc->params.crop.left = 0; |
405 | venc->params.crop.top = 0; |
406 | venc->params.crop.width = venc->params.src_width; |
407 | venc->params.crop.height = venc->params.src_height; |
408 | } |
409 | |
410 | inst->crop = venc->params.crop; |
411 | |
412 | return 0; |
413 | } |
414 | |
415 | static int venc_drain(struct vpu_inst *inst) |
416 | { |
417 | struct venc_t *venc = inst->priv; |
418 | int ret; |
419 | |
420 | if (!inst->fh.m2m_ctx) |
421 | return 0; |
422 | |
423 | if (inst->state != VPU_CODEC_STATE_DRAIN) |
424 | return 0; |
425 | |
426 | if (!vpu_is_source_empty(inst)) |
427 | return 0; |
428 | |
429 | if (!venc->input_ready) |
430 | return 0; |
431 | |
432 | venc->input_ready = false; |
433 | vpu_trace(inst->dev, "[%d]\n" , inst->id); |
434 | ret = vpu_session_stop(inst); |
435 | if (ret) |
436 | return ret; |
437 | inst->state = VPU_CODEC_STATE_STOP; |
438 | wake_up_all(&venc->wq); |
439 | |
440 | return 0; |
441 | } |
442 | |
443 | static int venc_request_eos(struct vpu_inst *inst) |
444 | { |
445 | inst->state = VPU_CODEC_STATE_DRAIN; |
446 | venc_drain(inst); |
447 | |
448 | return 0; |
449 | } |
450 | |
451 | static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd) |
452 | { |
453 | struct vpu_inst *inst = to_inst(filp: file); |
454 | int ret; |
455 | |
456 | ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec: cmd); |
457 | if (ret) |
458 | return ret; |
459 | |
460 | vpu_inst_lock(inst); |
461 | if (cmd->cmd == V4L2_ENC_CMD_STOP) { |
462 | if (inst->state == VPU_CODEC_STATE_DEINIT) |
463 | vpu_set_last_buffer_dequeued(inst, eos: true); |
464 | else |
465 | venc_request_eos(inst); |
466 | } |
467 | vpu_inst_unlock(inst); |
468 | |
469 | return 0; |
470 | } |
471 | |
472 | static int venc_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) |
473 | { |
474 | switch (sub->type) { |
475 | case V4L2_EVENT_EOS: |
476 | return v4l2_event_subscribe(fh, sub, elems: 0, NULL); |
477 | case V4L2_EVENT_CTRL: |
478 | return v4l2_ctrl_subscribe_event(fh, sub); |
479 | default: |
480 | return -EINVAL; |
481 | } |
482 | } |
483 | |
484 | static const struct v4l2_ioctl_ops venc_ioctl_ops = { |
485 | .vidioc_querycap = venc_querycap, |
486 | .vidioc_enum_fmt_vid_cap = venc_enum_fmt, |
487 | .vidioc_enum_fmt_vid_out = venc_enum_fmt, |
488 | .vidioc_enum_framesizes = venc_enum_framesizes, |
489 | .vidioc_enum_frameintervals = venc_enum_frameintervals, |
490 | .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, |
491 | .vidioc_g_fmt_vid_out_mplane = venc_g_fmt, |
492 | .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt, |
493 | .vidioc_try_fmt_vid_out_mplane = venc_try_fmt, |
494 | .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, |
495 | .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, |
496 | .vidioc_g_parm = venc_g_parm, |
497 | .vidioc_s_parm = venc_s_parm, |
498 | .vidioc_g_selection = venc_g_selection, |
499 | .vidioc_s_selection = venc_s_selection, |
500 | .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, |
501 | .vidioc_encoder_cmd = venc_encoder_cmd, |
502 | .vidioc_subscribe_event = venc_subscribe_event, |
503 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
504 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, |
505 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, |
506 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, |
507 | .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, |
508 | .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, |
509 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, |
510 | .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, |
511 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, |
512 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, |
513 | }; |
514 | |
515 | static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) |
516 | { |
517 | struct vpu_inst *inst = ctrl_to_inst(ctrl); |
518 | struct venc_t *venc = inst->priv; |
519 | int ret = 0; |
520 | |
521 | vpu_inst_lock(inst); |
522 | switch (ctrl->id) { |
523 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: |
524 | venc->params.profile = ctrl->val; |
525 | break; |
526 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: |
527 | venc->params.level = ctrl->val; |
528 | break; |
529 | case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: |
530 | venc->params.rc_enable = ctrl->val; |
531 | break; |
532 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
533 | venc->params.rc_mode = ctrl->val; |
534 | break; |
535 | case V4L2_CID_MPEG_VIDEO_BITRATE: |
536 | if (ctrl->val != venc->params.bitrate) |
537 | venc->bitrate_change = true; |
538 | venc->params.bitrate = ctrl->val; |
539 | break; |
540 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: |
541 | venc->params.bitrate_max = ctrl->val; |
542 | break; |
543 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: |
544 | venc->params.gop_length = ctrl->val; |
545 | break; |
546 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: |
547 | venc->params.bframes = ctrl->val; |
548 | break; |
549 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: |
550 | venc->params.i_frame_qp = ctrl->val; |
551 | break; |
552 | case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: |
553 | venc->params.p_frame_qp = ctrl->val; |
554 | break; |
555 | case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: |
556 | venc->params.b_frame_qp = ctrl->val; |
557 | break; |
558 | case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: |
559 | venc->request_key_frame = 1; |
560 | break; |
561 | case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: |
562 | venc->cpb_size = ctrl->val * 1024; |
563 | break; |
564 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: |
565 | venc->params.sar.enable = ctrl->val; |
566 | break; |
567 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: |
568 | venc->params.sar.idc = ctrl->val; |
569 | break; |
570 | case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: |
571 | venc->params.sar.width = ctrl->val; |
572 | break; |
573 | case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT: |
574 | venc->params.sar.height = ctrl->val; |
575 | break; |
576 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: |
577 | break; |
578 | default: |
579 | ret = -EINVAL; |
580 | break; |
581 | } |
582 | vpu_inst_unlock(inst); |
583 | |
584 | return ret; |
585 | } |
586 | |
587 | static const struct v4l2_ctrl_ops venc_ctrl_ops = { |
588 | .s_ctrl = venc_op_s_ctrl, |
589 | .g_volatile_ctrl = vpu_helper_g_volatile_ctrl, |
590 | }; |
591 | |
592 | static int venc_ctrl_init(struct vpu_inst *inst) |
593 | { |
594 | struct v4l2_ctrl *ctrl; |
595 | int ret; |
596 | |
597 | ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20); |
598 | if (ret) |
599 | return ret; |
600 | |
601 | v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
602 | V4L2_CID_MPEG_VIDEO_H264_PROFILE, |
603 | max: V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, |
604 | mask: ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | |
605 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | |
606 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), |
607 | def: V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); |
608 | |
609 | v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
610 | V4L2_CID_MPEG_VIDEO_H264_LEVEL, |
611 | max: V4L2_MPEG_VIDEO_H264_LEVEL_5_1, |
612 | mask: 0x0, |
613 | def: V4L2_MPEG_VIDEO_H264_LEVEL_4_0); |
614 | |
615 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
616 | V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, min: 0, max: 1, step: 1, def: 1); |
617 | |
618 | v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
619 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, |
620 | max: V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, |
621 | mask: ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | |
622 | (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)), |
623 | def: V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); |
624 | |
625 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
626 | V4L2_CID_MPEG_VIDEO_BITRATE, |
627 | BITRATE_MIN, |
628 | BITRATE_MAX, |
629 | BITRATE_STEP, |
630 | BITRATE_DEFAULT); |
631 | |
632 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
633 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, |
634 | BITRATE_MIN, BITRATE_MAX, |
635 | BITRATE_STEP, |
636 | BITRATE_DEFAULT_PEAK); |
637 | |
638 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
639 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, min: 1, max: 8000, step: 1, def: 30); |
640 | |
641 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
642 | V4L2_CID_MPEG_VIDEO_B_FRAMES, min: 0, max: 4, step: 1, def: 0); |
643 | |
644 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
645 | V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, min: 1, max: 51, step: 1, def: 26); |
646 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
647 | V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, min: 1, max: 51, step: 1, def: 28); |
648 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
649 | V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, min: 1, max: 51, step: 1, def: 30); |
650 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
651 | V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, min: 0, max: 0, step: 0, def: 0); |
652 | ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
653 | V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, min: 1, max: 32, step: 1, def: 2); |
654 | if (ctrl) |
655 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; |
656 | ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
657 | V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, min: 1, max: 32, step: 1, def: 2); |
658 | if (ctrl) |
659 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; |
660 | |
661 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
662 | V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, min: 64, max: 10240, step: 1, def: 1024); |
663 | |
664 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
665 | V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, min: 0, max: 1, step: 1, def: 1); |
666 | v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
667 | V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, |
668 | max: V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED, |
669 | mask: 0x0, |
670 | def: V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); |
671 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
672 | V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH, |
673 | min: 0, USHRT_MAX, step: 1, def: 1); |
674 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
675 | V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT, |
676 | min: 0, USHRT_MAX, step: 1, def: 1); |
677 | v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops, |
678 | V4L2_CID_MPEG_VIDEO_HEADER_MODE, |
679 | max: V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, |
680 | mask: ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), |
681 | def: V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); |
682 | |
683 | if (inst->ctrl_handler.error) { |
684 | ret = inst->ctrl_handler.error; |
685 | v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler); |
686 | return ret; |
687 | } |
688 | |
689 | ret = v4l2_ctrl_handler_setup(hdl: &inst->ctrl_handler); |
690 | if (ret) { |
691 | dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n" , inst->id, ret); |
692 | v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler); |
693 | return ret; |
694 | } |
695 | |
696 | return 0; |
697 | } |
698 | |
699 | static bool venc_check_ready(struct vpu_inst *inst, unsigned int type) |
700 | { |
701 | struct venc_t *venc = inst->priv; |
702 | |
703 | if (V4L2_TYPE_IS_OUTPUT(type)) { |
704 | if (vpu_helper_get_free_space(inst) < venc->cpb_size) |
705 | return false; |
706 | return venc->input_ready; |
707 | } |
708 | |
709 | if (list_empty(head: &venc->frames)) |
710 | return false; |
711 | return true; |
712 | } |
713 | |
714 | static u32 venc_get_enable_mask(u32 type) |
715 | { |
716 | if (V4L2_TYPE_IS_OUTPUT(type)) |
717 | return VENC_OUTPUT_ENABLE; |
718 | else |
719 | return VENC_CAPTURE_ENABLE; |
720 | } |
721 | |
722 | static void venc_set_enable(struct venc_t *venc, u32 type, int enable) |
723 | { |
724 | u32 mask = venc_get_enable_mask(type); |
725 | |
726 | if (enable) |
727 | venc->enable |= mask; |
728 | else |
729 | venc->enable &= ~mask; |
730 | } |
731 | |
732 | static u32 venc_get_enable(struct venc_t *venc, u32 type) |
733 | { |
734 | return venc->enable & venc_get_enable_mask(type); |
735 | } |
736 | |
737 | static void venc_input_done(struct vpu_inst *inst) |
738 | { |
739 | struct venc_t *venc = inst->priv; |
740 | |
741 | vpu_inst_lock(inst); |
742 | venc->input_ready = true; |
743 | vpu_process_output_buffer(inst); |
744 | if (inst->state == VPU_CODEC_STATE_DRAIN) |
745 | venc_drain(inst); |
746 | vpu_inst_unlock(inst); |
747 | } |
748 | |
749 | /* |
750 | * It's hardware limitation, that there may be several bytes |
751 | * redundant data at the beginning of frame. |
752 | * For android platform, the redundant data may cause cts test fail |
753 | * So driver will strip them |
754 | */ |
755 | static int venc_precheck_encoded_frame(struct vpu_inst *inst, struct venc_frame_t *frame) |
756 | { |
757 | struct venc_t *venc; |
758 | int skipped; |
759 | |
760 | if (!frame || !frame->bytesused) |
761 | return -EINVAL; |
762 | |
763 | venc = inst->priv; |
764 | skipped = vpu_helper_find_startcode(stream_buffer: &inst->stream_buffer, |
765 | pixelformat: inst->cap_format.pixfmt, |
766 | offset: frame->info.wptr - inst->stream_buffer.phys, |
767 | bytesused: frame->bytesused); |
768 | if (skipped > 0) { |
769 | frame->bytesused -= skipped; |
770 | frame->info.wptr = vpu_helper_step_walk(stream_buffer: &inst->stream_buffer, |
771 | pos: frame->info.wptr, step: skipped); |
772 | venc->skipped_bytes += skipped; |
773 | venc->skipped_count++; |
774 | } |
775 | |
776 | return 0; |
777 | } |
778 | |
779 | static int venc_get_one_encoded_frame(struct vpu_inst *inst, |
780 | struct venc_frame_t *frame, |
781 | struct vb2_v4l2_buffer *vbuf) |
782 | { |
783 | struct venc_t *venc = inst->priv; |
784 | struct vb2_v4l2_buffer *src_buf; |
785 | |
786 | if (!vbuf) |
787 | return -EAGAIN; |
788 | |
789 | src_buf = vpu_find_buf_by_sequence(inst, type: inst->out_format.type, sequence: frame->info.frame_id); |
790 | if (src_buf) { |
791 | v4l2_m2m_buf_copy_metadata(out_vb: src_buf, cap_vb: vbuf, copy_frame_flags: true); |
792 | vpu_set_buffer_state(vbuf: src_buf, state: VPU_BUF_STATE_IDLE); |
793 | v4l2_m2m_src_buf_remove_by_buf(m2m_ctx: inst->fh.m2m_ctx, vbuf: src_buf); |
794 | v4l2_m2m_buf_done(buf: src_buf, state: VB2_BUF_STATE_DONE); |
795 | } else { |
796 | vbuf->vb2_buf.timestamp = frame->info.timestamp; |
797 | } |
798 | if (!venc_get_enable(venc: inst->priv, type: vbuf->vb2_buf.type)) { |
799 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_ERROR); |
800 | return 0; |
801 | } |
802 | if (frame->bytesused > vbuf->vb2_buf.planes[0].length) { |
803 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_ERROR); |
804 | return -ENOMEM; |
805 | } |
806 | |
807 | venc_precheck_encoded_frame(inst, frame); |
808 | |
809 | if (frame->bytesused) { |
810 | u32 rptr = frame->info.wptr; |
811 | void *dst = vb2_plane_vaddr(vb: &vbuf->vb2_buf, plane_no: 0); |
812 | |
813 | vpu_helper_copy_from_stream_buffer(stream_buffer: &inst->stream_buffer, |
814 | rptr: &rptr, size: frame->bytesused, dst); |
815 | vpu_iface_update_stream_buffer(inst, ptr: rptr, write: 0); |
816 | } |
817 | vb2_set_plane_payload(vb: &vbuf->vb2_buf, plane_no: 0, size: frame->bytesused); |
818 | vbuf->sequence = frame->info.frame_id; |
819 | vbuf->field = inst->cap_format.field; |
820 | vbuf->flags |= frame->info.pic_type; |
821 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_IDLE); |
822 | dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n" , inst->id, vbuf->vb2_buf.timestamp); |
823 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_DONE); |
824 | venc->ready_count++; |
825 | |
826 | if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME) |
827 | dev_dbg(inst->dev, "[%d][%d]key frame\n" , inst->id, frame->info.frame_id); |
828 | |
829 | return 0; |
830 | } |
831 | |
832 | static int venc_get_encoded_frames(struct vpu_inst *inst) |
833 | { |
834 | struct venc_t *venc; |
835 | struct venc_frame_t *frame; |
836 | struct venc_frame_t *tmp; |
837 | |
838 | if (!inst->fh.m2m_ctx) |
839 | return 0; |
840 | venc = inst->priv; |
841 | list_for_each_entry_safe(frame, tmp, &venc->frames, list) { |
842 | if (venc_get_one_encoded_frame(inst, frame, |
843 | vbuf: v4l2_m2m_dst_buf_remove(m2m_ctx: inst->fh.m2m_ctx))) |
844 | break; |
845 | list_del_init(entry: &frame->list); |
846 | vfree(addr: frame); |
847 | } |
848 | |
849 | return 0; |
850 | } |
851 | |
852 | static int venc_frame_encoded(struct vpu_inst *inst, void *arg) |
853 | { |
854 | struct vpu_enc_pic_info *info = arg; |
855 | struct venc_frame_t *frame; |
856 | struct venc_t *venc; |
857 | int ret = 0; |
858 | |
859 | if (!info) |
860 | return -EINVAL; |
861 | venc = inst->priv; |
862 | frame = vzalloc(size: sizeof(*frame)); |
863 | if (!frame) |
864 | return -ENOMEM; |
865 | |
866 | memcpy(&frame->info, info, sizeof(frame->info)); |
867 | frame->bytesused = info->frame_size; |
868 | |
869 | vpu_inst_lock(inst); |
870 | list_add_tail(new: &frame->list, head: &venc->frames); |
871 | venc->encode_count++; |
872 | venc_get_encoded_frames(inst); |
873 | vpu_inst_unlock(inst); |
874 | |
875 | return ret; |
876 | } |
877 | |
878 | static void venc_set_last_buffer_dequeued(struct vpu_inst *inst) |
879 | { |
880 | struct venc_t *venc = inst->priv; |
881 | |
882 | if (venc->stopped && list_empty(head: &venc->frames)) |
883 | vpu_set_last_buffer_dequeued(inst, eos: true); |
884 | } |
885 | |
886 | static void venc_stop_done(struct vpu_inst *inst) |
887 | { |
888 | struct venc_t *venc = inst->priv; |
889 | |
890 | vpu_inst_lock(inst); |
891 | venc->stopped = true; |
892 | venc_set_last_buffer_dequeued(inst); |
893 | vpu_inst_unlock(inst); |
894 | |
895 | wake_up_all(&venc->wq); |
896 | } |
897 | |
898 | static void venc_event_notify(struct vpu_inst *inst, u32 event, void *data) |
899 | { |
900 | } |
901 | |
902 | static void venc_release(struct vpu_inst *inst) |
903 | { |
904 | } |
905 | |
906 | static void venc_cleanup(struct vpu_inst *inst) |
907 | { |
908 | struct venc_t *venc; |
909 | |
910 | if (!inst) |
911 | return; |
912 | |
913 | venc = inst->priv; |
914 | vfree(addr: venc); |
915 | inst->priv = NULL; |
916 | vfree(addr: inst); |
917 | } |
918 | |
919 | static int venc_start_session(struct vpu_inst *inst, u32 type) |
920 | { |
921 | struct venc_t *venc = inst->priv; |
922 | int stream_buffer_size; |
923 | int ret; |
924 | |
925 | venc_set_enable(venc, type, enable: 1); |
926 | if ((venc->enable & VENC_ENABLE_MASK) != VENC_ENABLE_MASK) |
927 | return 0; |
928 | |
929 | vpu_iface_init_instance(inst); |
930 | stream_buffer_size = vpu_iface_get_stream_buffer_size(core: inst->core); |
931 | if (stream_buffer_size > 0) { |
932 | inst->stream_buffer.length = max_t(u32, stream_buffer_size, venc->cpb_size * 3); |
933 | ret = vpu_alloc_dma(core: inst->core, buf: &inst->stream_buffer); |
934 | if (ret) |
935 | goto error; |
936 | |
937 | inst->use_stream_buffer = true; |
938 | vpu_iface_config_stream_buffer(inst, buf: &inst->stream_buffer); |
939 | } |
940 | |
941 | ret = vpu_iface_set_encode_params(inst, params: &venc->params, update: 0); |
942 | if (ret) |
943 | goto error; |
944 | ret = vpu_session_configure_codec(inst); |
945 | if (ret) |
946 | goto error; |
947 | |
948 | inst->state = VPU_CODEC_STATE_CONFIGURED; |
949 | /*vpu_iface_config_memory_resource*/ |
950 | |
951 | /*config enc expert mode parameter*/ |
952 | ret = vpu_iface_set_encode_params(inst, params: &venc->params, update: 1); |
953 | if (ret) |
954 | goto error; |
955 | |
956 | ret = vpu_session_start(inst); |
957 | if (ret) |
958 | goto error; |
959 | inst->state = VPU_CODEC_STATE_STARTED; |
960 | |
961 | venc->bitrate_change = false; |
962 | venc->input_ready = true; |
963 | venc->frame_count = 0; |
964 | venc->encode_count = 0; |
965 | venc->ready_count = 0; |
966 | venc->stopped = false; |
967 | vpu_process_output_buffer(inst); |
968 | if (venc->frame_count == 0) |
969 | dev_err(inst->dev, "[%d] there is no input when starting\n" , inst->id); |
970 | |
971 | return 0; |
972 | error: |
973 | venc_set_enable(venc, type, enable: 0); |
974 | inst->state = VPU_CODEC_STATE_DEINIT; |
975 | |
976 | vpu_free_dma(buf: &inst->stream_buffer); |
977 | return ret; |
978 | } |
979 | |
980 | static void venc_cleanup_mem_resource(struct vpu_inst *inst) |
981 | { |
982 | struct venc_t *venc; |
983 | u32 i; |
984 | |
985 | venc = inst->priv; |
986 | |
987 | for (i = 0; i < ARRAY_SIZE(venc->enc); i++) |
988 | vpu_free_dma(buf: &venc->enc[i]); |
989 | for (i = 0; i < ARRAY_SIZE(venc->ref); i++) |
990 | vpu_free_dma(buf: &venc->ref[i]); |
991 | } |
992 | |
993 | static void venc_request_mem_resource(struct vpu_inst *inst, |
994 | u32 enc_frame_size, |
995 | u32 enc_frame_num, |
996 | u32 ref_frame_size, |
997 | u32 ref_frame_num, |
998 | u32 act_frame_size, |
999 | u32 act_frame_num) |
1000 | { |
1001 | struct venc_t *venc; |
1002 | u32 i; |
1003 | int ret; |
1004 | |
1005 | venc = inst->priv; |
1006 | if (enc_frame_num > ARRAY_SIZE(venc->enc)) { |
1007 | dev_err(inst->dev, "[%d] enc num(%d) is out of range\n" , inst->id, enc_frame_num); |
1008 | return; |
1009 | } |
1010 | if (ref_frame_num > ARRAY_SIZE(venc->ref)) { |
1011 | dev_err(inst->dev, "[%d] ref num(%d) is out of range\n" , inst->id, ref_frame_num); |
1012 | return; |
1013 | } |
1014 | if (act_frame_num > ARRAY_SIZE(venc->act)) { |
1015 | dev_err(inst->dev, "[%d] act num(%d) is out of range\n" , inst->id, act_frame_num); |
1016 | return; |
1017 | } |
1018 | |
1019 | for (i = 0; i < enc_frame_num; i++) { |
1020 | venc->enc[i].length = enc_frame_size; |
1021 | ret = vpu_alloc_dma(core: inst->core, buf: &venc->enc[i]); |
1022 | if (ret) { |
1023 | venc_cleanup_mem_resource(inst); |
1024 | return; |
1025 | } |
1026 | } |
1027 | for (i = 0; i < ref_frame_num; i++) { |
1028 | venc->ref[i].length = ref_frame_size; |
1029 | ret = vpu_alloc_dma(core: inst->core, buf: &venc->ref[i]); |
1030 | if (ret) { |
1031 | venc_cleanup_mem_resource(inst); |
1032 | return; |
1033 | } |
1034 | } |
1035 | if (act_frame_num != 1 || act_frame_size > inst->act.length) { |
1036 | venc_cleanup_mem_resource(inst); |
1037 | return; |
1038 | } |
1039 | venc->act[0].length = act_frame_size; |
1040 | venc->act[0].phys = inst->act.phys; |
1041 | venc->act[0].virt = inst->act.virt; |
1042 | |
1043 | for (i = 0; i < enc_frame_num; i++) |
1044 | vpu_iface_config_memory_resource(inst, type: MEM_RES_ENC, index: i, buf: &venc->enc[i]); |
1045 | for (i = 0; i < ref_frame_num; i++) |
1046 | vpu_iface_config_memory_resource(inst, type: MEM_RES_REF, index: i, buf: &venc->ref[i]); |
1047 | for (i = 0; i < act_frame_num; i++) |
1048 | vpu_iface_config_memory_resource(inst, type: MEM_RES_ACT, index: i, buf: &venc->act[i]); |
1049 | } |
1050 | |
1051 | static void venc_cleanup_frames(struct venc_t *venc) |
1052 | { |
1053 | struct venc_frame_t *frame; |
1054 | struct venc_frame_t *tmp; |
1055 | |
1056 | list_for_each_entry_safe(frame, tmp, &venc->frames, list) { |
1057 | list_del_init(entry: &frame->list); |
1058 | vfree(addr: frame); |
1059 | } |
1060 | } |
1061 | |
1062 | static int venc_stop_session(struct vpu_inst *inst, u32 type) |
1063 | { |
1064 | struct venc_t *venc = inst->priv; |
1065 | |
1066 | venc_set_enable(venc, type, enable: 0); |
1067 | if (venc->enable & VENC_ENABLE_MASK) |
1068 | return 0; |
1069 | |
1070 | if (inst->state == VPU_CODEC_STATE_DEINIT) |
1071 | return 0; |
1072 | |
1073 | if (inst->state != VPU_CODEC_STATE_STOP) |
1074 | venc_request_eos(inst); |
1075 | |
1076 | call_void_vop(inst, wait_prepare); |
1077 | if (!wait_event_timeout(venc->wq, venc->stopped, VPU_TIMEOUT)) { |
1078 | set_bit(nr: inst->id, addr: &inst->core->hang_mask); |
1079 | vpu_session_debug(inst); |
1080 | } |
1081 | call_void_vop(inst, wait_finish); |
1082 | |
1083 | inst->state = VPU_CODEC_STATE_DEINIT; |
1084 | venc_cleanup_frames(venc: inst->priv); |
1085 | vpu_free_dma(buf: &inst->stream_buffer); |
1086 | venc_cleanup_mem_resource(inst); |
1087 | |
1088 | return 0; |
1089 | } |
1090 | |
1091 | static int venc_process_output(struct vpu_inst *inst, struct vb2_buffer *vb) |
1092 | { |
1093 | struct venc_t *venc = inst->priv; |
1094 | struct vb2_v4l2_buffer *vbuf; |
1095 | u32 flags; |
1096 | |
1097 | if (inst->state == VPU_CODEC_STATE_DEINIT) |
1098 | return -EINVAL; |
1099 | |
1100 | vbuf = to_vb2_v4l2_buffer(vb); |
1101 | if (inst->state == VPU_CODEC_STATE_STARTED) |
1102 | inst->state = VPU_CODEC_STATE_ACTIVE; |
1103 | |
1104 | flags = vbuf->flags; |
1105 | if (venc->request_key_frame) { |
1106 | vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME; |
1107 | venc->request_key_frame = 0; |
1108 | } |
1109 | if (venc->bitrate_change) { |
1110 | vpu_session_update_parameters(inst, arg: &venc->params); |
1111 | venc->bitrate_change = false; |
1112 | } |
1113 | dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n" , inst->id, vb->timestamp); |
1114 | vpu_iface_input_frame(inst, vb); |
1115 | vbuf->flags = flags; |
1116 | venc->input_ready = false; |
1117 | venc->frame_count++; |
1118 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_INUSE); |
1119 | |
1120 | return 0; |
1121 | } |
1122 | |
1123 | static int venc_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb) |
1124 | { |
1125 | struct venc_t *venc; |
1126 | struct venc_frame_t *frame = NULL; |
1127 | struct vb2_v4l2_buffer *vbuf; |
1128 | int ret; |
1129 | |
1130 | venc = inst->priv; |
1131 | if (list_empty(head: &venc->frames)) |
1132 | return -EINVAL; |
1133 | |
1134 | frame = list_first_entry(&venc->frames, struct venc_frame_t, list); |
1135 | vbuf = to_vb2_v4l2_buffer(vb); |
1136 | v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx: inst->fh.m2m_ctx, vbuf); |
1137 | ret = venc_get_one_encoded_frame(inst, frame, vbuf); |
1138 | if (ret) |
1139 | return ret; |
1140 | |
1141 | list_del_init(entry: &frame->list); |
1142 | vfree(addr: frame); |
1143 | return 0; |
1144 | } |
1145 | |
1146 | static void venc_on_queue_empty(struct vpu_inst *inst, u32 type) |
1147 | { |
1148 | struct venc_t *venc = inst->priv; |
1149 | |
1150 | if (V4L2_TYPE_IS_OUTPUT(type)) |
1151 | return; |
1152 | |
1153 | if (venc->stopped) |
1154 | venc_set_last_buffer_dequeued(inst); |
1155 | } |
1156 | |
1157 | static int venc_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i) |
1158 | { |
1159 | struct venc_t *venc = inst->priv; |
1160 | int num = -1; |
1161 | |
1162 | switch (i) { |
1163 | case 0: |
1164 | num = scnprintf(buf: str, size, fmt: "profile = %d\n" , venc->params.profile); |
1165 | break; |
1166 | case 1: |
1167 | num = scnprintf(buf: str, size, fmt: "level = %d\n" , venc->params.level); |
1168 | break; |
1169 | case 2: |
1170 | num = scnprintf(buf: str, size, fmt: "fps = %d/%d\n" , |
1171 | venc->params.frame_rate.numerator, |
1172 | venc->params.frame_rate.denominator); |
1173 | break; |
1174 | case 3: |
1175 | num = scnprintf(buf: str, size, fmt: "%d x %d -> %d x %d\n" , |
1176 | venc->params.src_width, |
1177 | venc->params.src_height, |
1178 | venc->params.out_width, |
1179 | venc->params.out_height); |
1180 | break; |
1181 | case 4: |
1182 | num = scnprintf(buf: str, size, fmt: "(%d, %d) %d x %d\n" , |
1183 | venc->params.crop.left, |
1184 | venc->params.crop.top, |
1185 | venc->params.crop.width, |
1186 | venc->params.crop.height); |
1187 | break; |
1188 | case 5: |
1189 | num = scnprintf(buf: str, size, |
1190 | fmt: "enable = 0x%x, input = %d, encode = %d, ready = %d, stopped = %d\n" , |
1191 | venc->enable, |
1192 | venc->frame_count, venc->encode_count, |
1193 | venc->ready_count, |
1194 | venc->stopped); |
1195 | break; |
1196 | case 6: |
1197 | num = scnprintf(buf: str, size, fmt: "gop = %d\n" , venc->params.gop_length); |
1198 | break; |
1199 | case 7: |
1200 | num = scnprintf(buf: str, size, fmt: "bframes = %d\n" , venc->params.bframes); |
1201 | break; |
1202 | case 8: |
1203 | num = scnprintf(buf: str, size, fmt: "rc: %s, mode = %d, bitrate = %d(%d), qp = %d\n" , |
1204 | venc->params.rc_enable ? "enable" : "disable" , |
1205 | venc->params.rc_mode, |
1206 | venc->params.bitrate, |
1207 | venc->params.bitrate_max, |
1208 | venc->params.i_frame_qp); |
1209 | break; |
1210 | case 9: |
1211 | num = scnprintf(buf: str, size, fmt: "sar: enable = %d, idc = %d, %d x %d\n" , |
1212 | venc->params.sar.enable, |
1213 | venc->params.sar.idc, |
1214 | venc->params.sar.width, |
1215 | venc->params.sar.height); |
1216 | |
1217 | break; |
1218 | case 10: |
1219 | num = scnprintf(buf: str, size, |
1220 | fmt: "colorspace: primaries = %d, transfer = %d, matrix = %d, full_range = %d\n" , |
1221 | venc->params.color.primaries, |
1222 | venc->params.color.transfer, |
1223 | venc->params.color.matrix, |
1224 | venc->params.color.full_range); |
1225 | break; |
1226 | case 11: |
1227 | num = scnprintf(buf: str, size, fmt: "skipped: count = %d, bytes = %d\n" , |
1228 | venc->skipped_count, venc->skipped_bytes); |
1229 | break; |
1230 | default: |
1231 | break; |
1232 | } |
1233 | |
1234 | return num; |
1235 | } |
1236 | |
1237 | static struct vpu_inst_ops venc_inst_ops = { |
1238 | .ctrl_init = venc_ctrl_init, |
1239 | .check_ready = venc_check_ready, |
1240 | .input_done = venc_input_done, |
1241 | .get_one_frame = venc_frame_encoded, |
1242 | .stop_done = venc_stop_done, |
1243 | .event_notify = venc_event_notify, |
1244 | .release = venc_release, |
1245 | .cleanup = venc_cleanup, |
1246 | .start = venc_start_session, |
1247 | .mem_request = venc_request_mem_resource, |
1248 | .stop = venc_stop_session, |
1249 | .process_output = venc_process_output, |
1250 | .process_capture = venc_process_capture, |
1251 | .on_queue_empty = venc_on_queue_empty, |
1252 | .get_debug_info = venc_get_debug_info, |
1253 | .wait_prepare = vpu_inst_unlock, |
1254 | .wait_finish = vpu_inst_lock, |
1255 | }; |
1256 | |
1257 | static void venc_init(struct file *file) |
1258 | { |
1259 | struct vpu_inst *inst = to_inst(filp: file); |
1260 | struct venc_t *venc; |
1261 | struct v4l2_format f; |
1262 | struct v4l2_streamparm parm; |
1263 | |
1264 | venc = inst->priv; |
1265 | venc->params.qp_min = 1; |
1266 | venc->params.qp_max = 51; |
1267 | venc->params.qp_min_i = 1; |
1268 | venc->params.qp_max_i = 51; |
1269 | venc->params.bitrate_min = BITRATE_MIN; |
1270 | |
1271 | memset(&f, 0, sizeof(f)); |
1272 | f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1273 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; |
1274 | f.fmt.pix_mp.width = 1280; |
1275 | f.fmt.pix_mp.height = 720; |
1276 | f.fmt.pix_mp.field = V4L2_FIELD_NONE; |
1277 | venc_s_fmt(file, fh: &inst->fh, f: &f); |
1278 | |
1279 | memset(&f, 0, sizeof(f)); |
1280 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1281 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; |
1282 | f.fmt.pix_mp.width = 1280; |
1283 | f.fmt.pix_mp.height = 720; |
1284 | f.fmt.pix_mp.field = V4L2_FIELD_NONE; |
1285 | venc_s_fmt(file, fh: &inst->fh, f: &f); |
1286 | |
1287 | memset(&parm, 0, sizeof(parm)); |
1288 | parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1289 | parm.parm.capture.timeperframe.numerator = 1; |
1290 | parm.parm.capture.timeperframe.denominator = 30; |
1291 | venc_s_parm(file, fh: &inst->fh, parm: &parm); |
1292 | } |
1293 | |
1294 | static int venc_open(struct file *file) |
1295 | { |
1296 | struct vpu_inst *inst; |
1297 | struct venc_t *venc; |
1298 | int ret; |
1299 | |
1300 | inst = vzalloc(size: sizeof(*inst)); |
1301 | if (!inst) |
1302 | return -ENOMEM; |
1303 | |
1304 | venc = vzalloc(size: sizeof(*venc)); |
1305 | if (!venc) { |
1306 | vfree(addr: inst); |
1307 | return -ENOMEM; |
1308 | } |
1309 | |
1310 | inst->ops = &venc_inst_ops; |
1311 | inst->formats = venc_formats; |
1312 | inst->type = VPU_CORE_TYPE_ENC; |
1313 | inst->priv = venc; |
1314 | INIT_LIST_HEAD(list: &venc->frames); |
1315 | init_waitqueue_head(&venc->wq); |
1316 | |
1317 | ret = vpu_v4l2_open(file, inst); |
1318 | if (ret) |
1319 | return ret; |
1320 | |
1321 | inst->min_buffer_out = VENC_MIN_BUFFER_OUT; |
1322 | inst->min_buffer_cap = VENC_MIN_BUFFER_CAP; |
1323 | venc_init(file); |
1324 | |
1325 | return 0; |
1326 | } |
1327 | |
1328 | static const struct v4l2_file_operations venc_fops = { |
1329 | .owner = THIS_MODULE, |
1330 | .open = venc_open, |
1331 | .release = vpu_v4l2_close, |
1332 | .unlocked_ioctl = video_ioctl2, |
1333 | .poll = v4l2_m2m_fop_poll, |
1334 | .mmap = v4l2_m2m_fop_mmap, |
1335 | }; |
1336 | |
1337 | const struct v4l2_ioctl_ops *venc_get_ioctl_ops(void) |
1338 | { |
1339 | return &venc_ioctl_ops; |
1340 | } |
1341 | |
1342 | const struct v4l2_file_operations *venc_get_fops(void) |
1343 | { |
1344 | return &venc_fops; |
1345 | } |
1346 | |