1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Contains the virtual decoder logic. The functions here control the |
4 | * tracing/TPG on a per-frame basis |
5 | */ |
6 | |
7 | #include "visl.h" |
8 | #include "visl-debugfs.h" |
9 | #include "visl-dec.h" |
10 | #include "visl-trace-fwht.h" |
11 | #include "visl-trace-mpeg2.h" |
12 | #include "visl-trace-vp8.h" |
13 | #include "visl-trace-vp9.h" |
14 | #include "visl-trace-h264.h" |
15 | #include "visl-trace-hevc.h" |
16 | #include "visl-trace-av1.h" |
17 | |
18 | #include <linux/delay.h> |
19 | #include <linux/workqueue.h> |
20 | #include <media/v4l2-mem2mem.h> |
21 | #include <media/tpg/v4l2-tpg.h> |
22 | |
23 | #define LAST_BUF_IDX (V4L2_AV1_REF_LAST_FRAME - V4L2_AV1_REF_LAST_FRAME) |
24 | #define LAST2_BUF_IDX (V4L2_AV1_REF_LAST2_FRAME - V4L2_AV1_REF_LAST_FRAME) |
25 | #define LAST3_BUF_IDX (V4L2_AV1_REF_LAST3_FRAME - V4L2_AV1_REF_LAST_FRAME) |
26 | #define GOLDEN_BUF_IDX (V4L2_AV1_REF_GOLDEN_FRAME - V4L2_AV1_REF_LAST_FRAME) |
27 | #define BWD_BUF_IDX (V4L2_AV1_REF_BWDREF_FRAME - V4L2_AV1_REF_LAST_FRAME) |
28 | #define ALT2_BUF_IDX (V4L2_AV1_REF_ALTREF2_FRAME - V4L2_AV1_REF_LAST_FRAME) |
29 | #define ALT_BUF_IDX (V4L2_AV1_REF_ALTREF_FRAME - V4L2_AV1_REF_LAST_FRAME) |
30 | |
31 | static void *plane_vaddr(struct tpg_data *tpg, struct vb2_buffer *buf, |
32 | u32 p, u32 bpl[TPG_MAX_PLANES], u32 h) |
33 | { |
34 | u32 i; |
35 | void *vbuf; |
36 | |
37 | if (p == 0 || tpg_g_buffers(tpg) > 1) |
38 | return vb2_plane_vaddr(vb: buf, plane_no: p); |
39 | vbuf = vb2_plane_vaddr(vb: buf, plane_no: 0); |
40 | for (i = 0; i < p; i++) |
41 | vbuf += bpl[i] * h / tpg->vdownsampling[i]; |
42 | return vbuf; |
43 | } |
44 | |
45 | static void visl_print_ts_idx(u8 **buf, __kernel_size_t *buflen, const char *name, |
46 | u64 ts, struct vb2_buffer *vb2_buf) |
47 | { |
48 | u32 len; |
49 | |
50 | if (tpg_verbose && vb2_buf) { |
51 | len = scnprintf(buf: *buf, size: *buflen, fmt: "%s: %lld, vb2_idx: %d\n" , name, |
52 | ts, vb2_buf->index); |
53 | } else { |
54 | len = scnprintf(buf: *buf, size: *buflen, fmt: "%s: %lld\n" , name, ts); |
55 | } |
56 | |
57 | *buf += len; |
58 | *buflen -= len; |
59 | } |
60 | |
61 | static void visl_get_ref_frames(struct visl_ctx *ctx, u8 *buf, |
62 | __kernel_size_t buflen, struct visl_run *run) |
63 | { |
64 | struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; |
65 | char [] = "Reference frames:\n" ; |
66 | u32 i; |
67 | u32 len; |
68 | |
69 | len = scnprintf(buf, size: buflen, fmt: header); |
70 | buf += len; |
71 | buflen -= len; |
72 | |
73 | switch (ctx->current_codec) { |
74 | case VISL_CODEC_NONE: |
75 | break; |
76 | |
77 | case VISL_CODEC_FWHT: { |
78 | struct vb2_buffer *vb2_buf; |
79 | |
80 | vb2_buf = vb2_find_buffer(q: cap_q, timestamp: run->fwht.params->backward_ref_ts); |
81 | |
82 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "backwards_ref_ts" , |
83 | ts: run->fwht.params->backward_ref_ts, vb2_buf); |
84 | |
85 | break; |
86 | } |
87 | |
88 | case VISL_CODEC_MPEG2: { |
89 | struct vb2_buffer *b_ref; |
90 | struct vb2_buffer *f_ref; |
91 | |
92 | b_ref = vb2_find_buffer(q: cap_q, timestamp: run->mpeg2.pic->backward_ref_ts); |
93 | f_ref = vb2_find_buffer(q: cap_q, timestamp: run->mpeg2.pic->forward_ref_ts); |
94 | |
95 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "backward_ref_ts" , |
96 | ts: run->mpeg2.pic->backward_ref_ts, vb2_buf: b_ref); |
97 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "forward_ref_ts" , |
98 | ts: run->mpeg2.pic->forward_ref_ts, vb2_buf: f_ref); |
99 | |
100 | break; |
101 | } |
102 | |
103 | case VISL_CODEC_VP8: { |
104 | struct vb2_buffer *last; |
105 | struct vb2_buffer *golden; |
106 | struct vb2_buffer *alt; |
107 | |
108 | last = vb2_find_buffer(q: cap_q, timestamp: run->vp8.frame->last_frame_ts); |
109 | golden = vb2_find_buffer(q: cap_q, timestamp: run->vp8.frame->golden_frame_ts); |
110 | alt = vb2_find_buffer(q: cap_q, timestamp: run->vp8.frame->alt_frame_ts); |
111 | |
112 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "last_ref_ts" , |
113 | ts: run->vp8.frame->last_frame_ts, vb2_buf: last); |
114 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "golden_ref_ts" , |
115 | ts: run->vp8.frame->golden_frame_ts, vb2_buf: golden); |
116 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "alt_ref_ts" , |
117 | ts: run->vp8.frame->alt_frame_ts, vb2_buf: alt); |
118 | |
119 | break; |
120 | } |
121 | |
122 | case VISL_CODEC_VP9: { |
123 | struct vb2_buffer *last; |
124 | struct vb2_buffer *golden; |
125 | struct vb2_buffer *alt; |
126 | |
127 | last = vb2_find_buffer(q: cap_q, timestamp: run->vp9.frame->last_frame_ts); |
128 | golden = vb2_find_buffer(q: cap_q, timestamp: run->vp9.frame->golden_frame_ts); |
129 | alt = vb2_find_buffer(q: cap_q, timestamp: run->vp9.frame->alt_frame_ts); |
130 | |
131 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "last_ref_ts" , |
132 | ts: run->vp9.frame->last_frame_ts, vb2_buf: last); |
133 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "golden_ref_ts" , |
134 | ts: run->vp9.frame->golden_frame_ts, vb2_buf: golden); |
135 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "alt_ref_ts" , |
136 | ts: run->vp9.frame->alt_frame_ts, vb2_buf: alt); |
137 | |
138 | break; |
139 | } |
140 | |
141 | case VISL_CODEC_H264: { |
142 | char entry[] = "dpb[%d]:%u, vb2_index: %d\n" ; |
143 | char entry_stable[] = "dpb[%d]:%u\n" ; |
144 | struct vb2_buffer *vb2_buf; |
145 | |
146 | for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++) { |
147 | vb2_buf = vb2_find_buffer(q: cap_q, |
148 | timestamp: run->h264.dpram->dpb[i].reference_ts); |
149 | if (tpg_verbose && vb2_buf) { |
150 | len = scnprintf(buf, size: buflen, fmt: entry, i, |
151 | run->h264.dpram->dpb[i].reference_ts, |
152 | vb2_buf->index); |
153 | } else { |
154 | len = scnprintf(buf, size: buflen, fmt: entry_stable, i, |
155 | run->h264.dpram->dpb[i].reference_ts); |
156 | } |
157 | buf += len; |
158 | buflen -= len; |
159 | } |
160 | |
161 | break; |
162 | } |
163 | |
164 | case VISL_CODEC_HEVC: { |
165 | char entry[] = "dpb[%d]:%u, vb2_index: %d\n" ; |
166 | char entry_stable[] = "dpb[%d]:%u\n" ; |
167 | struct vb2_buffer *vb2_buf; |
168 | |
169 | for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++) { |
170 | vb2_buf = vb2_find_buffer(q: cap_q, timestamp: run->hevc.dpram->dpb[i].timestamp); |
171 | if (tpg_verbose && vb2_buf) { |
172 | len = scnprintf(buf, size: buflen, fmt: entry, i, |
173 | run->hevc.dpram->dpb[i].timestamp, |
174 | vb2_buf->index); |
175 | } else { |
176 | len = scnprintf(buf, size: buflen, fmt: entry_stable, i, |
177 | run->hevc.dpram->dpb[i].timestamp); |
178 | } |
179 | |
180 | buf += len; |
181 | buflen -= len; |
182 | } |
183 | |
184 | break; |
185 | } |
186 | |
187 | case VISL_CODEC_AV1: { |
188 | int idx_last = run->av1.frame->ref_frame_idx[LAST_BUF_IDX]; |
189 | int idx_last2 = run->av1.frame->ref_frame_idx[LAST2_BUF_IDX]; |
190 | int idx_last3 = run->av1.frame->ref_frame_idx[LAST3_BUF_IDX]; |
191 | int idx_golden = run->av1.frame->ref_frame_idx[GOLDEN_BUF_IDX]; |
192 | int idx_bwd = run->av1.frame->ref_frame_idx[BWD_BUF_IDX]; |
193 | int idx_alt2 = run->av1.frame->ref_frame_idx[ALT2_BUF_IDX]; |
194 | int idx_alt = run->av1.frame->ref_frame_idx[ALT_BUF_IDX]; |
195 | |
196 | const u64 *reference_frame_ts = run->av1.frame->reference_frame_ts; |
197 | |
198 | struct vb2_buffer *ref_last = |
199 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_last]); |
200 | struct vb2_buffer *ref_last2 = |
201 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_last2]); |
202 | struct vb2_buffer *ref_last3 = |
203 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_last3]); |
204 | struct vb2_buffer *ref_golden = |
205 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_golden]); |
206 | struct vb2_buffer *ref_bwd = |
207 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_bwd]); |
208 | struct vb2_buffer *ref_alt2 = |
209 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_alt2]); |
210 | struct vb2_buffer *ref_alt = |
211 | vb2_find_buffer(q: cap_q, timestamp: reference_frame_ts[idx_alt]); |
212 | |
213 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_last_ts" , |
214 | ts: reference_frame_ts[idx_last], vb2_buf: ref_last); |
215 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_last2_ts" , |
216 | ts: reference_frame_ts[idx_last2], vb2_buf: ref_last2); |
217 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_last3_ts" , |
218 | ts: reference_frame_ts[idx_last3], vb2_buf: ref_last3); |
219 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_golden_ts" , |
220 | ts: reference_frame_ts[idx_golden], vb2_buf: ref_golden); |
221 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_bwd_ts" , |
222 | ts: reference_frame_ts[idx_bwd], vb2_buf: ref_bwd); |
223 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_alt2_ts" , |
224 | ts: reference_frame_ts[idx_alt2], vb2_buf: ref_alt2); |
225 | visl_print_ts_idx(buf: &buf, buflen: &buflen, name: "ref_alt_ts" , |
226 | ts: reference_frame_ts[idx_alt], vb2_buf: ref_alt); |
227 | |
228 | break; |
229 | } |
230 | } |
231 | } |
232 | |
233 | static char *visl_get_vb2_state(enum vb2_buffer_state state) |
234 | { |
235 | switch (state) { |
236 | case VB2_BUF_STATE_DEQUEUED: |
237 | return "Dequeued" ; |
238 | case VB2_BUF_STATE_IN_REQUEST: |
239 | return "In request" ; |
240 | case VB2_BUF_STATE_PREPARING: |
241 | return "Preparing" ; |
242 | case VB2_BUF_STATE_QUEUED: |
243 | return "Queued" ; |
244 | case VB2_BUF_STATE_ACTIVE: |
245 | return "Active" ; |
246 | case VB2_BUF_STATE_DONE: |
247 | return "Done" ; |
248 | case VB2_BUF_STATE_ERROR: |
249 | return "Error" ; |
250 | default: |
251 | return "" ; |
252 | } |
253 | } |
254 | |
255 | static int visl_fill_bytesused(struct vb2_v4l2_buffer *v4l2_vb2_buf, char *buf, size_t bufsz) |
256 | { |
257 | int len = 0; |
258 | u32 i; |
259 | |
260 | for (i = 0; i < v4l2_vb2_buf->vb2_buf.num_planes; i++) |
261 | len += scnprintf(buf, size: bufsz, |
262 | fmt: "bytesused[%u]: %u length[%u]: %u data_offset[%u]: %u" , |
263 | i, v4l2_vb2_buf->planes[i].bytesused, |
264 | i, v4l2_vb2_buf->planes[i].length, |
265 | i, v4l2_vb2_buf->planes[i].data_offset); |
266 | |
267 | return len; |
268 | } |
269 | |
270 | static void visl_tpg_fill_sequence(struct visl_ctx *ctx, |
271 | struct visl_run *run, char buf[], size_t bufsz) |
272 | { |
273 | u32 stream_ms; |
274 | int len; |
275 | |
276 | if (tpg_verbose) { |
277 | stream_ms = jiffies_to_msecs(j: get_jiffies_64() - ctx->capture_streamon_jiffies); |
278 | |
279 | len = scnprintf(buf, size: bufsz, |
280 | fmt: "stream time: %02d:%02d:%02d:%03d " , |
281 | (stream_ms / (60 * 60 * 1000)) % 24, |
282 | (stream_ms / (60 * 1000)) % 60, |
283 | (stream_ms / 1000) % 60, |
284 | stream_ms % 1000); |
285 | buf += len; |
286 | bufsz -= len; |
287 | } |
288 | |
289 | scnprintf(buf, size: bufsz, |
290 | fmt: "sequence:%u timestamp:%lld field:%s" , |
291 | run->dst->sequence, |
292 | run->dst->vb2_buf.timestamp, |
293 | (run->dst->field == V4L2_FIELD_ALTERNATE) ? |
294 | (run->dst->field == V4L2_FIELD_TOP ? |
295 | " top" : " bottom" ) : "none" ); |
296 | } |
297 | |
298 | static bool visl_tpg_fill_codec_specific(struct visl_ctx *ctx, |
299 | struct visl_run *run, |
300 | char buf[], size_t bufsz) |
301 | { |
302 | /* |
303 | * To add variability, we need a value that is stable for a given |
304 | * input but is different than already shown fields. |
305 | * The pic order count value defines the display order of the frames |
306 | * (which can be different than the decoding order that is shown with |
307 | * the sequence number). |
308 | * Therefore it is stable for a given input and will add a different |
309 | * value that is more specific to the way the input is encoded. |
310 | */ |
311 | switch (ctx->current_codec) { |
312 | case VISL_CODEC_H264: |
313 | scnprintf(buf, size: bufsz, |
314 | fmt: "H264: %u" , run->h264.dpram->pic_order_cnt_lsb); |
315 | break; |
316 | case VISL_CODEC_HEVC: |
317 | scnprintf(buf, size: bufsz, |
318 | fmt: "HEVC: %d" , run->hevc.dpram->pic_order_cnt_val); |
319 | break; |
320 | default: |
321 | return false; |
322 | } |
323 | |
324 | return true; |
325 | } |
326 | |
327 | static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run) |
328 | { |
329 | u8 *basep[TPG_MAX_PLANES][2]; |
330 | char *buf = ctx->tpg_str_buf; |
331 | char *tmp = buf; |
332 | char *line_str; |
333 | u32 line = 1; |
334 | const u32 line_height = 16; |
335 | u32 len; |
336 | struct vb2_queue *out_q = &ctx->fh.m2m_ctx->out_q_ctx.q; |
337 | struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; |
338 | struct v4l2_pix_format_mplane *coded_fmt = &ctx->coded_fmt.fmt.pix_mp; |
339 | struct v4l2_pix_format_mplane *decoded_fmt = &ctx->decoded_fmt.fmt.pix_mp; |
340 | u32 p; |
341 | u32 i; |
342 | |
343 | for (p = 0; p < tpg_g_planes(tpg: &ctx->tpg); p++) { |
344 | void *vbuf = plane_vaddr(tpg: &ctx->tpg, |
345 | buf: &run->dst->vb2_buf, p, |
346 | bpl: ctx->tpg.bytesperline, |
347 | h: ctx->tpg.buf_height); |
348 | |
349 | tpg_calc_text_basep(tpg: &ctx->tpg, basep, p, vbuf); |
350 | tpg_fill_plane_buffer(tpg: &ctx->tpg, std: 0, p, vbuf); |
351 | } |
352 | |
353 | visl_tpg_fill_sequence(ctx, run, buf, TPG_STR_BUF_SZ); |
354 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
355 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
356 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
357 | line++; |
358 | |
359 | if (visl_tpg_fill_codec_specific(ctx, run, buf, TPG_STR_BUF_SZ)) { |
360 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
361 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
362 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
363 | line++; |
364 | } |
365 | |
366 | visl_get_ref_frames(ctx, buf, TPG_STR_BUF_SZ, run); |
367 | |
368 | while ((line_str = strsep(&tmp, "\n" )) && strlen(line_str)) { |
369 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: line_str); |
370 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , line_str); |
371 | } |
372 | |
373 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
374 | line++; |
375 | |
376 | scnprintf(buf, |
377 | TPG_STR_BUF_SZ, |
378 | fmt: "OUTPUT pixelformat: %c%c%c%c, resolution: %dx%d, num_planes: %d" , |
379 | coded_fmt->pixelformat, |
380 | (coded_fmt->pixelformat >> 8) & 0xff, |
381 | (coded_fmt->pixelformat >> 16) & 0xff, |
382 | (coded_fmt->pixelformat >> 24) & 0xff, |
383 | coded_fmt->width, |
384 | coded_fmt->height, |
385 | coded_fmt->num_planes); |
386 | |
387 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
388 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
389 | |
390 | for (i = 0; i < coded_fmt->num_planes; i++) { |
391 | scnprintf(buf, |
392 | TPG_STR_BUF_SZ, |
393 | fmt: "plane[%d]: bytesperline: %d, sizeimage: %d" , |
394 | i, |
395 | coded_fmt->plane_fmt[i].bytesperline, |
396 | coded_fmt->plane_fmt[i].sizeimage); |
397 | |
398 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
399 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
400 | } |
401 | |
402 | if (tpg_verbose) { |
403 | line++; |
404 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
405 | scnprintf(buf, TPG_STR_BUF_SZ, fmt: "Output queue status:" ); |
406 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
407 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
408 | |
409 | len = 0; |
410 | for (i = 0; i < vb2_get_num_buffers(q: out_q); i++) { |
411 | char entry[] = "index: %u, state: %s, request_fd: %d, " ; |
412 | u32 old_len = len; |
413 | struct vb2_buffer *vb2; |
414 | char *q_status; |
415 | |
416 | vb2 = vb2_get_buffer(q: out_q, index: i); |
417 | if (!vb2) |
418 | continue; |
419 | |
420 | q_status = visl_get_vb2_state(state: vb2->state); |
421 | |
422 | len += scnprintf(buf: &buf[len], TPG_STR_BUF_SZ - len, |
423 | fmt: entry, i, q_status, |
424 | to_vb2_v4l2_buffer(vb2)->request_fd); |
425 | |
426 | len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2), |
427 | buf: &buf[len], |
428 | TPG_STR_BUF_SZ - len); |
429 | |
430 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: &buf[old_len]); |
431 | frame_dprintk(ctx->dev, run->dst->sequence, "%s" , &buf[old_len]); |
432 | } |
433 | } |
434 | |
435 | line++; |
436 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
437 | |
438 | scnprintf(buf, |
439 | TPG_STR_BUF_SZ, |
440 | fmt: "CAPTURE pixelformat: %c%c%c%c, resolution: %dx%d, num_planes: %d" , |
441 | decoded_fmt->pixelformat, |
442 | (decoded_fmt->pixelformat >> 8) & 0xff, |
443 | (decoded_fmt->pixelformat >> 16) & 0xff, |
444 | (decoded_fmt->pixelformat >> 24) & 0xff, |
445 | decoded_fmt->width, |
446 | decoded_fmt->height, |
447 | decoded_fmt->num_planes); |
448 | |
449 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
450 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
451 | |
452 | for (i = 0; i < decoded_fmt->num_planes; i++) { |
453 | scnprintf(buf, |
454 | TPG_STR_BUF_SZ, |
455 | fmt: "plane[%d]: bytesperline: %d, sizeimage: %d" , |
456 | i, |
457 | decoded_fmt->plane_fmt[i].bytesperline, |
458 | decoded_fmt->plane_fmt[i].sizeimage); |
459 | |
460 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
461 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
462 | } |
463 | |
464 | if (tpg_verbose) { |
465 | line++; |
466 | frame_dprintk(ctx->dev, run->dst->sequence, "" ); |
467 | scnprintf(buf, TPG_STR_BUF_SZ, fmt: "Capture queue status:" ); |
468 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: buf); |
469 | frame_dprintk(ctx->dev, run->dst->sequence, "%s\n" , buf); |
470 | |
471 | len = 0; |
472 | for (i = 0; i < vb2_get_num_buffers(q: cap_q); i++) { |
473 | u32 old_len = len; |
474 | struct vb2_buffer *vb2; |
475 | char *q_status; |
476 | |
477 | vb2 = vb2_get_buffer(q: cap_q, index: i); |
478 | if (!vb2) |
479 | continue; |
480 | |
481 | q_status = visl_get_vb2_state(state: vb2->state); |
482 | |
483 | len += scnprintf(buf: &buf[len], TPG_STR_BUF_SZ - len, |
484 | fmt: "index: %u, status: %s, timestamp: %llu, is_held: %d" , |
485 | vb2->index, q_status, |
486 | vb2->timestamp, |
487 | to_vb2_v4l2_buffer(vb2)->is_held); |
488 | |
489 | tpg_gen_text(tpg: &ctx->tpg, basep, y: line++ * line_height, x: 16, text: &buf[old_len]); |
490 | frame_dprintk(ctx->dev, run->dst->sequence, "%s" , &buf[old_len]); |
491 | } |
492 | } |
493 | } |
494 | |
495 | static void visl_trace_ctrls(struct visl_ctx *ctx, struct visl_run *run) |
496 | { |
497 | int i; |
498 | |
499 | switch (ctx->current_codec) { |
500 | default: |
501 | case VISL_CODEC_NONE: |
502 | break; |
503 | case VISL_CODEC_FWHT: |
504 | trace_v4l2_ctrl_fwht_params(p: run->fwht.params); |
505 | break; |
506 | case VISL_CODEC_MPEG2: |
507 | trace_v4l2_ctrl_mpeg2_sequence(s: run->mpeg2.seq); |
508 | trace_v4l2_ctrl_mpeg2_picture(p: run->mpeg2.pic); |
509 | trace_v4l2_ctrl_mpeg2_quantisation(q: run->mpeg2.quant); |
510 | break; |
511 | case VISL_CODEC_VP8: |
512 | trace_v4l2_ctrl_vp8_frame(f: run->vp8.frame); |
513 | trace_v4l2_ctrl_vp8_entropy(f: run->vp8.frame); |
514 | break; |
515 | case VISL_CODEC_VP9: |
516 | trace_v4l2_ctrl_vp9_frame(f: run->vp9.frame); |
517 | trace_v4l2_ctrl_vp9_compressed_hdr(h: run->vp9.probs); |
518 | trace_v4l2_ctrl_vp9_compressed_coeff(h: run->vp9.probs); |
519 | trace_v4l2_vp9_mv_probs(p: &run->vp9.probs->mv); |
520 | break; |
521 | case VISL_CODEC_H264: |
522 | trace_v4l2_ctrl_h264_sps(s: run->h264.sps); |
523 | trace_v4l2_ctrl_h264_pps(p: run->h264.pps); |
524 | trace_v4l2_ctrl_h264_scaling_matrix(s: run->h264.sm); |
525 | trace_v4l2_ctrl_h264_slice_params(s: run->h264.spram); |
526 | |
527 | for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++) |
528 | trace_v4l2_h264_ref_pic_list0(r: &run->h264.spram->ref_pic_list0[i], i); |
529 | for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++) |
530 | trace_v4l2_h264_ref_pic_list1(r: &run->h264.spram->ref_pic_list1[i], i); |
531 | |
532 | trace_v4l2_ctrl_h264_decode_params(d: run->h264.dpram); |
533 | |
534 | for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++) |
535 | trace_v4l2_h264_dpb_entry(e: &run->h264.dpram->dpb[i], i); |
536 | |
537 | trace_v4l2_ctrl_h264_pred_weights(p: run->h264.pwht); |
538 | break; |
539 | case VISL_CODEC_HEVC: |
540 | trace_v4l2_ctrl_hevc_sps(s: run->hevc.sps); |
541 | trace_v4l2_ctrl_hevc_pps(p: run->hevc.pps); |
542 | trace_v4l2_ctrl_hevc_slice_params(s: run->hevc.spram); |
543 | trace_v4l2_ctrl_hevc_scaling_matrix(s: run->hevc.sm); |
544 | trace_v4l2_ctrl_hevc_decode_params(d: run->hevc.dpram); |
545 | |
546 | for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++) |
547 | trace_v4l2_hevc_dpb_entry(e: &run->hevc.dpram->dpb[i]); |
548 | |
549 | trace_v4l2_hevc_pred_weight_table(p: &run->hevc.spram->pred_weight_table); |
550 | break; |
551 | case VISL_CODEC_AV1: |
552 | trace_v4l2_ctrl_av1_sequence(s: run->av1.seq); |
553 | trace_v4l2_ctrl_av1_frame(f: run->av1.frame); |
554 | trace_v4l2_ctrl_av1_film_grain(f: run->av1.grain); |
555 | trace_v4l2_ctrl_av1_tile_group_entry(t: run->av1.tge); |
556 | break; |
557 | } |
558 | } |
559 | |
560 | void visl_device_run(void *priv) |
561 | { |
562 | struct visl_ctx *ctx = priv; |
563 | struct visl_run run = {}; |
564 | struct media_request *src_req; |
565 | |
566 | run.src = v4l2_m2m_next_src_buf(m2m_ctx: ctx->fh.m2m_ctx); |
567 | run.dst = v4l2_m2m_next_dst_buf(m2m_ctx: ctx->fh.m2m_ctx); |
568 | |
569 | /* Apply request(s) controls if needed. */ |
570 | src_req = run.src->vb2_buf.req_obj.req; |
571 | |
572 | if (src_req) |
573 | v4l2_ctrl_request_setup(req: src_req, parent: &ctx->hdl); |
574 | |
575 | v4l2_m2m_buf_copy_metadata(out_vb: run.src, cap_vb: run.dst, copy_frame_flags: true); |
576 | run.dst->sequence = ctx->q_data[V4L2_M2M_DST].sequence++; |
577 | run.src->sequence = ctx->q_data[V4L2_M2M_SRC].sequence++; |
578 | run.dst->field = ctx->decoded_fmt.fmt.pix.field; |
579 | |
580 | switch (ctx->current_codec) { |
581 | default: |
582 | case VISL_CODEC_NONE: |
583 | break; |
584 | case VISL_CODEC_FWHT: |
585 | run.fwht.params = visl_find_control_data(ctx, V4L2_CID_STATELESS_FWHT_PARAMS); |
586 | break; |
587 | case VISL_CODEC_MPEG2: |
588 | run.mpeg2.seq = visl_find_control_data(ctx, V4L2_CID_STATELESS_MPEG2_SEQUENCE); |
589 | run.mpeg2.pic = visl_find_control_data(ctx, V4L2_CID_STATELESS_MPEG2_PICTURE); |
590 | run.mpeg2.quant = visl_find_control_data(ctx, |
591 | V4L2_CID_STATELESS_MPEG2_QUANTISATION); |
592 | break; |
593 | case VISL_CODEC_VP8: |
594 | run.vp8.frame = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP8_FRAME); |
595 | break; |
596 | case VISL_CODEC_VP9: |
597 | run.vp9.frame = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP9_FRAME); |
598 | run.vp9.probs = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR); |
599 | break; |
600 | case VISL_CODEC_H264: |
601 | run.h264.sps = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SPS); |
602 | run.h264.pps = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_PPS); |
603 | run.h264.sm = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SCALING_MATRIX); |
604 | run.h264.spram = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SLICE_PARAMS); |
605 | run.h264.dpram = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS); |
606 | run.h264.pwht = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_PRED_WEIGHTS); |
607 | break; |
608 | case VISL_CODEC_HEVC: |
609 | run.hevc.sps = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SPS); |
610 | run.hevc.pps = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_PPS); |
611 | run.hevc.spram = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SLICE_PARAMS); |
612 | run.hevc.sm = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); |
613 | run.hevc.dpram = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); |
614 | break; |
615 | case VISL_CODEC_AV1: |
616 | run.av1.seq = visl_find_control_data(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE); |
617 | run.av1.frame = visl_find_control_data(ctx, V4L2_CID_STATELESS_AV1_FRAME); |
618 | run.av1.tge = visl_find_control_data(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY); |
619 | run.av1.grain = visl_find_control_data(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN); |
620 | break; |
621 | } |
622 | |
623 | frame_dprintk(ctx->dev, run.dst->sequence, |
624 | "Got OUTPUT buffer sequence %d, timestamp %llu\n" , |
625 | run.src->sequence, run.src->vb2_buf.timestamp); |
626 | |
627 | frame_dprintk(ctx->dev, run.dst->sequence, |
628 | "Got CAPTURE buffer sequence %d, timestamp %llu\n" , |
629 | run.dst->sequence, run.dst->vb2_buf.timestamp); |
630 | |
631 | visl_tpg_fill(ctx, run: &run); |
632 | visl_trace_ctrls(ctx, run: &run); |
633 | |
634 | if (bitstream_trace_frame_start > -1 && |
635 | run.dst->sequence >= bitstream_trace_frame_start && |
636 | run.dst->sequence < bitstream_trace_frame_start + bitstream_trace_nframes) |
637 | visl_trace_bitstream(ctx, run: &run); |
638 | |
639 | /* Complete request(s) controls if needed. */ |
640 | if (src_req) |
641 | v4l2_ctrl_request_complete(req: src_req, parent: &ctx->hdl); |
642 | |
643 | if (visl_transtime_ms) |
644 | usleep_range(min: visl_transtime_ms * 1000, max: 2 * visl_transtime_ms * 1000); |
645 | |
646 | v4l2_m2m_buf_done_and_job_finish(m2m_dev: ctx->dev->m2m_dev, |
647 | m2m_ctx: ctx->fh.m2m_ctx, state: VB2_BUF_STATE_DONE); |
648 | } |
649 | |