video: driver: Enable flip and rotation

Enable encoder flip and rotation preprocessing features.

Change-Id: Icb0448c2d09fbe9504e3f58701cd2653dc4559b0
Signed-off-by: Mihir Ganu <mganu@codeaurora.org>
Signed-off-by: Akshata Sahukar <asahukar@codeaurora.org>
This commit is contained in:
Mihir Ganu
2021-04-21 16:11:45 -07:00
committed by Akshata Sahukar
parent f594a33c13
commit cf3fd457b3
9 changed files with 170 additions and 97 deletions

View File

@@ -233,7 +233,11 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
1, V4L2_MPEG_MSM_VIDC_DISABLE,
V4L2_CID_HFLIP,
HFI_PROP_FLIP,
CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT |
CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
{0},
{0},
NULL, msm_vidc_set_flip},
{VFLIP, ENC, CODECS_ALL,
V4L2_MPEG_MSM_VIDC_DISABLE,
@@ -241,13 +245,20 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
1, V4L2_MPEG_MSM_VIDC_DISABLE,
V4L2_CID_VFLIP,
HFI_PROP_FLIP,
CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
{0},
{0},
NULL, msm_vidc_set_flip},
{ROTATION, ENC, CODECS_ALL,
0, 270, 90, 0,
V4L2_CID_ROTATE,
HFI_PROP_ROTATION,
CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT,
{0},
{0},
NULL, msm_vidc_set_rotation},
{SUPER_FRAME, ENC, H264|HEVC,
0, 32, 1, 0,

View File

@@ -13,6 +13,7 @@
#include "msm_vidc_driver.h"
#include "msm_vidc_debug.h"
#include "msm_media_info.h"
#include "msm_vidc_control.h"
static u32 msm_vidc_decoder_bin_size_iris2(struct msm_vidc_inst *inst)
{
@@ -440,27 +441,34 @@ static u32 msm_vidc_encoder_arp_size_iris2(struct msm_vidc_inst *inst)
static u32 msm_vidc_encoder_vpss_size_iris2(struct msm_vidc_inst* inst)
{
u32 size = 0;
bool ds_enable, rot_enable, flip_enable, is_tenbit;
u32 width, height, pixfmt;
bool ds_enable = false, is_tenbit = false;
u32 rotation_val = HFI_ROTATION_NONE;
u32 flip_val = HFI_DISABLE_FLIP;
u32 width, height, driver_colorfmt;
struct v4l2_format* f;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return 0;
}
ds_enable = false; // TODO: fixme
rot_enable = false; // TODO: fixme
flip_enable = false; // TODO: fixme
f = &inst->fmts[OUTPUT_PORT];
width = f->fmt.pix_mp.width;
height = f->fmt.pix_mp.height;
ds_enable = is_scaling_enabled(inst);
msm_vidc_v4l2_to_hfi_enum(inst, ROTATION, &rotation_val);
if (inst->capabilities->cap[HFLIP].value)
flip_val |= HFI_HORIZONTAL_FLIP;
if (inst->capabilities->cap[VFLIP].value)
flip_val = HFI_VERTICAL_FLIP;
pixfmt = inst->capabilities->cap[PIX_FMTS].value;
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
width = inst->compose.width;
height = inst->compose.height;
f = &inst->fmts[INPUT_PORT];
driver_colorfmt = v4l2_colorformat_to_driver(
f->fmt.pix_mp.pixelformat, __func__);
is_tenbit = is_10bit_colorformat(driver_colorfmt);
HFI_BUFFER_VPSS_ENC(size, width, height, ds_enable,
rot_enable, flip_enable, is_tenbit);
rotation_val, flip_val, is_tenbit);
i_vpr_l(inst, "%s: size %d\n", __func__, size);
return size;
}

View File

@@ -16,6 +16,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst);
int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s);
int msm_venc_g_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s);

View File

@@ -79,6 +79,10 @@ int msm_vidc_set_nal_length(void* instance,
enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_session_priority(void *instance,
enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_flip(void *instance,
enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_rotation(void *instance,
enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_s32(void *instance,
enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_q16(void *instance,

View File

@@ -65,6 +65,14 @@ static inline is_output_meta_buffer(enum msm_vidc_buffer_type buffer_type)
return buffer_type == MSM_VIDC_BUF_OUTPUT_META;
}
static inline is_scaling_enabled(struct msm_vidc_inst *inst)
{
return inst->crop.left != inst->compose.left ||
inst->crop.top != inst->compose.top ||
inst->crop.width != inst->compose.width ||
inst->crop.height != inst->compose.height;
}
static inline is_internal_buffer(enum msm_vidc_buffer_type buffer_type)
{
return buffer_type == MSM_VIDC_BUF_BIN ||

View File

@@ -154,6 +154,8 @@ u32 hfi_buf_type_from_driver(enum msm_vidc_domain_type domain,
return HFI_BUFFER_DPB;
case MSM_VIDC_BUF_PERSIST:
return HFI_BUFFER_PERSIST;
case MSM_VIDC_BUF_VPSS:
return HFI_BUFFER_VPSS;
default:
d_vpr_e("invalid buffer type %d\n",
buffer_type);
@@ -200,6 +202,8 @@ u32 hfi_buf_type_to_driver(enum msm_vidc_domain_type domain,
return MSM_VIDC_BUF_DPB;
case HFI_BUFFER_PERSIST:
return MSM_VIDC_BUF_PERSIST;
case HFI_BUFFER_VPSS:
return MSM_VIDC_BUF_VPSS;
default:
d_vpr_e("invalid buffer type %d\n",
buffer_type);

View File

@@ -29,7 +29,6 @@ static const u32 msm_venc_input_set_prop[] = {
static const u32 msm_venc_output_set_prop[] = {
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_PROP_CROP_OFFSETS,
HFI_PROP_SCALAR,
HFI_PROP_BUFFER_HOST_MAX_COUNT,
HFI_PROP_CSC,
};
@@ -44,7 +43,7 @@ static const u32 msm_venc_output_subscribe_for_properties[] = {
HFI_PROP_WORST_COMPRESSION_RATIO,
};
static const u32 msm_venc_internal_buffer_type[] = {
static const u32 msm_venc_output_internal_buffer_type[] = {
MSM_VIDC_BUF_BIN,
MSM_VIDC_BUF_COMV,
MSM_VIDC_BUF_NON_COMV,
@@ -52,6 +51,10 @@ static const u32 msm_venc_internal_buffer_type[] = {
MSM_VIDC_BUF_DPB,
};
static const u32 msm_venc_input_internal_buffer_type[] = {
MSM_VIDC_BUF_VPSS,
};
struct msm_venc_prop_type_handle {
u32 type;
int (*handle)(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
@@ -232,6 +235,7 @@ static int msm_venc_set_crop_offsets(struct msm_vidc_inst *inst,
int rc = 0;
u32 left_offset, top_offset, right_offset, bottom_offset;
u32 crop[2] = {0};
u32 width, height;
if (port != OUTPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
@@ -240,10 +244,17 @@ static int msm_venc_set_crop_offsets(struct msm_vidc_inst *inst,
left_offset = inst->compose.left;
top_offset = inst->compose.top;
right_offset = (inst->fmts[port].fmt.pix_mp.width -
inst->compose.width);
bottom_offset = (inst->fmts[port].fmt.pix_mp.height -
inst->compose.height);
width = inst->compose.width;
height = inst->compose.height;
if (inst->capabilities->cap[ROTATION].value == 90 ||
inst->capabilities->cap[ROTATION].value == 270) {
width = inst->compose.height;
height = inst->compose.width;
}
right_offset = (inst->fmts[port].fmt.pix_mp.width - width);
bottom_offset = (inst->fmts[port].fmt.pix_mp.height - height);
if (is_image_session(inst))
right_offset = bottom_offset = 0;
@@ -266,43 +277,6 @@ static int msm_venc_set_crop_offsets(struct msm_vidc_inst *inst,
return 0;
}
static int msm_venc_set_scalar(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 scalar = 0;
if (port != OUTPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
if (inst->crop.left != inst->compose.left ||
inst->crop.top != inst->compose.top ||
inst->crop.width != inst->compose.width ||
inst->crop.height != inst->compose.height) {
scalar = 1;
i_vpr_h(inst,
"%s: crop: l %d t %d w %d h %d compose: l %d t %d w %d h %d\n",
__func__, inst->crop.left, inst->crop.top,
inst->crop.width, inst->crop.height,
inst->compose.left, inst->compose.top,
inst->compose.width, inst->compose.height);
}
i_vpr_h(inst, "%s: scalar: %d\n", __func__, scalar);
rc = venus_hfi_session_property(inst,
HFI_PROP_SCALAR,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_64_PACKED,
&scalar,
sizeof(u64));
if (rc)
return rc;
return 0;
}
static int msm_venc_set_host_max_buf_count(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
@@ -553,7 +527,6 @@ static int msm_venc_set_output_properties(struct msm_vidc_inst *inst)
static const struct msm_venc_prop_type_handle prop_type_handle_arr[] = {
{HFI_PROP_BITSTREAM_RESOLUTION, msm_venc_set_bitstream_resolution },
{HFI_PROP_CROP_OFFSETS, msm_venc_set_crop_offsets },
{HFI_PROP_SCALAR, msm_venc_set_scalar },
{HFI_PROP_BUFFER_HOST_MAX_COUNT, msm_venc_set_host_max_buf_count },
{HFI_PROP_CSC, msm_venc_set_csc },
};
@@ -613,8 +586,7 @@ static int msm_venc_set_internal_properties(struct msm_vidc_inst *inst)
static int msm_venc_get_input_internal_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
/* TODO: VPSS
int i, rc = 0;
struct msm_vidc_core *core;
if (!inst || !inst->core) {
@@ -623,50 +595,51 @@ static int msm_venc_get_input_internal_buffers(struct msm_vidc_inst *inst)
}
core = inst->core;
inst->buffers.vpss.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_VPSS) + 100000000;
for (i = 0; i < ARRAY_SIZE(msm_venc_input_internal_buffer_type); i++) {
rc = msm_vidc_get_internal_buffers(inst,
msm_venc_input_internal_buffer_type[i]);
if (rc)
return rc;
}
inst->buffers.dpb.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_VPSS);
i_vpr_h(inst, "%s: internal buffer: min size\n", __func__);
i_vpr_h(inst, "vpss buffer: %d %d\n",
inst->buffers.vpss.min_count,
inst->buffers.vpss.size);
*/
return rc;
}
static int msm_venc_create_input_internal_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
/* TODO: VPSS
int i, rc = 0;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_VPSS);
for (i = 0; i < ARRAY_SIZE(msm_venc_input_internal_buffer_type); i++) {
rc = msm_vidc_create_internal_buffers(inst,
msm_venc_input_internal_buffer_type[i]);
if (rc)
return rc;
*/
}
return rc;
}
static int msm_venc_queue_input_internal_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
int i, rc = 0;
/* TODO: VPSS
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_VPSS);
for (i = 0; i < ARRAY_SIZE(msm_venc_input_internal_buffer_type); i++) {
rc = msm_vidc_queue_internal_buffers(inst,
msm_venc_input_internal_buffer_type[i]);
if (rc)
return rc;
*/
}
return rc;
}
@@ -681,8 +654,9 @@ static int msm_venc_get_output_internal_buffers(struct msm_vidc_inst *inst)
}
core = inst->core;
for (i = 0; i < ARRAY_SIZE(msm_venc_internal_buffer_type); i++) {
rc = msm_vidc_get_internal_buffers(inst, msm_venc_internal_buffer_type[i]);
for (i = 0; i < ARRAY_SIZE(msm_venc_output_internal_buffer_type); i++) {
rc = msm_vidc_get_internal_buffers(inst,
msm_venc_output_internal_buffer_type[i]);
if (rc)
return rc;
}
@@ -699,8 +673,9 @@ static int msm_venc_create_output_internal_buffers(struct msm_vidc_inst *inst)
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(msm_venc_internal_buffer_type); i++) {
rc = msm_vidc_create_internal_buffers(inst, msm_venc_internal_buffer_type[i]);
for (i = 0; i < ARRAY_SIZE(msm_venc_output_internal_buffer_type); i++) {
rc = msm_vidc_create_internal_buffers(inst,
msm_venc_output_internal_buffer_type[i]);
if (rc)
return rc;
}
@@ -717,8 +692,9 @@ static int msm_venc_queue_output_internal_buffers(struct msm_vidc_inst *inst)
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(msm_venc_internal_buffer_type); i++) {
rc = msm_vidc_queue_internal_buffers(inst, msm_venc_internal_buffer_type[i]);
for (i = 0; i < ARRAY_SIZE(msm_venc_output_internal_buffer_type); i++) {
rc = msm_vidc_queue_internal_buffers(inst,
msm_venc_output_internal_buffer_type[i]);
if (rc)
return rc;
}
@@ -1108,12 +1084,13 @@ error:
return rc;
}
static int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f)
int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f)
{
int rc = 0;
struct v4l2_format *fmt;
struct msm_vidc_core *core;
u32 codec_align;
u32 width, height;
if (!inst || !inst->core || !f) {
d_vpr_e("%s: invalid params\n", __func__);
@@ -1134,9 +1111,17 @@ static int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format
codec_align = (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC ||
f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEIC) ? 32 : 16;
/* use rotated width height if rotation is enabled */
width = inst->compose.width;
height = inst->compose.height;
if (inst->capabilities->cap[ROTATION].value == 90 ||
inst->capabilities->cap[ROTATION].value == 270) {
width = inst->compose.height;
height = inst->compose.width;
}
/* width, height is readonly for client */
fmt->fmt.pix_mp.width = ALIGN(inst->compose.width, codec_align);
fmt->fmt.pix_mp.height = ALIGN(inst->compose.height, codec_align);
fmt->fmt.pix_mp.width = ALIGN(width, codec_align);
fmt->fmt.pix_mp.height = ALIGN(height, codec_align);
/* use grid dimension for image session */
if (is_image_session(inst))
fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.height = HEIC_GRID_DIMENSION;
@@ -1520,6 +1505,18 @@ int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
inst->compose.width = s->r.width;
inst->compose.height= s->r.height;
if (inst->crop.left != inst->compose.left ||
inst->crop.top != inst->compose.top ||
inst->crop.width != inst->compose.width ||
inst->crop.height != inst->compose.height) {
i_vpr_h(inst,
"%s: scaling enabled, crop: l %d t %d w %d h %d compose: l %d t %d w %d h %d\n",
__func__, inst->crop.left, inst->crop.top,
inst->crop.width, inst->crop.height,
inst->compose.left, inst->compose.top,
inst->compose.width, inst->compose.height);
}
/* update output format based on new compose dimensions */
output_fmt = &inst->fmts[OUTPUT_PORT];
rc = msm_venc_s_fmt_output(inst, output_fmt);

View File

@@ -10,6 +10,7 @@
#include "venus_hfi.h"
#include "msm_vidc_internal.h"
#include "msm_vidc_driver.h"
#include "msm_venc.h"
#define CAP_TO_8BIT_QP(a) { \
if ((a) < 0) \
@@ -663,6 +664,24 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
if (!inst->vb2q[OUTPUT_PORT].streaming) {
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
if (ctrl->id == V4L2_CID_ROTATE) {
if (ctrl->val == 90 || ctrl->val == 270) {
struct v4l2_format *output_fmt;
output_fmt = &inst->fmts[OUTPUT_PORT];
rc = msm_venc_s_fmt_output(inst, output_fmt);
if (rc)
return rc;
i_vpr_h(inst,
"%s: type %d: format %#x width %d height %d size %d\n",
__func__, output_fmt->type, output_fmt->fmt.pix_mp.pixelformat,
output_fmt->fmt.pix_mp.width,
output_fmt->fmt.pix_mp.height,
output_fmt->fmt.pix_mp.plane_fmt[0].sizeimage);
}
}
if (ctrl->id == V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE) {
rc = msm_vidc_update_bitstream_buffer_size(inst);
if (rc)
@@ -2382,7 +2401,6 @@ int msm_vidc_set_session_priority(void *instance,
return rc;
}
/* TODO
int msm_vidc_set_flip(void *instance,
enum msm_vidc_inst_capability_type cap_id)
{
@@ -2404,15 +2422,35 @@ int msm_vidc_set_flip(void *instance,
if (vflip)
hfi_value |= HFI_VERTICAL_FLIP;
i_vpr_h(inst, "set cap: name: %24s, value: %#10x, hfi: %#10x\n", cap_name(cap_id),
inst->capabilities->cap[cap_id].value, hfi_value);
rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM,
&hfi_value, sizeof(u32), __func__);
return rc;
}
*/
int msm_vidc_set_rotation(void *instance,
enum msm_vidc_inst_capability_type cap_id)
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
u32 hfi_value;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
rc = msm_vidc_v4l2_to_hfi_enum(inst, cap_id, &hfi_value);
if (rc)
return -EINVAL;
rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32,
&hfi_value, sizeof(u32), __func__);
if (rc)
return rc;
return rc;
}
int msm_vidc_set_q16(void *instance,
enum msm_vidc_inst_capability_type cap_id)

View File

@@ -156,7 +156,8 @@ bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
buffer_type != HFI_BUFFER_NON_COMV &&
buffer_type != HFI_BUFFER_LINE &&
buffer_type != HFI_BUFFER_DPB &&
buffer_type != HFI_BUFFER_PERSIST) {
buffer_type != HFI_BUFFER_PERSIST &&
buffer_type != HFI_BUFFER_VPSS) {
i_vpr_e(inst, "%s: invalid buffer type %#x\n",
func, buffer_type);
return false;
@@ -1035,6 +1036,7 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
{HFI_BUFFER_LINE, handle_release_internal_buffer },
{HFI_BUFFER_ARP, handle_release_internal_buffer },
{HFI_BUFFER_DPB, handle_release_internal_buffer },
{HFI_BUFFER_VPSS, handle_release_internal_buffer },
};
static const struct msm_vidc_hfi_buffer_handle dec_input_hfi_handle[] = {
{HFI_BUFFER_METADATA, handle_input_metadata_buffer },