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