xref: /rockchip-linux_mpp/utils/mpi_dec_utils.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2020 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 "mpi_dec_utils"
18 
19 #include <string.h>
20 #include <pthread.h>
21 
22 #include "rk_mpi.h"
23 
24 #include "mpp_env.h"
25 #include "mpp_mem.h"
26 #include "mpp_lock.h"
27 #include "mpp_time.h"
28 #include "mpp_common.h"
29 #include "mpp_buffer.h"
30 
31 #include "mpp_opt.h"
32 #include "mpi_dec_utils.h"
33 
34 #define IVF_HEADER_LENGTH           32
35 #define IVF_FRAME_HEADER_LENGTH     12
36 
37 #define DEFAULT_PACKET_SIZE         SZ_4K
38 
39 typedef enum {
40     FILE_NORMAL_TYPE,
41     FILE_JPEG_TYPE,
42     FILE_IVF_TYPE,
43     FILE_BUTT,
44 } FileType;
45 
46 typedef FileBufSlot *(*ReaderFunc)(FileReader data);
47 
48 typedef struct FileReader_t {
49     FILE            *fp_input;
50     size_t          file_size;
51 
52     MppCodingType   type;
53     FileType        file_type;
54     char            *buf;
55     size_t          buf_size;
56     size_t          stuff_size;
57     RK_S32          seek_base;
58     ReaderFunc      read_func;
59 
60     /* return value for each read */
61     size_t          read_total;
62     size_t          read_size;
63     MppBufferGroup  group;
64 
65     pthread_t       thd;
66     volatile RK_U32 thd_stop;
67 
68     RK_U32          slot_max;
69     RK_U32          slot_cnt;
70     RK_U32          slot_rd_idx;
71     FileBufSlot     **slots;
72 } FileReaderImpl;
73 
74 typedef struct DecBufMgrImpl_t {
75     MppDecBufMode   buf_mode;
76     RK_U32          buf_count;
77     RK_U32          buf_size;
78     MppBufferGroup  group;
79     MppBuffer       *bufs;
80 } DecBufMgrImpl;
81 
82 #define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
83 
add_new_slot(FileReaderImpl * impl,FileBufSlot * slot)84 static MPP_RET add_new_slot(FileReaderImpl* impl, FileBufSlot *slot)
85 {
86     mpp_assert(impl);
87 
88     slot->index = impl->slot_cnt;
89     impl->slots[impl->slot_cnt] = slot;
90     impl->slot_cnt++;
91 
92     if (impl->slot_cnt >= impl->slot_max) {
93         impl->slots = mpp_realloc(impl->slots, FileBufSlot*, impl->slot_max * 2);
94         if (!impl->slots)
95             return MPP_NOK;
96 
97         impl->slot_max *= 2;
98     }
99 
100     mpp_assert(impl->slots);
101     mpp_assert(impl->slot_cnt < impl->slot_max);
102 
103     return MPP_OK;
104 }
105 
read_ivf_file(FileReader data)106 static FileBufSlot *read_ivf_file(FileReader data)
107 {
108     FileReaderImpl *impl = (FileReaderImpl*)data;
109     RK_U8 ivf_data[IVF_FRAME_HEADER_LENGTH] = {0};
110     size_t ivf_data_size = IVF_FRAME_HEADER_LENGTH;
111     FILE *fp = impl->fp_input;
112     FileBufSlot *slot = NULL;
113     size_t data_size = 0;
114     size_t read_size = 0;
115     RK_U32 eos = 0;
116 
117     if (fread(ivf_data, 1, ivf_data_size, fp) != ivf_data_size) {
118         /* end of frame queue */
119         slot = mpp_calloc(FileBufSlot, 1);
120         slot->eos = 1;
121 
122         return slot;
123     }
124 
125     impl->read_total += ivf_data_size;
126     data_size = ivf_data[0] | (ivf_data[1] << 8) | (ivf_data[2] << 16) | (ivf_data[3] << 24);
127     slot = mpp_malloc_size(FileBufSlot, MPP_ALIGN(sizeof(FileBufSlot) + data_size, SZ_4K));
128     slot->data = (char *)(slot + 1);
129     read_size = fread(slot->data, 1, data_size, fp);
130     impl->read_total += read_size;
131     impl->read_size = read_size;
132 
133     if (!data_size)
134         mpp_err("data_size is zero! ftell size %d\n", ftell(fp));
135     /* check reach eos whether or not */
136     if (!data_size || read_size != data_size || feof(fp) || impl->read_total >= impl->file_size)
137         eos = 1;
138 
139     slot->buf = NULL;
140     slot->size = read_size;
141     slot->eos = eos;
142 
143     return slot;
144 }
145 
read_jpeg_file(FileReader data)146 static FileBufSlot *read_jpeg_file(FileReader data)
147 {
148     FileReaderImpl *impl = (FileReaderImpl*)data;
149     FILE *fp = impl->fp_input;
150     size_t read_size = 0;
151     size_t buf_size = impl->file_size;
152     MppBuffer hw_buf = NULL;
153     FileBufSlot *slot = mpp_calloc(FileBufSlot, 1);
154 
155     mpp_buffer_get(impl->group, &hw_buf, impl->file_size);
156     mpp_assert(hw_buf);
157 
158     slot->data = mpp_buffer_get_ptr(hw_buf);
159     mpp_assert(slot->data);
160     read_size = fread(slot->data, 1, buf_size, fp);
161 
162     mpp_assert(read_size == buf_size);
163 
164     impl->read_total += read_size;
165     impl->read_size = read_size;
166 
167     slot->buf   = hw_buf;
168     slot->size  = read_size;
169     slot->eos   = 1;
170 
171     return slot;
172 }
173 
read_normal_file(FileReader data)174 static FileBufSlot *read_normal_file(FileReader data)
175 {
176     FileReaderImpl *impl = (FileReaderImpl*)data;
177     FILE *fp = impl->fp_input;
178     size_t read_size = 0;
179     size_t buf_size = impl->buf_size;
180     size_t size = sizeof(FileBufSlot) + buf_size + impl->stuff_size;
181     FileBufSlot *slot = mpp_malloc_size(FileBufSlot, size);
182     RK_U32 eos = 0;
183 
184     slot->data = (char *)(slot + 1);
185     read_size = fread(slot->data, 1, buf_size, fp);
186     impl->read_total += read_size;
187     impl->read_size = read_size;
188 
189     /* check reach eos whether or not */
190     if (read_size != buf_size || feof(fp) || impl->read_total >= impl->file_size)
191         eos = 1;
192 
193     slot->buf = NULL;
194     slot->size  = read_size;
195     slot->eos   = eos;
196 
197     return slot;
198 }
199 
check_file_type(FileReader data,char * file_in,MppCodingType type)200 static void check_file_type(FileReader data, char *file_in, MppCodingType type)
201 {
202     FileReaderImpl *impl = (FileReaderImpl*)data;
203 
204     if (strstr(file_in, ".ivf")) {
205         impl->file_type     = FILE_IVF_TYPE;
206         impl->buf_size      = 0;
207         impl->stuff_size    = 0;
208         impl->seek_base     = IVF_HEADER_LENGTH;
209         impl->read_func     = read_ivf_file;
210         impl->slot_max      = 1024;     /* preset 1024 file slots */
211 
212         fseek(impl->fp_input, impl->seek_base, SEEK_SET);
213         impl->read_total = impl->seek_base;
214     } else if (strstr(file_in, ".jpg") ||
215                strstr(file_in, ".jpeg") ||
216                strstr(file_in, ".mjpeg") ||
217                type == MPP_VIDEO_CodingMJPEG) {
218         impl->file_type     = FILE_JPEG_TYPE;
219         impl->buf_size      = impl->file_size;
220         impl->stuff_size    = 0;
221         impl->seek_base     = 0;
222         impl->read_func     = read_jpeg_file;
223         impl->slot_max      = 1;
224         mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION);
225         mpp_assert(impl->group);
226     } else {
227         RK_U32 buf_size = 0;
228 
229         mpp_env_get_u32("reader_buf_size", &buf_size, DEFAULT_PACKET_SIZE);
230 
231         buf_size = MPP_MAX(buf_size, SZ_4K);
232         buf_size = MPP_ALIGN(buf_size, SZ_4K);
233 
234         impl->file_type     = FILE_NORMAL_TYPE;
235         impl->buf_size      = buf_size;
236         impl->stuff_size    = 256;
237         impl->seek_base     = 0;
238         impl->read_func     = read_normal_file;
239         impl->slot_max      = 1024;     /* preset 1024 file slots */
240     }
241 }
242 
reader_size(FileReader reader)243 size_t reader_size(FileReader reader)
244 {
245     FileReaderImpl *impl = (FileReaderImpl*)reader;
246     size_t size = 0;
247 
248     if (impl)
249         size = impl->file_size;
250 
251     return size;
252 }
253 
reader_read(FileReader reader,FileBufSlot ** buf)254 MPP_RET reader_read(FileReader reader, FileBufSlot **buf)
255 {
256     FileReaderImpl *impl = (FileReaderImpl*)reader;
257     FileBufSlot *slot = NULL;
258 
259     if (NULL == impl || NULL == impl->slots) {
260         mpp_log_f("invalid reader %p\n", reader);
261         return MPP_NOK;
262     }
263 
264     if (impl->slot_rd_idx >= impl->slot_max) {
265         mpp_log_f("invalid read index % max %d\n", impl->slot_rd_idx, impl->slot_max);
266         return MPP_NOK;
267     }
268 
269     do {
270         slot = impl->slots[impl->slot_rd_idx];
271         if (slot == NULL || (impl->slot_rd_idx > impl->slot_cnt))
272             msleep(1);
273     } while (slot == NULL);
274 
275     mpp_assert(slot);
276 
277     *buf  = slot;
278     impl->slot_rd_idx++;
279 
280     return MPP_OK;
281 }
282 
reader_index_read(FileReader reader,RK_S32 index,FileBufSlot ** buf)283 MPP_RET reader_index_read(FileReader reader, RK_S32 index, FileBufSlot **buf)
284 {
285     FileReaderImpl *impl = (FileReaderImpl*)reader;
286     FileBufSlot *slot = NULL;
287 
288     if (NULL == impl || NULL == impl->slots) {
289         mpp_log_f("invalid reader %p\n", reader);
290         return MPP_NOK;
291     }
292 
293     if (index >= (RK_S32)impl->slot_max) {
294         mpp_log_f("invalid read index % max %d\n", index, impl->slot_max);
295         return MPP_NOK;
296     }
297 
298     do {
299         slot = impl->slots[index];
300         if (slot == NULL)
301             msleep(1);
302     } while (slot == NULL);
303 
304     mpp_assert(slot);
305 
306     *buf  = slot;
307 
308     return MPP_OK;
309 }
310 
reader_rewind(FileReader reader)311 void reader_rewind(FileReader reader)
312 {
313     FileReaderImpl *impl = (FileReaderImpl*)reader;
314 
315     impl->slot_rd_idx = 0;
316 }
317 
reader_init(FileReader * reader,char * file_in,MppCodingType type)318 void reader_init(FileReader* reader, char* file_in, MppCodingType type)
319 {
320     FILE *fp_input = fopen(file_in, "rb");
321     FileReaderImpl *impl = NULL;
322 
323     if (!fp_input) {
324         mpp_err("failed to open input file %s\n", file_in);
325         *reader = NULL;
326         return;
327     }
328 
329     impl = mpp_calloc(FileReaderImpl, 1);
330     mpp_assert(impl);
331 
332     impl->fp_input = fp_input;
333     fseek(fp_input, 0L, SEEK_END);
334     impl->file_size = ftell(fp_input);
335     fseek(fp_input, 0L, SEEK_SET);
336 
337     check_file_type(impl, file_in, type);
338 
339     impl->slots = mpp_calloc(FileBufSlot*, impl->slot_max);
340 
341     reader_start(impl);
342 
343     *reader = impl;
344 }
345 
reader_deinit(FileReader reader)346 void reader_deinit(FileReader reader)
347 {
348     FileReaderImpl *impl = (FileReaderImpl*)(reader);
349     RK_U32 i;
350 
351     mpp_assert(impl);
352     reader_stop(impl);
353 
354     if (impl->fp_input) {
355         fclose(impl->fp_input);
356         impl->fp_input = NULL;
357     }
358 
359     for (i = 0; i < impl->slot_cnt; i++) {
360         FileBufSlot *slot = impl->slots[i];
361         if (!slot)
362             continue;
363 
364         if (slot->buf) {
365             mpp_buffer_put(slot->buf);
366             slot->buf = NULL;
367         }
368         MPP_FREE(impl->slots[i]);
369     }
370 
371     if (impl->group) {
372         mpp_buffer_group_put(impl->group);
373         impl->group = NULL;
374     }
375 
376     MPP_FREE(impl->slots);
377     MPP_FREE(impl);
378 }
379 
reader_worker(void * param)380 static void* reader_worker(void *param)
381 {
382     FileReaderImpl *impl = (FileReaderImpl*)param;
383     RK_U32 eos = 0;
384 
385     while (!impl->thd_stop && !eos) {
386         FileBufSlot *slot = impl->read_func(impl);
387 
388         if (NULL == slot)
389             break;
390 
391         add_new_slot(impl, slot);
392         eos = slot->eos;
393     }
394 
395     return NULL;
396 }
397 
reader_start(FileReader reader)398 void reader_start(FileReader reader)
399 {
400     FileReaderImpl *impl = (FileReaderImpl*)reader;
401 
402     impl->thd_stop = 0;
403     pthread_create(&impl->thd, NULL, reader_worker, impl);
404 }
405 
reader_sync(FileReader reader)406 void reader_sync(FileReader reader)
407 {
408     FileReaderImpl *impl = (FileReaderImpl*)reader;
409 
410     pthread_join(impl->thd, NULL);
411     impl->thd_stop = 1;
412 }
413 
reader_stop(FileReader reader)414 void reader_stop(FileReader reader)
415 {
416     FileReaderImpl *impl = (FileReaderImpl*)reader;
417 
418     if (MPP_BOOL_CAS(&impl->thd_stop, 0, 1))
419         pthread_join(impl->thd, NULL);
420 }
421 
show_dec_fps(RK_S64 total_time,RK_S64 total_count,RK_S64 last_time,RK_S64 last_count)422 void show_dec_fps(RK_S64 total_time, RK_S64 total_count, RK_S64 last_time, RK_S64 last_count)
423 {
424     float avg_fps = (float)total_count * 1000000 / total_time;
425     float ins_fps = (float)last_count * 1000000 / last_time;
426 
427     mpp_log("decoded %10lld frame fps avg %7.2f ins %7.2f\n",
428             total_count, avg_fps, ins_fps);
429 }
430 
mpi_dec_opt_i(void * ctx,const char * next)431 RK_S32 mpi_dec_opt_i(void *ctx, const char *next)
432 {
433     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
434 
435     if (next) {
436         strncpy(cmd->file_input, next, MAX_FILE_NAME_LENGTH - 1);
437         cmd->have_input = 1;
438         if (!cmd->type)
439             name_to_coding_type(cmd->file_input, &cmd->type);
440         return 1;
441     }
442 
443     mpp_err("input file is invalid\n");
444     return 0;
445 }
446 
mpi_dec_opt_o(void * ctx,const char * next)447 RK_S32 mpi_dec_opt_o(void *ctx, const char *next)
448 {
449     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
450 
451     if (next) {
452         strncpy(cmd->file_output, next, MAX_FILE_NAME_LENGTH - 1);
453         cmd->have_output = 1;
454         return 1;
455     }
456 
457     mpp_log("output file is invalid\n");
458     return 0;
459 }
460 
mpi_dec_opt_w(void * ctx,const char * next)461 RK_S32 mpi_dec_opt_w(void *ctx, const char *next)
462 {
463     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
464 
465     if (next) {
466         cmd->width = atoi(next);
467         return 1;
468     }
469 
470     mpp_err("invalid input width\n");
471     return 0;
472 }
473 
mpi_dec_opt_h(void * ctx,const char * next)474 RK_S32 mpi_dec_opt_h(void *ctx, const char *next)
475 {
476     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
477 
478     if (next) {
479         cmd->height = atoi(next);
480         return 1;
481     }
482 
483     mpp_err("invalid input height\n");
484     return 0;
485 }
486 
mpi_dec_opt_t(void * ctx,const char * next)487 RK_S32 mpi_dec_opt_t(void *ctx, const char *next)
488 {
489     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
490 
491     if (next) {
492         MPP_RET ret;
493 
494         cmd->type = (MppCodingType)atoi(next);
495         ret = mpp_check_support_format(MPP_CTX_DEC, cmd->type);
496         if (!ret)
497             return 1;
498     }
499 
500     mpp_err("invalid input coding type\n");
501     return 0;
502 }
503 
mpi_dec_opt_f(void * ctx,const char * next)504 RK_S32 mpi_dec_opt_f(void *ctx, const char *next)
505 {
506     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
507 
508     if (next) {
509         long number = 0;
510         MppFrameFormat format = MPP_FMT_BUTT;
511 
512         if (MPP_OK == str_to_frm_fmt(next, &number)) {
513             format = (MppFrameFormat)number;
514 
515             if (MPP_FRAME_FMT_IS_YUV(format) || MPP_FRAME_FMT_IS_RGB(format)) {
516                 cmd->format = format;
517                 return 1;
518             }
519 
520             mpp_err("invalid input format 0x%x\n", format);
521         }
522     }
523 
524     cmd->format = MPP_FMT_YUV420SP;
525     return 0;
526 }
527 
mpi_dec_opt_n(void * ctx,const char * next)528 RK_S32 mpi_dec_opt_n(void *ctx, const char *next)
529 {
530     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
531 
532     if (next) {
533         cmd->frame_num = atoi(next);
534 
535         if (cmd->frame_num < 0)
536             mpp_log("infinite loop decoding mode\n");
537 
538         return 1;
539     }
540 
541     mpp_err("invalid frame number\n");
542     return 0;
543 }
544 
mpi_dec_opt_s(void * ctx,const char * next)545 RK_S32 mpi_dec_opt_s(void *ctx, const char *next)
546 {
547     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
548 
549     cmd->nthreads = -1;
550     if (next) {
551         cmd->nthreads = atoi(next);
552         if (cmd->nthreads >= 1)
553             return 1;
554     }
555 
556     mpp_err("invalid nthreads %d\n", cmd->nthreads);
557     cmd->nthreads = 1;
558     return 0;
559 }
560 
mpi_dec_opt_v(void * ctx,const char * next)561 RK_S32 mpi_dec_opt_v(void *ctx, const char *next)
562 {
563     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
564 
565     if (next) {
566         if (strstr(next, "q"))
567             cmd->quiet = 1;
568         if (strstr(next, "f"))
569             cmd->trace_fps = 1;
570 
571         return 1;
572     }
573 
574     return 0;
575 }
576 
mpi_dec_opt_slt(void * ctx,const char * next)577 RK_S32 mpi_dec_opt_slt(void *ctx, const char *next)
578 {
579     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
580 
581     if (next) {
582         size_t len = strnlen(next, MAX_FILE_NAME_LENGTH);
583         if (len) {
584             cmd->file_slt = mpp_calloc(char, len + 1);
585             strncpy(cmd->file_slt, next, len);
586 
587             return 1;
588         }
589     }
590 
591     mpp_err("input slt verify file is invalid\n");
592     return 0;
593 }
594 
mpi_dec_opt_bufmode(void * ctx,const char * next)595 RK_S32 mpi_dec_opt_bufmode(void *ctx, const char *next)
596 {
597     MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
598 
599     if (next) {
600         if (strstr(next, "hi")) {
601             cmd->buf_mode = MPP_DEC_BUF_HALF_INT;
602         } else if (strstr(next, "i")) {
603             cmd->buf_mode = MPP_DEC_BUF_INTERNAL;
604         } else if (strstr(next, "e")) {
605             cmd->buf_mode = MPP_DEC_BUF_EXTERNAL;
606         } else {
607             cmd->buf_mode = MPP_DEC_BUF_HALF_INT;
608         }
609 
610         return 1;
611     }
612 
613     mpp_err("invalid ext buf mode value\n");
614     return 0;
615 }
616 
617 
mpi_dec_opt_help(void * ctx,const char * next)618 RK_S32 mpi_dec_opt_help(void *ctx, const char *next)
619 {
620     (void)ctx;
621     (void)next;
622     /* return invalid option to print help */
623     return -1;
624 }
625 
626 static MppOptInfo dec_opts[] = {
627     {"i",       "input_file",   "input bitstream file",             mpi_dec_opt_i},
628     {"o",       "output_file",  "output decoded frame file",        mpi_dec_opt_o},
629     {"w",       "width",        "the width of input bitstream",     mpi_dec_opt_w},
630     {"h",       "height",       "the height of input bitstream",    mpi_dec_opt_h},
631     {"t",       "type",         "input stream coding type",         mpi_dec_opt_t},
632     {"f",       "format",       "output frame format type",         mpi_dec_opt_f},
633     {"n",       "frame_number", "max output frame number",          mpi_dec_opt_n},
634     {"s",       "instance_nb",  "number of instances",              mpi_dec_opt_s},
635     {"v",       "trace option", "q - quiet f - show fps",           mpi_dec_opt_v},
636     {"slt",     "slt file",     "slt verify data file",             mpi_dec_opt_slt},
637     {"help",    "help",         "show help",                        mpi_dec_opt_help},
638     {"bufmode", "buffer mode",  "hi - half internal (default) i -internal e - external", mpi_dec_opt_bufmode},
639 };
640 
641 static RK_U32 dec_opt_cnt = MPP_ARRAY_ELEMS(dec_opts);
642 
mpi_dec_show_help(const char * name)643 RK_S32 mpi_dec_show_help(const char *name)
644 {
645     RK_U32 max_name = 1;
646     RK_U32 max_full_name = 1;
647     RK_U32 max_help = 1;
648     char logs[256];
649     RK_U32 len;
650     RK_U32 i;
651 
652     mpp_log("usage: %s [options]\n", name);
653 
654     for (i = 0; i < dec_opt_cnt; i++) {
655         MppOptInfo *opt = &dec_opts[i];
656 
657         if (opt->name) {
658             len = strlen(opt->name);
659             if (len > max_name)
660                 max_name = len;
661         }
662 
663         if (opt->full_name) {
664             len = strlen(opt->full_name);
665             if (len > max_full_name)
666                 max_full_name = len;
667         }
668 
669         if (opt->help) {
670             len = strlen(opt->help);
671             if (len > max_help)
672                 max_help = len;
673         }
674     }
675 
676     snprintf(logs, sizeof(logs) - 1, "-%%-%ds %%-%ds %%-%ds\n", max_name, max_full_name, max_help);
677 
678     for (i = 0; i < dec_opt_cnt; i++) {
679         MppOptInfo *opt = &dec_opts[i];
680 
681         mpp_log(logs, opt->name, opt->full_name, opt->help);
682     }
683     mpp_show_support_format();
684 
685     return -1;
686 }
687 
mpi_dec_test_cmd_init(MpiDecTestCmd * cmd,int argc,char ** argv)688 RK_S32 mpi_dec_test_cmd_init(MpiDecTestCmd* cmd, int argc, char **argv)
689 {
690     MppOpt opts = NULL;
691     RK_S32 ret = -1;
692     RK_U32 i;
693 
694     if ((argc < 2) || (cmd == NULL))
695         goto done;
696 
697     mpp_opt_init(&opts);
698     /* should change node count when option increases */
699     mpp_opt_setup(opts, cmd);
700 
701     for (i = 0; i < dec_opt_cnt; i++)
702         mpp_opt_add(opts, &dec_opts[i]);
703 
704     /* mark option end */
705     mpp_opt_add(opts, NULL);
706 
707     ret = mpp_opt_parse(opts, argc, argv);
708 
709     if (cmd->have_input) {
710         reader_init(&cmd->reader, cmd->file_input, cmd->type);
711         if (cmd->reader)
712             mpp_log("input file %s size %ld\n", cmd->file_input, reader_size(cmd->reader));
713     }
714     if (cmd->trace_fps) {
715         fps_calc_init(&cmd->fps);
716         mpp_assert(cmd->fps);
717         fps_calc_set_cb(cmd->fps, show_dec_fps);
718     }
719 
720 done:
721     if (opts) {
722         mpp_opt_deinit(opts);
723         opts = NULL;
724     }
725 
726     if (ret)
727         mpi_dec_show_help(argv[0]);
728 
729     return ret;
730 }
731 
mpi_dec_test_cmd_deinit(MpiDecTestCmd * cmd)732 RK_S32 mpi_dec_test_cmd_deinit(MpiDecTestCmd* cmd)
733 {
734     if (!cmd)
735         return 0;
736 
737     if (cmd->reader) {
738         reader_deinit(cmd->reader);
739         cmd->reader = NULL;
740     }
741 
742     MPP_FREE(cmd->file_slt);
743 
744     if (cmd->fps) {
745         fps_calc_deinit(cmd->fps);
746         cmd->fps = NULL;
747     }
748 
749     return 0;
750 }
751 
mpi_dec_test_cmd_options(MpiDecTestCmd * cmd)752 void mpi_dec_test_cmd_options(MpiDecTestCmd* cmd)
753 {
754     if (cmd->quiet)
755         return;
756 
757     mpp_log("cmd parse result:\n");
758     mpp_log("input  file name: %s\n", cmd->file_input);
759     mpp_log("output file name: %s\n", cmd->file_output);
760     mpp_log("width      : %4d\n", cmd->width);
761     mpp_log("height     : %4d\n", cmd->height);
762     mpp_log("type       : %4d\n", cmd->type);
763     mpp_log("max frames : %4d\n", cmd->frame_num);
764     if (cmd->file_slt)
765         mpp_log("verify     : %s\n", cmd->file_slt);
766 }
767 
dec_buf_mgr_init(DecBufMgr * mgr)768 MPP_RET dec_buf_mgr_init(DecBufMgr *mgr)
769 {
770     DecBufMgrImpl *impl = NULL;
771     MPP_RET ret = MPP_NOK;
772 
773     if (mgr) {
774         impl = mpp_calloc(DecBufMgrImpl, 1);
775         if (impl) {
776             ret = MPP_OK;
777         } else {
778             mpp_err_f("failed to create decoder buffer manager\n");
779         }
780 
781         *mgr = impl;
782     }
783 
784     return ret;
785 }
786 
dec_buf_mgr_deinit(DecBufMgr mgr)787 void dec_buf_mgr_deinit(DecBufMgr mgr)
788 {
789     DecBufMgrImpl *impl = (DecBufMgrImpl *)mgr;
790 
791     if (NULL == impl)
792         return;
793 
794     /* release buffer group for half internal and external mode */
795     if (impl->group) {
796         mpp_buffer_group_put(impl->group);
797         impl->group = NULL;
798     }
799 
800     /* release the buffers used in external mode */
801     if (impl->buf_count && impl->bufs) {
802         RK_U32 i;
803 
804         for (i = 0; i < impl->buf_count; i++) {
805             if (impl->bufs[i]) {
806                 mpp_buffer_put(impl->bufs[i]);
807                 impl->bufs[i] = NULL;
808             }
809         }
810 
811         MPP_FREE(impl->bufs);
812     }
813 
814     MPP_FREE(impl);
815 }
816 
dec_buf_mgr_setup(DecBufMgr mgr,RK_U32 size,RK_U32 count,MppDecBufMode mode)817 MppBufferGroup dec_buf_mgr_setup(DecBufMgr mgr, RK_U32 size, RK_U32 count, MppDecBufMode mode)
818 {
819     DecBufMgrImpl *impl = (DecBufMgrImpl *)mgr;
820     MPP_RET ret = MPP_NOK;
821 
822     if (!impl)
823         return NULL;
824 
825     /* cleanup old buffers if previous buffer group exists */
826     if (impl->group) {
827         if (mode != impl->buf_mode) {
828             /* switch to different buffer mode just release old buffer group */
829             mpp_buffer_group_put(impl->group);
830             impl->group = NULL;
831         } else {
832             /* otherwise just cleanup old buffers */
833             mpp_buffer_group_clear(impl->group);
834         }
835 
836         /* if there are external mode old buffers do cleanup */
837         if (impl->bufs) {
838             RK_U32 i;
839 
840             for (i = 0; i < impl->buf_count; i++) {
841                 if (impl->bufs[i]) {
842                     mpp_buffer_put(impl->bufs[i]);
843                     impl->bufs[i] = NULL;
844                 }
845             }
846 
847             MPP_FREE(impl->bufs);
848         }
849     }
850 
851     switch (mode) {
852     case MPP_DEC_BUF_HALF_INT : {
853         /* reuse previous half internal buffer group and just reconfig limit */
854         if (NULL == impl->group) {
855             ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION);
856             if (ret) {
857                 mpp_err_f("get mpp internal buffer group failed ret %d\n", ret);
858                 break;
859             }
860         }
861         /* Use limit config to limit buffer count and buffer size */
862         ret = mpp_buffer_group_limit_config(impl->group, size, count);
863         if (ret) {
864             mpp_err_f("limit buffer group failed ret %d\n", ret);
865         }
866     } break;
867     case MPP_DEC_BUF_INTERNAL : {
868         /* do nothing juse keep buffer group empty */
869         mpp_assert(NULL == impl->group);
870         ret = MPP_OK;
871     } break;
872     case MPP_DEC_BUF_EXTERNAL : {
873         RK_U32 i;
874         MppBufferInfo commit;
875 
876         impl->bufs = mpp_calloc(MppBuffer, count);
877         if (!impl->bufs) {
878             mpp_err_f("create %d external buffer record failed\n", count);
879             break;
880         }
881 
882         /* reuse previous external buffer group */
883         if (NULL == impl->group) {
884             ret = mpp_buffer_group_get_external(&impl->group, MPP_BUFFER_TYPE_ION);
885             if (ret) {
886                 mpp_err_f("get mpp external buffer group failed ret %d\n", ret);
887                 break;
888             }
889         }
890 
891         /*
892          * NOTE: Use default misc allocater here as external allocator for demo.
893          * But in practical case the external buffer could be GraphicBuffer or gst dmabuf.
894          * The misc allocator will cause the print at the end like:
895          * ~MppBufferService cleaning misc group
896          */
897         commit.type = MPP_BUFFER_TYPE_ION;
898         commit.size = size;
899 
900         for (i = 0; i < count; i++) {
901             ret = mpp_buffer_get(NULL, &impl->bufs[i], size);
902             if (ret || NULL == impl->bufs[i]) {
903                 mpp_err_f("get misc buffer failed ret %d\n", ret);
904                 break;
905             }
906 
907             commit.index = i;
908             commit.ptr = mpp_buffer_get_ptr(impl->bufs[i]);
909             commit.fd = mpp_buffer_get_fd(impl->bufs[i]);
910 
911             ret = mpp_buffer_commit(impl->group, &commit);
912             if (ret) {
913                 mpp_err_f("external buffer commit failed ret %d\n", ret);
914                 break;
915             }
916         }
917     } break;
918     default : {
919         mpp_err_f("unsupport buffer mode %d\n", mode);
920     } break;
921     }
922 
923     if (ret) {
924         dec_buf_mgr_deinit(impl);
925         impl = NULL;
926     } else {
927         impl->buf_count = count;
928         impl->buf_size = size;
929         impl->buf_mode = mode;
930     }
931 
932     return impl ? impl->group : NULL;
933 }