int hantro_get_format_depth(u32 fourcc)
{ switch (fourcc) { case V4L2_PIX_FMT_P010: case V4L2_PIX_FMT_P010_4L4: case V4L2_PIX_FMT_NV15: case V4L2_PIX_FMT_NV15_4L4: return 10; default: return 8;
}
}
staticbool
hantro_check_depth_match(conststruct hantro_fmt *fmt, int bit_depth)
{ int fmt_depth;
if (!fmt->match_depth && !fmt->postprocessed) returntrue;
/* 0 means default depth, which is 8 */ if (!bit_depth)
bit_depth = HANTRO_DEFAULT_BIT_DEPTH;
fmt_depth = hantro_get_format_depth(fmt->fourcc);
/* * Allow only downconversion for postproc formats for now. * It may be possible to relax that on some HW.
*/ if (!fmt->match_depth) return fmt_depth <= bit_depth;
formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) if (formats[i].fourcc == fourcc) return &formats[i];
formats = hantro_get_postproc_formats(ctx, &num_fmts); for (i = 0; i < num_fmts; i++) if (formats[i].fourcc == fourcc) return &formats[i]; return NULL;
}
/* * If the V4L2_FMTDESC_FLAG_ENUM_ALL flag is set, we want to enumerate all * hardware supported pixel formats
*/
enum_all_formats = !!(f->index & V4L2_FMTDESC_FLAG_ENUM_ALL);
f->index = index;
/* * When dealing with an encoder: * - on the capture side we want to filter out all MODE_NONE formats. * - on the output side we want to filter out all formats that are * not MODE_NONE. * When dealing with a decoder: * - on the capture side we want to filter out all formats that are * not MODE_NONE. * - on the output side we want to filter out all MODE_NONE formats.
*/
skip_mode_none = capture == ctx->is_encoder;
formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) { bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE;
fmt = &formats[i];
if (skip_mode_none == mode_none) continue; if (!hantro_check_depth_match(fmt, ctx->bit_depth) && !enum_all_formats) continue; if (j == index) {
f->pixelformat = fmt->fourcc; return 0;
}
++j;
}
/* * Enumerate post-processed formats. As per the specification, * we enumerated these formats after natively decoded formats * as a hint for applications on what's the preferred fomat.
*/ if (!capture) return -EINVAL;
formats = hantro_get_postproc_formats(ctx, &num_fmts); for (i = 0; i < num_fmts; i++) {
fmt = &formats[i];
if (!hantro_check_depth_match(fmt, ctx->bit_depth) && !enum_all_formats) continue; if (j == index) {
f->pixelformat = fmt->fourcc; return 0;
}
++j;
}
if (coded) {
pix_mp->num_planes = 1;
vpu_fmt = fmt;
} elseif (ctx->is_encoder) {
vpu_fmt = hantro_find_format(ctx, ctx->dst_fmt.pixelformat);
} else { /* * Width/height on the CAPTURE end of a decoder are ignored and * replaced by the OUTPUT ones.
*/
pix_mp->width = ctx->src_fmt.width;
pix_mp->height = ctx->src_fmt.height;
vpu_fmt = fmt;
}
switch (fourcc) { case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_MPEG2_SLICE: case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_HEVC_SLICE: case V4L2_PIX_FMT_VP9_FRAME:
vq->subsystem_flags &= ~(VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF); break; case V4L2_PIX_FMT_H264_SLICE:
vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; break; default: break;
}
}
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret) return ret;
if (!ctx->is_encoder) { /* * In order to support dynamic resolution change, * the decoder admits a resolution change, as long * as the pixelformat remains.
*/ if (vb2_is_streaming(vq) && pix_mp->pixelformat != ctx->src_fmt.pixelformat) { return -EBUSY;
}
} else { /* * The encoder doesn't admit a format change if * there are OUTPUT buffers allocated.
*/ if (vb2_is_busy(vq)) return -EBUSY;
}
/* * Current raw format might have become invalid with newly * selected codec, so reset it to default just to be safe and * keep internal driver state sane. User is mandated to set * the raw format again after we return, so we don't need * anything smarter. * Note that hantro_reset_raw_fmt() also propagates size * changes to the raw format.
*/ if (!ctx->is_encoder)
hantro_reset_raw_fmt(ctx,
hantro_get_format_depth(pix_mp->pixelformat),
need_postproc);
/* Colorimetry information are always propagated. */
ctx->dst_fmt.colorspace = pix_mp->colorspace;
ctx->dst_fmt.ycbcr_enc = pix_mp->ycbcr_enc;
ctx->dst_fmt.xfer_func = pix_mp->xfer_func;
ctx->dst_fmt.quantization = pix_mp->quantization;
staticint hantro_set_fmt_cap(struct hantro_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp)
{ int ret;
if (ctx->is_encoder) { struct vb2_queue *peer_vq;
/* * Since format change on the CAPTURE queue will reset * the OUTPUT queue, we can't allow doing so * when the OUTPUT queue has buffers allocated.
*/
peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (vb2_is_busy(peer_vq) &&
(pix_mp->pixelformat != ctx->dst_fmt.pixelformat ||
pix_mp->height != ctx->dst_fmt.height ||
pix_mp->width != ctx->dst_fmt.width)) return -EBUSY;
}
ret = hantro_try_fmt(ctx, pix_mp, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (ret) return ret;
ctx->vpu_dst_fmt = hantro_find_format(ctx, pix_mp->pixelformat);
ctx->dst_fmt = *pix_mp;
ret = hantro_set_reference_frames_format(ctx); if (ret) return ret;
/* * Current raw format might have become invalid with newly * selected codec, so reset it to default just to be safe and * keep internal driver state sane. User is mandated to set * the raw format again after we return, so we don't need * anything smarter. * Note that hantro_reset_raw_fmt() also propagates size * changes to the raw format.
*/ if (ctx->is_encoder)
hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);
/* Colorimetry information are always propagated. */
ctx->src_fmt.colorspace = pix_mp->colorspace;
ctx->src_fmt.ycbcr_enc = pix_mp->ycbcr_enc;
ctx->src_fmt.xfer_func = pix_mp->xfer_func;
ctx->src_fmt.quantization = pix_mp->quantization;
/* Crop only supported on source. */ if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL;
/* Change not allowed if the queue is streaming. */
vq = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx); if (vb2_is_streaming(vq)) return -EBUSY;
if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL;
/* * We do not support offsets, and we can crop only inside * right-most or bottom-most macroblocks.
*/ if (rect->left != 0 || rect->top != 0 ||
round_up(rect->width, MB_DIM) != ctx->src_fmt.width ||
round_up(rect->height, MB_DIM) != ctx->src_fmt.height) { /* Default to full frame for incorrect settings. */
rect->left = 0;
rect->top = 0;
rect->width = ctx->src_fmt.width;
rect->height = ctx->src_fmt.height;
} else { /* We support widths aligned to 4 pixels and arbitrary heights. */
rect->width = round_up(rect->width, 4);
}
if (*num_planes) { if (*num_planes != pixfmt->num_planes) return -EINVAL; for (i = 0; i < pixfmt->num_planes; ++i) if (sizes[i] < pixfmt->plane_fmt[i].sizeimage) return -EINVAL; return 0;
}
*num_planes = pixfmt->num_planes; for (i = 0; i < pixfmt->num_planes; ++i)
sizes[i] = pixfmt->plane_fmt[i].sizeimage; return 0;
}
for (i = 0; i < pixfmt->num_planes; ++i) {
sz = pixfmt->plane_fmt[i].sizeimage;
vpu_debug(4, "plane %d size: %ld, sizeimage: %u\n",
i, vb2_plane_size(vb, i), sz); if (vb2_plane_size(vb, i) < sz) {
vpu_err("plane %d is too small for output\n", i); return -EINVAL;
}
} return 0;
}
if (V4L2_TYPE_IS_OUTPUT(vq->type))
pix_fmt = &ctx->src_fmt; else
pix_fmt = &ctx->dst_fmt;
ret = hantro_buf_plane_check(vb, pix_fmt); if (ret) return ret; /* * Buffer's bytesused must be written by driver for CAPTURE buffers. * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets * it to buffer length).
*/ if (V4L2_TYPE_IS_CAPTURE(vq->type)) { if (ctx->is_encoder)
vb2_set_plane_payload(vb, 0, 0); else
vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
}
if (hantro_vq_is_coded(q)) {
hantro_postproc_free(ctx); if (ctx->codec_ops && ctx->codec_ops->exit)
ctx->codec_ops->exit(ctx);
}
/* * The mem2mem framework calls v4l2_m2m_cancel_job before * .stop_streaming, so there isn't any job running and * it is safe to return all the buffers.
*/ if (V4L2_TYPE_IS_OUTPUT(q->type))
hantro_return_bufs(q, v4l2_m2m_src_buf_remove); else
hantro_return_bufs(q, v4l2_m2m_dst_buf_remove);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.