1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
4 */
5
6 #if defined(_WIN32)
7 #include "vld.h"
8 #endif
9
10 #define MODULE_TAG "mpi_dec_nt_test"
11
12 #include <string.h>
13 #include "rk_mpi.h"
14
15 #include "mpp_mem.h"
16 #include "mpp_env.h"
17 #include "mpp_time.h"
18 #include "mpp_common.h"
19 #include "mpi_dec_utils.h"
20
21 typedef struct {
22 MpiDecTestCmd *cmd;
23 MppCtx ctx;
24 MppApi *mpi;
25 RK_U32 quiet;
26
27 /* end of stream flag when set quit the loop */
28 RK_U32 loop_end;
29
30 /* input and output */
31 DecBufMgr buf_mgr;
32 MppBufferGroup frm_grp;
33 MppPacket packet;
34 MppFrame frame;
35
36 FILE *fp_output;
37 RK_S32 frame_count;
38 RK_S32 frame_num;
39
40 RK_S64 first_pkt;
41 RK_S64 first_frm;
42
43 size_t max_usage;
44 float frame_rate;
45 RK_S64 elapsed_time;
46 RK_S64 delay;
47 FILE *fp_verify;
48 FrmCrc checkcrc;
49 } MpiDecLoopData;
50
dec_loop(MpiDecLoopData * data)51 static int dec_loop(MpiDecLoopData *data)
52 {
53 RK_U32 pkt_done = 0;
54 RK_U32 pkt_eos = 0;
55 MPP_RET ret = MPP_OK;
56 MpiDecTestCmd *cmd = data->cmd;
57 MppCtx ctx = data->ctx;
58 MppApi *mpi = data->mpi;
59 MppPacket packet = data->packet;
60 FileBufSlot *slot = NULL;
61 RK_U32 quiet = data->quiet;
62 FrmCrc *checkcrc = &data->checkcrc;
63
64 // when packet size is valid read the input binary file
65 ret = reader_read(cmd->reader, &slot);
66
67 mpp_assert(ret == MPP_OK);
68 mpp_assert(slot);
69
70 pkt_eos = slot->eos;
71
72 if (pkt_eos) {
73 if (data->frame_num < 0 || data->frame_num > data->frame_count) {
74 mpp_log_q(quiet, "%p loop again\n", ctx);
75 reader_rewind(cmd->reader);
76 pkt_eos = 0;
77 } else {
78 mpp_log_q(quiet, "%p found last packet\n", ctx);
79 data->loop_end = 1;
80 }
81 }
82
83 if (!slot->buf) {
84 /* non-jpeg decoding */
85 mpp_packet_set_data(packet, slot->data);
86 mpp_packet_set_size(packet, slot->size);
87 mpp_packet_set_pos(packet, slot->data);
88 mpp_packet_set_length(packet, slot->size);
89 } else {
90 /* jpeg decoding */
91 void *buf = mpp_buffer_get_ptr(slot->buf);
92 size_t size = mpp_buffer_get_size(slot->buf);
93
94 mpp_packet_set_data(packet, buf);
95 mpp_packet_set_size(packet, size);
96 mpp_packet_set_pos(packet, buf);
97 mpp_packet_set_length(packet, size);
98 mpp_packet_set_buffer(packet, slot->buf);
99 }
100
101 // setup eos flag
102 if (pkt_eos)
103 mpp_packet_set_eos(packet);
104
105 do {
106 RK_U32 frm_eos = 0;
107 RK_S32 get_frm = 0;
108 MppFrame frame = NULL;
109
110 // send the packet first if packet is not done
111 ret = mpi->decode(ctx, packet, &frame);
112 if (ret)
113 mpp_err("decode failed ret %d\n", ret);
114
115 // then get all available frame and release
116 if (frame) {
117 if (mpp_frame_get_info_change(frame)) {
118 RK_U32 width = mpp_frame_get_width(frame);
119 RK_U32 height = mpp_frame_get_height(frame);
120 RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
121 RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
122 RK_U32 buf_size = mpp_frame_get_buf_size(frame);
123 MppBufferGroup grp = NULL;
124
125 mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
126 mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
127 ctx, width, height, hor_stride, ver_stride, buf_size);
128
129 if (MPP_FRAME_FMT_IS_FBC(cmd->format)) {
130 MppFrame frm = NULL;
131
132 mpp_frame_init(&frm);
133 mpp_frame_set_width(frm, width);
134 mpp_frame_set_height(frm, height);
135 mpp_frame_set_fmt(frm, cmd->format);
136
137 ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm);
138 mpp_frame_deinit(&frm);
139
140 if (ret) {
141 mpp_err("set fbc frame info failed\n");
142 break;
143 }
144 }
145
146 grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
147 /* Set buffer to mpp decoder */
148 ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
149 if (ret) {
150 mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
151 break;
152 }
153
154 data->frm_grp = grp;
155
156 /*
157 * All buffer group config done. Set info change ready to let
158 * decoder continue decoding
159 */
160 ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
161 if (ret) {
162 mpp_err("%p info change ready failed ret %d\n", ctx, ret);
163 break;
164 }
165
166 mpp_frame_deinit(&frame);
167 continue;
168 } else {
169 char log_buf[256];
170 RK_S32 log_size = sizeof(log_buf) - 1;
171 RK_S32 log_len = 0;
172 RK_U32 err_info = mpp_frame_get_errinfo(frame);
173 RK_U32 discard = mpp_frame_get_discard(frame);
174
175 if (!data->first_frm)
176 data->first_frm = mpp_time();
177
178 log_len += snprintf(log_buf + log_len, log_size - log_len,
179 "decode get frame %d", data->frame_count);
180
181 if (mpp_frame_has_meta(frame)) {
182 MppMeta meta = mpp_frame_get_meta(frame);
183 RK_S32 temporal_id = 0;
184
185 mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id);
186
187 log_len += snprintf(log_buf + log_len, log_size - log_len,
188 " tid %d", temporal_id);
189 }
190
191 if (err_info || discard) {
192 log_len += snprintf(log_buf + log_len, log_size - log_len,
193 " err %x discard %x", err_info, discard);
194 }
195 mpp_log_q(quiet, "%p %s\n", ctx, log_buf);
196
197 data->frame_count++;
198 if (data->fp_output && !err_info)
199 dump_mpp_frame_to_file(frame, data->fp_output);
200
201 if (data->fp_verify) {
202 calc_frm_crc(frame, checkcrc);
203 write_frm_crc(data->fp_verify, checkcrc);
204 }
205
206 fps_calc_inc(cmd->fps);
207 }
208 frm_eos = mpp_frame_get_eos(frame);
209 mpp_frame_deinit(&frame);
210 get_frm = 1;
211 }
212
213 // try get runtime frame memory usage
214 if (data->frm_grp) {
215 size_t usage = mpp_buffer_group_usage(data->frm_grp);
216 if (usage > data->max_usage)
217 data->max_usage = usage;
218 }
219
220 // when get one output frame check the output frame count limit
221 if (get_frm) {
222 if (data->frame_num > 0) {
223 // when get enough frame quit
224 if (data->frame_count >= data->frame_num) {
225 data->loop_end = 1;
226 break;
227 }
228 } else {
229 // when get last frame quit
230 if (frm_eos) {
231 mpp_log_q(quiet, "%p found last packet\n", ctx);
232 data->loop_end = 1;
233 break;
234 }
235 }
236 }
237
238 if (packet) {
239 if (mpp_packet_get_length(packet)) {
240 msleep(1);
241 continue;
242 }
243
244 if (!data->first_pkt)
245 data->first_pkt = mpp_time();
246
247 packet = NULL;
248 pkt_done = 1;
249 }
250
251 mpp_assert(pkt_done);
252
253 // if last packet is send but last frame is not found continue
254 if (pkt_eos && !frm_eos) {
255 msleep(1);
256 continue;
257 }
258
259 if (pkt_done)
260 break;
261
262 /*
263 * why sleep here:
264 * mpi->decode_put_packet will failed when packet in internal queue is
265 * full,waiting the package is consumed .Usually hardware decode one
266 * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms
267 * * is enough.
268 */
269 msleep(1);
270 } while (1);
271
272 return ret;
273 }
274
thread_decode(void * arg)275 void *thread_decode(void *arg)
276 {
277 MpiDecLoopData *data = (MpiDecLoopData *)arg;
278 RK_S64 t_s, t_e;
279
280 memset(&data->checkcrc, 0, sizeof(data->checkcrc));
281 data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512);
282 data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512);
283
284 t_s = mpp_time();
285
286 while (!data->loop_end)
287 dec_loop(data);
288
289 t_e = mpp_time();
290 data->elapsed_time = t_e - t_s;
291 data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time;
292 data->delay = data->first_frm - data->first_pkt;
293
294 mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n",
295 data->frame_count, (RK_S64)(data->elapsed_time / 1000),
296 (RK_S32)(data->delay / 1000), data->frame_rate);
297
298 MPP_FREE(data->checkcrc.luma.sum);
299 MPP_FREE(data->checkcrc.chroma.sum);
300
301 return NULL;
302 }
303
dec_nt_decode(MpiDecTestCmd * cmd)304 int dec_nt_decode(MpiDecTestCmd *cmd)
305 {
306 // base flow context
307 MppCtx ctx = NULL;
308 MppApi *mpi = NULL;
309
310 // input / output
311 MppPacket packet = NULL;
312 MppFrame frame = NULL;
313
314 // paramter for resource malloc
315 RK_U32 width = cmd->width;
316 RK_U32 height = cmd->height;
317 MppCodingType type = cmd->type;
318
319 // config for runtime mode
320 MppDecCfg cfg = NULL;
321 RK_U32 need_split = 1;
322
323 // resources
324 MppBuffer frm_buf = NULL;
325 pthread_t thd;
326 pthread_attr_t attr;
327 MpiDecLoopData data;
328 MPP_RET ret = MPP_OK;
329
330 mpp_log("mpi_dec_test start\n");
331 memset(&data, 0, sizeof(data));
332 pthread_attr_init(&attr);
333
334 cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0);
335
336 if (cmd->have_output) {
337 data.fp_output = fopen(cmd->file_output, "w+b");
338 if (NULL == data.fp_output) {
339 mpp_err("failed to open output file %s\n", cmd->file_output);
340 goto MPP_TEST_OUT;
341 }
342 }
343
344 if (cmd->file_slt) {
345 data.fp_verify = fopen(cmd->file_slt, "wt");
346 if (!data.fp_verify)
347 mpp_err("failed to open verify file %s\n", cmd->file_slt);
348 }
349
350 ret = dec_buf_mgr_init(&data.buf_mgr);
351 if (ret) {
352 mpp_err("dec_buf_mgr_init failed\n");
353 goto MPP_TEST_OUT;
354 }
355
356 ret = mpp_packet_init(&packet, NULL, 0);
357 mpp_err_f("mpp_packet_init get %p\n", packet);
358 if (ret) {
359 mpp_err("mpp_packet_init failed\n");
360 goto MPP_TEST_OUT;
361 }
362
363 // decoder demo
364 ret = mpp_create(&ctx, &mpi);
365 if (ret) {
366 mpp_err("mpp_create failed\n");
367 goto MPP_TEST_OUT;
368 }
369
370 mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n",
371 ctx, width, height, type);
372
373 ret = mpi->control(ctx, MPP_SET_DISABLE_THREAD, NULL);
374
375 ret = mpp_init(ctx, MPP_CTX_DEC, type);
376 if (ret) {
377 mpp_err("%p mpp_init failed\n", ctx);
378 goto MPP_TEST_OUT;
379 }
380
381 mpp_dec_cfg_init(&cfg);
382
383 /* get default config from decoder context */
384 ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
385 if (ret) {
386 mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
387 goto MPP_TEST_OUT;
388 }
389
390 /*
391 * split_parse is to enable mpp internal frame spliter when the input
392 * packet is not aplited into frames.
393 */
394 ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
395 if (ret) {
396 mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
397 goto MPP_TEST_OUT;
398 }
399
400 ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
401 if (ret) {
402 mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
403 goto MPP_TEST_OUT;
404 }
405
406 data.cmd = cmd;
407 data.ctx = ctx;
408 data.mpi = mpi;
409 data.loop_end = 0;
410 data.packet = packet;
411 data.frame = frame;
412 data.frame_count = 0;
413 data.frame_num = cmd->frame_num;
414 data.quiet = cmd->quiet;
415
416 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
417
418 ret = pthread_create(&thd, &attr, thread_decode, &data);
419 if (ret) {
420 mpp_err("failed to create thread for input ret %d\n", ret);
421 goto MPP_TEST_OUT;
422 }
423
424 if (cmd->frame_num < 0) {
425 // wait for input then quit decoding
426 mpp_log("*******************************************\n");
427 mpp_log("**** Press Enter to stop loop decoding ****\n");
428 mpp_log("*******************************************\n");
429
430 getc(stdin);
431 data.loop_end = 1;
432 }
433
434 pthread_join(thd, NULL);
435
436 cmd->max_usage = data.max_usage;
437
438 ret = mpi->reset(ctx);
439 if (ret) {
440 mpp_err("%p mpi->reset failed\n", ctx);
441 goto MPP_TEST_OUT;
442 }
443
444 MPP_TEST_OUT:
445 if (data.packet) {
446 mpp_packet_deinit(&data.packet);
447 data.packet = NULL;
448 }
449
450 if (frame) {
451 mpp_frame_deinit(&frame);
452 frame = NULL;
453 }
454
455 if (ctx) {
456 mpp_destroy(ctx);
457 ctx = NULL;
458 }
459
460 if (!cmd->simple) {
461 if (frm_buf) {
462 mpp_buffer_put(frm_buf);
463 frm_buf = NULL;
464 }
465 }
466
467 data.frm_grp = NULL;
468 if (data.buf_mgr) {
469 dec_buf_mgr_deinit(data.buf_mgr);
470 data.buf_mgr = NULL;
471 }
472
473 if (data.fp_output) {
474 fclose(data.fp_output);
475 data.fp_output = NULL;
476 }
477
478 if (data.fp_verify) {
479 fclose(data.fp_verify);
480 data.fp_verify = NULL;
481 }
482
483 if (cfg) {
484 mpp_dec_cfg_deinit(cfg);
485 cfg = NULL;
486 }
487
488 pthread_attr_destroy(&attr);
489
490 return ret;
491 }
492
main(int argc,char ** argv)493 int main(int argc, char **argv)
494 {
495 RK_S32 ret = 0;
496 MpiDecTestCmd cmd_ctx;
497 MpiDecTestCmd* cmd = &cmd_ctx;
498
499 memset((void*)cmd, 0, sizeof(*cmd));
500 cmd->format = MPP_FMT_BUTT;
501 cmd->pkt_size = MPI_DEC_STREAM_SIZE;
502
503 // parse the cmd option
504 ret = mpi_dec_test_cmd_init(cmd, argc, argv);
505 if (ret)
506 goto RET;
507
508 mpi_dec_test_cmd_options(cmd);
509
510 ret = dec_nt_decode(cmd);
511 if (MPP_OK == ret)
512 mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20));
513 else
514 mpp_err("test failed ret %d\n", ret);
515
516 RET:
517 mpi_dec_test_cmd_deinit(cmd);
518
519 return ret;
520 }
521
522