xref: /OK3568_Linux_fs/external/mpp/mpp/codec/dec/h263/h263d_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 "h263d_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 "h263d_api.h"
27 #include "h263d_parser.h"
28 
29 #define h263d_INIT_STREAM_SIZE      SZ_64K
30 
31 typedef struct {
32     // parameter interact with mpp_dec
33     MppBufSlots     frame_slots;
34     MppBufSlots     packet_slots;
35     MppDecCfgSet    *cfg;
36 
37     RK_U8           *stream;
38     size_t          stream_size;
39     MppPacket       task_pkt;
40     RK_S64          task_pts;
41     RK_U32          task_eos;
42 
43     // runtime parameter
44     RK_U32          frame_count;
45 
46     // parser context
47     H263dParser     parser;
48 } H263dCtx;
49 
h263d_init(void * dec,ParserCfg * cfg)50 MPP_RET h263d_init(void *dec, ParserCfg *cfg)
51 {
52     H263dParser parser = NULL;
53     MppPacket task_pkt = NULL;
54     H263dCtx *p;
55     MPP_RET ret;
56     RK_U8 *stream;
57     size_t stream_size = h263d_INIT_STREAM_SIZE;
58 
59     if (NULL == dec) {
60         mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg);
61         return MPP_ERR_NULL_PTR;
62     }
63 
64     stream = mpp_malloc_size(RK_U8, stream_size);
65     if (NULL == stream) {
66         mpp_err_f("failed to malloc stream buffer size %d\n", stream_size);
67         return MPP_ERR_MALLOC;
68     }
69 
70     ret = mpp_packet_init(&task_pkt, stream, stream_size);
71     if (ret) {
72         mpp_err_f("failed to create mpp_packet for task\n");
73         goto ERR_RET;
74     }
75 
76     // reset task packet length to zero
77     // NOTE: set length must after set pos
78     mpp_packet_set_pos(task_pkt, stream);
79     mpp_packet_set_length(task_pkt, 0);
80 
81     ret = mpp_h263_parser_init(&parser, cfg->frame_slots);
82     if (ret) {
83         mpp_err_f("failed to init parser\n");
84         goto ERR_RET;
85     }
86 
87     p = (H263dCtx *)dec;
88     p->frame_slots  = cfg->frame_slots;
89     p->packet_slots = cfg->packet_slots;
90     p->cfg          = cfg->cfg;
91     p->stream       = stream;
92     p->stream_size  = stream_size;
93     p->task_pkt     = task_pkt;
94     p->parser       = parser;
95 
96     return MPP_OK;
97 ERR_RET:
98     if (task_pkt) {
99         mpp_packet_deinit(&task_pkt);
100     }
101     if (stream) {
102         mpp_free(stream);
103         stream = NULL;
104     }
105     return ret;
106 }
107 
h263d_deinit(void * dec)108 MPP_RET h263d_deinit(void *dec)
109 {
110     H263dCtx *p;
111     if (NULL == dec) {
112         mpp_err_f("found NULL intput\n");
113         return MPP_ERR_NULL_PTR;
114     }
115 
116     p = (H263dCtx *)dec;
117     if (p->parser) {
118         mpp_h263_parser_deinit(p->parser);
119         p->parser = NULL;
120     }
121 
122     if (p->task_pkt) {
123         mpp_packet_deinit(&p->task_pkt);
124     }
125 
126     if (p->stream) {
127         mpp_free(p->stream);
128         p->stream = NULL;
129     }
130     return MPP_OK;
131 }
132 
h263d_reset(void * dec)133 MPP_RET h263d_reset(void *dec)
134 {
135     if (NULL == dec) {
136         mpp_err_f("found NULL intput\n");
137         return MPP_ERR_NULL_PTR;
138     }
139 
140     H263dCtx *p = (H263dCtx *)dec;
141     return mpp_h263_parser_reset(p->parser);
142 }
143 
144 
h263d_flush(void * dec)145 MPP_RET h263d_flush(void *dec)
146 {
147     if (NULL == dec) {
148         mpp_err_f("found NULL intput\n");
149         return MPP_ERR_NULL_PTR;
150     }
151 
152     H263dCtx *p = (H263dCtx *)dec;
153     return mpp_h263_parser_flush(p->parser);
154 }
155 
156 
h263d_control(void * dec,MpiCmd cmd_type,void * param)157 MPP_RET h263d_control(void *dec, MpiCmd cmd_type, void *param)
158 {
159     if (NULL == dec) {
160         mpp_err_f("found NULL intput\n");
161         return MPP_ERR_NULL_PTR;
162     }
163     (void)cmd_type;
164     (void)param;
165     return MPP_OK;
166 }
167 
h263d_prepare(void * dec,MppPacket pkt,HalDecTask * task)168 MPP_RET h263d_prepare(void *dec, MppPacket pkt, HalDecTask *task)
169 {
170     H263dCtx *p;
171     RK_U8 *pos;
172     size_t length;
173     RK_U32 eos;
174 
175     if (NULL == dec || NULL == pkt || NULL == task) {
176         mpp_err_f("found NULL intput dec %p pkt %p task %p\n", dec, pkt, task);
177         return MPP_ERR_NULL_PTR;
178     }
179 
180     p = (H263dCtx *)dec;
181     pos     = mpp_packet_get_pos(pkt);
182     length  = mpp_packet_get_length(pkt);
183     eos     = mpp_packet_get_eos(pkt);
184 
185     if (eos && !length) {
186         task->valid = 0;
187         task->flags.eos = 1;
188         mpp_log("h263d flush eos");
189         h263d_flush(dec);
190         return MPP_OK;
191     }
192 
193     if (NULL == p->stream) {
194         mpp_err("failed to malloc task buffer for hardware with size %d\n", length);
195         return MPP_ERR_UNKNOW;
196     }
197 
198     if (!p->cfg->base.split_parse) {
199         /*
200          * Copy packet mode:
201          * Decoder's user will insure each packet is one frame for process
202          * Parser will just copy packet to the beginning of stream buffer
203          */
204         if (length > p->stream_size) {
205             // NOTE: here we double the buffer length to reduce frequency of realloc
206             do {
207                 p->stream_size <<= 1;
208             } while (length > p->stream_size);
209 
210             mpp_free(p->stream);
211             p->stream = mpp_malloc_size(RK_U8, p->stream_size);
212             mpp_assert(p->stream);
213             mpp_packet_set_data(p->task_pkt, p->stream);
214             mpp_packet_set_size(p->task_pkt, p->stream_size);
215         }
216 
217         memcpy(p->stream, pos, length);
218         mpp_packet_set_pos(p->task_pkt, p->stream);
219         mpp_packet_set_length(p->task_pkt, length);
220         // set input packet length to 0 here
221         // indicate that the input packet has been all consumed
222         mpp_packet_set_pos(pkt, pos + length);
223         // always use latest pts for current packet
224         p->task_pts = mpp_packet_get_pts(pkt);
225         p->task_eos = mpp_packet_get_eos(pkt);
226         /* this step will enable the task and goto parse stage */
227         task->valid = 1;
228     } else {
229         /*
230          * Split packet mode:
231          * Input packet can be any length and no need to be bound of on frame
232          * Parser will do split frame operation to find the beginning and end of one frame
233          */
234         /*
235          * NOTE: on split mode total length is the left size plus the new incoming
236          *       packet length.
237          */
238         size_t remain_length = mpp_packet_get_length(p->task_pkt);
239         size_t total_length = remain_length + length;
240         if (total_length > p->stream_size) {
241             RK_U8 *dst;
242             do {
243                 p->stream_size <<= 1;
244             } while (length > p->stream_size);
245 
246             // NOTE; split mode need to copy remaining stream to new buffer
247             dst = mpp_malloc_size(RK_U8, p->stream_size);
248             mpp_assert(dst);
249 
250             memcpy(dst, p->stream, remain_length);
251             mpp_free(p->stream);
252             p->stream = dst;
253             mpp_packet_set_data(p->task_pkt, p->stream);
254             mpp_packet_set_size(p->task_pkt, p->stream_size);
255         }
256 
257         // start parser split
258         if (MPP_OK == mpp_h263_parser_split(p->parser, p->task_pkt, pkt)) {
259             task->valid = 1;
260         }
261         p->task_pts = mpp_packet_get_pts(p->task_pkt);
262         p->task_eos = mpp_packet_get_eos(p->task_pkt);
263     }
264 
265     mpp_packet_set_pts(p->task_pkt, p->task_pts);
266     task->input_packet = p->task_pkt;
267     task->flags.eos    = p->task_eos;
268 
269     return MPP_OK;
270 }
271 
h263d_parse(void * dec,HalDecTask * task)272 MPP_RET h263d_parse(void *dec, HalDecTask *task)
273 {
274     MPP_RET ret;
275     H263dCtx *p;
276 
277     if (NULL == dec || NULL == task) {
278         mpp_err_f("found NULL intput dec %p task %p\n", dec, task);
279         return MPP_ERR_NULL_PTR;
280     }
281     p = (H263dCtx *)dec;
282     ret = mpp_h263_parser_decode(p->parser, task->input_packet);
283     if (ret) {
284         // found error on decoding drop this task and clear remaining length
285         task->valid  = 0;
286         task->output = -1;
287         mpp_packet_set_length(task->input_packet, 0);
288         return MPP_NOK;
289     }
290 
291     mpp_h263_parser_setup_syntax(p->parser, &task->syntax);
292     mpp_h263_parser_setup_hal_output(p->parser, &task->output);
293     mpp_h263_parser_setup_refer(p->parser, task->refer, MAX_DEC_REF_NUM);
294     mpp_h263_parser_update_dpb(p->parser);
295 
296     p->frame_count++;
297 
298     return MPP_OK;
299 }
300 
h263d_callback(void * dec,void * err_info)301 MPP_RET h263d_callback(void *dec, void *err_info)
302 {
303     (void)dec;
304     (void)err_info;
305     return MPP_OK;
306 }
307 
308 const ParserApi api_h263d_parser = {
309     .name = "api_h263d_parser",
310     .coding = MPP_VIDEO_CodingH263,
311     .ctx_size = sizeof(H263dCtx),
312     .flag = 0,
313     .init = h263d_init,
314     .deinit = h263d_deinit,
315     .prepare = h263d_prepare,
316     .parse = h263d_parse,
317     .reset = h263d_reset,
318     .flush = h263d_flush,
319     .control = h263d_control,
320     .callback = h263d_callback,
321 };
322 
323