summarylogtreecommitdiffstats
path: root/general-meson-vdec-add-handling-to-HEVC-decoder-.patch
blob: 93b3af995dd29060c62259747e5bc1dd9abeb42a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
From a9f750c672c4c1238cccd1d8d76a138a5602d035 Mon Sep 17 00:00:00 2001
From: benjamin545 <benjamin545@gmail.com>
Date: Mon, 2 Aug 2021 15:18:40 -0400
Subject: [PATCH 65/90] WIP: drivers: meson: vdec: add handling to HEVC decoder
 to show frames when ready

..rather than when no longer referenced

the HEVC decode driver would not show the next frame until it was no longer referenced,
this would cause a backup of frames that were ready to render but held up by one or more
frames that were still referenced. The decoded picture buffer would fill up and stall
playback as no new frames could be placed in the decoded picture buffer.
---
 drivers/staging/media/meson/vdec/codec_hevc.c | 52 ++++++++++++-------
 1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/media/meson/vdec/codec_hevc.c b/drivers/staging/media/meson/vdec/codec_hevc.c
index 3a6fd04a2d33..01218efde99b 100644
--- a/drivers/staging/media/meson/vdec/codec_hevc.c
+++ b/drivers/staging/media/meson/vdec/codec_hevc.c
@@ -223,6 +223,7 @@ struct hevc_frame {
 	u32 poc;
 
 	int referenced;
+	int show;
 	u32 num_reorder_pic;
 
 	u32 cur_slice_idx;
@@ -448,9 +449,11 @@ static void codec_hevc_update_referenced(struct codec_hevc *hevc)
 			       ((1 << (RPS_USED_BIT - 1)) - 1);
 			if (param->p.CUR_RPS[i] & (1 << (RPS_USED_BIT - 1))) {
 				poc_tmp = curr_poc -
-					  ((1 << (RPS_USED_BIT - 1)) - delt);
-			} else
+				      ((1 << (RPS_USED_BIT - 1)) - delt);
+			} else {
 				poc_tmp = curr_poc + delt;
+			}
+
 			if (poc_tmp == frame->poc) {
 				is_referenced = 1;
 				break;
@@ -462,13 +465,13 @@ static void codec_hevc_update_referenced(struct codec_hevc *hevc)
 }
 
 static struct hevc_frame *
-codec_hevc_get_lowest_poc_frame(struct codec_hevc *hevc)
+codec_hevc_get_next_ready_frame(struct codec_hevc *hevc)
 {
 	struct hevc_frame *tmp, *ret = NULL;
 	u32 poc = INT_MAX;
 
 	list_for_each_entry(tmp, &hevc->ref_frames_list, list) {
-		if (tmp->poc < poc) {
+		if ((tmp->poc < poc) && tmp->show) {
 			ret = tmp;
 			poc = tmp->poc;
 		}
@@ -478,28 +481,35 @@ codec_hevc_get_lowest_poc_frame(struct codec_hevc *hevc)
 }
 
 /* Try to output as many frames as possible */
-static void codec_hevc_output_frames(struct amvdec_session *sess)
+static void codec_hevc_show_frames(struct amvdec_session *sess)
 {
-	struct hevc_frame *tmp;
+	struct hevc_frame *tmp, *n;
 	struct codec_hevc *hevc = sess->priv;
 
-	while ((tmp = codec_hevc_get_lowest_poc_frame(hevc))) {
+	while ((tmp = codec_hevc_get_next_ready_frame(hevc))) {
 		if (hevc->curr_poc &&
-		    (tmp->referenced ||
-		     tmp->num_reorder_pic >= hevc->frames_num))
+		   (hevc->frames_num <= tmp->num_reorder_pic))
 			break;
 
 		dev_dbg(sess->core->dev, "DONE frame poc %u; vbuf %u\n",
 			tmp->poc, tmp->vbuf->vb2_buf.index);
 		amvdec_dst_buf_done_offset(sess, tmp->vbuf, tmp->offset,
 					   V4L2_FIELD_NONE, false);
+
+		tmp->show = 0;
+		hevc->frames_num--;
+	}
+
+	/* clean output frame buffer */
+	list_for_each_entry_safe(tmp, n, &hevc->ref_frames_list, list) {
+		if (tmp->referenced || tmp->show)
+			continue;
+
 		list_del(&tmp->list);
 		kfree(tmp);
-		hevc->frames_num--;
 	}
 }
 
-
 static int
 codec_hevc_setup_workspace(struct amvdec_session *sess,
 			   struct codec_hevc *hevc)
@@ -650,14 +660,17 @@ static int codec_hevc_start(struct amvdec_session *sess)
 static void codec_hevc_flush_output(struct amvdec_session *sess)
 {
 	struct codec_hevc *hevc = sess->priv;
-	struct hevc_frame *tmp;
+	struct hevc_frame *tmp, *n;
 
-	while (!list_empty(&hevc->ref_frames_list)) {
-		tmp = codec_hevc_get_lowest_poc_frame(hevc);
+	while ((tmp = codec_hevc_get_next_ready_frame(hevc))) {
 		amvdec_dst_buf_done(sess, tmp->vbuf, V4L2_FIELD_NONE);
+		tmp->show = 0;
+		hevc->frames_num--;
+	}
+
+	list_for_each_entry_safe(tmp, n, &hevc->ref_frames_list, list) {
 		list_del(&tmp->list);
 		kfree(tmp);
-		hevc->frames_num--;
 	}
 }
 
@@ -719,6 +732,7 @@ codec_hevc_prepare_new_frame(struct amvdec_session *sess)
 
 	new_frame->vbuf = vbuf;
 	new_frame->referenced = 1;
+	new_frame->show = 1;
 	new_frame->poc = hevc->curr_poc;
 	new_frame->cur_slice_type = params->p.slice_type;
 	new_frame->num_reorder_pic = params->p.sps_num_reorder_pics_0;
@@ -1267,7 +1281,7 @@ static int codec_hevc_process_segment(struct amvdec_session *sess)
 	/* First slice: new frame */
 	if (slice_segment_address == 0) {
 		codec_hevc_update_referenced(hevc);
-		codec_hevc_output_frames(sess);
+		codec_hevc_show_frames(sess);
 
 		hevc->cur_frame = codec_hevc_prepare_new_frame(sess);
 		if (!hevc->cur_frame)
@@ -1370,9 +1384,11 @@ static void codec_hevc_fetch_rpm(struct amvdec_session *sess)
 	u16 *rpm_vaddr = hevc->workspace_vaddr + RPM_OFFSET;
 	int i, j;
 
-	for (i = 0; i < RPM_SIZE; i += 4)
+	for (i = 0; i < RPM_SIZE; i += 4) {
 		for (j = 0; j < 4; j++)
-			hevc->rpm_param.l.data[i + j] = rpm_vaddr[i + 3 - j];
+			hevc->rpm_param.l.data[i + j] =
+				rpm_vaddr[i + 3 - j];
+	}
 }
 
 static void codec_hevc_resume(struct amvdec_session *sess)
-- 
2.35.1