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 }