1 /*
2 * Copyright 2016 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "rc_data_impl"
18
19 #include <string.h>
20
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_list.h"
24 #include "mpp_debug.h"
25 #include "mpp_common.h"
26
27 #include "rc_data.h"
28 #include "rc_data_impl.h"
29
30 #define RC_LIST_HEAD 1
31 #define RC_LIST_TAIL 0
32
33 #define RC_FRM_TYPE_I 0
34 #define RC_FRM_TYPE_P 1
35
36 #define RC_FRM_STATUS_VALID (0x00000001)
37 #define RC_HAL_SET_VALID (0x00000002)
38 #define RC_HAL_RET_VALID (0x00000004)
39
rc_data_indexes_init(RcDataIndexes * sort)40 static void rc_data_indexes_init(RcDataIndexes *sort)
41 {
42 RK_S32 i;
43
44 memset(sort, 0, sizeof(*sort));
45
46 INIT_LIST_HEAD(&sort->seq);
47
48 for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->type); i++)
49 INIT_LIST_HEAD(&sort->type[i]);
50
51 for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->tid); i++)
52 INIT_LIST_HEAD(&sort->tid[i]);
53
54 for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->status); i++)
55 INIT_LIST_HEAD(&sort->status[i]);
56 }
57
rc_data_node_init(DataGroupImpl * p,RcDataNode * node,RK_S32 slot_idx)58 static void rc_data_node_init(DataGroupImpl *p, RcDataNode *node, RK_S32 slot_idx)
59 {
60 RcDataIndexes *indexes = &p->indexes;
61 RcDataStatus status = RC_DATA_ST_UNUSED;
62 RcDataHead *head = &node->head;
63 RcDataBase *base = &node->base;
64
65 memset(node, 0, sizeof(*node));
66
67 head->node = node;
68 head->slot_id = slot_idx;
69
70 INIT_LIST_HEAD(&head->seq);
71 INIT_LIST_HEAD(&head->type);
72 INIT_LIST_HEAD(&head->tid);
73 INIT_LIST_HEAD(&head->status);
74 list_add_tail(&head->status, &indexes->status[status]);
75 indexes->status_cnt[status]++;
76
77 base->head = head;
78
79 node->extra = NULL;
80 }
81
rc_data_group_init(DataGroupImpl * p,RK_S32 base_cnt,RK_S32 extra_cnt)82 MPP_RET rc_data_group_init(DataGroupImpl *p, RK_S32 base_cnt, RK_S32 extra_cnt)
83 {
84 p->lock = new Mutex();
85
86 node_group_init(&p->node, sizeof(RcDataNode), base_cnt);
87 node_group_init(&p->extra, sizeof(RcDataExtra), extra_cnt);
88
89 mpp_assert(p->lock);
90 mpp_assert(p->node);
91 mpp_assert(p->extra);
92
93 p->base_cnt = base_cnt;
94 p->extra_cnt = extra_cnt;
95
96 rc_data_group_reset(p);
97
98 return MPP_OK;
99 }
100
rc_data_group_deinit(DataGroupImpl * p)101 MPP_RET rc_data_group_deinit(DataGroupImpl *p)
102 {
103 mpp_assert(p->lock);
104 mpp_assert(p->node);
105 mpp_assert(p->extra);
106
107 node_group_deinit(p->node);
108 node_group_deinit(p->extra);
109
110 delete p->lock;
111
112 return MPP_OK;
113 }
114
rc_data_group_reset(DataGroupImpl * p)115 MPP_RET rc_data_group_reset(DataGroupImpl *p)
116 {
117 RK_S32 i;
118
119 rc_data_indexes_init(&p->indexes);
120
121 for (i = 0; i < p->base_cnt; i++) {
122 RcDataNode *node = (RcDataNode *)node_group_get(p->node, i);
123
124 rc_data_node_init(p, node, i);
125 }
126
127 for (i = 0; i < p->extra_cnt; i++) {
128 RcDataExtra *extra = (RcDataExtra *)node_group_get(p->extra, i);
129
130 /* NOTE: node in head is NULL */
131 memset(extra, 0, sizeof(*extra));
132 }
133
134 return MPP_OK;
135 }
136
rc_data_group_get_node_by_seq_id(DataGroupImpl * p,RK_S32 seq_id)137 RcDataNode *rc_data_group_get_node_by_seq_id(DataGroupImpl *p, RK_S32 seq_id)
138 {
139 RcDataIndexes *indexes = &p->indexes;
140
141 if (list_empty(&indexes->seq))
142 return NULL;
143
144 RcDataNode *node = NULL;
145 RcDataHead *pos;
146
147 if (MPP_ABS(seq_id - indexes->seq_new) < MPP_ABS(seq_id - indexes->seq_old)) {
148 list_for_each_entry(pos, &indexes->seq, RcDataHead, seq) {
149 if (pos->seq_id == seq_id) {
150 node = pos->node;
151 break;
152 }
153 }
154 } else {
155 list_for_each_entry_reverse(pos, &indexes->seq, RcDataHead, seq) {
156 if (pos->seq_id == seq_id) {
157 node = pos->node;
158 break;
159 }
160 }
161 }
162
163 return node;
164 }
165
rc_data_group_get_node_by_status(DataGroupImpl * p,RcDataStatus status,RK_S32 whence)166 RcDataNode *rc_data_group_get_node_by_status(DataGroupImpl *p, RcDataStatus status, RK_S32 whence)
167 {
168 RcDataIndexes *indexes = &p->indexes;
169
170 mpp_assert(status >= RC_DATA_ST_UNUSED && status <= RC_DATA_ST_DONE);
171
172 struct list_head *list = &indexes->status[status];
173
174 if (list_empty(list))
175 return NULL;
176
177 list = (whence == RC_LIST_HEAD) ? (list->next) : (list->prev);
178 RcDataHead *head = list_entry(list, RcDataHead, status);
179 mpp_assert(head->data_status == status);
180 mpp_assert(head->node);
181 return head->node;
182 }
183
rc_data_group_put_node(DataGroupImpl * p,RcDataNode * node)184 void rc_data_group_put_node(DataGroupImpl *p, RcDataNode *node)
185 {
186 RcDataIndexes *indexes = &p->indexes;
187 RcDataHead *head = &node->head;
188
189 AutoMutex auto_lock(p->lock);
190 RcDataStatus data_status = head->data_status;
191
192 list_del_init(&head->status);
193 indexes->status_cnt[data_status]--;
194
195 if (data_status == RC_DATA_ST_FILLING) {
196 // ready on filling add to indexing list by property
197 EncFrmStatus frm_status = head->frm_status;
198 RK_S32 type_id = frm_status.is_intra ? RC_FRM_TYPE_I : RC_FRM_TYPE_P;
199 RK_S32 tid = frm_status.temporal_id;
200
201 mpp_assert(list_empty(&head->seq));
202 list_add_tail(&head->seq, &indexes->seq);
203 indexes->seq_cnt++;
204 indexes->seq_new = head->seq_id;
205
206 mpp_assert(list_empty(&head->type));
207 list_add_tail(&head->type, &indexes->type[type_id]);
208 indexes->type_cnt[type_id]++;
209
210 mpp_assert(tid < 4);
211 mpp_assert(list_empty(&head->tid));
212 list_add_tail(&head->tid, &indexes->tid[type_id]);
213 indexes->tid_cnt[type_id]++;
214 }
215
216 // goto next status
217 switch (data_status) {
218 case RC_DATA_ST_UNUSED : {
219 data_status = RC_DATA_ST_FILLING;
220 } break;
221 case RC_DATA_ST_FILLING : {
222 data_status = RC_DATA_ST_DONE;
223 } break;
224 case RC_DATA_ST_DONE : {
225 data_status = RC_DATA_ST_UNUSED;
226 } break;
227 default : {
228 data_status = RC_DATA_ST_BUTT;
229 mpp_assert(data_status != RC_DATA_ST_BUTT);
230 } break;
231 }
232
233 if (data_status == RC_DATA_ST_UNUSED) {
234 // removed from indexing list
235 EncFrmStatus frm_status = head->frm_status;
236
237 if (!list_empty(&head->seq)) {
238 list_del_init(&head->seq);
239 indexes->seq_cnt--;
240 indexes->seq_old = head->seq_id;
241 }
242
243 if (!list_empty(&head->type)) {
244 RK_S32 type_id = frm_status.is_intra ? RC_FRM_TYPE_I : RC_FRM_TYPE_P;
245
246 list_del_init(&head->type);
247 indexes->type_cnt[type_id]--;
248 }
249
250 if (!list_empty(&head->tid)) {
251 RK_S32 tid = frm_status.temporal_id;
252
253 mpp_assert(tid < 4);
254 list_del_init(&head->tid);
255 indexes->tid_cnt[tid]--;
256 }
257 }
258
259 list_add_tail(&head->status, &indexes->status[data_status]);
260 indexes->status_cnt[data_status]++;
261 head->data_status = data_status;
262 }
263
rc_data_get_next(DataGroup grp)264 RcData rc_data_get_next(DataGroup grp)
265 {
266 DataGroupImpl *p = (DataGroupImpl *)grp;
267 RcDataNode *node = rc_data_group_get_node_by_status(
268 p, RC_DATA_ST_UNUSED, RC_LIST_HEAD);
269
270 return (RcData)node;
271 }
272
rc_data_get_curr_latest(DataGroup grp)273 RcData rc_data_get_curr_latest(DataGroup grp)
274 {
275 DataGroupImpl *p = (DataGroupImpl *)grp;
276 RcDataNode *node = rc_data_group_get_node_by_status(
277 p, RC_DATA_ST_FILLING, RC_LIST_TAIL);
278
279 return (RcData)node;
280 }
281
rc_data_get_curr_oldest(DataGroup grp)282 RcData rc_data_get_curr_oldest(DataGroup grp)
283 {
284 DataGroupImpl *p = (DataGroupImpl *)grp;
285 RcDataNode *node = rc_data_group_get_node_by_status(
286 p, RC_DATA_ST_FILLING, RC_LIST_HEAD);
287
288 return (RcData)node;
289 }
290
rc_data_get_last_latest(DataGroup grp)291 RcData rc_data_get_last_latest(DataGroup grp)
292 {
293 DataGroupImpl *p = (DataGroupImpl *)grp;
294 RcDataNode *node = rc_data_group_get_node_by_status(
295 p, RC_DATA_ST_DONE, RC_LIST_TAIL);
296
297 return (RcData)node;
298 }
299
rc_data_get_last_oldest(DataGroup grp)300 RcData rc_data_get_last_oldest(DataGroup grp)
301 {
302 DataGroupImpl *p = (DataGroupImpl *)grp;
303 RcDataNode *node = rc_data_group_get_node_by_status(
304 p, RC_DATA_ST_DONE, RC_LIST_HEAD);
305
306 return (RcData)node;
307 }
308