xref: /rockchip-linux_mpp/mpp/codec/dec/av1/av1d_api.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 "av1d_api"
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "mpp_mem.h"
24 #include "mpp_debug.h"
25 #include "mpp_packet_impl.h"
26 
27 #include "av1d_codec.h"
28 #include "av1d_parser.h"
29 
30 #include "av1d_api.h"
31 
32 /*!
33  ***********************************************************************
34  * \brief
35  *   alloc all buffer
36  ***********************************************************************
37  */
38 
av1d_init(void * ctx,ParserCfg * init)39 MPP_RET av1d_init(void *ctx, ParserCfg *init)
40 {
41     MPP_RET ret = MPP_OK;
42     RK_U8 *buf = NULL;
43     RK_S32 size = SZ_512K;
44     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
45 
46     if (!av1_ctx || !init) {
47         mpp_err("av1d init fail");
48         return MPP_ERR_NULL_PTR;
49     }
50 
51     av1_ctx->pix_fmt = MPP_FMT_BUTT;
52     av1_ctx->usr_set_fmt = MPP_FMT_BUTT;
53 
54     if ((ret = av1d_parser_init(av1_ctx, init)) != MPP_OK)
55         goto _err_exit;
56 
57     if ((ret = av1d_split_init(av1_ctx)) != MPP_OK)
58         goto _err_exit;
59 
60     buf = mpp_malloc(RK_U8, size);
61     if (!buf) {
62         mpp_err("av1d init malloc stream buffer fail");
63         ret = MPP_ERR_NOMEM;
64         goto _err_exit;
65     }
66 
67     if ((ret = mpp_packet_init(&av1_ctx->pkt, (void *)buf, size)) != MPP_OK)
68         goto _err_exit;
69 
70     av1_ctx->stream = buf;
71     av1_ctx->stream_size = size;
72     mpp_packet_set_size(av1_ctx->pkt, size);
73     mpp_packet_set_length(av1_ctx->pkt, 0);
74 
75     return ret;
76 
77 _err_exit:
78     av1d_deinit(av1_ctx);
79     return ret;
80 }
81 
82 /*!
83  ***********************************************************************
84  * \brief
85  *   free all buffer
86  ***********************************************************************
87  */
av1d_deinit(void * ctx)88 MPP_RET av1d_deinit(void *ctx)
89 {
90     RK_U8 *buf = NULL;
91     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
92 
93     if (av1_ctx) {
94         av1d_parser_deinit(av1_ctx);
95         if (av1_ctx->pkt) {
96             buf = mpp_packet_get_data(av1_ctx->pkt);
97             MPP_FREE(buf);
98             mpp_packet_deinit(&av1_ctx->pkt);
99         }
100     }
101 
102     return MPP_OK;
103 }
104 
105 /*!
106  ***********************************************************************
107  * \brief
108  *   reset
109  ***********************************************************************
110  */
av1d_reset(void * ctx)111 MPP_RET  av1d_reset(void *ctx)
112 {
113     MPP_RET ret = MPP_ERR_UNKNOW;
114 
115     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
116     av1d_paser_reset(av1_ctx);
117     return ret = MPP_OK;
118 }
119 
120 /*!
121  ***********************************************************************
122  * \brief
123  *   flush
124  ***********************************************************************
125  */
av1d_flush(void * ctx)126 MPP_RET  av1d_flush(void *ctx)
127 {
128     MPP_RET ret = MPP_ERR_UNKNOW;
129 
130     (void)ctx;
131     return ret = MPP_OK;
132 }
133 
134 /*!
135  ***********************************************************************
136  * \brief
137  *   prepare
138  ***********************************************************************
139  */
av1d_prepare(void * ctx,MppPacket pkt,HalDecTask * task)140 MPP_RET av1d_prepare(void *ctx, MppPacket pkt, HalDecTask *task)
141 {
142     MPP_RET ret = MPP_OK;
143     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
144     AV1Context *s = (AV1Context *)av1_ctx->priv_data;
145     RK_S64 pts = -1;
146     RK_S64 dts = -1;
147     RK_U8 *buf = NULL;
148     RK_S32 length = 0;
149     RK_U8 *out_data = NULL;
150     RK_S32 out_size = -1;
151     RK_S32 consumed = 0;
152     RK_U8 *pos = NULL;
153     RK_U32 need_split = s->cfg->base.split_parse;
154 
155     need_split = 1;
156     task->valid = 0;
157     av1_ctx->new_frame = 0;
158 
159     pts = mpp_packet_get_pts(pkt);
160     dts = mpp_packet_get_dts(pkt);
161     buf = pos = mpp_packet_get_pos(pkt);
162     length = (RK_S32)mpp_packet_get_length(pkt);
163     if (mpp_packet_get_flag(pkt)& MPP_PACKET_FLAG_EXTRA_DATA) {
164         s->extra_has_frame = 0;
165         task = NULL;
166         s->current_obu.data = buf;
167         s->current_obu.data_size = length;
168         ret = mpp_av1_split_fragment(s, &s->current_obu, 1);
169         if (ret < 0) {
170             return ret;
171         }
172         ret = mpp_av1_read_fragment_content(s, &s->current_obu);
173         if (ret < 0) {
174             return ret;
175         }
176         if (!s->sequence_header) {
177             goto end;
178         }
179         ret = mpp_av1_set_context_with_sequence(av1_ctx, s->sequence_header);
180     end:
181         pos = buf + length;
182         mpp_packet_set_pos(pkt, pos);
183         mpp_av1_fragment_reset(&s->current_obu);
184         return ret;
185     }
186 
187     if (need_split) {
188         consumed = av1d_split_frame(av1_ctx, &out_data, &out_size, buf, length);
189     } else {
190         out_size = consumed = length;
191         av1_ctx->new_frame = 1;
192     }
193 
194     pos += (consumed >= 0) ? consumed : length;
195 
196     mpp_packet_set_pos(pkt, pos);
197     mpp_packet_set_length(pkt, length - consumed);
198     if (!mpp_packet_get_length(pkt))
199         av1_ctx->eos = mpp_packet_get_eos(pkt);
200     av1d_dbg(AV1D_DBG_STRMIN, "pkt_len=%d, pts=%lld , out_size %d consumed %d new frame %d eos %d\n",
201              length, pts, out_size, consumed, av1_ctx->new_frame, av1_ctx->eos);
202     if (out_size > 0) {
203         av1d_get_frame_stream(av1_ctx, buf, consumed);
204         task->input_packet = av1_ctx->pkt;
205         mpp_packet_set_pts(av1_ctx->pkt, pts);
206         mpp_packet_set_dts(av1_ctx->pkt, dts);
207     } else {
208         task->valid = 0;
209         if (av1_ctx->eos)
210             task->input_packet = av1_ctx->pkt;
211     }
212     if (av1_ctx->eos && !mpp_packet_get_length(pkt))
213         task->flags.eos = av1_ctx->eos;
214 
215     if (av1_ctx->new_frame || (task->flags.eos)) {
216         if (av1_ctx->stream_offset > 0)
217             task->valid = 1;
218         av1_ctx->stream_offset = 0;
219     }
220 
221     (void)pts;
222     (void)dts;
223     (void)task;
224     return ret = MPP_OK;
225 }
226 
227 /*!
228  ***********************************************************************
229  * \brief
230  *   parser
231  ***********************************************************************
232  */
av1d_parser(void * ctx,HalDecTask * in_task)233 MPP_RET av1d_parser(void *ctx, HalDecTask *in_task)
234 {
235     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
236     MPP_RET ret = MPP_OK;
237     av1d_parser_frame(av1_ctx, in_task);
238     return ret;
239 }
240 
241 /*!
242  ***********************************************************************
243  * \brief
244  *   control
245  ***********************************************************************
246  */
av1d_control(void * ctx,MpiCmd cmd,void * param)247 MPP_RET av1d_control(void *ctx, MpiCmd cmd, void *param)
248 {
249     Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
250     MPP_RET ret = MPP_OK;
251 
252     if (!ctx)
253         return MPP_ERR_VALUE;
254 
255     switch (cmd) {
256     case MPP_DEC_SET_OUTPUT_FORMAT : {
257         av1_ctx->usr_set_fmt = param ? *((MppFrameFormat *)param) : MPP_FMT_YUV420SP;
258     } break;
259     default:
260         break;
261     }
262 
263     return ret;
264 }
265 
266 /*!
267  ***********************************************************************
268  * \brief
269  *   callback
270  ***********************************************************************
271  */
av1d_callback(void * decoder,void * info)272 MPP_RET av1d_callback(void *decoder, void *info)
273 {
274     MPP_RET ret = MPP_ERR_UNKNOW;
275     Av1CodecContext *av1_ctx = (Av1CodecContext *)decoder;
276     av1d_parser_update(av1_ctx, info);
277 
278     return ret = MPP_OK;
279 }
280 
281 /*!
282  ***********************************************************************
283  * \brief
284  *   api struct interface
285  ***********************************************************************
286  */
287 
288 const ParserApi api_av1d_parser = {
289     .name = "av1d_parse",
290     .coding = MPP_VIDEO_CodingAV1,
291     .ctx_size = sizeof(Av1CodecContext),
292     .flag = 0,
293     .init = av1d_init,
294     .deinit = av1d_deinit,
295     .prepare = av1d_prepare,
296     .parse = av1d_parser,
297     .reset = av1d_reset,
298     .flush = av1d_flush,
299     .control = av1d_control,
300     .callback = av1d_callback,
301 };
302