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