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