xref: /OK3568_Linux_fs/external/mpp/test/mpi_enc_mt_test.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2022 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_enc_mt_test"
18 
19 #include <string.h>
20 #include "rk_mpi.h"
21 
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_time.h"
25 #include "mpp_list.h"
26 #include "mpp_lock.h"
27 #include "mpp_debug.h"
28 #include "mpp_common.h"
29 
30 #include "utils.h"
31 #include "mpi_enc_utils.h"
32 #include "camera_source.h"
33 #include "mpp_enc_roi_utils.h"
34 
35 #define BUF_COUNT   4
36 
37 typedef struct {
38     // base flow context
39     MppCtx ctx;
40     MppApi *mpi;
41     RK_S32 chn;
42 
43     // global flow control flag
44     RK_U32 frm_eos;
45     RK_U32 pkt_eos;
46     RK_U32 frm_pkt_cnt;
47     RK_S32 frame_num;
48     RK_S32 frm_cnt_in;
49     RK_S32 frm_cnt_out;
50     RK_U64 stream_size;
51     /* end of encoding flag when set quit the loop */
52     volatile RK_U32 loop_end;
53 
54     // src and dst
55     FILE *fp_input;
56     FILE *fp_output;
57     FILE *fp_verify;
58 
59     /* encoder config set */
60     MppEncCfg       cfg;
61     MppEncPrepCfg   prep_cfg;
62     MppEncRcCfg     rc_cfg;
63     MppEncCodecCfg  codec_cfg;
64     MppEncOSDPltCfg osd_plt_cfg;
65     MppEncOSDPlt    osd_plt;
66     MppEncOSDData   osd_data;
67     RoiRegionCfg    roi_region;
68     MppEncROICfg    roi_cfg;
69 
70     // input / output
71     mpp_list        *list_buf;
72     MppBufferGroup buf_grp;
73     MppBuffer frm_buf[BUF_COUNT];
74     MppBuffer pkt_buf[BUF_COUNT];
75     RK_S32 buf_idx;
76     MppEncSeiMode sei_mode;
77     MppEncHeaderMode header_mode;
78 
79     // paramter for resource malloc
80     RK_U32 width;
81     RK_U32 height;
82     RK_U32 hor_stride;
83     RK_U32 ver_stride;
84     MppFrameFormat fmt;
85     MppCodingType type;
86     RK_S32 loop_times;
87     CamSource *cam_ctx;
88     MppEncRoiCtx roi_ctx;
89 
90     // resources
91     size_t header_size;
92     size_t frame_size;
93     /* NOTE: packet buffer may overflow */
94     size_t packet_size;
95 
96     RK_U32 osd_enable;
97     RK_U32 osd_mode;
98     RK_U32 split_mode;
99     RK_U32 split_arg;
100     RK_U32 split_out;
101 
102     RK_U32 user_data_enable;
103     RK_U32 roi_enable;
104 
105     // rate control runtime parameter
106     RK_S32 fps_in_flex;
107     RK_S32 fps_in_den;
108     RK_S32 fps_in_num;
109     RK_S32 fps_out_flex;
110     RK_S32 fps_out_den;
111     RK_S32 fps_out_num;
112     RK_S32 bps;
113     RK_S32 bps_max;
114     RK_S32 bps_min;
115     RK_S32 rc_mode;
116     RK_S32 gop_mode;
117     RK_S32 gop_len;
118     RK_S32 vi_len;
119 
120     RK_S64 first_frm;
121     RK_S64 first_pkt;
122     RK_S64 last_pkt;
123 } MpiEncMtTestData;
124 
125 /* For each instance thread return value */
126 typedef struct {
127     float           frame_rate;
128     RK_U64          bit_rate;
129 
130     RK_S64          time_start;
131     RK_S64          time_delay;
132     RK_S64          time_total;
133 
134     RK_S64          elapsed_time;
135     RK_S32          frame_count;
136     RK_S64          stream_size;
137     RK_S64          delay;
138 } MpiEncMtCtxRet;
139 
140 typedef struct {
141     MpiEncTestArgs      *cmd;       // pointer to global command line info
142     const char          *name;
143     RK_S32              chn;
144 
145     pthread_t           thd_in;     // thread for for frame input
146     pthread_t           thd_out;    // thread for for packet output
147 
148     struct list_head    frm_list;
149     spinlock_t          frm_lock;
150 
151     MpiEncMtTestData    ctx;        // context of encoder
152     MpiEncMtCtxRet      ret;        // return of encoder
153 } MpiEncMtCtxInfo;
154 
mt_test_ctx_init(MpiEncMtCtxInfo * info)155 MPP_RET mt_test_ctx_init(MpiEncMtCtxInfo *info)
156 {
157     MpiEncTestArgs *cmd = info->cmd;
158     MpiEncMtTestData *p = &info->ctx;
159     MPP_RET ret = MPP_OK;
160 
161     // get paramter from cmd
162     p->width        = cmd->width;
163     p->height       = cmd->height;
164     p->hor_stride   = (cmd->hor_stride) ? (cmd->hor_stride) :
165                       (MPP_ALIGN(cmd->width, 16));
166     p->ver_stride   = (cmd->ver_stride) ? (cmd->ver_stride) :
167                       (MPP_ALIGN(cmd->height, 16));
168     p->fmt          = cmd->format;
169     p->type         = cmd->type;
170     p->bps          = cmd->bps_target;
171     p->bps_min      = cmd->bps_min;
172     p->bps_max      = cmd->bps_max;
173     p->rc_mode      = cmd->rc_mode;
174     p->frame_num    = cmd->frame_num;
175     if (cmd->type == MPP_VIDEO_CodingMJPEG && p->frame_num == 0) {
176         mpp_log("jpege default encode only one frame. Use -n [num] for rc case\n");
177         p->frame_num = 1;
178     }
179     p->gop_mode     = cmd->gop_mode;
180     p->gop_len      = cmd->gop_len;
181     p->vi_len       = cmd->vi_len;
182 
183     p->fps_in_flex  = cmd->fps_in_flex;
184     p->fps_in_den   = cmd->fps_in_den;
185     p->fps_in_num   = cmd->fps_in_num;
186     p->fps_out_flex = cmd->fps_out_flex;
187     p->fps_out_den  = cmd->fps_out_den;
188     p->fps_out_num  = cmd->fps_out_num;
189 
190     if (cmd->file_input) {
191         if (!strncmp(cmd->file_input, "/dev/video", 10)) {
192             mpp_log("open camera device");
193             p->cam_ctx = camera_source_init(cmd->file_input, 4, p->width, p->height, p->fmt);
194             mpp_log("new framecap ok");
195             if (p->cam_ctx == NULL)
196                 mpp_err("open %s fail", cmd->file_input);
197         } else {
198             p->fp_input = fopen(cmd->file_input, "rb");
199             if (NULL == p->fp_input) {
200                 mpp_err("failed to open input file %s\n", cmd->file_input);
201                 mpp_err("create default yuv image for test\n");
202             }
203         }
204     }
205 
206     if (cmd->file_output) {
207         p->fp_output = fopen(cmd->file_output, "w+b");
208         if (NULL == p->fp_output) {
209             mpp_err("failed to open output file %s\n", cmd->file_output);
210             ret = MPP_ERR_OPEN_FILE;
211         }
212     }
213 
214     if (cmd->file_slt) {
215         p->fp_verify = fopen(cmd->file_slt, "wt");
216         if (!p->fp_verify)
217             mpp_err("failed to open verify file %s\n", cmd->file_slt);
218     }
219 
220     // update resource parameter
221     switch (p->fmt & MPP_FRAME_FMT_MASK) {
222     case MPP_FMT_YUV420SP:
223     case MPP_FMT_YUV420P: {
224         p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2;
225     } break;
226 
227     case MPP_FMT_YUV422_YUYV :
228     case MPP_FMT_YUV422_YVYU :
229     case MPP_FMT_YUV422_UYVY :
230     case MPP_FMT_YUV422_VYUY :
231     case MPP_FMT_YUV422P :
232     case MPP_FMT_YUV422SP : {
233         p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2;
234     } break;
235     case MPP_FMT_RGB444 :
236     case MPP_FMT_BGR444 :
237     case MPP_FMT_RGB555 :
238     case MPP_FMT_BGR555 :
239     case MPP_FMT_RGB565 :
240     case MPP_FMT_BGR565 :
241     case MPP_FMT_RGB888 :
242     case MPP_FMT_BGR888 :
243     case MPP_FMT_RGB101010 :
244     case MPP_FMT_BGR101010 :
245     case MPP_FMT_ARGB8888 :
246     case MPP_FMT_ABGR8888 :
247     case MPP_FMT_BGRA8888 :
248     case MPP_FMT_RGBA8888 : {
249         p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64);
250     } break;
251 
252     default: {
253         p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4;
254     } break;
255     }
256 
257     if (MPP_FRAME_FMT_IS_FBC(p->fmt))
258         p->header_size = MPP_ALIGN(MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16, SZ_4K);
259     else
260         p->header_size = 0;
261 
262     return ret;
263 }
264 
mt_test_ctx_deinit(MpiEncMtCtxInfo * info)265 MPP_RET mt_test_ctx_deinit(MpiEncMtCtxInfo *info)
266 {
267     MpiEncMtTestData *p = NULL;
268 
269     if (NULL == info)
270         return MPP_OK;
271 
272     p = &info->ctx;
273 
274     if (p->cam_ctx) {
275         camera_source_deinit(p->cam_ctx);
276         p->cam_ctx = NULL;
277     }
278     if (p->fp_input) {
279         fclose(p->fp_input);
280         p->fp_input = NULL;
281     }
282     if (p->fp_output) {
283         fclose(p->fp_output);
284         p->fp_output = NULL;
285     }
286     if (p->fp_verify) {
287         fclose(p->fp_verify);
288         p->fp_verify = NULL;
289     }
290 
291     return MPP_OK;
292 }
293 
test_mt_cfg_setup(MpiEncMtCtxInfo * info)294 MPP_RET test_mt_cfg_setup(MpiEncMtCtxInfo *info)
295 {
296     MpiEncTestArgs *cmd = info->cmd;
297     MpiEncMtTestData *p = &info->ctx;
298     MppApi *mpi = p->mpi;
299     MppCtx ctx = p->ctx;
300     MppEncCfg cfg = p->cfg;
301     RK_U32 gop_mode = p->gop_mode;
302     RK_U32 quiet = cmd->quiet;
303     MPP_RET ret;
304     MppEncRefCfg ref = NULL;
305 
306     /* setup default parameter */
307     if (p->fps_in_den == 0)
308         p->fps_in_den = 1;
309     if (p->fps_in_num == 0)
310         p->fps_in_num = 30;
311     if (p->fps_out_den == 0)
312         p->fps_out_den = 1;
313     if (p->fps_out_num == 0)
314         p->fps_out_num = 30;
315 
316     if (!p->bps)
317         p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den);
318 
319     mpp_enc_cfg_set_s32(cfg, "prep:width", p->width);
320     mpp_enc_cfg_set_s32(cfg, "prep:height", p->height);
321     mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride);
322     mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride);
323     mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt);
324 
325     mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode);
326 
327     /* fix input / output frame rate */
328     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex);
329     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num);
330     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den);
331     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex);
332     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num);
333     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den);
334 
335     /* drop frame or not when bitrate overflow */
336     mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
337     mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20);        /* 20% of max bps */
338     mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1);         /* Do not continuous drop frame */
339 
340     /* setup bitrate for different rc_mode */
341     mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps);
342     switch (p->rc_mode) {
343     case MPP_ENC_RC_MODE_FIXQP : {
344         /* do not setup bitrate on FIXQP mode */
345     } break;
346     case MPP_ENC_RC_MODE_CBR : {
347         /* CBR mode has narrow bound */
348         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
349         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
350     } break;
351     case MPP_ENC_RC_MODE_VBR :
352     case MPP_ENC_RC_MODE_AVBR : {
353         /* VBR mode has wide bound */
354         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
355         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16);
356     } break;
357     default : {
358         /* default use CBR mode */
359         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
360         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
361     } break;
362     }
363 
364     /* setup qp for different codec and rc_mode */
365     switch (p->type) {
366     case MPP_VIDEO_CodingAVC :
367     case MPP_VIDEO_CodingHEVC : {
368         switch (p->rc_mode) {
369         case MPP_ENC_RC_MODE_FIXQP : {
370             RK_S32 fix_qp = cmd->qp_init;
371 
372             mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp);
373             mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp);
374             mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp);
375             mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp);
376             mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp);
377             mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0);
378         } break;
379         case MPP_ENC_RC_MODE_CBR :
380         case MPP_ENC_RC_MODE_VBR :
381         case MPP_ENC_RC_MODE_AVBR : {
382             mpp_enc_cfg_set_s32(cfg, "rc:qp_init", cmd->qp_init ? cmd->qp_init : -1);
383             mpp_enc_cfg_set_s32(cfg, "rc:qp_max", cmd->qp_max ? cmd->qp_max : 51);
384             mpp_enc_cfg_set_s32(cfg, "rc:qp_min", cmd->qp_min ? cmd->qp_min : 10);
385             mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", cmd->qp_max_i ? cmd->qp_max_i : 51);
386             mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", cmd->qp_min_i ? cmd->qp_min_i : 10);
387             mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
388         } break;
389         default : {
390             mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode);
391         } break;
392         }
393     } break;
394     case MPP_VIDEO_CodingVP8 : {
395         /* vp8 only setup base qp range */
396         mpp_enc_cfg_set_s32(cfg, "rc:qp_init", cmd->qp_init ? cmd->qp_init : 40);
397         mpp_enc_cfg_set_s32(cfg, "rc:qp_max",  cmd->qp_max ? cmd->qp_max : 127);
398         mpp_enc_cfg_set_s32(cfg, "rc:qp_min",  cmd->qp_min ? cmd->qp_min : 0);
399         mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", cmd->qp_max_i ? cmd->qp_max_i : 127);
400         mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", cmd->qp_min_i ? cmd->qp_min_i : 0);
401         mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
402     } break;
403     case MPP_VIDEO_CodingMJPEG : {
404         /* jpeg use special codec config to control qtable */
405         mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", cmd->qp_init ? cmd->qp_init : 80);
406         mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", cmd->qp_max ? cmd->qp_max : 99);
407         mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", cmd->qp_min ? cmd->qp_min : 1);
408     } break;
409     default : {
410     } break;
411     }
412 
413     /* setup codec  */
414     mpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
415     switch (p->type) {
416     case MPP_VIDEO_CodingAVC : {
417         /*
418          * H.264 profile_idc parameter
419          * 66  - Baseline profile
420          * 77  - Main profile
421          * 100 - High profile
422          */
423         mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
424         /*
425          * H.264 level_idc parameter
426          * 10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
427          * 20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
428          * 30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
429          * 40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
430          * 50 / 51 / 52         - 4K@30fps
431          */
432         mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
433         mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
434         mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
435         mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
436     } break;
437     case MPP_VIDEO_CodingHEVC :
438     case MPP_VIDEO_CodingMJPEG :
439     case MPP_VIDEO_CodingVP8 : {
440     } break;
441     default : {
442         mpp_err_f("unsupport encoder coding type %d\n", p->type);
443     } break;
444     }
445 
446     p->split_mode = 0;
447     p->split_arg = 0;
448     p->split_out = 0;
449 
450     mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE);
451     mpp_env_get_u32("split_arg", &p->split_arg, 0);
452     mpp_env_get_u32("split_out", &p->split_out, 0);
453 
454     if (p->split_mode) {
455         mpp_log_q(quiet, "%p split mode %d arg %d out %d\n", ctx,
456                   p->split_mode, p->split_arg, p->split_out);
457         mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode);
458         mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg);
459         mpp_enc_cfg_set_s32(cfg, "split:out", p->split_out);
460     }
461 
462     // config gop_len and ref cfg
463     mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2);
464 
465     mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
466 
467     if (gop_mode) {
468         mpp_enc_ref_cfg_init(&ref);
469 
470         if (p->gop_mode < 4)
471             mpi_enc_gen_ref_cfg(ref, gop_mode);
472         else
473             mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len);
474 
475         mpp_enc_cfg_set_ptr(cfg, "rc:ref_cfg", ref);
476     }
477 
478     ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
479     if (ret) {
480         mpp_err("mpi control enc set cfg failed ret %d\n", ret);
481         goto RET;
482     }
483 
484     if (ref)
485         mpp_enc_ref_cfg_deinit(&ref);
486 
487     /* optional */
488     p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
489     ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
490     if (ret) {
491         mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
492         goto RET;
493     }
494 
495     if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
496         p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
497         ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode);
498         if (ret) {
499             mpp_err("mpi control enc set header mode failed ret %d\n", ret);
500             goto RET;
501         }
502     }
503 
504     /* setup test mode by env */
505     mpp_env_get_u32("osd_enable", &p->osd_enable, 0);
506     mpp_env_get_u32("osd_mode", &p->osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT);
507     mpp_env_get_u32("roi_enable", &p->roi_enable, 0);
508     mpp_env_get_u32("user_data_enable", &p->user_data_enable, 0);
509 
510     if (p->roi_enable) {
511         mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4);
512         mpp_assert(p->roi_ctx);
513     }
514 
515 RET:
516     return ret;
517 }
518 
mt_test_res_init(MpiEncMtCtxInfo * info)519 MPP_RET mt_test_res_init(MpiEncMtCtxInfo *info)
520 {
521     MpiEncTestArgs *cmd = info->cmd;
522     MpiEncMtTestData *p = &info->ctx;
523     MppPollType timeout = MPP_POLL_NON_BLOCK;
524     RK_U32 quiet = cmd->quiet;
525     MPP_RET ret = MPP_OK;
526     RK_S32 i;
527 
528     mpp_log_q(quiet, "%s start\n", info->name);
529 
530     p->list_buf = new mpp_list(NULL);
531     if (NULL == p->list_buf) {
532         mpp_err_f("failed to get mpp buffer list\n");
533         return MPP_ERR_MALLOC;
534     }
535 
536     ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
537     if (ret) {
538         mpp_err_f("failed to get mpp buffer group ret %d\n", ret);
539         return ret;
540     }
541 
542     for (i = 0; i < BUF_COUNT; i++) {
543         ret = mpp_buffer_get(p->buf_grp, &p->frm_buf[i], p->frame_size + p->header_size);
544         if (ret) {
545             mpp_err_f("failed to get buffer for input frame ret %d\n", ret);
546             return ret;
547         }
548 
549         ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf[i], p->frame_size);
550         if (ret) {
551             mpp_err_f("failed to get buffer for output packet ret %d\n", ret);
552             return ret;
553         }
554 
555         p->list_buf->add_at_tail(&p->frm_buf[i], sizeof(p->frm_buf[i]));
556     }
557 
558     // encoder demo
559     ret = mpp_create(&p->ctx, &p->mpi);
560     if (ret) {
561         mpp_err("mpp_create failed ret %d\n", ret);
562         return ret;
563     }
564 
565     mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n",
566               p->ctx, p->width, p->height, p->type);
567 
568     ret = p->mpi->control(p->ctx, MPP_SET_INPUT_TIMEOUT, &timeout);
569     if (ret) {
570         mpp_err("mpi control set input timeout %d ret %d\n", timeout, ret);
571         return ret;
572     }
573 
574     timeout = MPP_POLL_BLOCK;
575 
576     ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
577     if (ret) {
578         mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret);
579         return ret;
580     }
581 
582     ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
583     if (ret) {
584         mpp_err("mpp_init failed ret %d\n", ret);
585         return ret;
586     }
587 
588     ret = mpp_enc_cfg_init(&p->cfg);
589     if (ret) {
590         mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret);
591         return ret;
592     }
593 
594     ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg);
595     if (ret) {
596         mpp_err_f("get enc cfg failed ret %d\n", ret);
597         return ret;
598     }
599 
600     ret = test_mt_cfg_setup(info);
601     if (ret) {
602         mpp_err_f("test mpp setup failed ret %d\n", ret);
603     }
604 
605     return ret;
606 }
607 
mt_test_res_deinit(MpiEncMtCtxInfo * info)608 MPP_RET mt_test_res_deinit(MpiEncMtCtxInfo *info)
609 {
610     MpiEncMtTestData *p = &info->ctx;
611     MPP_RET ret = MPP_OK;
612     RK_S32 i;
613 
614     p->mpi->reset(p->ctx);
615     if (ret) {
616         mpp_err("mpi->reset failed\n");
617         return ret;
618     }
619 
620     if (p->ctx) {
621         mpp_destroy(p->ctx);
622         p->ctx = NULL;
623     }
624 
625     if (p->cfg) {
626         mpp_enc_cfg_deinit(p->cfg);
627         p->cfg = NULL;
628     }
629 
630     for (i = 0; i < BUF_COUNT; i++) {
631         if (p->frm_buf[i]) {
632             mpp_buffer_put(p->frm_buf[i]);
633             p->frm_buf[i] = NULL;
634         }
635 
636         if (p->pkt_buf[i]) {
637             mpp_buffer_put(p->pkt_buf[i]);
638             p->pkt_buf[i] = NULL;
639         }
640     }
641 
642     if (p->osd_data.buf) {
643         mpp_buffer_put(p->osd_data.buf);
644         p->osd_data.buf = NULL;
645     }
646 
647     if (p->buf_grp) {
648         mpp_buffer_group_put(p->buf_grp);
649         p->buf_grp = NULL;
650     }
651 
652     if (p->list_buf) {
653         delete p->list_buf;
654         p->list_buf = NULL;
655     }
656 
657     if (p->roi_ctx) {
658         mpp_enc_roi_deinit(p->roi_ctx);
659         p->roi_ctx = NULL;
660     }
661 
662     return MPP_OK;
663 }
664 
enc_test_input(void * arg)665 void *enc_test_input(void *arg)
666 {
667     MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg;
668     MpiEncTestArgs *cmd = info->cmd;
669     MpiEncMtTestData *p = &info->ctx;
670     RK_S32 chn = info->chn;
671     MppApi *mpi = p->mpi;
672     MppCtx ctx = p->ctx;
673     mpp_list *list_buf = p->list_buf;
674     RK_U32 cap_num = 0;
675     RK_U32 quiet = cmd->quiet;
676     MPP_RET ret = MPP_OK;
677 
678     mpp_log_q(quiet, "%s start\n", info->name);
679 
680     while (1) {
681         MppMeta meta = NULL;
682         MppFrame frame = NULL;
683         MppBuffer buffer = NULL;
684         void *buf = NULL;
685         RK_S32 cam_frm_idx = -1;
686         MppBuffer cam_buf = NULL;
687 
688         {
689             AutoMutex autolock(list_buf->mutex());
690             if (!list_buf->list_size())
691                 list_buf->wait();
692 
693             buffer = NULL;
694             list_buf->del_at_head(&buffer, sizeof(buffer));
695             if (NULL == buffer)
696                 continue;
697 
698             buf = mpp_buffer_get_ptr(buffer);
699         }
700 
701         if (p->fp_input) {
702             ret = read_image((RK_U8 *)buf, p->fp_input, p->width, p->height,
703                              p->hor_stride, p->ver_stride, p->fmt);
704             if (ret == MPP_NOK || feof(p->fp_input)) {
705                 p->frm_eos = 1;
706 
707                 if (p->frame_num < 0 || p->frm_cnt_in < p->frame_num) {
708                     clearerr(p->fp_input);
709                     rewind(p->fp_input);
710                     p->frm_eos = 0;
711                     mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times);
712                     continue;
713                 }
714                 mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input));
715             } else if (ret == MPP_ERR_VALUE)
716                 break;
717         } else {
718             if (p->cam_ctx == NULL) {
719                 ret = fill_image((RK_U8 *)buf, p->width, p->height, p->hor_stride,
720                                  p->ver_stride, p->fmt, p->frm_cnt_in);
721                 if (ret)
722                     break;
723             } else {
724                 cam_frm_idx = camera_source_get_frame(p->cam_ctx);
725                 mpp_assert(cam_frm_idx >= 0);
726 
727                 /* skip unstable frames */
728                 if (cap_num++ < 50) {
729                     camera_source_put_frame(p->cam_ctx, cam_frm_idx);
730                     continue;
731                 }
732 
733                 cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx);
734                 mpp_assert(cam_buf);
735             }
736         }
737 
738         ret = mpp_frame_init(&frame);
739         if (ret) {
740             mpp_err_f("mpp_frame_init failed\n");
741             break;
742         }
743 
744         mpp_frame_set_width(frame, p->width);
745         mpp_frame_set_height(frame, p->height);
746         mpp_frame_set_hor_stride(frame, p->hor_stride);
747         mpp_frame_set_ver_stride(frame, p->ver_stride);
748         mpp_frame_set_fmt(frame, p->fmt);
749         mpp_frame_set_eos(frame, p->frm_eos);
750 
751         if (p->fp_input && feof(p->fp_input))
752             mpp_frame_set_buffer(frame, NULL);
753         else if (cam_buf)
754             mpp_frame_set_buffer(frame, cam_buf);
755         else
756             mpp_frame_set_buffer(frame, buffer);
757 
758         meta = mpp_frame_get_meta(frame);
759 
760         if (p->osd_enable || p->user_data_enable || p->roi_enable) {
761             if (p->user_data_enable) {
762                 MppEncUserData user_data;
763                 const char *str = "this is user data\n";
764 
765                 if ((p->frm_cnt_in & 10) == 0) {
766                     user_data.pdata = (void *)str;
767                     user_data.len = strlen(str) + 1;
768                     mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data);
769                 }
770                 static RK_U8 uuid_debug_info[16] = {
771                     0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
772                     0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
773                 };
774 
775                 MppEncUserDataSet data_group;
776                 MppEncUserDataFull datas[2];
777                 const char *str1 = "this is user data 1\n";
778                 const char *str2 = "this is user data 2\n";
779                 data_group.count = 2;
780                 datas[0].len = strlen(str1) + 1;
781                 datas[0].pdata = (void *)str1;
782                 datas[0].uuid = uuid_debug_info;
783 
784                 datas[1].len = strlen(str2) + 1;
785                 datas[1].pdata = (void *)str2;
786                 datas[1].uuid = uuid_debug_info;
787 
788                 data_group.datas = datas;
789 
790                 mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group);
791             }
792 
793             if (p->osd_enable) {
794                 /* gen and cfg osd plt */
795                 mpi_enc_gen_osd_plt(&p->osd_plt, p->frm_cnt_in);
796 
797                 p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL;
798                 p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF;
799                 p->osd_plt_cfg.plt = &p->osd_plt;
800 
801                 ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg);
802                 if (ret) {
803                     mpp_err("mpi control enc set osd plt failed ret %d\n", ret);
804                     break;
805                 }
806 
807                 /* gen and cfg osd plt */
808                 mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width,
809                                      p->height, p->frm_cnt_in);
810                 mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data);
811             }
812 
813             if (p->roi_enable) {
814                 RoiRegionCfg *region = &p->roi_region;
815 
816                 /* calculated in pixels */
817                 region->x = MPP_ALIGN(p->width / 8, 16);
818                 region->y = MPP_ALIGN(p->height / 8, 16);
819                 region->w = 128;
820                 region->h = 256;
821                 region->force_intra = 0;
822                 region->qp_mode = 1;
823                 region->qp_val = 24;
824 
825                 mpp_enc_roi_add_region(p->roi_ctx, region);
826 
827                 region->x = MPP_ALIGN(p->width / 2, 16);
828                 region->y = MPP_ALIGN(p->height / 4, 16);
829                 region->w = 256;
830                 region->h = 128;
831                 region->force_intra = 1;
832                 region->qp_mode = 1;
833                 region->qp_val = 10;
834 
835                 mpp_enc_roi_add_region(p->roi_ctx, region);
836 
837                 /* send roi info by metadata */
838                 mpp_enc_roi_setup_meta(p->roi_ctx, meta);
839             }
840         }
841 
842         if (!p->first_frm)
843             p->first_frm = mpp_time();
844         /*
845          * NOTE: in non-block mode the frame can be resent.
846          * The default input timeout mode is block.
847          *
848          * User should release the input frame to meet the requirements of
849          * resource creator must be the resource destroyer.
850          */
851         p->frm_cnt_in++;
852         do {
853             ret = mpi->encode_put_frame(ctx, frame);
854             if (ret)
855                 msleep(1);
856         } while (ret);
857 
858         if (cam_frm_idx >= 0)
859             camera_source_put_frame(p->cam_ctx, cam_frm_idx);
860 
861         if (p->frame_num > 0 && p->frm_cnt_in >= p->frame_num) {
862             p->frm_eos = 1;
863             break;
864         }
865 
866         if (p->loop_end) {
867             p->frm_eos = 1;
868             break;
869         }
870 
871         if (p->frm_eos)
872             break;
873     }
874 
875     return NULL;
876 }
877 
enc_test_output(void * arg)878 void *enc_test_output(void *arg)
879 {
880     MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg;
881     MpiEncTestArgs *cmd = info->cmd;
882     MpiEncMtTestData *p = &info->ctx;
883     MpiEncMtCtxRet *enc_ret = &info->ret;
884     mpp_list *list_buf = p->list_buf;
885     RK_S32 chn = info->chn;
886     MppApi *mpi = p->mpi;
887     MppCtx ctx = p->ctx;
888     RK_U32 quiet = cmd->quiet;
889     MPP_RET ret = MPP_OK;
890     MppPacket packet = NULL;
891     RK_U32 eoi = 1;
892 
893     void *ptr;
894     size_t len;
895     char log_buf[256];
896     RK_S32 log_size = sizeof(log_buf) - 1;
897     RK_S32 log_len = 0;
898 
899     while (1) {
900         ret = mpi->encode_get_packet(ctx, &packet);
901         if (ret || NULL == packet) {
902             msleep(1);
903             continue;
904         }
905 
906         p->last_pkt = mpp_time();
907 
908         // write packet to file here
909         ptr = mpp_packet_get_pos(packet);
910         len = mpp_packet_get_length(packet);
911         log_size = sizeof(log_buf) - 1;
912         log_len = 0;
913 
914         if (!p->first_pkt)
915             p->first_pkt = mpp_time();
916 
917         p->pkt_eos = mpp_packet_get_eos(packet);
918 
919         if (p->fp_output)
920             fwrite(ptr, 1, len, p->fp_output);
921 
922         log_len += snprintf(log_buf + log_len, log_size - log_len,
923                             "encoded frame %-4d", p->frm_cnt_out);
924 
925         /* for low delay partition encoding */
926         if (mpp_packet_is_partition(packet)) {
927             eoi = mpp_packet_is_eoi(packet);
928 
929             log_len += snprintf(log_buf + log_len, log_size - log_len,
930                                 " pkt %d", p->frm_pkt_cnt);
931             p->frm_pkt_cnt = (eoi) ? (0) : (p->frm_pkt_cnt + 1);
932         }
933 
934         log_len += snprintf(log_buf + log_len, log_size - log_len,
935                             " size %-7zu", len);
936 
937         if (mpp_packet_has_meta(packet)) {
938             MppMeta meta = mpp_packet_get_meta(packet);
939             MppFrame frm = NULL;
940             RK_S32 temporal_id = 0;
941             RK_S32 lt_idx = -1;
942             RK_S32 avg_qp = -1;
943 
944             if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id))
945                 log_len += snprintf(log_buf + log_len, log_size - log_len,
946                                     " tid %d", temporal_id);
947 
948             if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, &lt_idx))
949                 log_len += snprintf(log_buf + log_len, log_size - log_len,
950                                     " lt %d", lt_idx);
951 
952             if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp))
953                 log_len += snprintf(log_buf + log_len, log_size - log_len,
954                                     " qp %d", avg_qp);
955 
956             if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) {
957                 MppBuffer frm_buf = NULL;
958 
959                 mpp_assert(frm);
960                 frm_buf = mpp_frame_get_buffer(frm);
961 
962                 if (frm_buf) {
963                     AutoMutex autolock(list_buf->mutex());
964                     list_buf->add_at_tail(&frm_buf, sizeof(frm_buf));
965                     list_buf->signal();
966                 }
967 
968                 mpp_frame_deinit(&frm);
969             }
970         }
971 
972         mpp_log_q(quiet, "chn %d %s\n", chn, log_buf);
973 
974         mpp_packet_deinit(&packet);
975         fps_calc_inc(cmd->fps);
976 
977         p->stream_size += len;
978         p->frm_cnt_out += eoi;
979 
980         if (p->frm_cnt_out != p->frm_cnt_in)
981             continue;
982 
983         if (p->frame_num > 0 && p->frm_cnt_out >= p->frame_num) {
984             p->pkt_eos = 1;
985             break;
986         }
987 
988         if (p->frm_eos) {
989             p->pkt_eos = 1;
990             break;
991         }
992 
993         if (p->pkt_eos) {
994             mpp_log_q(quiet, "chn %d found last packet\n", chn);
995             mpp_assert(p->frm_eos);
996             break;
997         }
998     } while (!eoi);
999 
1000     enc_ret->elapsed_time = p->last_pkt - p->first_frm;
1001     enc_ret->frame_count = p->frm_cnt_out;
1002     enc_ret->stream_size = p->stream_size;
1003     enc_ret->frame_rate = (float)p->frm_cnt_out * 1000000 / enc_ret->elapsed_time;
1004     enc_ret->bit_rate = (p->stream_size * 8 * (p->fps_out_num / p->fps_out_den)) / p->frm_cnt_out;
1005     enc_ret->delay = p->first_pkt - p->first_frm;
1006 
1007     return NULL;
1008 }
1009 
enc_test_mt(MpiEncTestArgs * cmd,const char * name)1010 int enc_test_mt(MpiEncTestArgs* cmd, const char *name)
1011 {
1012     MpiEncMtCtxInfo *ctxs = NULL;
1013     float total_rate = 0.0;
1014     RK_S32 ret = MPP_NOK;
1015     RK_S32 i = 0;
1016 
1017     ctxs = mpp_calloc(MpiEncMtCtxInfo, cmd->nthreads);
1018     if (NULL == ctxs) {
1019         mpp_err("failed to alloc context for instances\n");
1020         return -1;
1021     }
1022 
1023     for (i = 0; i < cmd->nthreads; i++) {
1024         ctxs[i].cmd = cmd;
1025         ctxs[i].name = name;
1026         ctxs[i].chn = i;
1027 
1028         ret = mt_test_ctx_init(&ctxs[i]);
1029         if (ret) {
1030             mpp_err_f("test ctx init failed ret %d\n", ret);
1031             return ret;
1032         }
1033 
1034         ret = mt_test_res_init(&ctxs[i]);
1035         if (ret) {
1036             mpp_err_f("test resource deinit failed ret %d\n", ret);
1037             return ret;
1038         }
1039 
1040         ret = pthread_create(&ctxs[i].thd_out, NULL, enc_test_output, &ctxs[i]);
1041         if (ret) {
1042             mpp_err("failed to create thread %d\n", i);
1043             return ret;
1044         }
1045 
1046         ret = pthread_create(&ctxs[i].thd_in, NULL, enc_test_input, &ctxs[i]);
1047         if (ret) {
1048             mpp_err("failed to create thread %d\n", i);
1049             return ret;
1050         }
1051     }
1052 
1053 
1054     if (cmd->frame_num < 0) {
1055         // wait for input then quit encoding
1056         mpp_log("*******************************************\n");
1057         mpp_log("**** Press Enter to stop loop encoding ****\n");
1058         mpp_log("*******************************************\n");
1059 
1060         getc(stdin);
1061         for (i = 0; i < cmd->nthreads; i++)
1062             ctxs[i].ctx.loop_end = 1;
1063     }
1064 
1065     for (i = 0; i < cmd->nthreads; i++) {
1066         pthread_join(ctxs[i].thd_in, NULL);
1067         pthread_join(ctxs[i].thd_out, NULL);
1068 
1069         ret = mt_test_res_deinit(&ctxs[i]);
1070         if (ret) {
1071             mpp_err_f("test resource deinit failed ret %d\n", ret);
1072             return ret;
1073         }
1074 
1075         ret = mt_test_ctx_deinit(&ctxs[i]);
1076         if (ret) {
1077             mpp_err_f("test ctx deinit failed ret %d\n", ret);
1078             return ret;
1079         }
1080     }
1081 
1082     for (i = 0; i < cmd->nthreads; i++) {
1083         MpiEncMtCtxRet *enc_ret = &ctxs[i].ret;
1084 
1085         mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n",
1086                 i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000),
1087                 (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate);
1088 
1089         total_rate += enc_ret->frame_rate;
1090     }
1091 
1092     MPP_FREE(ctxs);
1093 
1094     total_rate /= cmd->nthreads;
1095     mpp_log("%s average frame rate %.2f\n", name, total_rate);
1096 
1097     return ret;
1098 }
1099 
main(int argc,char ** argv)1100 int main(int argc, char **argv)
1101 {
1102     RK_S32 ret = MPP_NOK;
1103     MpiEncTestArgs* cmd = mpi_enc_test_cmd_get();
1104 
1105     // parse the cmd option
1106     ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argv);
1107     if (ret)
1108         goto DONE;
1109 
1110     mpi_enc_test_cmd_show_opt(cmd);
1111 
1112     ret = enc_test_mt(cmd, argv[0]);
1113 
1114 DONE:
1115     mpi_enc_test_cmd_put(cmd);
1116 
1117     return ret;
1118 }
1119