media: venus: venc: Add support for constant quality control
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Tue, 16 Jun 2020 12:14:22 +0000 (14:14 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 1 Sep 2020 12:13:29 +0000 (14:13 +0200)
Adds implementation of V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY v4l
control when the bitrate mode is CQ.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/hfi_cmds.c
drivers/media/platform/qcom/venus/hfi_helper.h
drivers/media/platform/qcom/venus/venc.c
drivers/media/platform/qcom/venus/venc_ctrls.c

index b0cc544..85f2e2c 100644 (file)
@@ -206,6 +206,7 @@ struct venc_controls {
        u32 bitrate;
        u32 bitrate_peak;
        u32 rc_enable;
+       u32 const_quality;
 
        u32 h264_i_period;
        u32 h264_entropy_mode;
index c67e412..7022368 100644 (file)
@@ -640,6 +640,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
                case HFI_RATE_CONTROL_CBR_VFR:
                case HFI_RATE_CONTROL_VBR_CFR:
                case HFI_RATE_CONTROL_VBR_VFR:
+               case HFI_RATE_CONTROL_CQ:
                        break;
                default:
                        ret = -EINVAL;
@@ -1218,6 +1219,37 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
        return 0;
 }
 
+static int
+pkt_session_set_property_6xx(struct hfi_session_set_property_pkt *pkt,
+                            void *cookie, u32 ptype, void *pdata)
+{
+       void *prop_data;
+
+       if (!pkt || !cookie || !pdata)
+               return -EINVAL;
+
+       prop_data = &pkt->data[1];
+
+       pkt->shdr.hdr.size = sizeof(*pkt);
+       pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY;
+       pkt->shdr.session_id = hash32_ptr(cookie);
+       pkt->num_properties = 1;
+       pkt->data[0] = ptype;
+
+       switch (ptype) {
+       case HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY: {
+               struct hfi_heic_frame_quality *in = pdata, *cq = prop_data;
+
+               cq->frame_quality = in->frame_quality;
+               pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cq);
+               break;
+       } default:
+               return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
+       }
+
+       return 0;
+}
+
 int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt,
                             void *cookie, u32 ptype)
 {
@@ -1236,7 +1268,10 @@ int pkt_session_set_property(struct hfi_session_set_property_pkt *pkt,
        if (hfi_ver == HFI_VERSION_3XX)
                return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata);
 
-       return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
+       if (hfi_ver == HFI_VERSION_4XX)
+               return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
+
+       return pkt_session_set_property_6xx(pkt, cookie, ptype, pdata);
 }
 
 void pkt_set_version(enum hfi_version version)
index f6613df..758c70a 100644 (file)
 #define HFI_RATE_CONTROL_VBR_CFR               0x1000003
 #define HFI_RATE_CONTROL_CBR_VFR               0x1000004
 #define HFI_RATE_CONTROL_CBR_CFR               0x1000005
+#define HFI_RATE_CONTROL_CQ                    0x1000008
 
 #define HFI_VIDEO_CODEC_H264                   0x00000002
 #define HFI_VIDEO_CODEC_H263                   0x00000004
 #define HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER              0x200600b
 #define HFI_PROPERTY_CONFIG_VENC_LTRPERIOD                     0x200600c
 #define HFI_PROPERTY_CONFIG_VENC_PERF_MODE                     0x200600e
+#define HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY                 0x2006014
 
 /*
  * HFI_PROPERTY_PARAM_VPE_COMMON_START
 enum hfi_version {
        HFI_VERSION_1XX,
        HFI_VERSION_3XX,
-       HFI_VERSION_4XX
+       HFI_VERSION_4XX,
+       HFI_VERSION_6XX,
 };
 
 struct hfi_buffer_info {
@@ -725,6 +728,11 @@ struct hfi_quality_vs_speed {
        u32 quality_vs_speed;
 };
 
+struct hfi_heic_frame_quality {
+       u32 frame_quality;
+       u32 reserved[3];
+};
+
 struct hfi_quantization {
        u32 qp_i;
        u32 qp_p;
index 80cb9fa..c072ac6 100644 (file)
@@ -746,14 +746,26 @@ static int venc_set_properties(struct venus_inst *inst)
                rate_control = HFI_RATE_CONTROL_OFF;
        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
                rate_control = HFI_RATE_CONTROL_VBR_CFR;
-       else
+       else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
                rate_control = HFI_RATE_CONTROL_CBR_CFR;
+       else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
+               rate_control = HFI_RATE_CONTROL_CQ;
 
        ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
        ret = hfi_session_set_property(inst, ptype, &rate_control);
        if (ret)
                return ret;
 
+       if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
+               struct hfi_heic_frame_quality quality = {};
+
+               ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
+               quality.frame_quality = ctr->const_quality;
+               ret = hfi_session_set_property(inst, ptype, &quality);
+               if (ret)
+                       return ret;
+       }
+
        if (!ctr->bitrate)
                bitrate = 64000;
        else
index 8362dde..c0d1ef4 100644 (file)
@@ -202,6 +202,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
        case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
                ctr->rc_enable = ctrl->val;
                break;
+       case V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY:
+               ctr->const_quality = ctrl->val;
+               break;
        default:
                return -EINVAL;
        }
@@ -217,7 +220,7 @@ int venc_ctrl_init(struct venus_inst *inst)
 {
        int ret;
 
-       ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 31);
+       ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 32);
        if (ret)
                return ret;
 
@@ -225,7 +228,8 @@ int venc_ctrl_init(struct venus_inst *inst)
                V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
                V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
                ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
-                 (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)),
+                 (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
+                 (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)),
                V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 
        v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
@@ -357,6 +361,9 @@ int venc_ctrl_init(struct venus_inst *inst)
        v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
                          V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);
 
+       v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+                         V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY, 0, 100, 1, 0);
+
        ret = inst->ctrl_handler.error;
        if (ret)
                goto err;