0c078e310b
A virtual stateless device for stateless uAPI development purposes. This tool's objective is to help the development and testing of userspace applications that use the V4L2 stateless API to decode media. A userspace implementation can use visl to run a decoding loop even when no hardware is available or when the kernel uAPI for the codec has not been upstreamed yet. This can reveal bugs at an early stage. This driver can also trace the contents of the V4L2 controls submitted to it. It can also dump the contents of the vb2 buffers through a debugfs interface. This is in many ways similar to the tracing infrastructure available for other popular encode/decode APIs out there and can help develop a userspace application by using another (working) one as a reference. Note that no actual decoding of video frames is performed by visl. The V4L2 test pattern generator is used to write various debug information to the capture buffers instead. Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
500 lines
15 KiB
C
500 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Contains the virtual decoder logic. The functions here control the
|
|
* tracing/TPG on a per-frame basis
|
|
*/
|
|
|
|
#include "visl.h"
|
|
#include "visl-debugfs.h"
|
|
#include "visl-dec.h"
|
|
#include "visl-trace-fwht.h"
|
|
#include "visl-trace-mpeg2.h"
|
|
#include "visl-trace-vp8.h"
|
|
#include "visl-trace-vp9.h"
|
|
#include "visl-trace-h264.h"
|
|
#include "visl-trace-hevc.h"
|
|
|
|
#include <linux/delay.h>
|
|
#include <linux/workqueue.h>
|
|
#include <media/v4l2-mem2mem.h>
|
|
#include <media/tpg/v4l2-tpg.h>
|
|
|
|
static void *plane_vaddr(struct tpg_data *tpg, struct vb2_buffer *buf,
|
|
u32 p, u32 bpl[TPG_MAX_PLANES], u32 h)
|
|
{
|
|
u32 i;
|
|
void *vbuf;
|
|
|
|
if (p == 0 || tpg_g_buffers(tpg) > 1)
|
|
return vb2_plane_vaddr(buf, p);
|
|
vbuf = vb2_plane_vaddr(buf, 0);
|
|
for (i = 0; i < p; i++)
|
|
vbuf += bpl[i] * h / tpg->vdownsampling[i];
|
|
return vbuf;
|
|
}
|
|
|
|
static void visl_get_ref_frames(struct visl_ctx *ctx, u8 *buf,
|
|
__kernel_size_t buflen, struct visl_run *run)
|
|
{
|
|
struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q;
|
|
char header[] = "Reference frames:\n";
|
|
u32 i;
|
|
u32 len;
|
|
|
|
len = scnprintf(buf, buflen, header);
|
|
buf += len;
|
|
buflen -= len;
|
|
|
|
switch (ctx->current_codec) {
|
|
case VISL_CODEC_NONE:
|
|
break;
|
|
|
|
case VISL_CODEC_FWHT: {
|
|
struct vb2_buffer *vb2_buf;
|
|
|
|
vb2_buf = vb2_find_buffer(cap_q, run->fwht.params->backward_ref_ts);
|
|
|
|
scnprintf(buf, buflen, "backwards_ref_ts: %lld, vb2_idx: %d",
|
|
run->fwht.params->backward_ref_ts,
|
|
vb2_buf ? vb2_buf->index : -1);
|
|
break;
|
|
}
|
|
|
|
case VISL_CODEC_MPEG2: {
|
|
struct vb2_buffer *b_ref;
|
|
struct vb2_buffer *f_ref;
|
|
|
|
b_ref = vb2_find_buffer(cap_q, run->mpeg2.pic->backward_ref_ts);
|
|
f_ref = vb2_find_buffer(cap_q, run->mpeg2.pic->forward_ref_ts);
|
|
|
|
scnprintf(buf, buflen,
|
|
"backward_ref_ts: %llu, vb2_idx: %d\n"
|
|
"forward_ref_ts: %llu, vb2_idx: %d\n",
|
|
run->mpeg2.pic->backward_ref_ts,
|
|
b_ref ? b_ref->index : -1,
|
|
run->mpeg2.pic->forward_ref_ts,
|
|
f_ref ? f_ref->index : -1);
|
|
break;
|
|
}
|
|
|
|
case VISL_CODEC_VP8: {
|
|
struct vb2_buffer *last;
|
|
struct vb2_buffer *golden;
|
|
struct vb2_buffer *alt;
|
|
|
|
last = vb2_find_buffer(cap_q, run->vp8.frame->last_frame_ts);
|
|
golden = vb2_find_buffer(cap_q, run->vp8.frame->golden_frame_ts);
|
|
alt = vb2_find_buffer(cap_q, run->vp8.frame->alt_frame_ts);
|
|
|
|
scnprintf(buf, buflen,
|
|
"last_ref_ts: %llu, vb2_idx: %d\n"
|
|
"golden_ref_ts: %llu, vb2_idx: %d\n"
|
|
"alt_ref_ts: %llu, vb2_idx: %d\n",
|
|
run->vp8.frame->last_frame_ts,
|
|
last ? last->index : -1,
|
|
run->vp8.frame->golden_frame_ts,
|
|
golden ? golden->index : -1,
|
|
run->vp8.frame->alt_frame_ts,
|
|
alt ? alt->index : -1);
|
|
break;
|
|
}
|
|
|
|
case VISL_CODEC_VP9: {
|
|
struct vb2_buffer *last;
|
|
struct vb2_buffer *golden;
|
|
struct vb2_buffer *alt;
|
|
|
|
last = vb2_find_buffer(cap_q, run->vp9.frame->last_frame_ts);
|
|
golden = vb2_find_buffer(cap_q, run->vp9.frame->golden_frame_ts);
|
|
alt = vb2_find_buffer(cap_q, run->vp9.frame->alt_frame_ts);
|
|
|
|
scnprintf(buf, buflen,
|
|
"last_ref_ts: %llu, vb2_idx: %d\n"
|
|
"golden_ref_ts: %llu, vb2_idx: %d\n"
|
|
"alt_ref_ts: %llu, vb2_idx: %d\n",
|
|
run->vp9.frame->last_frame_ts,
|
|
last ? last->index : -1,
|
|
run->vp9.frame->golden_frame_ts,
|
|
golden ? golden->index : -1,
|
|
run->vp9.frame->alt_frame_ts,
|
|
alt ? alt->index : -1);
|
|
break;
|
|
}
|
|
|
|
case VISL_CODEC_H264: {
|
|
char entry[] = "dpb[%d]:%u, vb2_index: %d\n";
|
|
struct vb2_buffer *vb2_buf;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++) {
|
|
vb2_buf = vb2_find_buffer(cap_q, run->h264.dpram->dpb[i].reference_ts);
|
|
len = scnprintf(buf, buflen, entry, i,
|
|
run->h264.dpram->dpb[i].reference_ts,
|
|
vb2_buf ? vb2_buf->index : -1);
|
|
buf += len;
|
|
buflen -= len;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VISL_CODEC_HEVC: {
|
|
char entry[] = "dpb[%d]:%u, vb2_index: %d\n";
|
|
struct vb2_buffer *vb2_buf;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++) {
|
|
vb2_buf = vb2_find_buffer(cap_q, run->hevc.dpram->dpb[i].timestamp);
|
|
len = scnprintf(buf, buflen, entry, i,
|
|
run->hevc.dpram->dpb[i].timestamp,
|
|
vb2_buf ? vb2_buf->index : -1);
|
|
buf += len;
|
|
buflen -= len;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static char *visl_get_vb2_state(enum vb2_buffer_state state)
|
|
{
|
|
switch (state) {
|
|
case VB2_BUF_STATE_DEQUEUED:
|
|
return "Dequeued";
|
|
case VB2_BUF_STATE_IN_REQUEST:
|
|
return "In request";
|
|
case VB2_BUF_STATE_PREPARING:
|
|
return "Preparing";
|
|
case VB2_BUF_STATE_QUEUED:
|
|
return "Queued";
|
|
case VB2_BUF_STATE_ACTIVE:
|
|
return "Active";
|
|
case VB2_BUF_STATE_DONE:
|
|
return "Done";
|
|
case VB2_BUF_STATE_ERROR:
|
|
return "Error";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
static int visl_fill_bytesused(struct vb2_v4l2_buffer *v4l2_vb2_buf, char *buf, size_t bufsz)
|
|
{
|
|
int len = 0;
|
|
u32 i;
|
|
|
|
for (i = 0; i < v4l2_vb2_buf->vb2_buf.num_planes; i++)
|
|
len += scnprintf(buf, bufsz,
|
|
"bytesused[%u]: %u length[%u]: %u data_offset[%u]: %u",
|
|
i, v4l2_vb2_buf->planes[i].bytesused,
|
|
i, v4l2_vb2_buf->planes[i].length,
|
|
i, v4l2_vb2_buf->planes[i].data_offset);
|
|
|
|
return len;
|
|
}
|
|
|
|
static void visl_tpg_fill_sequence(struct visl_ctx *ctx,
|
|
struct visl_run *run, char buf[], size_t bufsz)
|
|
{
|
|
u32 stream_ms;
|
|
|
|
stream_ms = jiffies_to_msecs(get_jiffies_64() - ctx->capture_streamon_jiffies);
|
|
|
|
scnprintf(buf, bufsz,
|
|
"stream time: %02d:%02d:%02d:%03d sequence:%u timestamp:%lld field:%s",
|
|
(stream_ms / (60 * 60 * 1000)) % 24,
|
|
(stream_ms / (60 * 1000)) % 60,
|
|
(stream_ms / 1000) % 60,
|
|
stream_ms % 1000,
|
|
run->dst->sequence,
|
|
run->dst->vb2_buf.timestamp,
|
|
(run->dst->field == V4L2_FIELD_ALTERNATE) ?
|
|
(run->dst->field == V4L2_FIELD_TOP ?
|
|
" top" : " bottom") : "none");
|
|
}
|
|
|
|
static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
|
|
{
|
|
u8 *basep[TPG_MAX_PLANES][2];
|
|
char *buf = ctx->tpg_str_buf;
|
|
char *tmp = buf;
|
|
char *line_str;
|
|
u32 line = 1;
|
|
const u32 line_height = 16;
|
|
u32 len;
|
|
struct vb2_queue *out_q = &ctx->fh.m2m_ctx->out_q_ctx.q;
|
|
struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q;
|
|
struct v4l2_pix_format_mplane *coded_fmt = &ctx->coded_fmt.fmt.pix_mp;
|
|
struct v4l2_pix_format_mplane *decoded_fmt = &ctx->decoded_fmt.fmt.pix_mp;
|
|
u32 p;
|
|
u32 i;
|
|
|
|
for (p = 0; p < tpg_g_planes(&ctx->tpg); p++) {
|
|
void *vbuf = plane_vaddr(&ctx->tpg,
|
|
&run->dst->vb2_buf, p,
|
|
ctx->tpg.bytesperline,
|
|
ctx->tpg.buf_height);
|
|
|
|
tpg_calc_text_basep(&ctx->tpg, basep, p, vbuf);
|
|
tpg_fill_plane_buffer(&ctx->tpg, 0, p, vbuf);
|
|
}
|
|
|
|
visl_tpg_fill_sequence(ctx, run, buf, TPG_STR_BUF_SZ);
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "");
|
|
line++;
|
|
|
|
visl_get_ref_frames(ctx, buf, TPG_STR_BUF_SZ, run);
|
|
|
|
while ((line_str = strsep(&tmp, "\n")) && strlen(line_str)) {
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, line_str);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", line_str);
|
|
}
|
|
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "");
|
|
line++;
|
|
|
|
scnprintf(buf,
|
|
TPG_STR_BUF_SZ,
|
|
"OUTPUT pixelformat: %c%c%c%c, resolution: %dx%d, num_planes: %d",
|
|
coded_fmt->pixelformat,
|
|
(coded_fmt->pixelformat >> 8) & 0xff,
|
|
(coded_fmt->pixelformat >> 16) & 0xff,
|
|
(coded_fmt->pixelformat >> 24) & 0xff,
|
|
coded_fmt->width,
|
|
coded_fmt->height,
|
|
coded_fmt->num_planes);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
|
|
for (i = 0; i < coded_fmt->num_planes; i++) {
|
|
scnprintf(buf,
|
|
TPG_STR_BUF_SZ,
|
|
"plane[%d]: bytesperline: %d, sizeimage: %d",
|
|
i,
|
|
coded_fmt->plane_fmt[i].bytesperline,
|
|
coded_fmt->plane_fmt[i].sizeimage);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
}
|
|
|
|
line++;
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "");
|
|
scnprintf(buf, TPG_STR_BUF_SZ, "Output queue status:");
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
|
|
len = 0;
|
|
for (i = 0; i < out_q->num_buffers; i++) {
|
|
char entry[] = "index: %u, state: %s, request_fd: %d, ";
|
|
u32 old_len = len;
|
|
char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
|
|
|
|
len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
|
|
entry, i, q_status,
|
|
to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
|
|
|
|
len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
|
|
&buf[len],
|
|
TPG_STR_BUF_SZ - len);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
|
|
}
|
|
|
|
line++;
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "");
|
|
|
|
scnprintf(buf,
|
|
TPG_STR_BUF_SZ,
|
|
"CAPTURE pixelformat: %c%c%c%c, resolution: %dx%d, num_planes: %d",
|
|
decoded_fmt->pixelformat,
|
|
(decoded_fmt->pixelformat >> 8) & 0xff,
|
|
(decoded_fmt->pixelformat >> 16) & 0xff,
|
|
(decoded_fmt->pixelformat >> 24) & 0xff,
|
|
decoded_fmt->width,
|
|
decoded_fmt->height,
|
|
decoded_fmt->num_planes);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
|
|
for (i = 0; i < decoded_fmt->num_planes; i++) {
|
|
scnprintf(buf,
|
|
TPG_STR_BUF_SZ,
|
|
"plane[%d]: bytesperline: %d, sizeimage: %d",
|
|
i,
|
|
decoded_fmt->plane_fmt[i].bytesperline,
|
|
decoded_fmt->plane_fmt[i].sizeimage);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
}
|
|
|
|
line++;
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "");
|
|
scnprintf(buf, TPG_STR_BUF_SZ, "Capture queue status:");
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, buf);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s\n", buf);
|
|
|
|
len = 0;
|
|
for (i = 0; i < cap_q->num_buffers; i++) {
|
|
u32 old_len = len;
|
|
char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
|
|
|
|
len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
|
|
"index: %u, status: %s, timestamp: %llu, is_held: %d",
|
|
cap_q->bufs[i]->index, q_status,
|
|
cap_q->bufs[i]->timestamp,
|
|
to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
|
|
|
|
tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
|
|
frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
|
|
}
|
|
}
|
|
|
|
static void visl_trace_ctrls(struct visl_ctx *ctx, struct visl_run *run)
|
|
{
|
|
int i;
|
|
|
|
switch (ctx->current_codec) {
|
|
default:
|
|
case VISL_CODEC_NONE:
|
|
break;
|
|
case VISL_CODEC_FWHT:
|
|
trace_v4l2_ctrl_fwht_params(run->fwht.params);
|
|
break;
|
|
case VISL_CODEC_MPEG2:
|
|
trace_v4l2_ctrl_mpeg2_sequence(run->mpeg2.seq);
|
|
trace_v4l2_ctrl_mpeg2_picture(run->mpeg2.pic);
|
|
trace_v4l2_ctrl_mpeg2_quantisation(run->mpeg2.quant);
|
|
break;
|
|
case VISL_CODEC_VP8:
|
|
trace_v4l2_ctrl_vp8_frame(run->vp8.frame);
|
|
trace_v4l2_ctrl_vp8_entropy(run->vp8.frame);
|
|
break;
|
|
case VISL_CODEC_VP9:
|
|
trace_v4l2_ctrl_vp9_frame(run->vp9.frame);
|
|
trace_v4l2_ctrl_vp9_compressed_hdr(run->vp9.probs);
|
|
trace_v4l2_ctrl_vp9_compressed_coeff(run->vp9.probs);
|
|
trace_v4l2_vp9_mv_probs(&run->vp9.probs->mv);
|
|
break;
|
|
case VISL_CODEC_H264:
|
|
trace_v4l2_ctrl_h264_sps(run->h264.sps);
|
|
trace_v4l2_ctrl_h264_pps(run->h264.pps);
|
|
trace_v4l2_ctrl_h264_scaling_matrix(run->h264.sm);
|
|
trace_v4l2_ctrl_h264_slice_params(run->h264.spram);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
|
|
trace_v4l2_h264_ref_pic_list0(&run->h264.spram->ref_pic_list0[i], i);
|
|
for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
|
|
trace_v4l2_h264_ref_pic_list1(&run->h264.spram->ref_pic_list1[i], i);
|
|
|
|
trace_v4l2_ctrl_h264_decode_params(run->h264.dpram);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++)
|
|
trace_v4l2_h264_dpb_entry(&run->h264.dpram->dpb[i], i);
|
|
|
|
trace_v4l2_ctrl_h264_pred_weights(run->h264.pwht);
|
|
break;
|
|
case VISL_CODEC_HEVC:
|
|
trace_v4l2_ctrl_hevc_sps(run->hevc.sps);
|
|
trace_v4l2_ctrl_hevc_pps(run->hevc.pps);
|
|
trace_v4l2_ctrl_hevc_slice_params(run->hevc.spram);
|
|
trace_v4l2_ctrl_hevc_scaling_matrix(run->hevc.sm);
|
|
trace_v4l2_ctrl_hevc_decode_params(run->hevc.dpram);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++)
|
|
trace_v4l2_hevc_dpb_entry(&run->hevc.dpram->dpb[i]);
|
|
|
|
trace_v4l2_hevc_pred_weight_table(&run->hevc.spram->pred_weight_table);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void visl_device_run(void *priv)
|
|
{
|
|
struct visl_ctx *ctx = priv;
|
|
struct visl_run run = {};
|
|
struct media_request *src_req;
|
|
|
|
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
|
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
|
|
|
/* Apply request(s) controls if needed. */
|
|
src_req = run.src->vb2_buf.req_obj.req;
|
|
|
|
if (src_req)
|
|
v4l2_ctrl_request_setup(src_req, &ctx->hdl);
|
|
|
|
v4l2_m2m_buf_copy_metadata(run.src, run.dst, true);
|
|
run.dst->sequence = ctx->q_data[V4L2_M2M_DST].sequence++;
|
|
run.src->sequence = ctx->q_data[V4L2_M2M_SRC].sequence++;
|
|
run.dst->field = ctx->decoded_fmt.fmt.pix.field;
|
|
|
|
switch (ctx->current_codec) {
|
|
default:
|
|
case VISL_CODEC_NONE:
|
|
break;
|
|
case VISL_CODEC_FWHT:
|
|
run.fwht.params = visl_find_control_data(ctx, V4L2_CID_STATELESS_FWHT_PARAMS);
|
|
break;
|
|
case VISL_CODEC_MPEG2:
|
|
run.mpeg2.seq = visl_find_control_data(ctx, V4L2_CID_STATELESS_MPEG2_SEQUENCE);
|
|
run.mpeg2.pic = visl_find_control_data(ctx, V4L2_CID_STATELESS_MPEG2_PICTURE);
|
|
run.mpeg2.quant = visl_find_control_data(ctx,
|
|
V4L2_CID_STATELESS_MPEG2_QUANTISATION);
|
|
break;
|
|
case VISL_CODEC_VP8:
|
|
run.vp8.frame = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP8_FRAME);
|
|
break;
|
|
case VISL_CODEC_VP9:
|
|
run.vp9.frame = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP9_FRAME);
|
|
run.vp9.probs = visl_find_control_data(ctx, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR);
|
|
break;
|
|
case VISL_CODEC_H264:
|
|
run.h264.sps = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SPS);
|
|
run.h264.pps = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_PPS);
|
|
run.h264.sm = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SCALING_MATRIX);
|
|
run.h264.spram = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_SLICE_PARAMS);
|
|
run.h264.dpram = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS);
|
|
run.h264.pwht = visl_find_control_data(ctx, V4L2_CID_STATELESS_H264_PRED_WEIGHTS);
|
|
break;
|
|
case VISL_CODEC_HEVC:
|
|
run.hevc.sps = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SPS);
|
|
run.hevc.pps = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_PPS);
|
|
run.hevc.spram = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SLICE_PARAMS);
|
|
run.hevc.sm = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
|
|
run.hevc.dpram = visl_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
|
|
break;
|
|
}
|
|
|
|
frame_dprintk(ctx->dev, run.dst->sequence,
|
|
"Got OUTPUT buffer sequence %d, timestamp %llu\n",
|
|
run.src->sequence, run.src->vb2_buf.timestamp);
|
|
|
|
frame_dprintk(ctx->dev, run.dst->sequence,
|
|
"Got CAPTURE buffer sequence %d, timestamp %llu\n",
|
|
run.dst->sequence, run.dst->vb2_buf.timestamp);
|
|
|
|
visl_tpg_fill(ctx, &run);
|
|
visl_trace_ctrls(ctx, &run);
|
|
|
|
if (bitstream_trace_frame_start > -1 &&
|
|
run.dst->sequence >= bitstream_trace_frame_start &&
|
|
run.dst->sequence < bitstream_trace_frame_start + bitstream_trace_nframes)
|
|
visl_trace_bitstream(ctx, &run);
|
|
|
|
/* Complete request(s) controls if needed. */
|
|
if (src_req)
|
|
v4l2_ctrl_request_complete(src_req, &ctx->hdl);
|
|
|
|
if (visl_transtime_ms)
|
|
usleep_range(visl_transtime_ms * 1000, 2 * visl_transtime_ms * 1000);
|
|
|
|
v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev,
|
|
ctx->fh.m2m_ctx, VB2_BUF_STATE_DONE);
|
|
}
|