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 #define MODULE_TAG "dummy_dec_api"
18
19 #include <string.h>
20
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23 #include "mpp_common.h"
24
25 #include "dummy_dec_api.h"
26
27 #define DUMMY_DEC_FRAME_WIDTH 1280
28 #define DUMMY_DEC_FRAME_HEIGHT 720
29
30 #define DUMMY_DEC_FRAME_NEW_WIDTH 1920
31 #define DUMMY_DEC_FRAME_NEW_HEIGHT 1088
32
33 #define DUMMY_DEC_FRAME_SIZE SZ_1M
34 #define DUMMY_DEC_FRAME_COUNT 16
35 #define DUMMY_DEC_REF_COUNT 2
36
37 typedef struct DummyDec_t {
38 MppBufSlots frame_slots;
39 MppBufSlots packet_slots;
40 RK_S32 task_count;
41 void *stream;
42 size_t stream_size;
43 MppPacket task_pkt;
44
45 RK_S64 task_pts;
46 RK_U32 task_eos;
47
48 RK_U32 slots_inited;
49 RK_U32 frame_count;
50 RK_S32 prev_index;
51 RK_S32 slot_index[DUMMY_DEC_REF_COUNT];
52 } DummyDec;
53
dummy_dec_init(void * dec,ParserCfg * cfg)54 MPP_RET dummy_dec_init(void *dec, ParserCfg *cfg)
55 {
56 DummyDec *p;
57 RK_S32 i;
58 void *stream;
59 size_t stream_size = SZ_512K;
60 MppPacket task_pkt;
61
62 if (NULL == dec) {
63 mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg);
64 return MPP_ERR_NULL_PTR;
65 }
66
67 stream = mpp_malloc_size(void, stream_size);
68 if (NULL == stream) {
69 mpp_err_f("failed to malloc stream buffer size %d\n", stream_size);
70 return MPP_ERR_MALLOC;
71 }
72
73 mpp_packet_init(&task_pkt, stream, stream_size);
74 if (NULL == task_pkt) {
75 mpp_err_f("failed to create mpp_packet for task\n");
76 return MPP_ERR_UNKNOW;
77 }
78
79 p = (DummyDec *)dec;
80 p->frame_slots = cfg->frame_slots;
81 p->packet_slots = cfg->packet_slots;
82 p->task_count = 2;
83 p->stream = stream;
84 p->stream_size = stream_size;
85 p->task_pkt = task_pkt;
86 for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) {
87 p->slot_index[i] = -1;
88 }
89 return MPP_OK;
90 }
91
dummy_dec_deinit(void * dec)92 MPP_RET dummy_dec_deinit(void *dec)
93 {
94 DummyDec *p;
95 if (NULL == dec) {
96 mpp_err_f("found NULL intput\n");
97 return MPP_ERR_NULL_PTR;
98 }
99
100 p = (DummyDec *)dec;
101 if (p->task_pkt)
102 mpp_packet_deinit(&p->task_pkt);
103 if (p->stream)
104 mpp_free(p->stream);
105 return MPP_OK;
106 }
107
dummy_dec_reset(void * dec)108 MPP_RET dummy_dec_reset(void *dec)
109 {
110 if (NULL == dec) {
111 mpp_err_f("found NULL intput\n");
112 return MPP_ERR_NULL_PTR;
113 }
114 return MPP_OK;
115 }
116
117
dummy_dec_flush(void * dec)118 MPP_RET dummy_dec_flush(void *dec)
119 {
120 if (NULL == dec) {
121 mpp_err_f("found NULL intput\n");
122 return MPP_ERR_NULL_PTR;
123 }
124 return MPP_OK;
125 }
126
127
dummy_dec_control(void * dec,MpiCmd cmd_type,void * param)128 MPP_RET dummy_dec_control(void *dec, MpiCmd cmd_type, void *param)
129 {
130 if (NULL == dec) {
131 mpp_err_f("found NULL intput\n");
132 return MPP_ERR_NULL_PTR;
133 }
134 (void)cmd_type;
135 (void)param;
136 return MPP_OK;
137 }
138
dummy_dec_prepare(void * dec,MppPacket pkt,HalDecTask * task)139 MPP_RET dummy_dec_prepare(void *dec, MppPacket pkt, HalDecTask *task)
140 {
141 DummyDec *p;
142 RK_U8 *data;
143 size_t length;
144
145 if (NULL == dec) {
146 mpp_err_f("found NULL intput\n");
147 return MPP_ERR_NULL_PTR;
148 }
149
150 p = (DummyDec *)dec;
151
152 /*********************************************************************
153 * do packet prepare here
154 * including connet nals into a big buffer, setup packet for task copy
155 * pts/eos record
156 *********************************************************************/
157 p->task_pts = mpp_packet_get_pts(pkt);
158 p->task_eos = mpp_packet_get_eos(pkt);
159
160 // set pos to indicate that buffer is done
161 data = mpp_packet_get_data(pkt);
162 length = mpp_packet_get_length(pkt);
163 if (length > p->stream_size) {
164 p->stream = mpp_realloc(p->stream, RK_U8, length);
165 mpp_packet_set_data(p->task_pkt, p->stream);
166 p->stream_size = length;
167 }
168 if (p->stream) {
169 memcpy(p->stream, data, length);
170 mpp_packet_set_length(p->task_pkt, length);
171 } else {
172 mpp_err("failed to found task buffer for hardware\n");
173 return MPP_ERR_UNKNOW;
174 }
175 mpp_packet_set_pos(pkt, data + length);
176
177 /*
178 * this step will enable the task and goto parse stage
179 */
180 task->input_packet = p->task_pkt;
181 task->flags.eos = p->task_eos;
182 task->valid = 1;
183 return MPP_OK;
184 }
dummy_dec_parse(void * dec,HalDecTask * task)185 MPP_RET dummy_dec_parse(void *dec, HalDecTask *task)
186 {
187 DummyDec *p;
188 RK_S32 output;
189 MppFrame frame = NULL;
190 RK_U32 frame_count;
191 MppBufSlots slots;
192 RK_S32 i;
193 RK_U32 width, height;
194
195 if (NULL == dec) {
196 mpp_err_f("found NULL intput\n");
197 return MPP_ERR_NULL_PTR;
198 }
199 p = (DummyDec *)dec;
200
201 slots = p->frame_slots;
202 frame_count = p->frame_count;
203
204 width = DUMMY_DEC_FRAME_WIDTH;
205 height = DUMMY_DEC_FRAME_HEIGHT;
206
207 mpp_frame_init(&frame);
208
209 if (!p->slots_inited) {
210 mpp_buf_slot_setup(slots, DUMMY_DEC_FRAME_COUNT);
211 p->slots_inited = 1;
212 } else if (frame_count >= 2) {
213 // do info change test
214 width = DUMMY_DEC_FRAME_NEW_WIDTH;
215 height = DUMMY_DEC_FRAME_NEW_HEIGHT;
216 }
217
218 mpp_frame_set_width(frame, width);
219 mpp_frame_set_height(frame, height);
220 mpp_frame_set_hor_stride(frame, MPP_ALIGN(width, 16));
221 mpp_frame_set_ver_stride(frame, MPP_ALIGN(height, 16));
222
223 /*
224 * set slots information
225 * 1. output index MUST be set
226 * 2. get unused index for output if needed
227 * 3. set output index as hal_input
228 * 4. set frame information to output index
229 * 5. if one frame can be display, it SHOULD be enqueued to display queue
230 */
231 mpp_buf_slot_get_unused(slots, &output);
232 mpp_buf_slot_set_flag(slots, output, SLOT_HAL_OUTPUT);
233 task->output = output;
234
235 mpp_frame_set_pts(frame, p->task_pts);
236 mpp_buf_slot_set_prop(slots, output, SLOT_FRAME, frame);
237 mpp_frame_deinit(&frame);
238 mpp_assert(NULL == frame);
239
240 /*
241 * setup output task
242 * 1. valid flag MUST be set if need hardware to run once
243 * 2. set output slot index
244 * 3. set reference slot index
245 */
246 memset(&task->refer, -1, sizeof(task->refer));
247 for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) {
248 RK_S32 index = p->slot_index[i];
249 if (index >= 0) {
250 task->refer[i] = index;
251 mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT);
252 mpp_buf_slot_set_flag(slots, index, SLOT_CODEC_USE);
253 }
254 }
255
256 /*
257 * update dpb status assuming that hw has decoded the frame
258 */
259 mpp_buf_slot_set_flag(slots, output, SLOT_QUEUE_USE);
260 mpp_buf_slot_enqueue(slots, output, QUEUE_DISPLAY);
261
262 // add new reference buffer
263 if (p->task_eos) {
264 for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) {
265 mpp_buf_slot_clr_flag(slots, p->slot_index[i], SLOT_CODEC_USE);
266 p->slot_index[i] = -1;
267 }
268 } else {
269 // clear unreference buffer
270 RK_U32 replace_index = frame_count & 1;
271 if (p->slot_index[replace_index] >= 0)
272 mpp_buf_slot_clr_flag(slots, p->slot_index[replace_index], SLOT_CODEC_USE);
273
274 p->slot_index[replace_index] = output;
275 mpp_buf_slot_set_flag(slots, output, SLOT_CODEC_USE);
276 }
277
278 p->frame_count = ++frame_count;
279
280 return MPP_OK;
281 }
282
dummy_dec_callback(void * dec,void * err_info)283 MPP_RET dummy_dec_callback(void *dec, void *err_info)
284 {
285 (void)dec;
286 (void)err_info;
287 return MPP_OK;
288 }
289 const ParserApi dummy_dec_parser = {
290 .name = "dummy_dec_parser",
291 .coding = MPP_VIDEO_CodingUnused,
292 .ctx_size = sizeof(DummyDec),
293 .flag = 0,
294 .init = dummy_dec_init,
295 .deinit = dummy_dec_deinit,
296 .prepare = dummy_dec_prepare,
297 .parse = dummy_dec_parse,
298 .reset = dummy_dec_reset,
299 .flush = dummy_dec_flush,
300 .control = dummy_dec_control,
301 .callback = dummy_dec_callback,
302 };
303
304