Browse Source

video: driver: Add support for enc auto framerate

1. Calculate framerate based on buffer timestamp
2. If framerate changed and stable for 2 frames,
   update it to firmware and in driver internally.

Change-Id: I7feda86dec8fcfc1dff6defac8c15a97c1b8393e
Signed-off-by: Priyanka Gujjula <[email protected]>
Priyanka Gujjula 4 năm trước cách đây
mục cha
commit
e61b55879b

+ 1 - 0
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -93,6 +93,7 @@ static struct msm_platform_core_capability core_data_waipio[] = {
 	{DECODE_BATCH_TIMEOUT, 200},
 	{AV_SYNC_WINDOW_SIZE, 40},
 	{NON_FATAL_FAULTS, 1},
+	{ENC_AUTO_FRAMERATE, 1},
 };
 
 static struct msm_platform_inst_capability instance_data_waipio[] = {

+ 1 - 1
driver/variant/iris2/src/msm_vidc_power_iris2.c

@@ -48,7 +48,7 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size)
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
 	fps = msm_vidc_get_fps(inst);
 
-	buf_timetamps_fps = msm_vidc_calc_framerate(inst);
+	buf_timetamps_fps = msm_vidc_calc_window_avg_framerate(inst);
 
 	/*
 	 * when buffer detected fps is more than client set value by 10%,

+ 2 - 1
driver/vidc/inc/msm_vidc_driver.h

@@ -423,7 +423,8 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
 int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
 int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
-int msm_vidc_calc_framerate(struct msm_vidc_inst *inst);
+int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp);
+int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst);
 int msm_vidc_flush_ts(struct msm_vidc_inst *inst);
 const char *buf_name(enum msm_vidc_buffer_type type);
 void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst,

+ 1 - 0
driver/vidc/inc/msm_vidc_inst.h

@@ -153,5 +153,6 @@ struct msm_vidc_inst {
 	u32                                max_input_data_size;
 	u32                                dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
 	u32                                max_map_output_count;
+	u32                                auto_framerate;
 };
 #endif // _MSM_VIDC_INST_H_

+ 3 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -69,6 +69,8 @@
 #define MAX_SUPPORTED_MIN_QUALITY            70
 
 #define DCVS_WINDOW 16
+#define ENC_FPS_WINDOW 3
+#define DEC_FPS_WINDOW 10
 /* Superframe can have maximum of 32 frames */
 #define VIDC_SUPERFRAME_MAX 32
 #define COLOR_RANGE_UNSPECIFIED (-1)
@@ -327,6 +329,7 @@ enum msm_vidc_core_capability_type {
 	AV_SYNC_WINDOW_SIZE,
 	CLK_FREQ_THRESHOLD,
 	NON_FATAL_FAULTS,
+	ENC_AUTO_FRAMERATE,
 	CORE_CAP_MAX,
 };
 

+ 1 - 0
driver/vidc/src/msm_venc.c

@@ -1604,6 +1604,7 @@ set_default:
 				"%s: failed to set frame rate to fw\n", __func__);
 			goto exit;
 		}
+		inst->auto_framerate = q16_rate;
 	}
 
 	return 0;

+ 8 - 0
driver/vidc/src/msm_vidc.c

@@ -433,6 +433,7 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
 	int rc = 0;
 	struct msm_vidc_inst *inst = instance;
 	struct vb2_queue *q;
+	u64 timestamp_us = 0;
 
 	if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
 		d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
@@ -444,6 +445,12 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
 		rc = -EINVAL;
 		goto exit;
 	}
+
+	if (is_encode_session(inst) && b->type == INPUT_MPLANE) {
+		timestamp_us = (u64)((b->timestamp.tv_sec * USEC_PER_SEC) +
+			b->timestamp.tv_usec);
+		msm_vidc_set_auto_framerate(inst, timestamp_us);
+	}
 	inst->last_qbuf_time_ns = ktime_get_ns();
 
 	rc = vb2_qbuf(q, mdev, b);
@@ -775,6 +782,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	inst->request = false;
 	inst->ipsc_properties_set = false;
 	inst->opsc_properties_set = false;
+	inst->auto_framerate = DEFAULT_FPS << 16;
 	kref_init(&inst->kref);
 	mutex_init(&inst->lock);
 	msm_vidc_update_debug_str(inst);

+ 69 - 5
driver/vidc/src/msm_vidc_driver.c

@@ -40,8 +40,6 @@ extern struct msm_vidc_core *g_core;
 #define SSR_ADDR_ID 0xFFFFFFFF00000000
 #define SSR_ADDR_SHIFT 32
 
-#define FPS_WINDOW 10
-
 struct msm_vidc_cap_name {
 	enum msm_vidc_inst_capability_type cap;
 	char *name;
@@ -2014,7 +2012,67 @@ int msm_vidc_memory_unmap_completely(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-int msm_vidc_calc_framerate(struct msm_vidc_inst *inst)
+int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp)
+{
+	struct msm_vidc_core *core;
+	struct msm_vidc_timestamp *ts;
+	struct msm_vidc_timestamp *prev = NULL;
+	u32 counter = 0, prev_fr = 0, curr_fr = 0;
+	u64 ts_ms = 0;
+	int rc = 0;
+
+	if (!inst || !inst->core || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	core = inst->core;
+	if (!core->capabilities[ENC_AUTO_FRAMERATE].value ||
+			is_image_session(inst) || msm_vidc_is_super_buffer(inst))
+		goto exit;
+
+	rc = msm_vidc_update_timestamp(inst, timestamp);
+	if (rc)
+		goto exit;
+
+	list_for_each_entry(ts, &inst->timestamps.list, sort.list) {
+		if (prev) {
+			ts_ms = div_u64(ts->sort.val - prev->sort.val, 1000);
+			prev_fr = curr_fr;
+			curr_fr = ts_ms ? div_u64(MSEC_PER_SEC, ts_ms) << 16 :
+					inst->auto_framerate;
+			if (curr_fr > inst->capabilities->cap[FRAME_RATE].max)
+				curr_fr = inst->capabilities->cap[FRAME_RATE].max;
+		}
+		prev = ts;
+		counter++;
+	}
+
+	if (counter < ENC_FPS_WINDOW)
+		goto exit;
+
+	/* if framerate changed and stable for 2 frames, set to firmware */
+	if (curr_fr == prev_fr && curr_fr != inst->auto_framerate) {
+		i_vpr_l(inst, "%s: updated fps to %u\n", __func__, curr_fr >> 16);
+		rc = venus_hfi_session_property(inst,
+				HFI_PROP_FRAME_RATE,
+				HFI_HOST_FLAGS_NONE,
+				HFI_PORT_BITSTREAM,
+				HFI_PAYLOAD_Q16,
+				&curr_fr,
+				sizeof(u32));
+		if (rc) {
+			i_vpr_e(inst, "%s: set auto frame rate failed\n",
+				__func__);
+			goto exit;
+		}
+		inst->auto_framerate = curr_fr;
+	}
+exit:
+	return rc;
+}
+
+int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_timestamp *ts;
 	struct msm_vidc_timestamp *prev = NULL;
@@ -2124,6 +2182,7 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
 {
 	struct msm_vidc_timestamp *ts;
 	int rc = 0;
+	u32 window_size = 0;
 
 	if (!inst) {
 		d_vpr_e("%s: Invalid params\n", __func__);
@@ -2144,8 +2203,13 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
 		return rc;
 	inst->timestamps.count++;
 
-	/* keep sliding window of 10 ts nodes */
-	if (inst->timestamps.count > FPS_WINDOW) {
+	if (is_encode_session(inst))
+		window_size = ENC_FPS_WINDOW;
+	else
+		window_size = DEC_FPS_WINDOW;
+
+	/* keep sliding window */
+	if (inst->timestamps.count > window_size) {
 		ts = msm_vidc_get_least_rank_ts(inst);
 		if (!ts) {
 			i_vpr_e(inst, "%s: least rank ts is NULL\n", __func__);

+ 1 - 1
driver/vidc/src/msm_vidc_power.c

@@ -223,7 +223,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
 	vote_data->lcu_size = (codec == V4L2_PIX_FMT_HEVC ||
 			codec == V4L2_PIX_FMT_VP9) ? 32 : 16;
 	vote_data->fps = msm_vidc_get_fps(inst);
-	buf_ts_fps = msm_vidc_calc_framerate(inst);
+	buf_ts_fps = msm_vidc_calc_window_avg_framerate(inst);
 	if (buf_ts_fps > vote_data->fps) {
 		i_vpr_l(inst, "%s: bitstream: fps %d, client rate %u\n", __func__,
 			buf_ts_fps, vote_data->fps);

+ 0 - 4
driver/vidc/src/venus_hfi.c

@@ -3399,7 +3399,6 @@ int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
 		/* Create yuv packet */
 		update_offset(hfi_buffer.addr_offset, (cnt ? frame_size : 0u));
 		update_timestamp(hfi_buffer.timestamp, (cnt ? ts_delta_us : 0u));
-		msm_vidc_update_timestamp(inst, hfi_buffer.timestamp);
 		rc = hfi_create_packet(inst->packet,
 				inst->packet_size,
 				HFI_CMD_BUFFER,
@@ -3467,9 +3466,6 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 	if (rc)
 		goto unlock;
 
-	if (is_encode_session(inst) && is_input_buffer(buffer->type))
-		msm_vidc_update_timestamp(inst, hfi_buffer.timestamp);
-
 	rc = hfi_create_header(inst->packet, inst->packet_size,
 			   inst->session_id, core->header_id++);
 	if (rc)