xref: /OK3568_Linux_fs/external/mpp/test/mpi_dec_test.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 #if defined(_WIN32)
18 #include "vld.h"
19 #endif
20 
21 #define MODULE_TAG "mpi_dec_test"
22 
23 #include <string.h>
24 #include "rk_mpi.h"
25 
26 #include "mpp_mem.h"
27 #include "mpp_env.h"
28 #include "mpp_time.h"
29 #include "mpp_common.h"
30 #include "mpi_dec_utils.h"
31 
32 typedef struct {
33     MpiDecTestCmd   *cmd;
34     MppCtx          ctx;
35     MppApi          *mpi;
36     RK_U32          quiet;
37 
38     /* end of stream flag when set quit the loop */
39     RK_U32          loop_end;
40 
41     /* input and output */
42     MppBufferGroup  frm_grp;
43     MppPacket       packet;
44     MppFrame        frame;
45 
46     FILE            *fp_output;
47     RK_S32          frame_count;
48     RK_S32          frame_num;
49 
50     RK_S64          first_pkt;
51     RK_S64          first_frm;
52 
53     size_t          max_usage;
54     float           frame_rate;
55     RK_S64          elapsed_time;
56     RK_S64          delay;
57     FILE            *fp_verify;
58     FrmCrc          checkcrc;
59 } MpiDecLoopData;
60 
dec_simple(MpiDecLoopData * data)61 static int dec_simple(MpiDecLoopData *data)
62 {
63     RK_U32 pkt_done = 0;
64     RK_U32 pkt_eos  = 0;
65     MPP_RET ret = MPP_OK;
66     MpiDecTestCmd *cmd = data->cmd;
67     MppCtx ctx  = data->ctx;
68     MppApi *mpi = data->mpi;
69     MppPacket packet = data->packet;
70     FileBufSlot *slot = NULL;
71     RK_U32 quiet = data->quiet;
72     FrmCrc *checkcrc = &data->checkcrc;
73 
74     // when packet size is valid read the input binary file
75     ret = reader_read(cmd->reader, &slot);
76 
77     mpp_assert(ret == MPP_OK);
78     mpp_assert(slot);
79 
80     pkt_eos = slot->eos;
81 
82     if (pkt_eos) {
83         if (data->frame_num < 0 || data->frame_num > data->frame_count) {
84             mpp_log_q(quiet, "%p loop again\n", ctx);
85             reader_rewind(cmd->reader);
86             pkt_eos = 0;
87         } else {
88             mpp_log_q(quiet, "%p found last packet\n", ctx);
89             data->loop_end = 1;
90         }
91     }
92 
93     mpp_packet_set_data(packet, slot->data);
94     mpp_packet_set_size(packet, slot->size);
95     mpp_packet_set_pos(packet, slot->data);
96     mpp_packet_set_length(packet, slot->size);
97     // setup eos flag
98     if (pkt_eos)
99         mpp_packet_set_eos(packet);
100 
101     do {
102         RK_U32 frm_eos = 0;
103         RK_S32 times = 30;
104 
105         // send the packet first if packet is not done
106         if (!pkt_done) {
107             ret = mpi->decode_put_packet(ctx, packet);
108             if (MPP_OK == ret) {
109                 pkt_done = 1;
110                 if (!data->first_pkt)
111                     data->first_pkt = mpp_time();
112             }
113         }
114 
115         // then get all available frame and release
116         do {
117             RK_S32 get_frm = 0;
118             MppFrame frame = NULL;
119 
120         try_again:
121             ret = mpi->decode_get_frame(ctx, &frame);
122             if (MPP_ERR_TIMEOUT == ret) {
123                 if (times > 0) {
124                     times--;
125                     msleep(1);
126                     goto try_again;
127                 }
128                 mpp_err("%p decode_get_frame failed too much time\n", ctx);
129             }
130             if (ret) {
131                 mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx);
132                 break;
133             }
134 
135             if (frame) {
136                 if (mpp_frame_get_info_change(frame)) {
137                     RK_U32 width = mpp_frame_get_width(frame);
138                     RK_U32 height = mpp_frame_get_height(frame);
139                     RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
140                     RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
141                     RK_U32 buf_size = mpp_frame_get_buf_size(frame);
142 
143                     mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
144                     mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
145                               ctx, width, height, hor_stride, ver_stride, buf_size);
146 
147                     /*
148                      * NOTE: We can choose decoder's buffer mode here.
149                      * There are three mode that decoder can support:
150                      *
151                      * Mode 1: Pure internal mode
152                      * In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP
153                      * control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY
154                      * to let decoder go on. Then decoder will use create buffer
155                      * internally and user need to release each frame they get.
156                      *
157                      * Advantage:
158                      * Easy to use and get a demo quickly
159                      * Disadvantage:
160                      * 1. The buffer from decoder may not be return before
161                      * decoder is close. So memroy leak or crash may happen.
162                      * 2. The decoder memory usage can not be control. Decoder
163                      * is on a free-to-run status and consume all memory it can
164                      * get.
165                      * 3. Difficult to implement zero-copy display path.
166                      *
167                      * Mode 2: Half internal mode
168                      * This is the mode current test code using. User need to
169                      * create MppBufferGroup according to the returned info
170                      * change MppFrame. User can use mpp_buffer_group_limit_config
171                      * function to limit decoder memory usage.
172                      *
173                      * Advantage:
174                      * 1. Easy to use
175                      * 2. User can release MppBufferGroup after decoder is closed.
176                      *    So memory can stay longer safely.
177                      * 3. Can limit the memory usage by mpp_buffer_group_limit_config
178                      * Disadvantage:
179                      * 1. The buffer limitation is still not accurate. Memory usage
180                      * is 100% fixed.
181                      * 2. Also difficult to implement zero-copy display path.
182                      *
183                      * Mode 3: Pure external mode
184                      * In this mode use need to create empty MppBufferGroup and
185                      * import memory from external allocator by file handle.
186                      * On Android surfaceflinger will create buffer. Then
187                      * mediaserver get the file handle from surfaceflinger and
188                      * commit to decoder's MppBufferGroup.
189                      *
190                      * Advantage:
191                      * 1. Most efficient way for zero-copy display
192                      * Disadvantage:
193                      * 1. Difficult to learn and use.
194                      * 2. Player work flow may limit this usage.
195                      * 3. May need a external parser to get the correct buffer
196                      * size for the external allocator.
197                      *
198                      * The required buffer size caculation:
199                      * hor_stride * ver_stride * 3 / 2 for pixel data
200                      * hor_stride * ver_stride / 2 for extra info
201                      * Total hor_stride * ver_stride * 2 will be enough.
202                      *
203                      * For H.264/H.265 20+ buffers will be enough.
204                      * For other codec 10 buffers will be enough.
205                      */
206 
207                     if (NULL == data->frm_grp) {
208                         /* If buffer group is not set create one and limit it */
209                         ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION);
210                         if (ret) {
211                             mpp_err("%p get mpp buffer group failed ret %d\n", ctx, ret);
212                             break;
213                         }
214 
215                         /* Set buffer to mpp decoder */
216                         ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
217                         if (ret) {
218                             mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
219                             break;
220                         }
221                     } else {
222                         /* If old buffer group exist clear it */
223                         ret = mpp_buffer_group_clear(data->frm_grp);
224                         if (ret) {
225                             mpp_err("%p clear buffer group failed ret %d\n", ctx, ret);
226                             break;
227                         }
228                     }
229 
230                     /* Use limit config to limit buffer count to 24 with buf_size */
231                     ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
232                     if (ret) {
233                         mpp_err("%p limit buffer group failed ret %d\n", ctx, ret);
234                         break;
235                     }
236 
237                     /*
238                      * All buffer group config done. Set info change ready to let
239                      * decoder continue decoding
240                      */
241                     ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
242                     if (ret) {
243                         mpp_err("%p info change ready failed ret %d\n", ctx, ret);
244                         break;
245                     }
246                 } else {
247                     char log_buf[256];
248                     RK_S32 log_size = sizeof(log_buf) - 1;
249                     RK_S32 log_len = 0;
250                     RK_U32 err_info = mpp_frame_get_errinfo(frame);
251                     RK_U32 discard = mpp_frame_get_discard(frame);
252 
253                     if (!data->first_frm)
254                         data->first_frm = mpp_time();
255 
256                     log_len += snprintf(log_buf + log_len, log_size - log_len,
257                                         "decode get frame %d", data->frame_count);
258 
259                     if (mpp_frame_has_meta(frame)) {
260                         MppMeta meta = mpp_frame_get_meta(frame);
261                         RK_S32 temporal_id = 0;
262 
263                         mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id);
264 
265                         log_len += snprintf(log_buf + log_len, log_size - log_len,
266                                             " tid %d", temporal_id);
267                     }
268 
269                     if (err_info || discard) {
270                         log_len += snprintf(log_buf + log_len, log_size - log_len,
271                                             " err %x discard %x", err_info, discard);
272                     }
273                     mpp_log_q(quiet, "%p %s\n", ctx, log_buf);
274 
275                     data->frame_count++;
276                     if (data->fp_output && !err_info)
277                         dump_mpp_frame_to_file(frame, data->fp_output);
278 
279                     if (data->fp_verify) {
280                         calc_frm_crc(frame, checkcrc);
281                         write_frm_crc(data->fp_verify, checkcrc);
282                     }
283 
284                     fps_calc_inc(cmd->fps);
285                 }
286                 frm_eos = mpp_frame_get_eos(frame);
287                 mpp_frame_deinit(&frame);
288                 get_frm = 1;
289             }
290 
291             // try get runtime frame memory usage
292             if (data->frm_grp) {
293                 size_t usage = mpp_buffer_group_usage(data->frm_grp);
294                 if (usage > data->max_usage)
295                     data->max_usage = usage;
296             }
297 
298             // if last packet is send but last frame is not found continue
299             if (pkt_eos && pkt_done && !frm_eos) {
300                 msleep(1);
301                 continue;
302             }
303 
304             if (frm_eos) {
305                 mpp_log_q(quiet, "%p found last packet\n", ctx);
306                 break;
307             }
308 
309             if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) ||
310                 ((data->frame_num == 0) && frm_eos))
311                 break;
312 
313             if (get_frm)
314                 continue;
315             break;
316         } while (1);
317 
318         if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) ||
319             ((data->frame_num == 0) && frm_eos)) {
320             data->loop_end = 1;
321             break;
322         }
323 
324         if (pkt_done)
325             break;
326 
327         /*
328          * why sleep here:
329          * mpi->decode_put_packet will failed when packet in internal queue is
330          * full,waiting the package is consumed .Usually hardware decode one
331          * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms
332          * * is enough.
333          */
334         msleep(1);
335     } while (1);
336 
337     return ret;
338 }
339 
dec_advanced(MpiDecLoopData * data)340 static int dec_advanced(MpiDecLoopData *data)
341 {
342     MPP_RET ret = MPP_OK;
343     MpiDecTestCmd *cmd = data->cmd;
344     MppCtx ctx  = data->ctx;
345     MppApi *mpi = data->mpi;
346     MppPacket packet = NULL;
347     MppFrame  frame  = data->frame;
348     MppTask task = NULL;
349     RK_U32 quiet = data->quiet;
350     FileBufSlot *slot = NULL;
351     FrmCrc *checkcrc = &data->checkcrc;
352 
353     ret = reader_index_read(cmd->reader, 0, &slot);
354     mpp_assert(ret == MPP_OK);
355     mpp_assert(slot);
356 
357     mpp_packet_init_with_buffer(&packet, slot->buf);
358 
359     // setup eos flag
360     if (slot->eos)
361         mpp_packet_set_eos(packet);
362 
363     ret = mpi->poll(ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
364     if (ret) {
365         mpp_err("%p mpp input poll failed\n", ctx);
366         return ret;
367     }
368 
369     ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task);  /* input queue */
370     if (ret) {
371         mpp_err("%p mpp task input dequeue failed\n", ctx);
372         return ret;
373     }
374 
375     mpp_assert(task);
376 
377     mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet);
378     mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME,  frame);
379 
380     ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task);  /* input queue */
381     if (ret) {
382         mpp_err("%p mpp task input enqueue failed\n", ctx);
383         return ret;
384     }
385 
386     if (!data->first_pkt)
387         data->first_pkt = mpp_time();
388 
389     /* poll and wait here */
390     ret = mpi->poll(ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK);
391     if (ret) {
392         mpp_err("%p mpp output poll failed\n", ctx);
393         return ret;
394     }
395 
396     ret = mpi->dequeue(ctx, MPP_PORT_OUTPUT, &task); /* output queue */
397     if (ret) {
398         mpp_err("%p mpp task output dequeue failed\n", ctx);
399         return ret;
400     }
401 
402     mpp_assert(task);
403 
404     if (task) {
405         MppFrame frame_out = NULL;
406 
407         mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out);
408 
409         if (frame) {
410             if (!data->first_frm)
411                 data->first_frm = mpp_time();
412 
413             /* write frame to file here */
414             if (data->fp_output)
415                 dump_mpp_frame_to_file(frame, data->fp_output);
416 
417             if (data->fp_verify) {
418                 calc_frm_crc(frame, checkcrc);
419                 write_frm_crc(data->fp_verify, checkcrc);
420             }
421 
422             mpp_log_q(quiet, "%p decoded frame %d\n", ctx, data->frame_count);
423             data->frame_count++;
424 
425             if (mpp_frame_get_eos(frame_out)) {
426                 mpp_log_q(quiet, "%p found eos frame\n", ctx);
427             }
428             fps_calc_inc(cmd->fps);
429         }
430 
431         if (data->frame_num > 0) {
432             if (data->frame_count >= data->frame_num)
433                 data->loop_end = 1;
434         } else if (data->frame_num == 0) {
435             if (slot->eos)
436                 data->loop_end = 1;
437         }
438 
439         /* output queue */
440         ret = mpi->enqueue(ctx, MPP_PORT_OUTPUT, task);
441         if (ret)
442             mpp_err("%p mpp task output enqueue failed\n", ctx);
443     }
444 
445     /*
446      * The following input port task dequeue and enqueue is to make sure that
447      * the input packet can be released. We can directly deinit the input packet
448      * after frame output in most cases.
449      */
450     if (0) {
451         mpp_packet_deinit(&packet);
452     } else {
453         ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task);  /* input queue */
454         if (ret) {
455             mpp_err("%p mpp task input dequeue failed\n", ctx);
456             return ret;
457         }
458 
459         mpp_assert(task);
460         if (task) {
461             MppPacket packet_out = NULL;
462 
463             mpp_task_meta_get_packet(task, KEY_INPUT_PACKET, &packet_out);
464 
465             if (!packet_out || packet_out != packet)
466                 mpp_err_f("mismatch packet %p -> %p\n", packet, packet_out);
467 
468             mpp_packet_deinit(&packet_out);
469 
470             /* input empty task back to mpp to maintain task status */
471             ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task);
472             if (ret)
473                 mpp_err("%p mpp task input enqueue failed\n", ctx);
474         }
475     }
476 
477     return ret;
478 }
479 
thread_decode(void * arg)480 void *thread_decode(void *arg)
481 {
482     MpiDecLoopData *data = (MpiDecLoopData *)arg;
483     MpiDecTestCmd *cmd = data->cmd;
484     MppCtx ctx  = data->ctx;
485     MppApi *mpi = data->mpi;
486     RK_S64 t_s, t_e;
487 
488     memset(&data->checkcrc, 0, sizeof(data->checkcrc));
489     data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512);
490     data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512);
491 
492     t_s = mpp_time();
493 
494     if (cmd->simple) {
495         while (!data->loop_end)
496             dec_simple(data);
497     } else {
498         /* NOTE: change output format before jpeg decoding */
499         if (MPP_FRAME_FMT_IS_YUV(cmd->format) || MPP_FRAME_FMT_IS_RGB(cmd->format)) {
500             MPP_RET ret = mpi->control(ctx, MPP_DEC_SET_OUTPUT_FORMAT, &cmd->format);
501             if (ret) {
502                 mpp_err("Failed to set output format %d\n", cmd->format);
503                 return NULL;
504             }
505         }
506 
507         while (!data->loop_end)
508             dec_advanced(data);
509     }
510 
511     t_e = mpp_time();
512     data->elapsed_time = t_e - t_s;
513     data->frame_count = data->frame_count;
514     data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time;
515     data->delay = data->first_frm - data->first_pkt;
516 
517     mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n",
518             data->frame_count, (RK_S64)(data->elapsed_time / 1000),
519             (RK_S32)(data->delay / 1000), data->frame_rate);
520 
521     MPP_FREE(data->checkcrc.luma.sum);
522     MPP_FREE(data->checkcrc.chroma.sum);
523 
524     return NULL;
525 }
526 
dec_decode(MpiDecTestCmd * cmd)527 int dec_decode(MpiDecTestCmd *cmd)
528 {
529     // base flow context
530     MppCtx ctx          = NULL;
531     MppApi *mpi         = NULL;
532 
533     // input / output
534     MppPacket packet    = NULL;
535     MppFrame  frame     = NULL;
536 
537     // paramter for resource malloc
538     RK_U32 width        = cmd->width;
539     RK_U32 height       = cmd->height;
540     MppCodingType type  = cmd->type;
541 
542     // config for runtime mode
543     MppDecCfg cfg       = NULL;
544     RK_U32 need_split   = 1;
545 
546     // resources
547     MppBuffer frm_buf   = NULL;
548     pthread_t thd;
549     pthread_attr_t attr;
550     MpiDecLoopData data;
551     MPP_RET ret = MPP_OK;
552 
553     mpp_log("mpi_dec_test start\n");
554     memset(&data, 0, sizeof(data));
555     pthread_attr_init(&attr);
556 
557     cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0);
558 
559     if (cmd->have_output) {
560         data.fp_output = fopen(cmd->file_output, "w+b");
561         if (NULL == data.fp_output) {
562             mpp_err("failed to open output file %s\n", cmd->file_output);
563             goto MPP_TEST_OUT;
564         }
565     }
566 
567     if (cmd->file_slt) {
568         data.fp_verify = fopen(cmd->file_slt, "wt");
569         if (!data.fp_verify)
570             mpp_err("failed to open verify file %s\n", cmd->file_slt);
571     }
572 
573     if (cmd->simple) {
574         ret = mpp_packet_init(&packet, NULL, 0);
575         if (ret) {
576             mpp_err("mpp_packet_init failed\n");
577             goto MPP_TEST_OUT;
578         }
579     } else {
580         RK_U32 hor_stride = MPP_ALIGN(width, 16);
581         RK_U32 ver_stride = MPP_ALIGN(height, 16);
582 
583         ret = mpp_buffer_group_get_internal(&data.frm_grp, MPP_BUFFER_TYPE_ION);
584         if (ret) {
585             mpp_err("failed to get buffer group for input frame ret %d\n", ret);
586             goto MPP_TEST_OUT;
587         }
588 
589         ret = mpp_frame_init(&frame); /* output frame */
590         if (ret) {
591             mpp_err("mpp_frame_init failed\n");
592             goto MPP_TEST_OUT;
593         }
594 
595         /*
596          * NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
597          * larger for output. And the buffer dimension should align to 16.
598          * YUV420 buffer is 3/2 times of w*h.
599          * YUV422 buffer is 2 times of w*h.
600          * So create larger buffer with 2 times w*h.
601          */
602         ret = mpp_buffer_get(data.frm_grp, &frm_buf, hor_stride * ver_stride * 4);
603         if (ret) {
604             mpp_err("failed to get buffer for input frame ret %d\n", ret);
605             goto MPP_TEST_OUT;
606         }
607 
608         mpp_frame_set_buffer(frame, frm_buf);
609     }
610 
611     // decoder demo
612     ret = mpp_create(&ctx, &mpi);
613     if (ret) {
614         mpp_err("mpp_create failed\n");
615         goto MPP_TEST_OUT;
616     }
617 
618     mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n",
619             ctx, width, height, type);
620 
621     ret = mpp_init(ctx, MPP_CTX_DEC, type);
622     if (ret) {
623         mpp_err("%p mpp_init failed\n", ctx);
624         goto MPP_TEST_OUT;
625     }
626 
627     mpp_dec_cfg_init(&cfg);
628 
629     /* get default config from decoder context */
630     ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
631     if (ret) {
632         mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
633         goto MPP_TEST_OUT;
634     }
635 
636     /*
637      * split_parse is to enable mpp internal frame spliter when the input
638      * packet is not aplited into frames.
639      */
640     ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
641     if (ret) {
642         mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
643         goto MPP_TEST_OUT;
644     }
645 
646     ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
647     if (ret) {
648         mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
649         goto MPP_TEST_OUT;
650     }
651 
652     data.cmd            = cmd;
653     data.ctx            = ctx;
654     data.mpi            = mpi;
655     data.loop_end       = 0;
656     data.packet         = packet;
657     data.frame          = frame;
658     data.frame_count    = 0;
659     data.frame_num      = cmd->frame_num;
660     data.quiet          = cmd->quiet;
661 
662     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
663 
664     ret = pthread_create(&thd, &attr, thread_decode, &data);
665     if (ret) {
666         mpp_err("failed to create thread for input ret %d\n", ret);
667         goto MPP_TEST_OUT;
668     }
669 
670     if (cmd->frame_num < 0) {
671         // wait for input then quit decoding
672         mpp_log("*******************************************\n");
673         mpp_log("**** Press Enter to stop loop decoding ****\n");
674         mpp_log("*******************************************\n");
675 
676         getc(stdin);
677         data.loop_end = 1;
678     }
679 
680     pthread_join(thd, NULL);
681 
682     cmd->max_usage = data.max_usage;
683 
684     ret = mpi->reset(ctx);
685     if (ret) {
686         mpp_err("%p mpi->reset failed\n", ctx);
687         goto MPP_TEST_OUT;
688     }
689 
690 MPP_TEST_OUT:
691     if (data.packet) {
692         mpp_packet_deinit(&data.packet);
693         data.packet = NULL;
694     }
695 
696     if (frame) {
697         mpp_frame_deinit(&frame);
698         frame = NULL;
699     }
700 
701     if (ctx) {
702         mpp_destroy(ctx);
703         ctx = NULL;
704     }
705 
706     if (!cmd->simple) {
707         if (frm_buf) {
708             mpp_buffer_put(frm_buf);
709             frm_buf = NULL;
710         }
711     }
712 
713     if (data.frm_grp) {
714         mpp_buffer_group_put(data.frm_grp);
715         data.frm_grp = NULL;
716     }
717 
718     if (data.fp_output) {
719         fclose(data.fp_output);
720         data.fp_output = NULL;
721     }
722 
723     if (data.fp_verify) {
724         fclose(data.fp_verify);
725         data.fp_verify = NULL;
726     }
727 
728     if (cfg) {
729         mpp_dec_cfg_deinit(cfg);
730         cfg = NULL;
731     }
732 
733     pthread_attr_destroy(&attr);
734 
735     return ret;
736 }
737 
main(int argc,char ** argv)738 int main(int argc, char **argv)
739 {
740     RK_S32 ret = 0;
741     MpiDecTestCmd  cmd_ctx;
742     MpiDecTestCmd* cmd = &cmd_ctx;
743 
744     memset((void*)cmd, 0, sizeof(*cmd));
745     cmd->format = MPP_FMT_BUTT;
746     cmd->pkt_size = MPI_DEC_STREAM_SIZE;
747 
748     // parse the cmd option
749     ret = mpi_dec_test_cmd_init(cmd, argc, argv);
750     if (ret)
751         goto RET;
752 
753     mpi_dec_test_cmd_options(cmd);
754 
755     ret = dec_decode(cmd);
756     if (MPP_OK == ret)
757         mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20));
758     else
759         mpp_err("test failed ret %d\n", ret);
760 
761 RET:
762     mpi_dec_test_cmd_deinit(cmd);
763 
764     return ret;
765 }
766 
767