1 /*
2 * Copyright 2021 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 "avs2d_api"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "mpp_mem.h"
24 #include "mpp_log.h"
25 #include "mpp_debug.h"
26 #include "mpp_env.h"
27 #include "mpp_packet_impl.h"
28 #include "mpp_buffer_impl.h"
29
30 #include "avs2d_syntax.h"
31 #include "avs2d_api.h"
32 #include "avs2d_parse.h"
33 #include "avs2d_dpb.h"
34 #include "mpp_dec_cb_param.h"
35
36 RK_U32 avs2d_parse_debug = 0;
37
avs2d_deinit(void * decoder)38 MPP_RET avs2d_deinit(void *decoder)
39 {
40 MPP_RET ret = MPP_OK;
41 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
42
43 INP_CHECK(ret, !decoder);
44 AVS2D_PARSE_TRACE("In.");
45
46 MPP_FREE(p_dec->p_stream->pbuf);
47 MPP_FREE(p_dec->p_header->pbuf);
48 MPP_FREE(p_dec->mem);
49 MPP_FREE(p_dec->p_nals);
50 mpp_packet_deinit(&p_dec->task_pkt);
51 avs2d_dpb_destroy(p_dec);
52
53 __RETURN:
54 AVS2D_PARSE_TRACE("Out.");
55 return ret;
56 }
57
avs2d_init(void * decoder,ParserCfg * init)58 MPP_RET avs2d_init(void *decoder, ParserCfg *init)
59 {
60 MPP_RET ret = MPP_OK;
61 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
62
63 AVS2D_PARSE_TRACE("In.");
64 INP_CHECK(ret, !p_dec);
65
66 memset(p_dec, 0, sizeof(Avs2dCtx_t));
67 mpp_env_get_u32("avs2d_debug", &avs2d_parse_debug, 0);
68 //!< restore init parameters
69 p_dec->init = *init;
70 // p_dec->init.cfg->base.split_parse = 1;
71 p_dec->frame_slots = init->frame_slots;
72 p_dec->packet_slots = init->packet_slots;
73 //!< decoder parameters
74 mpp_buf_slot_setup(p_dec->frame_slots, AVS2_MAX_BUF_NUM);
75
76 p_dec->mem = mpp_calloc(Avs2dMemory_t, 1);
77 MEM_CHECK(ret, p_dec->mem);
78 p_dec->p_header = &p_dec->mem->headerbuf;
79 p_dec->p_header->size = MAX_HEADER_SIZE;
80 p_dec->p_header->pbuf = mpp_calloc(RK_U8, p_dec->p_header->size);
81 MEM_CHECK(ret, p_dec->p_header->pbuf);
82
83 p_dec->p_stream = &p_dec->mem->streambuf;
84 p_dec->p_stream->size = MAX_STREAM_SIZE;
85 p_dec->p_stream->pbuf = mpp_calloc(RK_U8, p_dec->p_stream->size);
86 MEM_CHECK(ret, p_dec->p_stream->pbuf);
87
88 p_dec->p_nals = mpp_calloc(Avs2dNalu_t, MAX_NALU_NUM);
89 MEM_CHECK(ret, p_dec->p_nals);
90 p_dec->nal_allocated = MAX_NALU_NUM;
91 p_dec->nal_cnt = 0;
92
93 mpp_packet_init(&p_dec->task_pkt, p_dec->p_stream->pbuf, p_dec->p_stream->size);
94 mpp_packet_set_length(p_dec->task_pkt, 0);
95 MEM_CHECK(ret, p_dec->task_pkt);
96
97 __RETURN:
98 AVS2D_PARSE_TRACE("Out.");
99 return ret;
100 __FAILED:
101 avs2d_deinit(decoder);
102
103 return ret;
104 }
105
avs2d_reset(void * decoder)106 MPP_RET avs2d_reset(void *decoder)
107 {
108 MPP_RET ret = MPP_OK;
109 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
110
111 AVS2D_PARSE_TRACE("In.");
112
113 //!< flush dpb
114 avs2d_dpb_flush(p_dec);
115
116 //!< reset parser parameters
117 avs2d_reset_parser(p_dec);
118
119 //!< reset decoder parameters
120 p_dec->pkt_no = 0;
121 p_dec->frame_no = 0;
122 p_dec->has_get_eos = 0;
123
124 AVS2D_PARSE_TRACE("Out.");
125 return ret;
126 }
127
avs2d_flush(void * decoder)128 MPP_RET avs2d_flush(void *decoder)
129 {
130 MPP_RET ret = MPP_OK;
131 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
132 AVS2D_PARSE_TRACE("In.");
133
134 dpb_remove_unused_frame(p_dec);
135
136 AVS2D_PARSE_TRACE("Out.");
137 return ret;
138 }
139
avs2d_control(void * decoder,MpiCmd cmd_type,void * param)140 MPP_RET avs2d_control(void *decoder, MpiCmd cmd_type, void *param)
141 {
142 MPP_RET ret = MPP_OK;
143
144 AVS2D_PARSE_TRACE("In.");
145 (void)decoder;
146 (void)cmd_type;
147 (void)param;
148 AVS2D_PARSE_TRACE("Out.");
149 return ret;
150 }
151
152
avs2d_prepare(void * decoder,MppPacket pkt,HalDecTask * task)153 MPP_RET avs2d_prepare(void *decoder, MppPacket pkt, HalDecTask *task)
154 {
155 MPP_RET ret = MPP_OK;
156 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
157 RK_S64 pts = -1;
158 RK_S64 dts = -1;
159 RK_U32 length = 0;
160 RK_U32 pkt_eos = 0;
161
162 AVS2D_PARSE_TRACE("In.");
163 INP_CHECK(ret, !decoder && !pkt && !task);
164
165 task->valid = 0;
166
167 pkt_eos = mpp_packet_get_eos(pkt);
168
169 pts = mpp_packet_get_pts(pkt);
170 dts = mpp_packet_get_dts(pkt);
171 length = (RK_U32)mpp_packet_get_length(pkt);
172
173 AVS2D_DBG(AVS2D_DBG_INPUT, "[pkt_in_timeUs] in_pts=%lld, dts=%lld, len=%d, eos=%d, pkt_no=%lld\n",
174 pts, dts, length, pkt_eos, p_dec->pkt_no);
175 p_dec->pkt_no++;
176
177 AVS2D_DBG(AVS2D_DBG_INPUT, "packet length %d, eos %d\n", length, pkt_eos);
178
179 if (pkt_eos) {
180 p_dec->has_get_eos = 1;
181 task->flags.eos = 1;
182 }
183
184 if (!length) {
185 AVS2D_PARSE_TRACE("Input have no stream.");
186 task->valid = 0;
187
188 if (pkt_eos)
189 avs2d_dpb_flush(p_dec);
190
191 goto __RETURN;
192 }
193
194 if (!p_dec->init.cfg->base.split_parse) {
195 ret = avs2d_parse_prepare_fast(p_dec, pkt, task);
196 } else {
197 ret = avs2d_parse_prepare_split(p_dec, pkt, task);
198 }
199
200 if (task->valid) {
201 //!< bit stream
202 RK_U32 align_len = MPP_ALIGN(p_dec->p_stream->len + 32, 16);
203
204 mpp_assert(p_dec->p_stream->size > align_len);
205 memset(p_dec->p_stream->pbuf + p_dec->p_stream->len,
206 0, align_len - p_dec->p_stream->len);
207
208 p_dec->syntax.bitstream_size = align_len;
209 p_dec->syntax.bitstream = p_dec->p_stream->pbuf;
210
211 mpp_packet_set_data(p_dec->task_pkt, p_dec->syntax.bitstream);
212 mpp_packet_set_length(p_dec->task_pkt, p_dec->syntax.bitstream_size);
213 mpp_packet_set_size(p_dec->task_pkt, p_dec->p_stream->size);
214
215 mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt));
216 mpp_packet_set_dts(p_dec->task_pkt, mpp_packet_get_dts(pkt));
217 task->input_packet = p_dec->task_pkt;
218
219 p_dec->p_stream->len = 0;
220 p_dec->p_header->len = 0;
221 } else {
222 task->input_packet = NULL;
223 }
224
225 __RETURN:
226 AVS2D_PARSE_TRACE("Out.");
227 return ret;
228 }
229
avs2d_parse(void * decoder,HalDecTask * task)230 MPP_RET avs2d_parse(void *decoder, HalDecTask *task)
231 {
232 MPP_RET ret = MPP_OK;
233 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
234 AVS2D_PARSE_TRACE("In.");
235
236 task->valid = 0;
237
238 ret = avs2d_parse_stream(p_dec, task);
239 if (ret) {
240 mpp_err_f("Parse stream failed!");
241 }
242 if (task->valid) {
243 AVS2D_PARSE_TRACE("-------- Frame %lld--------", p_dec->frame_no);
244 avs2d_dpb_insert(p_dec, task);
245 avs2d_fill_parameters(p_dec, &p_dec->syntax);
246 avs2d_commit_syntaxs(&p_dec->syntax, task);
247 AVS2D_PARSE_TRACE("--------------------------");
248 } else {
249 task->flags.parse_err = 1;
250 }
251
252 if (p_dec->has_get_eos)
253 avs2d_dpb_flush(p_dec);
254
255 AVS2D_PARSE_TRACE("Out.");
256
257 return ret;
258 }
259
avs2d_callback(void * decoder,void * info)260 MPP_RET avs2d_callback(void *decoder, void *info)
261 {
262 MPP_RET ret = MPP_ERR_UNKNOW;
263 Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder;
264 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
265 DecCbHalDone *ctx = (DecCbHalDone *)info;
266 HalDecTask *task_dec = (HalDecTask *)ctx->task;
267 MppFrame mframe = NULL;
268 MppFrame ref_frm = NULL;
269 RK_U32 i = 0;
270 RK_U32 error = 0;
271 RK_U32 discard = 0;
272 RK_U32 ref_used_flag = 0;
273
274 AVS2D_PARSE_TRACE("In.");
275 mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe);
276
277 if (!mframe) {
278 ret = MPP_ERR_UNKNOW;
279 AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: failed to get frame\n");
280 goto __FAILED;
281 }
282
283 if (ctx->hard_err || task_dec->flags.ref_err) {
284 if (task_dec->flags.used_for_ref) {
285 error = 1;
286 } else {
287 discard = 1;
288 }
289 } else {
290 if (task_dec->flags.ref_miss & task_dec->flags.ref_used) {
291 discard = 1;
292 AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: fake ref used, miss 0x%x used 0x%x\n",
293 task_dec->flags.ref_miss, task_dec->flags.ref_used);
294 }
295 }
296
297 for (i = 0; i < AVS2_MAX_REFS; i++) {
298 if (!mgr->refs[i] || !mgr->refs[i]->frame || mgr->refs[i]->slot_idx < 0)
299 continue;
300
301 mpp_buf_slot_get_prop(p_dec->frame_slots, mgr->refs[i]->slot_idx, SLOT_FRAME_PTR, &ref_frm);
302 if (!ref_frm)
303 continue;
304
305 ref_used_flag = (task_dec->flags.ref_used >> i) & 1;
306 //TODO: In fast mode, ref list isn't kept sync with task flag.ref_used
307 AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: ref_frm poc %d, err %d, dis %d, ref_used %d\n",
308 mpp_frame_get_poc(ref_frm), mpp_frame_get_errinfo(ref_frm),
309 mpp_frame_get_discard(ref_frm), ref_used_flag);
310
311 if (ref_used_flag) {
312 discard |= mpp_frame_get_discard(ref_frm);
313 error |= mpp_frame_get_errinfo(ref_frm);
314 }
315 }
316
317 mpp_frame_set_errinfo(mframe, error);
318 mpp_frame_set_discard(mframe, discard);
319
320 AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: frame poc %d, ref=%d, dpberr=%d, harderr=%d, err:dis=%d:%d\n",
321 mpp_frame_get_poc(mframe), task_dec->flags.used_for_ref, task_dec->flags.ref_err,
322 ctx->hard_err, error, discard);
323
324 __FAILED:
325 AVS2D_PARSE_TRACE("Out.");
326 return ret;
327 }
328
329 const ParserApi api_avs2d_parser = {
330 .name = "avs2d_parse",
331 .coding = MPP_VIDEO_CodingAVS2,
332 .ctx_size = sizeof(Avs2dCtx_t),
333 .flag = 0,
334 .init = avs2d_init,
335 .deinit = avs2d_deinit,
336 .prepare = avs2d_prepare,
337 .parse = avs2d_parse,
338 .reset = avs2d_reset,
339 .flush = avs2d_flush,
340 .control = avs2d_control,
341 .callback = avs2d_callback,
342 };
343