xref: /rockchip-linux_mpp/test/mpi_dec_nt_test.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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