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 av1d_split_deinit(av1_ctx);
96 if (av1_ctx->pkt) {
97 buf = mpp_packet_get_data(av1_ctx->pkt);
98 MPP_FREE(buf);
99 mpp_packet_deinit(&av1_ctx->pkt);
100 }
101 }
102
103 return MPP_OK;
104 }
105
106 /*!
107 ***********************************************************************
108 * \brief
109 * reset
110 ***********************************************************************
111 */
av1d_reset(void * ctx)112 MPP_RET av1d_reset(void *ctx)
113 {
114 MPP_RET ret = MPP_ERR_UNKNOW;
115
116 Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
117 av1d_paser_reset(av1_ctx);
118 return ret = MPP_OK;
119 }
120
121 /*!
122 ***********************************************************************
123 * \brief
124 * flush
125 ***********************************************************************
126 */
av1d_flush(void * ctx)127 MPP_RET av1d_flush(void *ctx)
128 {
129 MPP_RET ret = MPP_ERR_UNKNOW;
130
131 (void)ctx;
132 return ret = MPP_OK;
133 }
134
135 /*!
136 ***********************************************************************
137 * \brief
138 * prepare
139 ***********************************************************************
140 */
av1d_prepare(void * ctx,MppPacket pkt,HalDecTask * task)141 MPP_RET av1d_prepare(void *ctx, MppPacket pkt, HalDecTask *task)
142 {
143 MPP_RET ret = MPP_OK;
144 Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
145 AV1Context *s = (AV1Context *)av1_ctx->priv_data;
146 RK_S64 pts = -1;
147 RK_S64 dts = -1;
148 RK_U8 *buf = NULL;
149 RK_S32 length = 0;
150 RK_U8 *out_data = NULL;
151 RK_S32 out_size = -1;
152 RK_S32 consumed = 0;
153 RK_U8 *pos = NULL;
154 RK_U32 need_split = s->cfg->base.split_parse;
155
156 need_split = 1;
157 task->valid = 0;
158 av1_ctx->new_frame = 0;
159
160 pts = mpp_packet_get_pts(pkt);
161 dts = mpp_packet_get_dts(pkt);
162 buf = pos = mpp_packet_get_pos(pkt);
163 length = (RK_S32)mpp_packet_get_length(pkt);
164 if (mpp_packet_get_flag(pkt)& MPP_PACKET_FLAG_EXTRA_DATA) {
165 s->extra_has_frame = 0;
166 task = NULL;
167 s->current_obu.data = buf;
168 s->current_obu.data_size = length;
169 ret = mpp_av1_split_fragment(s, &s->current_obu, 1);
170 if (ret < 0) {
171 return ret;
172 }
173 ret = mpp_av1_read_fragment_content(s, &s->current_obu);
174 if (ret < 0) {
175 return ret;
176 }
177 if (!s->sequence_header) {
178 goto end;
179 }
180 ret = mpp_av1_set_context_with_sequence(av1_ctx, s->sequence_header);
181 end:
182 pos = buf + length;
183 mpp_packet_set_pos(pkt, pos);
184 mpp_av1_fragment_reset(&s->current_obu);
185 return ret;
186 }
187
188 if (need_split) {
189 consumed = av1d_split_frame(av1_ctx, &out_data, &out_size, buf, length);
190 } else {
191 out_size = consumed = length;
192 av1_ctx->new_frame = 1;
193 }
194
195 pos += (consumed >= 0) ? consumed : length;
196
197 mpp_packet_set_pos(pkt, pos);
198 mpp_packet_set_length(pkt, length - consumed);
199 if (!mpp_packet_get_length(pkt))
200 av1_ctx->eos = mpp_packet_get_eos(pkt);
201 av1d_dbg(AV1D_DBG_STRMIN, "pkt_len=%d, pts=%lld , out_size %d consumed %d new frame %d eos %d\n",
202 length, pts, out_size, consumed, av1_ctx->new_frame, av1_ctx->eos);
203 if (out_size > 0) {
204 av1d_get_frame_stream(av1_ctx, buf, consumed);
205 task->input_packet = av1_ctx->pkt;
206 mpp_packet_set_pts(av1_ctx->pkt, pts);
207 mpp_packet_set_dts(av1_ctx->pkt, dts);
208 } else {
209 task->valid = 0;
210 if (av1_ctx->eos) {
211 task->input_packet = av1_ctx->pkt;
212 mpp_packet_set_length(av1_ctx->pkt, 0);
213 mpp_packet_set_pts(av1_ctx->pkt, pts);
214 mpp_packet_set_dts(av1_ctx->pkt, dts);
215 }
216 }
217 if (av1_ctx->eos && !mpp_packet_get_length(pkt))
218 task->flags.eos = av1_ctx->eos;
219
220 if (av1_ctx->new_frame || (task->flags.eos)) {
221 task->valid = 1;
222 av1_ctx->stream_offset = 0;
223 }
224
225 (void)pts;
226 (void)dts;
227 (void)task;
228 return ret = MPP_OK;
229 }
230
231 /*!
232 ***********************************************************************
233 * \brief
234 * parser
235 ***********************************************************************
236 */
av1d_parser(void * ctx,HalDecTask * in_task)237 MPP_RET av1d_parser(void *ctx, HalDecTask *in_task)
238 {
239 Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
240 MPP_RET ret = MPP_OK;
241 av1d_parser_frame(av1_ctx, in_task);
242 return ret;
243 }
244
245 /*!
246 ***********************************************************************
247 * \brief
248 * control
249 ***********************************************************************
250 */
av1d_control(void * ctx,MpiCmd cmd,void * param)251 MPP_RET av1d_control(void *ctx, MpiCmd cmd, void *param)
252 {
253 Av1CodecContext *av1_ctx = (Av1CodecContext *)ctx;
254 MPP_RET ret = MPP_OK;
255
256 if (!ctx)
257 return MPP_ERR_VALUE;
258
259 switch (cmd) {
260 case MPP_DEC_SET_OUTPUT_FORMAT : {
261 av1_ctx->usr_set_fmt = param ? *((MppFrameFormat *)param) : MPP_FMT_YUV420SP;
262 } break;
263 default:
264 break;
265 }
266
267 return ret;
268 }
269
270 /*!
271 ***********************************************************************
272 * \brief
273 * callback
274 ***********************************************************************
275 */
av1d_callback(void * decoder,void * info)276 MPP_RET av1d_callback(void *decoder, void *info)
277 {
278 MPP_RET ret = MPP_ERR_UNKNOW;
279 Av1CodecContext *av1_ctx = (Av1CodecContext *)decoder;
280 av1d_parser_update(av1_ctx, info);
281
282 return ret = MPP_OK;
283 }
284
285 /*!
286 ***********************************************************************
287 * \brief
288 * api struct interface
289 ***********************************************************************
290 */
291
292 const ParserApi api_av1d_parser = {
293 .name = "av1d_parse",
294 .coding = MPP_VIDEO_CodingAV1,
295 .ctx_size = sizeof(Av1CodecContext),
296 .flag = 0,
297 .init = av1d_init,
298 .deinit = av1d_deinit,
299 .prepare = av1d_prepare,
300 .parse = av1d_parser,
301 .reset = av1d_reset,
302 .flush = av1d_flush,
303 .control = av1d_control,
304 .callback = av1d_callback,
305 };
306