xref: /rockchip-linux_mpp/mpp/codec/dec/avs/avsd_api.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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     case MPP_DEC_SET_DIS_ERR_CLR_MARK: {
186         p_dec->dis_err_clr_mark = *((RK_U32 *)param);
187     } break;
188     default : {
189     } break;
190     }
191 
192     AVSD_PARSE_TRACE("Out.");
193     return ret = MPP_OK;
194 }
195 
196 
197 /*!
198 ***********************************************************************
199 * \brief
200 *   prepare
201 ***********************************************************************
202 */
avsd_prepare(void * decoder,MppPacket pkt,HalDecTask * task)203 static MPP_RET avsd_prepare(void *decoder, MppPacket pkt, HalDecTask *task)
204 {
205     MPP_RET ret = MPP_ERR_UNKNOW;
206 
207     AVSD_PARSE_TRACE("In.");
208     INP_CHECK(ret, !decoder && !pkt && !task);
209 
210     AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
211     RK_U8 *pos = mpp_packet_get_pos(pkt);
212     size_t length = mpp_packet_get_length(pkt);
213     RK_U32 eos = mpp_packet_get_eos(pkt);
214 
215     task->valid = 0;
216     if (p_dec->got_eos) {
217         AVSD_DBG(AVSD_DBG_INPUT, "got eos packet.\n");
218         mpp_packet_set_length(pkt, 0);
219         goto __RETURN;
220     }
221     AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] pts=%lld, eos=%d, len=%d, pkt_no=%d\n",
222              mpp_packet_get_pts(pkt), eos, (RK_U32)length, (RK_U32)p_dec->pkt_no);
223     p_dec->pkt_no++;
224 
225     if (mpp_packet_get_eos(pkt)) {
226         if (mpp_packet_get_length(pkt) < 4) {
227             avsd_flush(decoder);
228         }
229         p_dec->got_eos = 1;
230         task->flags.eos = p_dec->got_eos;
231         goto __RETURN;
232     }
233     if (mpp_packet_get_length(pkt) > MAX_STREAM_SIZE) {
234         AVSD_DBG(AVSD_DBG_ERROR, "[pkt_in_timeUs] input error, stream too large");
235         mpp_packet_set_length(pkt, 0);
236         ret = MPP_NOK;
237         goto __RETURN;
238     }
239 
240     mpp_packet_set_length(p_dec->task_pkt, p_dec->left_length);
241 
242     RK_U32 total_length = MPP_ALIGN(p_dec->left_length + length, 16) + 64;
243     if (total_length > p_dec->stream_size) {
244         do {
245             p_dec->stream_size <<= 1;
246         } while (total_length > p_dec->stream_size);
247 
248         RK_U8 *dst = mpp_malloc_size(RK_U8, p_dec->stream_size);
249         mpp_assert(dst);
250 
251         if (p_dec->left_length > 0) {
252             memcpy(dst, p_dec->streambuf, p_dec->left_length);
253         }
254         mpp_free(p_dec->streambuf);
255         p_dec->streambuf = dst;
256 
257         mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
258         mpp_packet_set_size(p_dec->task_pkt, p_dec->stream_size);
259     }
260 
261     if (!p_dec->need_split) {
262         p_dec->got_eos = eos;
263         // empty eos packet
264         if (eos && (length < 4)) {
265             avsd_flush(decoder);
266             goto __RETURN;
267         }
268         // copy packet direct
269         memcpy(p_dec->streambuf, pos, length);
270         mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
271         mpp_packet_set_length(p_dec->task_pkt, length);
272         mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt));
273         mpp_packet_set_dts(p_dec->task_pkt, mpp_packet_get_dts(pkt));
274         // set input packet length to 0 here
275         mpp_packet_set_length(pkt, 0);
276         /* this step will enable the task and goto parse stage */
277         task->valid = 1;
278     } else {
279         /* Split packet mode */
280         if (MPP_OK == avsd_parser_split(p_dec, p_dec->task_pkt, pkt)) {
281             p_dec->left_length = 0;
282             task->valid = 1;
283         } else {
284             task->valid = 0;
285             p_dec->left_length = mpp_packet_get_length(p_dec->task_pkt);
286         }
287         p_dec->got_eos = mpp_packet_get_eos(p_dec->task_pkt);
288     }
289     task->input_packet = p_dec->task_pkt;
290     task->flags.eos = p_dec->got_eos;
291 
292 __RETURN:
293     AVSD_PARSE_TRACE("Out.");
294     return ret = MPP_OK;
295 }
296 /*!
297 ***********************************************************************
298 * \brief
299 *   parser
300 ***********************************************************************
301 */
avsd_parse(void * decoder,HalDecTask * task)302 static MPP_RET avsd_parse(void *decoder, HalDecTask *task)
303 {
304     MPP_RET ret = MPP_ERR_UNKNOW;
305     AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
306     AVSD_PARSE_TRACE("In.");
307 
308     task->valid = 0;
309     memset(task->refer, -1, sizeof(task->refer));
310 
311     avsd_parse_stream(p_dec, task);
312     if (task->valid) {
313         avsd_fill_parameters(p_dec, p_dec->syn);
314         avsd_set_dpb(p_dec, task);
315 
316         avsd_commit_syntaxs(p_dec->syn, task);
317         avsd_update_dpb(p_dec);
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     MppFrame mframe = NULL;
335     HalDecTask *task_dec = (HalDecTask *)ctx->task;
336 
337     AVSD_PARSE_TRACE("In.");
338 
339     mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe);
340     if (mframe) {
341         if (ctx->hard_err || task_dec->flags.ref_err) {
342             if (task_dec->flags.used_for_ref) {
343                 mpp_frame_set_errinfo(mframe, MPP_FRAME_FLAG_PAIRED_FIELD);
344             } else {
345                 mpp_frame_set_discard(mframe, MPP_FRAME_FLAG_PAIRED_FIELD);
346             }
347         }
348     }
349 
350     if (!ctx->hard_err && p_dec->ph.picture_coding_type == I_PICTURE)
351         p_dec->vsh.version_checked = 1;
352 
353     AVSD_PARSE_TRACE("Out.");
354 
355     return ret = MPP_OK;
356 }
357 /*!
358 ***********************************************************************
359 * \brief
360 *   api struct interface
361 ***********************************************************************
362 */
363 const ParserApi api_avsd_parser = {
364     .name = "avsd_parse",
365     .coding = MPP_VIDEO_CodingAVS,
366     .ctx_size = sizeof(AvsdCtx_t),
367     .flag = 0,
368     .init = avsd_init,
369     .deinit = avsd_deinit,
370     .prepare = avsd_prepare,
371     .parse = avsd_parse,
372     .reset = avsd_reset,
373     .flush = avsd_flush,
374     .control = avsd_control,
375     .callback = avsd_callback,
376 };
377 
378 const ParserApi api_avsd_plus_parser = {
379     .name = "avsd_parse",
380     .coding = MPP_VIDEO_CodingAVSPLUS,
381     .ctx_size = sizeof(AvsdCtx_t),
382     .flag = 0,
383     .init = avsd_init,
384     .deinit = avsd_deinit,
385     .prepare = avsd_prepare,
386     .parse = avsd_parse,
387     .reset = avsd_reset,
388     .flush = avsd_flush,
389     .control = avsd_control,
390     .callback = avsd_callback,
391 };
392