Explorar o código

video: driver: add support for timestamp reorder

Added support for timestamp reorder. It is default
disabled.

Change-Id: I51a6fc785860081b651fc67f443132cb2675b9fd
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal %!s(int64=3) %!d(string=hai) anos
pai
achega
1e55de3d4a

+ 5 - 0
driver/platform/diwali/src/msm_vidc_diwali.c

@@ -381,6 +381,11 @@ static struct msm_platform_inst_capability instance_data_diwali_v0[] = {
 		{0},
 		NULL, msm_vidc_set_u32},
 
+	{TS_REORDER, DEC, H264|HEVC,
+		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
+		1, V4L2_MPEG_MSM_VIDC_DISABLE,
+		V4L2_CID_MPEG_VIDC_TS_REORDER},
+
 	{HFLIP, ENC, CODECS_ALL,
 		V4L2_MPEG_MSM_VIDC_DISABLE,
 		V4L2_MPEG_MSM_VIDC_ENABLE,

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

@@ -262,6 +262,11 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		{0},
 		NULL, msm_vidc_set_u32},
 
+	{TS_REORDER, DEC, H264|HEVC,
+		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
+		1, V4L2_MPEG_MSM_VIDC_DISABLE,
+		V4L2_CID_MPEG_VIDC_TS_REORDER},
+
 	{HFLIP, ENC, CODECS_ALL,
 		V4L2_MPEG_MSM_VIDC_DISABLE,
 		V4L2_MPEG_MSM_VIDC_ENABLE,

+ 10 - 0
driver/vidc/inc/msm_vidc_driver.h

@@ -67,6 +67,12 @@ static inline is_output_meta_buffer(enum msm_vidc_buffer_type buffer_type)
 	return buffer_type == MSM_VIDC_BUF_OUTPUT_META;
 }
 
+static inline is_ts_reorder_allowed(struct msm_vidc_inst *inst)
+{
+	return !!(inst->capabilities->cap[TS_REORDER].value &&
+		is_decode_session(inst) && !is_image_session(inst));
+}
+
 static inline is_scaling_enabled(struct msm_vidc_inst *inst)
 {
 	return inst->crop.left != inst->compose.left ||
@@ -428,6 +434,10 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
 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);
+int msm_vidc_ts_reorder_insert_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
+int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
+int msm_vidc_ts_reorder_get_first_timestamp(struct msm_vidc_inst *inst, u64 *timestamp);
+int msm_vidc_ts_reorder_flush(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,
 	enum msm_vidc_ctrl_list_type list_type);

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

@@ -118,6 +118,7 @@ struct msm_vidc_inst {
 	struct msm_vidc_mappings_info      mappings;
 	struct msm_vidc_allocations_info   allocations;
 	struct msm_vidc_timestamps         timestamps;
+	struct msm_vidc_timestamps         ts_reorder; /* list of struct msm_vidc_timestamp */
 	bool                               subscribed_input_psc;
 	bool                               subscribed_output_psc;
 	bool                               subscribed_input_prop;

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

@@ -363,6 +363,7 @@ enum msm_vidc_inst_capability_type {
 	MB_CYCLES_FW,
 	MB_CYCLES_FW_VPP,
 	SECURE_MODE,
+	TS_REORDER,
 	HFLIP,
 	VFLIP,
 	ROTATION,

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

@@ -1610,6 +1610,10 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
+	rc = msm_vidc_ts_reorder_flush(inst);
+	if (rc)
+		goto error;
+
 	return 0;
 
 error:

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

@@ -840,6 +840,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	}
 	INIT_LIST_HEAD(&inst->response_works);
 	INIT_LIST_HEAD(&inst->timestamps.list);
+	INIT_LIST_HEAD(&inst->ts_reorder.list);
 	INIT_LIST_HEAD(&inst->buffers.input.list);
 	INIT_LIST_HEAD(&inst->buffers.input_meta.list);
 	INIT_LIST_HEAD(&inst->buffers.output.list);

+ 111 - 0
driver/vidc/src/msm_vidc_driver.c

@@ -81,6 +81,7 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{MB_CYCLES_FW,                   "MB_CYCLES_FW"               },
 	{MB_CYCLES_FW_VPP,               "MB_CYCLES_FW_VPP"           },
 	{SECURE_MODE,                    "SECURE_MODE"                },
+	{TS_REORDER,                     "TS_REORDER"                 },
 	{HFLIP,                          "HFLIP"                      },
 	{VFLIP,                          "VFLIP"                      },
 	{ROTATION,                       "ROTATION"                   },
@@ -2404,6 +2405,102 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
 	return 0;
 }
 
+int msm_vidc_ts_reorder_insert_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
+{
+	struct msm_vidc_timestamp *ts;
+
+	if (!inst) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* allocate ts from pool */
+	ts = msm_memory_alloc(inst, MSM_MEM_POOL_TIMESTAMP);
+	if (!ts) {
+		i_vpr_e(inst, "%s: ts alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* initialize ts node */
+	INIT_LIST_HEAD(&ts->sort.list);
+	ts->sort.val = timestamp;
+	inst->ts_reorder.count++;
+	list_add_tail(&ts->sort.list, &inst->ts_reorder.list);
+
+	return 0;
+}
+
+int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
+{
+	struct msm_vidc_timestamp *ts, *temp;
+
+	if (!inst) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* remove matching node */
+	list_for_each_entry_safe(ts, temp, &inst->ts_reorder.list, sort.list) {
+		if (ts->sort.val == timestamp) {
+			list_del_init(&ts->sort.list);
+			inst->ts_reorder.count--;
+			msm_memory_free(inst, ts);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int msm_vidc_ts_reorder_get_first_timestamp(struct msm_vidc_inst *inst, u64 *timestamp)
+{
+	struct msm_vidc_timestamp *ts;
+
+	if (!inst || !timestamp) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* check if list empty */
+	if (list_empty(&inst->ts_reorder.list)) {
+		i_vpr_e(inst, "%s: list empty. ts %lld\n", __func__, timestamp);
+		return -EINVAL;
+	}
+
+	/* get 1st node from reorder list */
+	ts = list_first_entry(&inst->ts_reorder.list,
+		struct msm_vidc_timestamp, sort.list);
+	list_del_init(&ts->sort.list);
+
+	/* copy timestamp */
+	*timestamp = ts->sort.val;
+
+	inst->ts_reorder.count--;
+	msm_memory_free(inst, ts);
+
+	return 0;
+}
+
+int msm_vidc_ts_reorder_flush(struct msm_vidc_inst *inst)
+{
+	struct msm_vidc_timestamp *temp, *ts = NULL;
+
+	if (!inst) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* flush all entries */
+	list_for_each_entry_safe(ts, temp, &inst->ts_reorder.list, sort.list) {
+		i_vpr_l(inst, "%s: flushing ts: val %lld\n", __func__, ts->sort.val);
+		list_del(&ts->sort.list);
+		msm_memory_free(inst, ts);
+	}
+	inst->ts_reorder.count = 0;
+
+	return 0;
+}
+
 int msm_vidc_get_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map *map)
 {
 	int rc = 0;
@@ -3094,6 +3191,13 @@ static int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buf
 		meta->attr |= MSM_VIDC_ATTR_QUEUED;
 	}
 
+	/* insert timestamp for ts_reorder enable case */
+	if (is_ts_reorder_allowed(inst) && is_input_buffer(buf->type)) {
+		rc = msm_vidc_ts_reorder_insert_timestamp(inst, buf->timestamp);
+		if (rc)
+			i_vpr_e(inst, "%s: insert timestamp failed\n", __func__);
+	}
+
 	if (is_input_buffer(buf->type))
 		inst->power.buffer_counter++;
 
@@ -5019,6 +5123,13 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
 		msm_memory_free(inst, ts);
 	}
 
+	list_for_each_entry_safe(ts, dummy_ts, &inst->ts_reorder.list, sort.list) {
+		i_vpr_e(inst, "%s: removing reorder ts: val %lld\n",
+			__func__, ts->sort.val);
+		list_del(&ts->sort.list);
+		msm_memory_free(inst, ts);
+	}
+
 	list_for_each_entry_safe(dbuf, dummy_dbuf, &inst->dmabuf_tracker, list) {
 		i_vpr_e(inst, "%s: removing dma_buf %#x, refcount %u\n",
 			__func__, dbuf->dmabuf, dbuf->refcount);

+ 11 - 0
driver/vidc/src/venus_hfi_response.c

@@ -755,6 +755,13 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
 	buf->flags = 0;
 	buf->flags = get_driver_buffer_flags(inst, buffer->flags);
 
+	/* handle ts_reorder for no_output prop attached input buffer */
+	if (is_ts_reorder_allowed(inst) && inst->hfi_frame_info.no_output) {
+		i_vpr_h(inst, "%s: received no_output buffer. remove timestamp %lld\n",
+			__func__, buf->timestamp);
+		msm_vidc_ts_reorder_remove_timestamp(inst, buf->timestamp);
+	}
+
 	print_vidc_buffer(VIDC_HIGH, "high", "dqbuf", inst, buf);
 	msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_EBD);
 
@@ -886,6 +893,10 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	if (!is_image_session(inst) && is_decode_session(inst) && buf->data_size)
 		msm_vidc_update_timestamp(inst, buf->timestamp);
 
+	/* update output buffer timestamp, if ts_reorder is enabled */
+	if (is_ts_reorder_allowed(inst) && buf->data_size)
+		msm_vidc_ts_reorder_get_first_timestamp(inst, &buf->timestamp);
+
 	print_vidc_buffer(VIDC_HIGH, "high", "dqbuf", inst, buf);
 	msm_vidc_update_stats(inst, buf, MSM_VIDC_DEBUGFS_EVENT_FBD);
 

+ 2 - 0
include/uapi/vidc/media/v4l2_vidc_extensions.h

@@ -189,6 +189,8 @@ enum v4l2_mpeg_video_av1_tier {
 	V4L2_MPEG_VIDEO_AV1_TIER_MAIN  = 0,
 	V4L2_MPEG_VIDEO_AV1_TIER_HIGH  = 1,
 };
+/* Decoder Timestamp Reorder control */
+#define V4L2_CID_MPEG_VIDC_TS_REORDER           (V4L2_CID_MPEG_VIDC_BASE + 0x34)
 
 /* Deprecate below controls once availble in gki and gsi bionic header */
 #ifndef V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID