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, ¶ms, 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, <_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 }