xref: /OK3568_Linux_fs/external/rknpu2/examples/rknn_yolov5_demo/utils/mpp_encoder.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include <stdio.h>
2 #include <string.h>
3 
4 #include "mpp_encoder.h"
5 #include "rockchip/mpp_buffer.h"
6 
7 #define MPP_ALIGN(x, a)         (((x)+(a)-1)&~((a)-1))
8 #define SZ_4K 4096
9 #define LOGD printf
10 // #define LOGD
11 #define LOGE printf
12 
InitParams(MppEncoderParams & params)13 int MppEncoder::InitParams(MppEncoderParams& params)
14 {
15     memcpy(&enc_params, &params, sizeof(MppEncoderParams));
16 
17     // get paramter from cmd
18     if (enc_params.hor_stride == 0) {
19         enc_params.hor_stride = MPP_ALIGN(enc_params.width, 16);
20     }
21     if (enc_params.ver_stride == 0) {
22         enc_params.ver_stride = (MPP_ALIGN(enc_params.height, 16));
23     }
24 
25     if (enc_params.fps_in_den == 0)
26         enc_params.fps_in_den = 1;
27     if (enc_params.fps_in_num == 0)
28         enc_params.fps_in_num = 30;
29     if (enc_params.fps_out_den == 0)
30         enc_params.fps_out_den = 1;
31     if (enc_params.fps_out_num == 0)
32         enc_params.fps_out_num = 30;
33 
34     if (!enc_params.bps)
35         enc_params.bps = enc_params.width * enc_params.height / 8 * (enc_params.fps_out_num / enc_params.fps_out_den);
36 
37     this->mdinfo_size  = (MPP_VIDEO_CodingHEVC == enc_params.type) ?
38                       (MPP_ALIGN(enc_params.hor_stride, 32) >> 5) *
39                       (MPP_ALIGN(enc_params.ver_stride, 32) >> 5) * 16 :
40                       (MPP_ALIGN(enc_params.hor_stride, 64) >> 6) *
41                       (MPP_ALIGN(enc_params.ver_stride, 16) >> 4) * 16;
42 
43     // update resource parameter
44     switch (enc_params.fmt & MPP_FRAME_FMT_MASK) {
45     case MPP_FMT_YUV420SP:
46     case MPP_FMT_YUV420P: {
47         this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64) * 3 / 2;
48     } break;
49 
50     case MPP_FMT_YUV422_YUYV :
51     case MPP_FMT_YUV422_YVYU :
52     case MPP_FMT_YUV422_UYVY :
53     case MPP_FMT_YUV422_VYUY :
54     case MPP_FMT_YUV422P :
55     case MPP_FMT_YUV422SP : {
56         this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64) * 2;
57     } break;
58     case MPP_FMT_RGB444 :
59     case MPP_FMT_BGR444 :
60     case MPP_FMT_RGB555 :
61     case MPP_FMT_BGR555 :
62     case MPP_FMT_RGB565 :
63     case MPP_FMT_BGR565 :
64     case MPP_FMT_RGB888 :
65     case MPP_FMT_BGR888 :
66     case MPP_FMT_RGB101010 :
67     case MPP_FMT_BGR101010 :
68     case MPP_FMT_ARGB8888 :
69     case MPP_FMT_ABGR8888 :
70     case MPP_FMT_BGRA8888 :
71     case MPP_FMT_RGBA8888 : {
72         this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64);
73     } break;
74 
75     default: {
76         this->frame_size = MPP_ALIGN(enc_params.hor_stride, 64) * MPP_ALIGN(enc_params.ver_stride, 64) * 4;
77     } break;
78     }
79 
80     if (MPP_FRAME_FMT_IS_FBC(enc_params.fmt)) {
81         if ((enc_params.fmt & MPP_FRAME_FBC_MASK) == MPP_FRAME_FBC_AFBC_V1)
82             this->header_size = MPP_ALIGN(MPP_ALIGN(enc_params.width, 16) * MPP_ALIGN(enc_params.height, 16) / 16, SZ_4K);
83         else
84             this->header_size = MPP_ALIGN(enc_params.width, 16) * MPP_ALIGN(enc_params.height, 16) / 16;
85     } else {
86         this->header_size = 0;
87     }
88 
89     return 0;
90 }
91 
SetupEncCfg()92 int MppEncoder::SetupEncCfg()
93 {
94     MPP_RET ret;
95 
96     ret = mpp_enc_cfg_init(&cfg);
97     if (ret) {
98         LOGE("mpp_enc_cfg_init failed ret %d\n", ret);
99         return -1;
100     }
101 
102     /* setup default parameter */
103     if (enc_params.fps_in_den == 0)
104         enc_params.fps_in_den = 1;
105     if (enc_params.fps_in_num == 0)
106         enc_params.fps_in_num = 30;
107     if (enc_params.fps_out_den == 0)
108         enc_params.fps_out_den = 1;
109     if (enc_params.fps_out_num == 0)
110         enc_params.fps_out_num = 30;
111 
112     if (!enc_params.bps)
113         enc_params.bps = enc_params.width * enc_params.height / 8 * (enc_params.fps_out_num / enc_params.fps_out_den);
114 
115     mpp_enc_cfg_set_s32(cfg, "prep:width", enc_params.width);
116     mpp_enc_cfg_set_s32(cfg, "prep:height", enc_params.height);
117     mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", enc_params.hor_stride);
118     mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", enc_params.ver_stride);
119     mpp_enc_cfg_set_s32(cfg, "prep:format", enc_params.fmt);
120 
121     mpp_enc_cfg_set_s32(cfg, "rc:mode", enc_params.rc_mode);
122 
123     /* fix input / output frame rate */
124     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", enc_params.fps_in_flex);
125     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", enc_params.fps_in_num);
126     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", enc_params.fps_in_den);
127     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", enc_params.fps_out_flex);
128     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", enc_params.fps_out_num);
129     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", enc_params.fps_out_den);
130     mpp_enc_cfg_set_s32(cfg, "rc:gop", enc_params.gop_len ? enc_params.gop_len : enc_params.fps_out_num * 2);
131 
132     /* drop frame or not when bitrate overflow */
133     mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
134     mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20);        /* 20% of max bps */
135     mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1);         /* Do not continuous drop frame */
136 
137     /* setup bitrate for different rc_mode */
138     mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_params.bps);
139     switch (enc_params.rc_mode) {
140     case MPP_ENC_RC_MODE_FIXQP : {
141         /* do not setup bitrate on FIXQP mode */
142     } break;
143     case MPP_ENC_RC_MODE_CBR : {
144         /* CBR mode has narrow bound */
145         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
146         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 15 / 16);
147     } break;
148     case MPP_ENC_RC_MODE_VBR :
149     case MPP_ENC_RC_MODE_AVBR : {
150         /* VBR mode has wide bound */
151         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
152         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 1 / 16);
153     } break;
154     default : {
155         /* default use CBR mode */
156         mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_params.bps_max ? enc_params.bps_max : enc_params.bps * 17 / 16);
157         mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_params.bps_min ? enc_params.bps_min : enc_params.bps * 15 / 16);
158     } break;
159     }
160 
161     /* setup qp for different codec and rc_mode */
162     switch (enc_params.type) {
163     case MPP_VIDEO_CodingAVC :
164     case MPP_VIDEO_CodingHEVC : {
165         switch (enc_params.rc_mode) {
166         case MPP_ENC_RC_MODE_FIXQP : {
167             RK_S32 fix_qp = enc_params.qp_init;
168 
169             mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp);
170             mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp);
171             mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp);
172             mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp);
173             mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp);
174             mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0);
175         } break;
176         case MPP_ENC_RC_MODE_CBR :
177         case MPP_ENC_RC_MODE_VBR :
178         case MPP_ENC_RC_MODE_AVBR : {
179             mpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1);
180             mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51);
181             mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10);
182             mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51);
183             mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10);
184             mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
185         } break;
186         default : {
187             LOGE("unsupport encoder rc mode %d\n", enc_params.rc_mode);
188         } break;
189         }
190     } break;
191     case MPP_VIDEO_CodingVP8 : {
192         /* vp8 only setup base qp range */
193         mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40);
194         mpp_enc_cfg_set_s32(cfg, "rc:qp_max",  127);
195         mpp_enc_cfg_set_s32(cfg, "rc:qp_min",  0);
196         mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127);
197         mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0);
198         mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
199     } break;
200     case MPP_VIDEO_CodingMJPEG : {
201         /* jpeg use special codec config to control qtable */
202         mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80);
203         mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99);
204         mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
205     } break;
206     default : {
207     } break;
208     }
209 
210     /* setup codec  */
211     mpp_enc_cfg_set_s32(cfg, "codec:type", enc_params.type);
212     switch (enc_params.type) {
213     case MPP_VIDEO_CodingAVC : {
214         RK_U32 constraint_set = enc_params.constraint_set;
215 
216         /*
217          * H.264 profile_idc parameter
218          * 66  - Baseline profile
219          * 77  - Main profile
220          * 100 - High profile
221          */
222         mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
223         /*
224          * H.264 level_idc parameter
225          * 10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
226          * 20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
227          * 30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
228          * 40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
229          * 50 / 51 / 52         - 4K@30fps
230          */
231         mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
232         mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
233         mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
234         mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
235 
236         if (constraint_set & 0x3f0000)
237             mpp_enc_cfg_set_s32(cfg, "h264:constraint_set", constraint_set);
238     } break;
239     case MPP_VIDEO_CodingHEVC :
240     case MPP_VIDEO_CodingMJPEG :
241     case MPP_VIDEO_CodingVP8 : {
242     } break;
243     default : {
244         LOGE("unsupport encoder coding type %d\n", enc_params.type);
245     } break;
246     }
247 
248     if (enc_params.split_mode) {
249         LOGD("%p split mode %d arg %d out %d\n", mpp_ctx,
250                   enc_params.split_mode, enc_params.split_arg, enc_params.split_out);
251         mpp_enc_cfg_set_s32(cfg, "split:mode", enc_params.split_mode);
252         mpp_enc_cfg_set_s32(cfg, "split:arg", enc_params.split_arg);
253         mpp_enc_cfg_set_s32(cfg, "split:out", enc_params.split_out);
254     }
255 
256     mpp_enc_cfg_set_s32(cfg, "prep:mirroring", enc_params.mirroring);
257     mpp_enc_cfg_set_s32(cfg, "prep:rotation", enc_params.rotation);
258     mpp_enc_cfg_set_s32(cfg, "prep:flip", enc_params.flip);
259 
260     ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_CFG, cfg);
261     if (ret) {
262         LOGE("mpi control enc set cfg failed ret %d\n", ret);
263         goto RET;
264     }
265 
266 #if 0
267     /* optional */
268     {
269         ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_SEI_CFG, &enc_params.sei_mode);
270         if (ret) {
271             LOGE("mpi control enc set sei cfg failed ret %d\n", ret);
272             goto RET;
273         }
274     }
275 #endif
276 
277     if (enc_params.type == MPP_VIDEO_CodingAVC || enc_params.type == MPP_VIDEO_CodingHEVC) {
278         enc_params.header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
279         ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_HEADER_MODE, &enc_params.header_mode);
280         if (ret) {
281             LOGE("mpi control enc set header mode failed ret %d\n", ret);
282             goto RET;
283         }
284     }
285 
286 #if 0
287     RK_U32 gop_mode = enc_params.gop_mode;
288     if (gop_mode) {
289         MppEncRefCfg ref;
290 
291         mpp_enc_ref_cfg_init(&ref);
292 
293         if (enc_params.gop_mode < 4)
294             mpi_enc_gen_ref_cfg(ref, gop_mode);
295         else
296             mpi_enc_gen_smart_gop_ref_cfg(ref, enc_params.gop_len, enc_params.vi_len);
297 
298         ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_REF_CFG, ref);
299         if (ret) {
300             LOGE("mpi control enc set ref cfg failed ret %d\n", ret);
301             goto RET;
302         }
303         mpp_enc_ref_cfg_deinit(&ref);
304     }
305 
306     if (enc_params.roi_enable) {
307         mpp_enc_roi_init(&enc_params.roi_mpp_ctx, enc_params.width, enc_params.height, enc_params.type, 4);
308         mpp_assert(enc_params.roi_mpp_ctx);
309     }
310 #endif
311 
312 RET:
313     return ret;
314 }
315 
MppEncoder()316 MppEncoder::MppEncoder() {
317     memset(&enc_params, 0, sizeof(MppEncoderParams));
318     this->mpp_ctx = NULL;
319     this->mpp_mpi = NULL;
320     memset(&osd_data, 0, sizeof(MppEncOSDData));
321 }
322 
~MppEncoder()323 MppEncoder::~MppEncoder() {
324     if (this->mpp_ctx) {
325         mpp_destroy(this->mpp_ctx);
326         this->mpp_ctx = NULL;
327     }
328 
329     if (this->cfg) {
330         mpp_enc_cfg_deinit(this->cfg);
331         this->cfg = NULL;
332     }
333 
334     if (this->frm_buf) {
335         mpp_buffer_put(this->frm_buf);
336         this->frm_buf = NULL;
337     }
338 
339     if (this->pkt_buf) {
340         mpp_buffer_put(this->pkt_buf);
341         this->pkt_buf = NULL;
342     }
343 
344     if (this->md_info) {
345         mpp_buffer_put(this->md_info);
346         this->md_info = NULL;
347     }
348 
349     if (this->osd_data.buf) {
350         mpp_buffer_put(this->osd_data.buf);
351         this->osd_data.buf = NULL;
352     }
353 
354     if (this->buf_grp) {
355         mpp_buffer_group_put(this->buf_grp);
356         this->buf_grp = NULL;
357     }
358 }
359 
Init(MppEncoderParams & params,void * userdata)360 int MppEncoder::Init(MppEncoderParams& params, void* userdata) {
361     int ret;
362     MppPollType timeout = MPP_POLL_BLOCK;
363 
364     this->userdata = userdata;
365 
366     this->InitParams(params);
367 
368     ret = mpp_buffer_group_get_internal(&this->buf_grp, MPP_BUFFER_TYPE_DRM);
369     if (ret) {
370         LOGD("failed to get mpp buffer group ret %d\n", ret);
371         goto MPP_TEST_OUT;
372     }
373 
374     ret = mpp_buffer_get(this->buf_grp, &this->pkt_buf, this->frame_size);
375     if (ret) {
376         LOGD("failed to get buffer for output packet ret %d\n", ret);
377         goto MPP_TEST_OUT;
378     }
379 
380     ret = mpp_buffer_get(this->buf_grp, &this->md_info, this->mdinfo_size);
381     if (ret) {
382         LOGD("failed to get buffer for motion info output packet ret %d\n", ret);
383         goto MPP_TEST_OUT;
384     }
385 
386     // encoder demo
387     ret = mpp_create(&this->mpp_ctx, &this->mpp_mpi);
388     if (ret) {
389         LOGE("mpp_create failed ret %d\n", ret);
390         goto MPP_TEST_OUT;
391     }
392 
393     LOGD("%p encoder test start w %d h %d type %d\n",
394               this->mpp_ctx, enc_params.width, enc_params.height, enc_params.type);
395 
396     ret = mpp_mpi->control(mpp_ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
397     if (MPP_OK != ret) {
398         LOGE("mpi control set output timeout %d ret %d\n", timeout, ret);
399         goto MPP_TEST_OUT;
400     }
401 
402     ret = mpp_init(mpp_ctx, MPP_CTX_ENC, enc_params.type);
403     if (ret) {
404         LOGE("mpp_init failed ret %d\n", ret);
405         goto MPP_TEST_OUT;
406     }
407 
408     this->SetupEncCfg();
409 
410 MPP_TEST_OUT:
411     if (ret) {
412         if (this->mpp_ctx) {
413             mpp_destroy(this->mpp_ctx);
414             this->mpp_ctx = NULL;
415         }
416 
417         if (this->cfg) {
418             mpp_enc_cfg_deinit(this->cfg);
419             this->cfg = NULL;
420         }
421 
422         if (this->frm_buf) {
423             mpp_buffer_put(this->frm_buf);
424             this->frm_buf = NULL;
425         }
426 
427         if (this->pkt_buf) {
428             mpp_buffer_put(this->pkt_buf);
429             this->pkt_buf = NULL;
430         }
431 
432         if (this->md_info) {
433             mpp_buffer_put(this->md_info);
434             this->md_info = NULL;
435         }
436 
437         if (this->osd_data.buf) {
438             mpp_buffer_put(this->osd_data.buf);
439             this->osd_data.buf = NULL;
440         }
441 
442         if (this->buf_grp) {
443             mpp_buffer_group_put(this->buf_grp);
444             this->buf_grp = NULL;
445         }
446 
447         // if (this->roi_ctx) {
448         //     mpp_enc_roi_deinit(this->roi_ctx);
449         //     this->roi_ctx = NULL;
450         // }
451     }
452 
453     return ret;
454 }
455 
SetCallback(MppEncoderFrameCallback callback)456 int MppEncoder::SetCallback(MppEncoderFrameCallback callback) {
457     this->callback = callback;
458 }
459 
GetHeader(char * enc_buf,int max_size)460 int MppEncoder::GetHeader(char* enc_buf, int max_size) {
461     int ret;
462     void* out_ptr = enc_buf;
463     size_t out_len = 0;
464 
465     if (enc_params.type == MPP_VIDEO_CodingAVC || enc_params.type == MPP_VIDEO_CodingHEVC) {
466         MppPacket packet = NULL;
467 
468         /*
469          * Can use packet with normal malloc buffer as input not pkt_buf.
470          * Please refer to vpu_api_legacy.cpp for normal buffer case.
471          * Using pkt_buf buffer here is just for simplifing demo.
472          */
473         mpp_packet_init_with_buffer(&packet, this->pkt_buf);
474         /* NOTE: It is important to clear output packet length!! */
475         mpp_packet_set_length(packet, 0);
476 
477         ret = mpp_mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, packet);
478         if (ret) {
479             LOGD("mpi control enc get extra info failed\n");
480             return -1;
481         } else {
482             /* get and write sps/pps for H.264 */
483 
484             void *ptr   = mpp_packet_get_pos(packet);
485             size_t len  = mpp_packet_get_length(packet);
486 
487             memcpy(out_ptr, ptr, len);
488             out_ptr = (char*)(out_ptr) + len;
489             out_len += len;
490         }
491 
492         mpp_packet_deinit(&packet);
493     }
494     return out_len;
495 }
496 
Encode(void * mpp_buf,char * enc_buf,int max_size)497 int MppEncoder::Encode(void* mpp_buf, char* enc_buf, int max_size) {
498     MPP_RET ret;
499     void* out_ptr = enc_buf;
500     size_t out_len = 0;
501 
502     MppMeta meta = NULL;
503     MppFrame frame = NULL;
504     MppPacket packet = NULL;
505     // void *buf = mpp_buffer_get_ptr(this->frm_buf);
506     // RK_S32 cam_frm_idx = -1;
507     // MppBuffer cam_buf = NULL;
508     RK_U32 eoi = 1;
509     RK_U32 frm_eos = 0;
510 
511     ret = mpp_frame_init(&frame);
512     if (ret) {
513         LOGD("mpp_frame_init failed\n");
514         return -1;
515     }
516 
517     mpp_frame_set_width(frame, enc_params.width);
518     mpp_frame_set_height(frame, enc_params.height);
519     mpp_frame_set_hor_stride(frame, enc_params.hor_stride);
520     mpp_frame_set_ver_stride(frame, enc_params.ver_stride);
521     mpp_frame_set_fmt(frame, enc_params.fmt);
522     mpp_frame_set_eos(frame, frm_eos);
523     mpp_frame_set_buffer(frame, mpp_buf);
524 
525     meta = mpp_frame_get_meta(frame);
526     mpp_packet_init_with_buffer(&packet, pkt_buf);
527     /* NOTE: It is important to clear output packet length!! */
528     mpp_packet_set_length(packet, 0);
529     mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);
530     mpp_meta_set_buffer(meta, KEY_MOTION_INFO, this->md_info);
531 
532 #if 0
533     if (enc_params.osd_enable || enc_params.user_data_enable || enc_params.roi_enable) {
534         if (enc_params.user_data_enable) {
535             MppEncUserData user_data;
536             char *str = "this is user data\n";
537 
538             if ((enc_params.frame_count & 10) == 0) {
539                 user_data.pdata = str;
540                 user_data.len = strlen(str) + 1;
541                 mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data);
542             }
543             static RK_U8 uuid_debug_info[16] = {
544                 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
545                 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
546             };
547 
548             MppEncUserDataSet data_group;
549             MppEncUserDataFull datas[2];
550             char *str1 = "this is user data 1\n";
551             char *str2 = "this is user data 2\n";
552             data_group.count = 2;
553             datas[0].len = strlen(str1) + 1;
554             datas[0].pdata = str1;
555             datas[0].uuid = uuid_debug_info;
556 
557             datas[1].len = strlen(str2) + 1;
558             datas[1].pdata = str2;
559             datas[1].uuid = uuid_debug_info;
560 
561             data_group.datas = datas;
562 
563             mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group);
564         }
565 
566         if (enc_params.osd_enable) {
567             /* gen and cfg osd plt */
568             mpi_enc_gen_osd_plt(&enc_params.osd_plt, enc_params.frame_count);
569 
570             enc_params.osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL;
571             enc_params.osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF;
572             enc_params.osd_plt_cfg.plt = &enc_params.osd_plt;
573 
574             ret = mpp_mpi->control(mpp_ctx, MPP_ENC_SET_OSD_PLT_CFG, &enc_params.osd_plt_cfg);
575             if (ret) {
576                 LOGD("mpi control enc set osd plt failed ret %d\n", ret);
577                 goto RET;
578             }
579 
580             /* gen and cfg osd plt */
581             mpi_enc_gen_osd_data(&enc_params.osd_data, enc_params.buf_grp, enc_params.width,
582                                  enc_params.height, enc_params.frame_count);
583             mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&enc_params.osd_data);
584         }
585 
586         if (enc_params.roi_enable) {
587             RoiRegionCfg *region = &enc_params.roi_region;
588 
589             /* calculated in pixels */
590             region->x = MPP_ALIGN(enc_params.width / 8, 16);
591             region->y = MPP_ALIGN(enc_params.height / 8, 16);
592             region->w = 128;
593             region->h = 256;
594             region->force_intra = 0;
595             region->qp_mode = 1;
596             region->qp_val = 24;
597 
598             mpp_enc_roi_add_region(enc_params.roi_mpp_ctx, region);
599 
600             region->x = MPP_ALIGN(enc_params.width / 2, 16);
601             region->y = MPP_ALIGN(enc_params.height / 4, 16);
602             region->w = 256;
603             region->h = 128;
604             region->force_intra = 1;
605             region->qp_mode = 1;
606             region->qp_val = 10;
607 
608             mpp_enc_roi_add_region(enc_params.roi_mpp_ctx, region);
609 
610             /* send roi info by metadata */
611             mpp_enc_roi_setup_meta(enc_params.roi_mpp_ctx, meta);
612         }
613     }
614 #endif
615 
616     /*
617         * NOTE: in non-block mode the frame can be resent.
618         * The default input timeout mode is block.
619         *
620         * User should release the input frame to meet the requirements of
621         * resource creator must be the resource destroyer.
622         */
623     ret = mpp_mpi->encode_put_frame(mpp_ctx, frame);
624     mpp_frame_deinit(&frame);
625 
626     if (ret) {
627         LOGD("chn %d encode put frame failed\n", chn);
628         return -1;
629     }
630 
631     do {
632         ret = mpp_mpi->encode_get_packet(mpp_ctx, &packet);
633         if (ret) {
634             LOGD("chn %d encode get packet failed\n", chn);
635             return -1;
636         }
637 
638         // mpp_assert(packet);
639 
640         if (packet) {
641             // write packet to file here
642             void *ptr   = mpp_packet_get_pos(packet);
643             size_t len  = mpp_packet_get_length(packet);
644             char log_buf[256];
645             RK_S32 log_size = sizeof(log_buf) - 1;
646             RK_S32 log_len = 0;
647 
648             // if (!enc_params.first_pkt)
649             //     enc_params.first_pkt = mpp_time();
650 
651             RK_U32 pkt_eos = mpp_packet_get_eos(packet);
652 
653             /* set encode result */
654             if (this->callback != nullptr) {
655                 this->callback(this->userdata, (const char*)ptr, len);
656             }
657             if (enc_buf != nullptr && max_size > 0) {
658                 if (out_len + log_len < max_size) {
659                     memcpy(out_ptr, ptr, len);
660                     out_len += len;
661                     out_ptr = (char*)out_ptr + len;
662                 } else {
663                     LOGE("error enc_buf no enought");
664                 }
665             }
666 
667             // log_len += snprintf(log_buf + log_len, log_size - log_len,
668             //                     "encoded frame %-4d", enc_params.frame_count);
669 
670             /* for low delay partition encoding */
671             if (mpp_packet_is_partition(packet)) {
672                 eoi = mpp_packet_is_eoi(packet);
673 
674                 // log_len += snprintf(log_buf + log_len, log_size - log_len,
675                 //                     " pkt %d", enc_params.frm_pkt_cnt);
676                 // enc_params.frm_pkt_cnt = (eoi) ? (0) : (enc_params.frm_pkt_cnt + 1);
677             }
678 
679             log_len += snprintf(log_buf + log_len, log_size - log_len,
680                                 " size %-7zu", len);
681 
682             if (mpp_packet_has_meta(packet)) {
683                 meta = mpp_packet_get_meta(packet);
684                 RK_S32 temporal_id = 0;
685                 RK_S32 lt_idx = -1;
686                 RK_S32 avg_qp = -1;
687 
688                 if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id))
689                     log_len += snprintf(log_buf + log_len, log_size - log_len,
690                                         " tid %d", temporal_id);
691 
692                 if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, &lt_idx))
693                     log_len += snprintf(log_buf + log_len, log_size - log_len,
694                                         " lt %d", lt_idx);
695 
696                 if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp))
697                     log_len += snprintf(log_buf + log_len, log_size - log_len,
698                                         " qp %d", avg_qp);
699             }
700 
701             LOGD("chn %d %s\n", chn, log_buf);
702 
703             mpp_packet_deinit(&packet);
704 
705             // enc_params.stream_size += len;
706             // enc_params.frame_count += eoi;
707 
708             // if (enc_params.pkt_eos) {
709             //     LOGD("chn %d found last packet\n", chn);
710             //     mpp_assert(enc_params.frm_eos);
711             // }
712         }
713     } while (!eoi);
714 
715     // if (enc_params.frm_eos && enc_params.pkt_eos)
716     //     break;
717     return out_len;
718 }
719 
Reset()720 int MppEncoder::Reset() {
721     if (mpp_mpi != NULL) {
722         mpp_mpi->reset(mpp_ctx);
723     }
724     return 0;
725 }
726 
GetFrameSize()727 size_t MppEncoder::GetFrameSize() {
728     return this->frame_size;
729 }
730 
ImportBuffer(int index,size_t size,int fd,int type)731 void* MppEncoder::ImportBuffer(int index, size_t size, int fd, int type) {
732     MppBuffer buf;
733     MppBufferInfo info;
734     memset(&info, 0, sizeof(MppBufferInfo));
735     info.type = (MppBufferType)type; // MPP_BUFFER_TYPE_EXT_DMA
736     info.fd =  fd;
737     info.size = size;
738     info.index = index;
739     mpp_buffer_import(&buf, &info);
740     return buf;
741 }
742 
GetInputFrameBuffer()743 void* MppEncoder::GetInputFrameBuffer() {
744     int ret;
745     if (this->frm_buf == nullptr) {
746         ret = mpp_buffer_get(this->buf_grp, &this->frm_buf, this->frame_size);
747         if (ret) {
748             LOGD("failed to get buffer for input frame ret %d\n", ret);
749             return NULL;
750         }
751     }
752     return this->frm_buf;
753 }
754 
GetInputFrameBufferFd(void * mpp_buffer)755 int MppEncoder::GetInputFrameBufferFd(void* mpp_buffer) {
756     return mpp_buffer_get_fd(mpp_buffer);
757 }
758 
GetInputFrameBufferAddr(void * mpp_buffer)759 void* MppEncoder::GetInputFrameBufferAddr(void* mpp_buffer) {
760     return mpp_buffer_get_ptr(mpp_buffer);
761 }