1 /*
2 * Copyright 2015 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 "avsd_api"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "mpp_env.h"
24 #include "mpp_mem.h"
25 #include "mpp_debug.h"
26 #include "mpp_packet_impl.h"
27
28 #include "avsd_syntax.h"
29 #include "avsd_api.h"
30 #include "avsd_parse.h"
31 #include "mpp_dec_cb_param.h"
32
33 RK_U32 avsd_parse_debug = 0;
34
35
36 /*!
37 ***********************************************************************
38 * \brief
39 * free all buffer
40 ***********************************************************************
41 */
avsd_deinit(void * decoder)42 MPP_RET avsd_deinit(void *decoder)
43 {
44 MPP_RET ret = MPP_ERR_UNKNOW;
45 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
46
47 INP_CHECK(ret, !decoder);
48 AVSD_PARSE_TRACE("In.");
49
50 mpp_packet_deinit(&p_dec->task_pkt);
51 MPP_FREE(p_dec->streambuf);
52 MPP_FREE(p_dec->mem);
53
54 __RETURN:
55 (void)decoder;
56 AVSD_PARSE_TRACE("Out.");
57 return ret = MPP_OK;
58 }
59
60 /*!
61 ***********************************************************************
62 * \brief
63 * alloc all buffer
64 ***********************************************************************
65 */
66
avsd_init(void * decoder,ParserCfg * init)67 static MPP_RET avsd_init(void *decoder, ParserCfg *init)
68 {
69 MPP_RET ret = MPP_ERR_UNKNOW;
70 RK_S32 i = 0;
71 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
72
73 AVSD_PARSE_TRACE("In.");
74 INP_CHECK(ret, !p_dec);
75
76 memset(p_dec, 0, sizeof(AvsdCtx_t));
77 mpp_env_get_u32("avsd_debug", &avsd_parse_debug, 0);
78 //!< restore init parameters
79 p_dec->init = *init;
80 p_dec->frame_slots = init->frame_slots;
81 p_dec->packet_slots = init->packet_slots;
82 //!< decoder parameters
83 mpp_buf_slot_setup(p_dec->frame_slots, 12);
84 p_dec->mem = mpp_calloc(AvsdMemory_t, 1);
85 MEM_CHECK(ret, p_dec->mem);
86
87 p_dec->syn = &p_dec->mem->syntax;
88 p_dec->stream_size = MAX_STREAM_SIZE;
89 p_dec->streambuf = mpp_malloc(RK_U8, p_dec->stream_size);
90 MEM_CHECK(ret, p_dec->streambuf);
91 mpp_packet_init(&p_dec->task_pkt, p_dec->streambuf, p_dec->stream_size);
92
93 mpp_packet_set_length(p_dec->task_pkt, 0);
94 MEM_CHECK(ret, p_dec->task_pkt);
95 for (i = 0; i < 3; i++) {
96 AvsdFrame_t *frm = &p_dec->mem->save[i];
97
98 memset(frm, 0, sizeof(*frm));
99 frm->idx = i;
100 frm->slot_idx = -1;
101 }
102 p_dec->bx = &p_dec->mem->bitctx;
103 p_dec->need_split = 1;
104
105 __RETURN:
106 AVSD_PARSE_TRACE("Out.");
107 return ret = MPP_OK;
108 __FAILED:
109 avsd_deinit(decoder);
110
111 return ret;
112 }
113
114 /*!
115 ***********************************************************************
116 * \brief
117 * reset
118 ***********************************************************************
119 */
avsd_reset(void * decoder)120 static MPP_RET avsd_reset(void *decoder)
121 {
122 MPP_RET ret = MPP_ERR_UNKNOW;
123 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
124
125 AVSD_PARSE_TRACE("In.");
126
127 avsd_reset_parameters(p_dec);
128 p_dec->got_vsh = 0;
129 p_dec->got_ph = 0;
130 p_dec->got_keyframe = 0;
131 p_dec->vec_flag = 0;
132 p_dec->got_eos = 0;
133 p_dec->left_length = 0;
134 p_dec->state = 0xFFFFFFFF;
135 p_dec->vop_header_found = 0;
136
137 mpp_packet_set_length(p_dec->task_pkt, 0);
138 mpp_packet_set_flag(p_dec->task_pkt, 0);
139
140 AVSD_PARSE_TRACE("Out.");
141
142 return ret = MPP_OK;
143 }
144
145 /*!
146 ***********************************************************************
147 * \brief
148 * flush
149 ***********************************************************************
150 */
avsd_flush(void * decoder)151 static MPP_RET avsd_flush(void *decoder)
152 {
153 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
154
155 AVSD_PARSE_TRACE("In.");
156
157 set_frame_output(p_dec, p_dec->dpb[1]);
158 set_frame_output(p_dec, p_dec->dpb[0]);
159 set_frame_output(p_dec, p_dec->cur);
160
161 p_dec->got_eos = 0;
162
163 AVSD_PARSE_TRACE("Out.");
164
165 return MPP_OK;
166 }
167
168 /*!
169 ***********************************************************************
170 * \brief
171 * control/perform
172 ***********************************************************************
173 */
avsd_control(void * decoder,MpiCmd cmd_type,void * param)174 static MPP_RET avsd_control(void *decoder, MpiCmd cmd_type, void *param)
175 {
176 MPP_RET ret = MPP_ERR_UNKNOW;
177 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
178
179 AVSD_PARSE_TRACE("In.");
180
181 switch (cmd_type) {
182 case MPP_DEC_SET_DISABLE_ERROR: {
183 p_dec->disable_error = *((RK_U32 *)param);
184 } break;
185 default : {
186 } break;
187 }
188
189 AVSD_PARSE_TRACE("Out.");
190 return ret = MPP_OK;
191 }
192
193
194 /*!
195 ***********************************************************************
196 * \brief
197 * prepare
198 ***********************************************************************
199 */
avsd_prepare(void * decoder,MppPacket pkt,HalDecTask * task)200 static MPP_RET avsd_prepare(void *decoder, MppPacket pkt, HalDecTask *task)
201 {
202 MPP_RET ret = MPP_ERR_UNKNOW;
203
204 AVSD_PARSE_TRACE("In.");
205 INP_CHECK(ret, !decoder && !pkt && !task);
206
207 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
208 RK_U8 *pos = mpp_packet_get_pos(pkt);
209 size_t length = mpp_packet_get_length(pkt);
210 RK_U32 eos = mpp_packet_get_eos(pkt);
211
212 task->valid = 0;
213 if (p_dec->got_eos) {
214 AVSD_DBG(AVSD_DBG_INPUT, "got eos packet.\n");
215 mpp_packet_set_length(pkt, 0);
216 goto __RETURN;
217 }
218 AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] pts=%lld, eos=%d, len=%d, pkt_no=%d\n",
219 mpp_packet_get_pts(pkt), eos, (RK_U32)length, (RK_U32)p_dec->pkt_no);
220 p_dec->pkt_no++;
221
222 if (mpp_packet_get_eos(pkt)) {
223 if (mpp_packet_get_length(pkt) < 4) {
224 avsd_flush(decoder);
225 }
226 p_dec->got_eos = 1;
227 task->flags.eos = p_dec->got_eos;
228 goto __RETURN;
229 }
230 if (mpp_packet_get_length(pkt) > MAX_STREAM_SIZE) {
231 AVSD_DBG(AVSD_DBG_ERROR, "[pkt_in_timeUs] input error, stream too large");
232 mpp_packet_set_length(pkt, 0);
233 ret = MPP_NOK;
234 goto __RETURN;
235 }
236
237 mpp_packet_set_length(p_dec->task_pkt, p_dec->left_length);
238
239 RK_U32 total_length = MPP_ALIGN(p_dec->left_length + length, 16) + 64;
240 if (total_length > p_dec->stream_size) {
241 do {
242 p_dec->stream_size <<= 1;
243 } while (total_length > p_dec->stream_size);
244
245 RK_U8 *dst = mpp_malloc_size(RK_U8, p_dec->stream_size);
246 mpp_assert(dst);
247
248 if (p_dec->left_length > 0) {
249 memcpy(dst, p_dec->streambuf, p_dec->left_length);
250 }
251 mpp_free(p_dec->streambuf);
252 p_dec->streambuf = dst;
253
254 mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
255 mpp_packet_set_size(p_dec->task_pkt, p_dec->stream_size);
256 }
257
258 if (!p_dec->need_split) {
259 p_dec->got_eos = eos;
260 // empty eos packet
261 if (eos && (length < 4)) {
262 avsd_flush(decoder);
263 goto __RETURN;
264 }
265 // copy packet direct
266 memcpy(p_dec->streambuf, pos, length);
267 mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
268 mpp_packet_set_length(p_dec->task_pkt, length);
269 mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt));
270 // set input packet length to 0 here
271 mpp_packet_set_length(pkt, 0);
272 /* this step will enable the task and goto parse stage */
273 task->valid = 1;
274 } else {
275 /* Split packet mode */
276 if (MPP_OK == avsd_parser_split(p_dec, p_dec->task_pkt, pkt)) {
277 p_dec->left_length = 0;
278 task->valid = 1;
279 } else {
280 task->valid = 0;
281 p_dec->left_length = mpp_packet_get_length(p_dec->task_pkt);
282 }
283 p_dec->got_eos = mpp_packet_get_eos(p_dec->task_pkt);
284 }
285 task->input_packet = p_dec->task_pkt;
286 task->flags.eos = p_dec->got_eos;
287
288 __RETURN:
289 AVSD_PARSE_TRACE("Out.");
290 return ret = MPP_OK;
291 }
292 /*!
293 ***********************************************************************
294 * \brief
295 * parser
296 ***********************************************************************
297 */
avsd_parse(void * decoder,HalDecTask * task)298 static MPP_RET avsd_parse(void *decoder, HalDecTask *task)
299 {
300 MPP_RET ret = MPP_ERR_UNKNOW;
301 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
302 AVSD_PARSE_TRACE("In.");
303
304 task->valid = 0;
305 memset(task->refer, -1, sizeof(task->refer));
306
307 avsd_parse_stream(p_dec, task);
308 if (task->valid) {
309 avsd_fill_parameters(p_dec, p_dec->syn);
310 avsd_set_dpb(p_dec, task);
311
312 avsd_commit_syntaxs(p_dec->syn, task);
313 avsd_update_dpb(p_dec);
314 }
315 if (p_dec->disable_error) {
316 task->flags.ref_err = 0;
317 task->flags.parse_err = 0;
318 }
319 AVSD_PARSE_TRACE("Out.");
320
321 return ret = MPP_OK;
322 }
323 /*!
324 ***********************************************************************
325 * \brief
326 * callback
327 ***********************************************************************
328 */
avsd_callback(void * decoder,void * info)329 static MPP_RET avsd_callback(void *decoder, void *info)
330 {
331 MPP_RET ret = MPP_ERR_UNKNOW;
332 AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
333 DecCbHalDone *ctx = (DecCbHalDone *)info;
334
335 AVSD_PARSE_TRACE("In.");
336 if (!p_dec->disable_error) {
337 MppFrame mframe = NULL;
338 HalDecTask *task_dec = (HalDecTask *)ctx->task;
339
340 mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe);
341 if (mframe) {
342 if (ctx->hard_err || task_dec->flags.ref_err) {
343 if (task_dec->flags.used_for_ref) {
344 mpp_frame_set_errinfo(mframe, MPP_FRAME_FLAG_PAIRED_FIELD);
345 } else {
346 mpp_frame_set_discard(mframe, MPP_FRAME_FLAG_PAIRED_FIELD);
347 }
348 }
349 }
350 }
351
352 if (!ctx->hard_err && p_dec->ph.picture_coding_type == I_PICTURE)
353 p_dec->vsh.version_checked = 1;
354
355 AVSD_PARSE_TRACE("Out.");
356
357 return ret = MPP_OK;
358 }
359 /*!
360 ***********************************************************************
361 * \brief
362 * api struct interface
363 ***********************************************************************
364 */
365 const ParserApi api_avsd_parser = {
366 .name = "avsd_parse",
367 .coding = MPP_VIDEO_CodingAVS,
368 .ctx_size = sizeof(AvsdCtx_t),
369 .flag = 0,
370 .init = avsd_init,
371 .deinit = avsd_deinit,
372 .prepare = avsd_prepare,
373 .parse = avsd_parse,
374 .reset = avsd_reset,
375 .flush = avsd_flush,
376 .control = avsd_control,
377 .callback = avsd_callback,
378 };
379
380 const ParserApi api_avsd_plus_parser = {
381 .name = "avsd_parse",
382 .coding = MPP_VIDEO_CodingAVSPLUS,
383 .ctx_size = sizeof(AvsdCtx_t),
384 .flag = 0,
385 .init = avsd_init,
386 .deinit = avsd_deinit,
387 .prepare = avsd_prepare,
388 .parse = avsd_parse,
389 .reset = avsd_reset,
390 .flush = avsd_flush,
391 .control = avsd_control,
392 .callback = avsd_callback,
393 };
394