xref: /rockchip-linux_mpp/mpp/codec/dec/mpg4/mpg4d_api.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2 *
3 * Copyright 2015 Rockchip Electronics Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 
18 #define MODULE_TAG "mpg4d_api"
19 
20 #include <string.h>
21 
22 #include "mpp_mem.h"
23 #include "mpp_debug.h"
24 #include "mpp_common.h"
25 
26 #include "mpg4d_api.h"
27 #include "mpg4d_parser.h"
28 #include "mpp_packet_impl.h"
29 #include "mpp_dec_cb_param.h"
30 
31 #define MPG4D_INIT_STREAM_SIZE      SZ_64K
32 
33 typedef struct {
34     // parameter interact with mpp_dec
35     MppBufSlots     frame_slots;
36     MppBufSlots     packet_slots;
37     RK_S32          task_count;
38     RK_U8           *stream;
39     size_t          stream_size;
40     size_t          left_length;
41     MppPacket       task_pkt;
42     RK_U32          got_eos;
43 
44     // runtime parameter
45     RK_U32          frame_count;
46     MppDecCfgSet    *dec_cfg;
47 
48     // parser context
49     Mpg4dParser     parser;
50 } Mpg4dCtx;
51 
mpg4d_init(void * dec,ParserCfg * cfg)52 static MPP_RET mpg4d_init(void *dec, ParserCfg *cfg)
53 {
54     Mpg4dParser parser = NULL;
55     MppPacket task_pkt = NULL;
56     Mpg4dCtx *p;
57     MPP_RET ret;
58     RK_U8 *stream;
59     size_t stream_size = MPG4D_INIT_STREAM_SIZE;
60 
61     if (NULL == dec) {
62         mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg);
63         return MPP_ERR_NULL_PTR;
64     }
65 
66     stream = mpp_malloc_size(RK_U8, stream_size);
67     if (NULL == stream) {
68         mpp_err_f("failed to malloc stream buffer size %d\n", stream_size);
69         return MPP_ERR_MALLOC;
70     }
71 
72     ret = mpp_packet_init(&task_pkt, stream, stream_size);
73     if (ret) {
74         mpp_err_f("failed to create mpp_packet for task\n");
75         goto ERR_RET;
76     }
77 
78     // reset task packet length to zero
79     // NOTE: set length must after set pos
80     mpp_packet_set_pos(task_pkt, stream);
81     mpp_packet_set_length(task_pkt, 0);
82 
83     ret = mpp_mpg4_parser_init(&parser, cfg);
84     if (ret) {
85         mpp_err_f("failed to init parser\n");
86         goto ERR_RET;
87     }
88 
89     p = (Mpg4dCtx *)dec;
90     p->frame_slots  = cfg->frame_slots;
91     p->packet_slots = cfg->packet_slots;
92     p->task_count   = 2;
93     p->dec_cfg      = cfg->cfg;
94     p->stream       = stream;
95     p->stream_size  = stream_size;
96     p->task_pkt     = task_pkt;
97     p->parser       = parser;
98     p->left_length  = 0;
99     return MPP_OK;
100 ERR_RET:
101     if (task_pkt) {
102         mpp_packet_deinit(&task_pkt);
103     }
104     if (stream) {
105         mpp_free(stream);
106         stream = NULL;
107     }
108     return ret;
109 }
110 
mpg4d_deinit(void * dec)111 static MPP_RET mpg4d_deinit(void *dec)
112 {
113     Mpg4dCtx *p;
114     if (NULL == dec) {
115         mpp_err_f("found NULL intput\n");
116         return MPP_ERR_NULL_PTR;
117     }
118 
119     p = (Mpg4dCtx *)dec;
120     if (p->parser) {
121         mpp_mpg4_parser_deinit(p->parser);
122         p->parser = NULL;
123     }
124 
125     if (p->task_pkt) {
126         mpp_packet_deinit(&p->task_pkt);
127     }
128 
129     if (p->stream) {
130         mpp_free(p->stream);
131         p->stream = NULL;
132     }
133     return MPP_OK;
134 }
135 
mpg4d_reset(void * dec)136 static MPP_RET mpg4d_reset(void *dec)
137 {
138     if (NULL == dec) {
139         mpp_err_f("found NULL intput\n");
140         return MPP_ERR_NULL_PTR;
141     }
142 
143     Mpg4dCtx *p = (Mpg4dCtx *)dec;
144     p->left_length  = 0;
145     p->got_eos = 0;
146     mpp_packet_set_length(p->task_pkt, 0);
147     mpp_packet_set_flag(p->task_pkt, 0);
148 
149     return mpp_mpg4_parser_reset(p->parser);
150 }
151 
mpg4d_flush(void * dec)152 static MPP_RET mpg4d_flush(void *dec)
153 {
154     if (NULL == dec) {
155         mpp_err_f("found NULL intput\n");
156         return MPP_ERR_NULL_PTR;
157     }
158 
159     Mpg4dCtx *p = (Mpg4dCtx *)dec;
160     return mpp_mpg4_parser_flush(p->parser);
161 }
162 
mpg4d_control(void * dec,MpiCmd cmd_type,void * param)163 static MPP_RET mpg4d_control(void *dec, MpiCmd cmd_type, void *param)
164 {
165     if (NULL == dec) {
166         mpp_err_f("found NULL intput\n");
167         return MPP_ERR_NULL_PTR;
168     }
169     (void)cmd_type;
170     (void)param;
171     return MPP_OK;
172 }
173 
mpg4d_prepare(void * dec,MppPacket pkt,HalDecTask * task)174 static MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task)
175 {
176     Mpg4dCtx *p;
177     RK_U8 *pos;
178     size_t length;
179     RK_U32 eos;
180 
181     if (NULL == dec || NULL == pkt || NULL == task) {
182         mpp_err_f("found NULL intput dec %p pkt %p task %p\n", dec, pkt, task);
183         return MPP_ERR_NULL_PTR;
184     }
185 
186     task->valid = 0;
187     p = (Mpg4dCtx *)dec;
188     pos     = mpp_packet_get_pos(pkt);
189     length  = mpp_packet_get_length(pkt);
190     eos     = mpp_packet_get_eos(pkt);
191 
192     if (p->got_eos) {
193         mpp_log_f("has got eos packet.\n");
194         mpp_packet_set_length(pkt, 0);
195         return MPP_OK;
196     }
197 
198     if (NULL == p->stream) {
199         mpp_err("failed to malloc task buffer for hardware with size %d\n", length);
200         return MPP_ERR_UNKNOW;
201     }
202     mpp_packet_set_length(p->task_pkt, p->left_length);
203 
204     /*
205     * Check have enough buffer to store stream
206     * NOTE: total length is the left size plus the new incoming
207     *       packet length.
208     */
209     size_t total_length = MPP_ALIGN(p->left_length + length, 16) + 64; // add extra 64 bytes in tails
210 
211     if (total_length > p->stream_size) {
212         RK_U8 *dst = NULL;
213         do {
214             p->stream_size <<= 1;
215         } while (total_length > p->stream_size);
216 
217         dst = mpp_malloc_size(RK_U8, p->stream_size);
218         mpp_assert(dst);
219         // NOTE: copy remaining stream to new buffer
220         if (p->left_length > 0) {
221             memcpy(dst, p->stream, p->left_length);
222         }
223         mpp_free(p->stream);
224         p->stream = dst;
225         mpp_packet_set_data(p->task_pkt, p->stream);
226         mpp_packet_set_size(p->task_pkt, p->stream_size);
227     }
228 
229     if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) {
230         if (p->left_length > 0) {
231             p->left_length = 0;
232             task->valid = 1;
233             return MPP_OK;
234         }
235     }
236 
237     if (!p->dec_cfg->base.split_parse ||
238         (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA)) {
239         p->got_eos = eos;
240         task->flags.eos = eos;
241         // NOTE: empty eos packet
242         if (eos && !length) {
243             mpg4d_flush(dec);
244             return MPP_OK;
245         }
246         /*
247          * Copy packet mode:
248          * Decoder's user will insure each packet is one frame for process
249          * Parser will just copy packet to the beginning of stream buffer
250          */
251         memcpy(p->stream, pos, length);
252         mpp_packet_set_pos(p->task_pkt, p->stream);
253         mpp_packet_set_length(p->task_pkt, length);
254         mpp_packet_set_pts(p->task_pkt, mpp_packet_get_pts(pkt));
255         mpp_packet_set_dts(p->task_pkt, mpp_packet_get_dts(pkt));
256         // set input packet length to 0 here
257         // indicate that the input packet has been all consumed
258         mpp_packet_set_pos(pkt, pos + length);
259         mpp_packet_set_length(pkt, 0);
260         /* this step will enable the task and goto parse stage */
261         task->valid = 1;
262     } else {
263         /*
264          * Split packet mode:
265          * Input packet can be any length and no need to be bound of on frame
266          * Parser will do split frame operation to find the beginning and end of one frame
267          */
268         if (MPP_OK == mpp_mpg4_parser_split(p->parser, p->task_pkt, pkt)) {
269             p->left_length = 0;
270             task->valid = 1;
271         } else {
272             task->valid = 0;
273             p->left_length = mpp_packet_get_length(p->task_pkt);
274         }
275         p->got_eos = mpp_packet_get_eos(p->task_pkt);
276         task->flags.eos = p->got_eos;
277     }
278     task->input_packet = p->task_pkt;
279 
280     return MPP_OK;
281 }
282 
mpg4d_parse(void * dec,HalDecTask * task)283 static MPP_RET mpg4d_parse(void *dec, HalDecTask *task)
284 {
285     MPP_RET ret;
286     Mpg4dCtx *p;
287 
288     if (NULL == dec || NULL == task) {
289         mpp_err_f("found NULL intput dec %p task %p\n", dec, task);
290         return MPP_ERR_NULL_PTR;
291     }
292     p = (Mpg4dCtx *)dec;
293     ret = mpp_mpg4_parser_decode(p->parser, task->input_packet);
294     if (ret) {
295         // found error on decoding drop this task and clear remaining length
296         task->valid  = 0;
297         task->output = -1;
298         mpp_packet_set_length(task->input_packet, 0);
299 
300         return MPP_NOK;
301     }
302 
303     mpp_mpg4_parser_setup_syntax(p->parser, &task->syntax);
304     mpp_mpg4_parser_setup_hal_output(p->parser, &task->output);
305     mpp_mpg4_parser_setup_refer(p->parser, task->refer, MAX_DEC_REF_NUM);
306     mpp_mpg4_parser_update_dpb(p->parser);
307 
308     if (p->got_eos) {
309         task->flags.eos = 1;
310         mpg4d_flush(dec);
311         return MPP_OK;
312     }
313 
314     p->frame_count++;
315 
316     return MPP_OK;
317 }
318 
mpg4d_callback(void * dec,void * err_info)319 static MPP_RET mpg4d_callback(void *dec, void *err_info)
320 {
321     Mpg4dCtx *p_Dec = (Mpg4dCtx *)dec;
322     DecCbHalDone *ctx = (DecCbHalDone *)err_info;
323 
324     if (NULL == dec || NULL == err_info) {
325         mpp_err_f("found NULL input dec %p err_info %p\n", dec, err_info);
326         return MPP_ERR_NULL_PTR;
327     }
328 
329     MppFrame mframe = NULL;
330     HalDecTask *task_dec = (HalDecTask *)ctx->task;
331 
332     mpp_buf_slot_get_prop(p_Dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe);
333     if (mframe) {
334         RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err;
335         if (ctx->hard_err || task_err) {
336             mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW);
337             mpp_log_f("[CALLBACK] g_no=%d, out_idx=%d, dpberr=%d, harderr=%d, ref_flag=%d, errinfo=%d, discard=%d\n",
338                       p_Dec->frame_count, task_dec->output, task_err, ctx->hard_err, task_dec->flags.used_for_ref,
339                       mpp_frame_get_errinfo(mframe), mpp_frame_get_discard(mframe));
340         }
341     }
342     return MPP_OK;
343 }
344 
345 const ParserApi api_mpg4d_parser = {
346     .name = "api_mpg4d_parser",
347     .coding = MPP_VIDEO_CodingMPEG4,
348     .ctx_size = sizeof(Mpg4dCtx),
349     .flag = 0,
350     .init = mpg4d_init,
351     .deinit = mpg4d_deinit,
352     .prepare = mpg4d_prepare,
353     .parse = mpg4d_parse,
354     .reset = mpg4d_reset,
355     .flush = mpg4d_flush,
356     .control = mpg4d_control,
357     .callback = mpg4d_callback,
358 };
359 
360