xref: /OK3568_Linux_fs/external/mpp/mpp/codec/dec/avs/avsd_api.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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