Browse Source

video: driver: Modify buffer_stats logic

For super buffer usecase, All the ETB's gets queued with updated
timestamp in hfi_buffer, therefore all the fbd's being recieved
are of different timestamp. And only the last EBD is considered
for dequeued flag and hence for remove_buffer_stat.

Therefore when first FBD arrives which has the matched TS to
the stat's TS will get skipped since last EBD in the batch has
not arrived yet and rest all FBDs are with updated TS, hence
the buffer stat doesn't get's removed from the list.

Modified the logic to add stats during hfi_buffer queue and
add stats for all sub-frames in super buffer usecase.
Modified the logic for Multi-In single-Out usecase as well.

Change-Id: I0643e6f64bdfc3cbfa67baeb1cf9157de92ce569
Signed-off-by: Vedang Nagar <[email protected]>
Vedang Nagar 2 năm trước cách đây
mục cha
commit
b3f107df87

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

@@ -599,9 +599,9 @@ int signal_session_msg_receipt(struct msm_vidc_inst *inst,
 int msm_vidc_get_properties(struct msm_vidc_inst *inst);
 int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us);
 int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
-	struct msm_vidc_buffer *buf);
+	struct msm_vidc_buffer *buf, u64 timestamp);
 int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst,
-	struct msm_vidc_buffer *buf);
+	struct msm_vidc_buffer *buf, u64 timestamp);
 int msm_vidc_flush_buffer_stats(struct msm_vidc_inst *inst);
 int msm_vidc_get_input_rate(struct msm_vidc_inst *inst);
 int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst);

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

@@ -917,12 +917,14 @@ struct msm_vidc_buffer_stats {
 	u32                                fbd_time_ms;
 	u32                                data_size;
 	u32                                flags;
+	u32                                ts_offset;
 };
 
 enum msm_vidc_buffer_stats_flag {
-	MSM_VIDC_STATS_FLAG_CORRUPT     = BIT(0),
-	MSM_VIDC_STATS_FLAG_OVERFLOW    = BIT(1),
-	MSM_VIDC_STATS_FLAG_NO_OUTPUT   = BIT(2),
+	MSM_VIDC_STATS_FLAG_CORRUPT        = BIT(0),
+	MSM_VIDC_STATS_FLAG_OVERFLOW       = BIT(1),
+	MSM_VIDC_STATS_FLAG_NO_OUTPUT      = BIT(2),
+	MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT = BIT(3),
 };
 
 struct msm_vidc_sort {

+ 59 - 37
driver/vidc/src/msm_vidc_driver.c

@@ -318,6 +318,9 @@ static u32 msm_vidc_get_buffer_stats_flag(struct msm_vidc_inst *inst)
 	if (inst->hfi_frame_info.no_output)
 		flags |= MSM_VIDC_STATS_FLAG_NO_OUTPUT;
 
+	if (inst->hfi_frame_info.subframe_input)
+		flags |= MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT;
+
 	return flags;
 }
 
@@ -359,7 +362,7 @@ static int msm_vidc_try_suspend(struct msm_vidc_inst *inst)
 }
 
 int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
-	struct msm_vidc_buffer *buf)
+	struct msm_vidc_buffer *buf, u64 timestamp)
 {
 	struct msm_vidc_buffer_stats *stats = NULL;
 	struct msm_vidc_core *core;
@@ -370,6 +373,9 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
 	}
 	core = inst->core;
 
+	if (!(msm_vidc_debug & VIDC_STAT))
+		return 0;
+
 	/* stats applicable only to input & output buffers */
 	if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT)
 		return -EINVAL;
@@ -388,7 +394,8 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
 	list_add_tail(&stats->list, &inst->buffer_stats_list);
 
 	stats->frame_num = inst->debug_count.etb;
-	stats->timestamp = buf->timestamp;
+	stats->timestamp = timestamp;
+	stats->ts_offset = 0;
 	stats->etb_time_ms = buf->start_time_ms;
 	if (is_decode_session(inst))
 		stats->data_size =  buf->data_size;
@@ -397,10 +404,12 @@ int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
 }
 
 int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst,
-	struct msm_vidc_buffer *buf)
+	struct msm_vidc_buffer *buf, u64 timestamp)
 {
 	struct msm_vidc_buffer_stats *stats = NULL, *dummy_stats = NULL;
+	struct msm_vidc_buffer_stats *prev_stats = NULL;
 	struct msm_vidc_core *core;
+	bool remove_stat = false, is_first_stat = false;;
 
 	if (!inst || !inst->core || !buf) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -408,6 +417,9 @@ int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst,
 	}
 	core = inst->core;
 
+	if (!(msm_vidc_debug & VIDC_STAT))
+		return 0;
+
 	/* stats applicable only to input & output buffers */
 	if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT)
 		return -EINVAL;
@@ -416,38 +428,51 @@ int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst,
 	buf->end_time_ms = (ktime_get_ns() / 1000 - inst->initial_time_us) / 1000;
 
 	list_for_each_entry_safe(stats, dummy_stats, &inst->buffer_stats_list, list) {
-		if (stats->timestamp == buf->timestamp) {
-			if (buf->type == MSM_VIDC_BUF_INPUT) {
-				/* skip - already updated(multiple input - single output case) */
-				if (stats->ebd_time_ms)
-					continue;
-
-				/* ebd: update end ts and return */
-				stats->ebd_time_ms = buf->end_time_ms;
-				stats->flags |= msm_vidc_get_buffer_stats_flag(inst);
-
-				/* remove entry - no output attached */
-				if (stats->flags & MSM_VIDC_STATS_FLAG_NO_OUTPUT) {
-					list_del_init(&stats->list);
-					msm_vidc_pool_free(inst, stats);
-				}
-			} else if (buf->type == MSM_VIDC_BUF_OUTPUT) {
-				/* skip - ebd not arrived(single input - multiple output case) */
-				if (!stats->ebd_time_ms)
-					continue;
-
-				/* fbd: update end ts and remove entry */
-				list_del_init(&stats->list);
-				stats->ftb_time_ms = buf->start_time_ms;
-				stats->fbd_time_ms = buf->end_time_ms;
-				stats->flags |= msm_vidc_get_buffer_stats_flag(inst);
-				if (is_encode_session(inst))
-					stats->data_size = buf->data_size;
-
-				print_buffer_stats(VIDC_STAT, "stat", inst, stats);
-
-				msm_vidc_pool_free(inst, stats);
+		if (stats->timestamp - stats->ts_offset != timestamp)
+			continue;
+
+		remove_stat = false;
+		if (buf->type == MSM_VIDC_BUF_INPUT) {
+			/* skip - ebd already updated(multiple input - single output case) */
+			if (stats->ebd_time_ms)
+				continue;
+
+			/* ebd: update end ts and return */
+			stats->ebd_time_ms = buf->end_time_ms;
+			stats->flags |= msm_vidc_get_buffer_stats_flag(inst);
+
+			/* multi in - single out (interlace/slice decoding case) */
+			is_first_stat = list_is_first(&stats->list, &inst->buffer_stats_list);
+			if (!is_first_stat) {
+				prev_stats = list_prev_entry(stats, list);
+
+				/* add offset if FW requires more etb's to process output */
+				if (prev_stats->flags & MSM_VIDC_STATS_FLAG_SUBFRAME_INPUT)
+					stats->ts_offset = stats->timestamp - prev_stats->timestamp;
 			}
+
+			/* remove entry - no output attached */
+			remove_stat = !!(stats->flags & MSM_VIDC_STATS_FLAG_NO_OUTPUT);
+			remove_stat |= stats->ebd_time_ms && stats->fbd_time_ms;
+		} else if (buf->type == MSM_VIDC_BUF_OUTPUT) {
+			/* skip - ebd already updated(encoder superframe case) */
+			if (stats->fbd_time_ms)
+				continue;
+
+			/* fbd: update end ts */
+			stats->ftb_time_ms = buf->start_time_ms;
+			stats->fbd_time_ms = buf->end_time_ms;
+			stats->flags |= msm_vidc_get_buffer_stats_flag(inst);
+			if (is_encode_session(inst))
+				stats->data_size = buf->data_size;
+
+			remove_stat |= stats->ebd_time_ms && stats->fbd_time_ms;
+		}
+		/* remove stats node */
+		if (remove_stat) {
+			list_del_init(&stats->list);
+			print_buffer_stats(VIDC_STAT, "stat", inst, stats);
+			msm_vidc_pool_free(inst, stats);
 		}
 	}
 
@@ -2832,9 +2857,6 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
 		}
 	}
 
-	/* update start timestamp */
-	msm_vidc_add_buffer_stats(inst, buf);
-
 	return buf;
 }
 

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

@@ -1825,6 +1825,9 @@ int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
 		if (rc)
 			goto unlock;
 
+		/* update start timestamp */
+		msm_vidc_add_buffer_stats(inst, buffer, hfi_buffer.timestamp);
+
 		cnt++;
 	}
 unlock:
@@ -1884,7 +1887,7 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 {
 	int rc = 0;
 	struct msm_vidc_core *core;
-	struct hfi_buffer hfi_buffer;
+	struct hfi_buffer hfi_buffer, hfi_meta_buffer;
 
 	if (!inst || !inst->core || !inst->packet || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -1920,7 +1923,7 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 		goto unlock;
 
 	if (metabuf) {
-		rc = get_hfi_buffer(inst, metabuf, &hfi_buffer);
+		rc = get_hfi_buffer(inst, metabuf, &hfi_meta_buffer);
 		if (rc)
 			goto unlock;
 		rc = hfi_create_packet(inst->packet,
@@ -1930,8 +1933,8 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 			HFI_PAYLOAD_STRUCTURE,
 			get_hfi_port_from_buffer_type(inst, metabuf->type),
 			core->packet_id++,
-			&hfi_buffer,
-			sizeof(hfi_buffer));
+			&hfi_meta_buffer,
+			sizeof(hfi_meta_buffer));
 		if (rc)
 			goto unlock;
 	}
@@ -1964,6 +1967,9 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 	if (rc)
 		goto unlock;
 
+	/* update start timestamp */
+	msm_vidc_add_buffer_stats(inst, buffer, hfi_buffer.timestamp);
+
 unlock:
 	core_unlock(core, __func__);
 	return rc;

+ 5 - 3
driver/vidc/src/venus_hfi_response.c

@@ -822,6 +822,8 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
 		if (buffer->addr_offset / frame_size < batch_size - 1) {
 			i_vpr_l(inst, "%s: superframe last buffer not reached: %u, %u, %u\n",
 				__func__, buffer->addr_offset, frame_size, batch_size);
+			/* remove buffer stats for all the subframes in a superframe */
+			msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp);
 			return 0;
 		}
 	}
@@ -848,8 +850,8 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
 	print_vidc_buffer(VIDC_HIGH, "high", "dqbuf", inst, buf);
 	msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_EBD);
 
-	/* etd: update end timestamp and flags in stats entry */
-	msm_vidc_remove_buffer_stats(inst, buf);
+	/* ebd: update end timestamp and flags in stats entry */
+	msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp);
 
 	return rc;
 }
@@ -1026,7 +1028,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_FBD);
 
 	/* fbd: print stats and remove entry */
-	msm_vidc_remove_buffer_stats(inst, buf);
+	msm_vidc_remove_buffer_stats(inst, buf, buffer->timestamp);
 
 	return rc;
 }