1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_enc"
7
8 #include <string.h>
9 #include <stdarg.h>
10 #include <limits.h>
11
12 #include "mpp_2str.h"
13 #include "mpp_time.h"
14 #include "mpp_mem.h"
15 #include "mpp_common.h"
16 #include "mpp_buffer_impl.h"
17
18 #include "mpp_enc_refs.h"
19 #include "mpp_frame_impl.h"
20 #include "mpp_packet_impl.h"
21
22 #include "mpp.h"
23 #include "mpp_soc.h"
24 #include "mpp_enc_debug.h"
25 #include "mpp_enc_cfg.h"
26 #include "mpp_enc_impl.h"
27 #include "mpp_enc_cb_param.h"
28
29 #include "h264_syntax.h"
30
31 typedef union EncAsyncWait_u {
32 RK_U32 val;
33 struct {
34 RK_U32 enc_frm_in : 1; // 0x0001 MPP_ENC_NOTIFY_FRAME_ENQUEUE
35 RK_U32 reserv0002 : 1; // 0x0002
36 RK_U32 reserv0004 : 1; // 0x0004
37 RK_U32 enc_pkt_out : 1; // 0x0008 MPP_ENC_NOTIFY_PACKET_ENQUEUE
38
39 RK_U32 task_hnd : 1; // 0x0010
40 RK_U32 reserv0020 : 1; // 0x0020
41 RK_U32 reserv0040 : 1; // 0x0040
42 RK_U32 reserv0080 : 1; // 0x0080
43
44 RK_U32 reserv0100 : 1; // 0x0100
45 RK_U32 reserv0200 : 1; // 0x0200
46 RK_U32 reserv0400 : 1; // 0x0400
47 RK_U32 reserv0800 : 1; // 0x0800
48
49 RK_U32 reserv1000 : 1; // 0x1000
50 RK_U32 reserv2000 : 1; // 0x2000
51 RK_U32 reserv4000 : 1; // 0x4000
52 RK_U32 reserv8000 : 1; // 0x8000
53 };
54 } EncAsyncWait;
55
56 static RK_U8 uuid_version[16] = {
57 0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8,
58 0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac,
59 };
60
61 static RK_U8 uuid_rc_cfg[16] = {
62 0xd7, 0xdc, 0x03, 0xc3, 0xc5, 0x6f, 0x40, 0xe0,
63 0x8e, 0xa9, 0x17, 0x1a, 0xd2, 0xef, 0x5e, 0x23,
64 };
65
66 static RK_U8 uuid_usr_data[16] = {
67 0xfe, 0x39, 0xac, 0x4c, 0x4a, 0x8e, 0x4b, 0x4b,
68 0x85, 0xd9, 0xb2, 0xa2, 0x4f, 0xa1, 0x19, 0x5b,
69 };
70
71 static RK_U8 uuid_debug_info[16] = {
72 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
73 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
74 };
75
76 RK_U8 uuid_refresh_cfg[16] = {
77 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
78 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x00
79 };
80
81 static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info);
reset_hal_enc_task(HalEncTask * task)82 static void reset_hal_enc_task(HalEncTask *task)
83 {
84 memset(task, 0, sizeof(*task));
85 }
86
reset_enc_rc_task(EncRcTask * task)87 static void reset_enc_rc_task(EncRcTask *task)
88 {
89 memset(task, 0, sizeof(*task));
90 }
91
reset_enc_task(MppEncImpl * enc)92 static void reset_enc_task(MppEncImpl *enc)
93 {
94 enc->task_in = NULL;
95 enc->task_out = NULL;
96 enc->packet = NULL;
97 enc->frame = NULL;
98
99 enc->frm_buf = NULL;
100 enc->pkt_buf = NULL;
101
102 /* NOTE: clear add_by flags */
103 enc->hdr_status.val = enc->hdr_status.ready;
104 }
105
update_enc_hal_info(MppEncImpl * enc)106 static void update_enc_hal_info(MppEncImpl *enc)
107 {
108 MppDevInfoCfg data[32];
109 RK_S32 size = sizeof(data);
110 RK_S32 i;
111
112 if (NULL == enc->hal_info || NULL == enc->dev)
113 return ;
114
115 hal_info_from_enc_cfg(enc->hal_info, enc->cfg);
116 hal_info_get(enc->hal_info, data, &size);
117
118 if (size) {
119 size /= sizeof(data[0]);
120 for (i = 0; i < size; i++)
121 mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &data[i]);
122 }
123 }
124
update_hal_info_fps(MppEncImpl * enc)125 static void update_hal_info_fps(MppEncImpl *enc)
126 {
127 MppDevInfoCfg cfg;
128
129 RK_S32 time_diff = ((RK_S32)(enc->time_end - enc->time_base) / 1000);
130 RK_U64 fps = hal_info_to_float(enc->frame_count * 1000, time_diff);
131
132 cfg.type = ENC_INFO_FPS_CALC;
133 cfg.flag = CODEC_INFO_FLAG_STRING;
134 cfg.data = fps;
135
136 mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &cfg);
137
138 enc->time_base = enc->time_end;
139 enc->frame_count = 0;
140 }
141
release_task_in_port(MppPort port)142 static MPP_RET release_task_in_port(MppPort port)
143 {
144 MPP_RET ret = MPP_OK;
145 MppPacket packet = NULL;
146 MppFrame frame = NULL;
147 MppTask mpp_task;
148
149 do {
150 ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK);
151 if (ret < 0)
152 break;
153
154 mpp_port_dequeue(port, &mpp_task);
155 mpp_assert(mpp_task);
156 if (mpp_task) {
157 packet = NULL;
158 frame = NULL;
159 ret = mpp_task_meta_get_frame(mpp_task, KEY_INPUT_FRAME, &frame);
160 if (frame) {
161 mpp_frame_deinit(&frame);
162 frame = NULL;
163 }
164 ret = mpp_task_meta_get_packet(mpp_task, KEY_OUTPUT_PACKET, &packet);
165 if (packet) {
166 mpp_packet_deinit(&packet);
167 packet = NULL;
168 }
169
170 mpp_port_enqueue(port, mpp_task);
171 mpp_task = NULL;
172 } else
173 break;
174 } while (1);
175
176 return ret;
177 }
178
check_hal_task_pkt_len(HalEncTask * task,const char * reason)179 static void check_hal_task_pkt_len(HalEncTask *task, const char *reason)
180 {
181 RK_U32 task_length = task->length;
182 RK_U32 packet_length = mpp_packet_get_length(task->packet);
183
184 if (task_length != packet_length) {
185 mpp_err_f("%s check failed: task length is not match to packet length %d vs %d\n",
186 reason, task_length, packet_length);
187 }
188 }
189
check_enc_task_wait(MppEncImpl * enc,EncAsyncWait * wait)190 static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncAsyncWait *wait)
191 {
192 MPP_RET ret = MPP_OK;
193 RK_U32 notify = enc->notify_flag;
194 RK_U32 last_wait = enc->status_flag;
195 RK_U32 curr_wait = wait->val;
196 RK_U32 wait_chg = last_wait & (~curr_wait);
197 RK_U32 keep_notify = 0;
198
199 do {
200 if (enc->reset_flag)
201 break;
202
203 // NOTE: User control should always be processed
204 if (notify & MPP_ENC_CONTROL) {
205 keep_notify = notify & (~MPP_ENC_CONTROL);
206 break;
207 }
208
209 // NOTE: When condition is not fulfilled check nofify flag again
210 if (!curr_wait || (curr_wait & notify))
211 break;
212
213 ret = MPP_NOK;
214 } while (0);
215
216 enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
217 last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
218
219 enc->status_flag = wait->val;
220 enc->notify_flag = keep_notify;
221
222 if (ret) {
223 enc->wait_count++;
224 } else {
225 enc->work_count++;
226 }
227
228 return ret;
229 }
230
check_hal_info_update(MpiCmd cmd)231 static RK_S32 check_hal_info_update(MpiCmd cmd)
232 {
233 if (cmd == MPP_ENC_SET_CFG ||
234 cmd == MPP_ENC_SET_REF_CFG) {
235 return 1;
236 }
237
238 return 0;
239 }
240
check_low_delay_part_mode(MppEncImpl * enc)241 static void check_low_delay_part_mode(MppEncImpl *enc)
242 {
243 MppEncCfgSet *cfg = enc->cfg;
244
245 enc->low_delay_part_mode = 0;
246
247 if (!(cfg->base.low_delay))
248 return;
249
250 if (!cfg->split.split_mode)
251 return;
252
253 if (mpp_enc_hal_check_part_mode(enc->enc_hal))
254 return;
255
256 enc->low_delay_part_mode = 1;
257 }
258
check_low_delay_output(MppEncImpl * enc)259 static void check_low_delay_output(MppEncImpl *enc)
260 {
261 MppEncCfgSet *cfg = enc->cfg;
262
263 enc->low_delay_output = 0;
264
265 if (!cfg->split.split_mode || !(cfg->split.split_out & MPP_ENC_SPLIT_OUT_LOWDELAY))
266 return;
267
268 if (cfg->rc.max_reenc_times) {
269 mpp_log_f("can not enable lowdelay output with reencode enabled\n");
270 cfg->rc.max_reenc_times = 0;
271 }
272
273 if (cfg->rc.drop_mode) {
274 mpp_log_f("can not enable lowdelay output with drop mode enabled\n");
275 cfg->rc.drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED;
276 }
277
278 if (cfg->rc.super_mode) {
279 mpp_log_f("can not enable lowdelay output with super frame mode enabled\n");
280 cfg->rc.super_mode = MPP_ENC_RC_SUPER_FRM_NONE;
281 }
282
283 enc->low_delay_output = 1;
284 }
285
mpp_enc_callback(const char * caller,void * ctx,RK_S32 cmd,void * param)286 MPP_RET mpp_enc_callback(const char *caller, void *ctx, RK_S32 cmd, void *param)
287 {
288 MppEncImpl *enc = (MppEncImpl *)ctx;
289 EncOutParam *out = (EncOutParam *)param;
290 HalEncTask *task = NULL;
291 MppPacket packet = NULL;
292 MppPacketImpl *impl = NULL;
293 RK_U8 *last_pos = NULL;
294 RK_S32 slice_length = 0;
295 RK_U32 part_first = 0;
296 MPP_RET ret = MPP_OK;
297 Mpp *mpp = (Mpp*)enc->mpp;
298 (void) caller;
299
300 if (!enc->low_delay_output)
301 return ret;
302
303 task = (HalEncTask *)out->task;
304 mpp_assert(task);
305 part_first = task->part_first;
306 packet = task->packet;
307
308 if (part_first) {
309 task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
310 task->part_length = mpp_packet_get_length(packet);
311
312 enc_dbg_slice("first slice previous length %d\n", task->part_length);
313 mpp_assert(task->part_pos);
314 task->part_first = 0;
315 slice_length = task->part_length;
316 }
317
318 last_pos = (RK_U8 *)task->part_pos;
319 slice_length += out->length;
320
321 enc_dbg_slice("last_pos %p len %d:%d\n", last_pos, out->length, slice_length);
322
323 switch (cmd) {
324 case ENC_OUTPUT_FINISH : {
325 enc_dbg_slice("slice pos %p len %5d last\n", last_pos, slice_length);
326
327 impl = (MppPacketImpl *)packet;
328
329 impl->pos = last_pos;
330 impl->length = slice_length;
331 impl->status.val = 0;
332 impl->status.partition = 1;
333 impl->status.soi = part_first;
334 impl->status.eoi = 1;
335
336 task->part_pos += slice_length;
337 task->part_length += slice_length;
338 task->part_count++;
339 task->part_last = 1;
340 } break;
341 case ENC_OUTPUT_SLICE : {
342 enc_dbg_slice("slice pos %p len %5d\n", last_pos, slice_length);
343
344 mpp_packet_new((MppPacket *)&impl);
345 mpp_assert(impl);
346
347 /* copy the source data */
348 memcpy(impl, packet, sizeof(*impl));
349
350 impl->pos = last_pos;
351 impl->length = slice_length;
352 impl->status.val = 0;
353 impl->status.partition = 1;
354 impl->status.soi = part_first;
355 impl->status.eoi = 0;
356
357 if (impl->buffer)
358 mpp_buffer_inc_ref(impl->buffer);
359
360 mpp_meta_get(&impl->meta);
361 if (impl->meta) {
362 EncFrmStatus *frm = &task->rc_task->frm;
363
364 mpp_meta_set_s32(impl->meta, KEY_OUTPUT_INTRA, frm->is_intra);
365 }
366
367 mpp_packet_copy_segment_info(impl, packet);
368 mpp_packet_reset_segment(packet);
369
370 enc_dbg_detail("pkt %d new pos %p len %d\n", task->part_count,
371 last_pos, slice_length);
372
373 task->part_pos += slice_length;
374 task->part_length += slice_length;
375 task->part_count++;
376 if (!mpp->mEncAyncProc) {
377 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, impl);
378 mpp_port_enqueue(enc->output, enc->task_out);
379
380 ret = mpp_port_poll(enc->output, MPP_POLL_BLOCK);
381 mpp_assert(ret > 0);
382 ret = mpp_port_dequeue(enc->output, &enc->task_out);
383 mpp_assert(enc->task_out);
384 } else {
385 if (mpp->mPktOut) {
386 MppList *pkt_out = mpp->mPktOut;
387
388 mpp_mutex_cond_lock(&pkt_out->cond_lock);
389 mpp_list_add_at_tail(pkt_out, &impl, sizeof(impl));
390 mpp->mPacketPutCount++;
391 mpp_list_signal(pkt_out);
392 mpp_mutex_cond_unlock(&pkt_out->cond_lock);
393 }
394 }
395 } break;
396 default : {
397 } break;
398 }
399
400 return ret;
401 }
402
enc_set_rc_updated(MppEncImpl * enc,const char * log_str)403 static void enc_set_rc_updated(MppEncImpl *enc, const char *log_str)
404 {
405 if (!enc->rc_status.rc_api_user_cfg) {
406 enc->rc_status.rc_api_user_cfg = 1;
407 if (log_str)
408 enc_dbg_cfg("rc cfg updated for %s\n", log_str);
409 }
410 }
411
enc_set_resend_hdr(MppEncImpl * enc,const char * log_str)412 static void enc_set_resend_hdr(MppEncImpl *enc, const char *log_str)
413 {
414 if (enc->coding != MPP_VIDEO_CodingAVC && enc->coding != MPP_VIDEO_CodingHEVC)
415 return;
416
417 if (!(enc->frm_cfg.force_flag & ENC_FORCE_IDR)) {
418 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
419 if (log_str)
420 enc_dbg_cfg("resend header and force idr for %s\n", log_str);
421 }
422 enc->hdr_status.val = 0;
423 }
424
show_prep_update(MppEncPrepCfg * cfg,MppEncPrepCfg * set)425 static void show_prep_update(MppEncPrepCfg *cfg, MppEncPrepCfg *set)
426 {
427 char str[256];
428 rk_s32 len;
429 rk_s32 base;
430
431 len = snprintf(str, sizeof(str) - 1, "set prep cfg ");
432 base = len;
433
434 if (set->width != cfg->width || set->height != cfg->height) {
435 len += snprintf(str + len, sizeof(str) - len - 1,
436 "w:h [%d:%d] -> [%d:%d] ",
437 cfg->width, cfg->height, set->width, set->height);
438 }
439
440 if (set->hor_stride != cfg->hor_stride || set->ver_stride != cfg->ver_stride) {
441 len += snprintf(str + len, sizeof(str) - len - 1,
442 "stride [%d:%d] -> [%d:%d] ",
443 cfg->hor_stride, cfg->ver_stride,
444 set->hor_stride, set->ver_stride);
445 }
446
447 if (set->format != cfg->format) {
448 len += snprintf(str + len, sizeof(str) - len - 1,
449 "fmt %d -> %d ", cfg->format, set->format);
450 }
451
452 if (set->rotation != cfg->rotation) {
453 len += snprintf(str + len, sizeof(str) - len - 1,
454 "rotate %d -> %d ", cfg->rotation, set->rotation);
455 }
456
457 if (set->mirroring != cfg->mirroring) {
458 len += snprintf(str + len, sizeof(str) - len - 1,
459 "mirror %d -> %d ", cfg->mirroring, set->mirroring);
460 }
461
462 if (len > base)
463 enc_dbg_cfg("%s\n", str);
464
465 mpp_logi("set prep cfg w:h [%d:%d] stride [%d:%d] fmt %d rotate %d mirror %d\n",
466 set->width, set->height, set->hor_stride, set->ver_stride,
467 set->format, set->rotation, set->mirroring);
468 }
469
proc_prep_cfg(MppEncImpl * enc)470 static void proc_prep_cfg(MppEncImpl *enc)
471 {
472 MppEncPrepCfg *cfg = &enc->cfg->prep;
473 MppEncPrepCfg *set = &enc->set->prep;
474 rk_u32 flag = *mpp_enc_cfg_prep_change(enc->set);
475 rk_u32 change_res = 0;
476 rk_u32 change_rot = 0;
477 rk_u32 restore = 0;
478 rk_s32 mirroring;
479 rk_s32 rotation;
480
481 enc_dbg_cfg("prep cfg change 0x%x\n", flag);
482
483 if (!flag)
484 return;
485
486 { /* chekc input and format change */
487 static KmppObjDef def = NULL;
488 static KmppEntry *tbl_input = NULL;
489 static KmppEntry *tbl_format = NULL;
490 static KmppEntry *tbl_rotation = NULL;
491 static rk_s32 once = 1;
492
493 if (!def && once) {
494 def = kmpp_obj_to_objdef(enc->set_obj);
495 kmpp_objdef_get_entry(def, "prep:width", &tbl_input);
496 kmpp_objdef_get_entry(def, "prep:format", &tbl_format);
497 kmpp_objdef_get_entry(def, "prep:rotation", &tbl_rotation);
498
499 if (!tbl_input || !tbl_format || !tbl_rotation)
500 mpp_loge("failed to get input and format table\n");
501
502 once = 0;
503 }
504
505 if (kmpp_obj_tbl_test(enc->set_obj, tbl_input) ||
506 kmpp_obj_tbl_test(enc->set_obj, tbl_format)) {
507 change_res = 1;
508 }
509 if (kmpp_obj_tbl_test(enc->set_obj, tbl_input) ||
510 kmpp_obj_tbl_test(enc->set_obj, tbl_rotation)) {
511 change_rot = 1;
512 }
513 }
514
515 if (set->rotation_ext >= MPP_ENC_ROT_BUTT || set->rotation_ext < 0 ||
516 set->mirroring_ext < 0 || set->flip < 0) {
517 mpp_loge("invalid rotation %d mirroring %d flip %d\n",
518 set->rotation_ext, set->mirroring_ext, set->flip);
519 mpp_loge("restore rotation %d mirroring %d flip %d\n",
520 cfg->rotation_ext, cfg->mirroring_ext, cfg->flip);
521 set->rotation_ext = cfg->rotation_ext;
522 set->mirroring_ext = cfg->mirroring_ext;
523 set->flip = cfg->flip;
524 }
525
526 /*
527 * For unifying the encoder's params used by CFG_SET and CFG_GET command,
528 * there is distinction between user's set and set in hal.
529 * User can externally set rotation_ext, mirroring_ext and flip,
530 * which should be transformed to mirroring and rotation in hal.
531 */
532 rotation = set->rotation_ext;
533 mirroring = set->mirroring_ext;
534
535 if (set->flip) {
536 mirroring = !mirroring;
537 rotation += MPP_ENC_ROT_180;
538 rotation &= MPP_ENC_ROT_270;
539 }
540
541 set->mirroring = mirroring;
542 set->rotation = (MppEncRotationCfg)rotation;
543
544 if (MPP_FRAME_FMT_IS_FBC(set->format) && (set->mirroring || set->rotation)) {
545 mpp_loge("conflict fbc input format %x with mirror %d or rotaion %d\n",
546 set->format, set->mirroring, set->rotation);
547 mpp_loge("disable mirror and rotation\n");
548 set->mirroring = 0;
549 set->rotation = MPP_ENC_ROT_0;
550 }
551
552 if (set->range >= MPP_FRAME_RANGE_NB ||
553 set->color >= MPP_FRAME_SPC_NB ||
554 set->colorprim >= MPP_FRAME_PRI_NB ||
555 set->colortrc >= MPP_FRAME_TRC_NB) {
556 mpp_loge("invalid color range %d colorspace %d primaries %d transfer characteristic %d\n",
557 set->range, set->color, set->colorprim, set->colortrc);
558 mpp_loge("restore color range %d colorspace %d primaries %d transfer characteristic %d\n",
559 cfg->range, cfg->color, cfg->colorprim, cfg->colortrc);
560 set->range = cfg->range;
561 set->color = cfg->color;
562 set->colorprim = cfg->colorprim;
563 set->colortrc = cfg->colortrc;
564 }
565
566 if (set->rotation == MPP_ENC_ROT_90 || set->rotation == MPP_ENC_ROT_270) {
567 set->height = set->width_set;
568 set->width = set->height_set;
569
570 if (set->height > set->hor_stride || set->width > set->ver_stride)
571 restore = 1;
572 } else {
573 set->width = set->width_set;
574 set->height = set->height_set;
575
576 if (set->width > set->hor_stride || set->height > set->ver_stride)
577 restore = 1;
578 }
579
580 if (restore) {
581 mpp_loge("invalid set w:h [%d:%d] stride [%d:%d] rotation %d\n",
582 set->width, set->height, set->hor_stride, set->ver_stride, set->rotation);
583 mpp_loge("restore cfg w:h [%d:%d] stride [%d:%d] rotation %d\n",
584 cfg->width, cfg->height, cfg->hor_stride, cfg->ver_stride, cfg->rotation);
585 set->width = cfg->width;
586 set->height = cfg->height;
587 set->width_set = cfg->width;
588 set->height_set = cfg->height;
589 set->hor_stride = cfg->hor_stride;
590 set->ver_stride = cfg->ver_stride;
591 set->rotation = cfg->rotation;
592 }
593
594 if (!set->max_height || !set->max_width) {
595 set->max_width = set->width;
596 set->max_height = set->height;
597 }
598
599 show_prep_update(cfg, set);
600 memcpy(cfg, set, sizeof(*cfg));
601 enc_set_resend_hdr(enc, "change prep cfg");
602
603 /* NOTE: only set change res flag and NOT clear */
604 if (change_res || change_rot) {
605 cfg->change_res = 1;
606 }
607 }
608
609 #define RC_CHANGE_MODE (1 << 0)
610 #define RC_CHANGE_BPS (1 << 1)
611 #define RC_CHANGE_FPS_IN (1 << 2)
612 #define RC_CHANGE_FPS_OUT (1 << 3)
613 #define RC_CHANGE_GOP (1 << 4)
614
615 static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param);
show_rc_update(MppEncRcCfg * cfg,MppEncRcCfg * set,rk_u32 change)616 static void show_rc_update(MppEncRcCfg *cfg, MppEncRcCfg *set, rk_u32 change)
617 {
618 char str[256];
619 rk_s32 len;
620 rk_s32 base;
621
622 len = snprintf(str, sizeof(str) - 1, "set rc cfg ");
623 base = len;
624
625 if (change & RC_CHANGE_MODE) {
626 len += snprintf(str + len, sizeof(str) - len - 1, "mode %s -> %s ",
627 strof_rc_mode(cfg->rc_mode), strof_rc_mode(set->rc_mode));
628 }
629
630 if (change & RC_CHANGE_BPS) {
631 len += snprintf(str + len, sizeof(str) - len - 1,
632 "bps [%d:%d:%d] -> [%d:%d:%d] ",
633 cfg->bps_target, cfg->bps_max, cfg->bps_min,
634 set->bps_target, set->bps_max, set->bps_min);
635 }
636
637 if (len > base) {
638 enc_dbg_cfg("%s\n", str);
639 len = base;
640 }
641
642 if (change & RC_CHANGE_FPS_IN) {
643 len += snprintf(str + len, sizeof(str) - len - 1,
644 "fps in [%d:%d:%s] -> [%d:%d:%s] ",
645 cfg->fps_in_num, cfg->fps_in_denom,
646 cfg->fps_in_flex ? "flex" : "fix",
647 set->fps_in_num, set->fps_in_denom,
648 set->fps_in_flex ? "flex" : "fix");
649 }
650
651 if (change & RC_CHANGE_FPS_OUT) {
652 len += snprintf(str + len, sizeof(str) - len - 1,
653 "fps out [%d:%d:%s] -> [%d:%d:%s] ",
654 cfg->fps_out_num, cfg->fps_out_denom,
655 cfg->fps_out_flex ? "flex" : "fix",
656 set->fps_out_num, set->fps_out_denom,
657 set->fps_out_flex ? "flex" : "fix");
658 }
659
660 if (change & RC_CHANGE_GOP) {
661 len += snprintf(str + len, sizeof(str) - len - 1,
662 "gop %d -> %d ", cfg->gop, set->gop);
663 }
664
665 if (len > base)
666 enc_dbg_cfg("%s\n", str);
667
668 mpp_logi("set rc %s bps [%d:%d:%d] fps [%d:%d:%s] - [%d:%d:%s] gop %d\n",
669 strof_rc_mode(set->rc_mode), set->bps_target, set->bps_max, set->bps_min,
670 set->fps_in_num, set->fps_in_denom, set->fps_in_flex ? "flex" : "fix",
671 set->fps_out_num, set->fps_out_denom, set->fps_out_flex ? "flex" : "fix",
672 set->gop);
673 }
674
proc_rc_cfg(MppEncImpl * enc)675 static void proc_rc_cfg(MppEncImpl *enc)
676 {
677 MppEncRcCfg *cfg = &enc->cfg->rc;
678 MppEncRcCfg *set = &enc->set->rc;
679 rk_u32 flag = *mpp_enc_cfg_rc_change(enc->set);
680 rk_u32 change = 0;
681 rk_s32 i;
682
683 enc_dbg_cfg("rc cfg change 0x%x\n", flag);
684
685 if (!flag)
686 return;
687
688 /* 1. check input rc config for invalid value and revert to valid value */
689 if (set->rc_priority >= MPP_ENC_RC_PRIORITY_BUTT) {
690 mpp_loge("invalid rc_priority %d should be in range [%d:%d]\n",
691 set->rc_priority, MPP_ENC_RC_BY_BITRATE_FIRST, MPP_ENC_RC_PRIORITY_BUTT);
692 mpp_loge("restore rc_priority to %d\n", cfg->rc_priority);
693 set->rc_priority = cfg->rc_priority;
694 }
695
696 if (set->super_mode >= MPP_ENC_RC_SUPER_FRM_BUTT) {
697 mpp_loge("invalid super_mode %d should be in range [%d:%d]\n",
698 set->super_mode, MPP_ENC_RC_SUPER_FRM_NONE, MPP_ENC_RC_SUPER_FRM_BUTT);
699 mpp_loge("restore super_mode to %d\n", cfg->super_mode);
700 set->super_mode = cfg->super_mode;
701 }
702
703 if (set->debreath_en && set->debre_strength > 35) {
704 mpp_loge("invalid debre_strength %d should be in range [%d:%d]\n",
705 set->debre_strength, 0, 35, cfg->debre_strength);
706 mpp_loge("restore debre_strength to %d\n", cfg->debre_strength);
707 set->debre_strength = cfg->debre_strength;
708 }
709
710 if (set->rc_mode >= MPP_ENC_RC_MODE_BUTT) {
711 mpp_loge("invalid rc mode %d must be in range [0:%d]\n",
712 set->rc_mode, MPP_ENC_RC_MODE_BUTT - 1);
713
714 for (i = 0; i < MPP_ENC_RC_MODE_BUTT; i++)
715 mpp_loge("%d - %s\n", i, strof_rc_mode((MppEncRcMode)i));
716
717 mpp_loge("restore rc mode to %d\n", cfg->rc_mode);
718 set->rc_mode = cfg->rc_mode;
719 }
720
721 if (set->quality >= MPP_ENC_RC_QUALITY_BUTT) {
722 mpp_loge("invalid quality %d must be in ranget [0:%d]\n",
723 set->quality, MPP_ENC_RC_QUALITY_BUTT - 1);
724 mpp_loge("0 - MPP_ENC_RC_QUALITY_WORST\n");
725 mpp_loge("1 - MPP_ENC_RC_QUALITY_BAD\n");
726 mpp_loge("2 - MPP_ENC_RC_QUALITY_MEDIUM\n");
727 mpp_loge("3 - MPP_ENC_RC_QUALITY_BETTER\n");
728 mpp_loge("4 - MPP_ENC_RC_QUALITY_BEST\n");
729 mpp_loge("5 - MPP_ENC_RC_QUALITY_CQP\n");
730 mpp_loge("6 - MPP_ENC_RC_QUALITY_AQ_ONLY\n");
731 mpp_loge("restore quality to %d\n", cfg->quality);
732 set->quality = cfg->quality;
733 }
734
735 if (set->rc_mode != MPP_ENC_RC_MODE_FIXQP) {
736 if ((set->bps_target >= 100 * SZ_1M || set->bps_target <= 1 * SZ_1K) ||
737 (set->bps_max >= 100 * SZ_1M || set->bps_max <= 1 * SZ_1K) ||
738 (set->bps_min >= 100 * SZ_1M || set->bps_min <= 1 * SZ_1K)) {
739 mpp_loge("invalid bit per second (bps) %d [%d:%d] out of range 1K~100M\n",
740 set->bps_target, set->bps_min, set->bps_max);
741 mpp_loge("restore bps to %d [%d:%d]\n",
742 cfg->bps_target, cfg->bps_min, cfg->bps_max);
743 set->bps_target = cfg->bps_target;
744 set->bps_max = cfg->bps_max;
745 set->bps_min = cfg->bps_min;
746 }
747 }
748
749 // if I frame min/max is not set use normal case
750 if (set->qp_min_i <= 0)
751 set->qp_min_i = set->qp_min;
752 if (set->qp_max_i <= 0)
753 set->qp_max_i = set->qp_max;
754 if (set->qp_min < 0 || set->qp_max < 0 ||
755 set->qp_min > set->qp_max || set->qp_min_i < 0 ||
756 set->qp_max_i < 0 || set->qp_min_i > set->qp_max_i ||
757 (set->qp_init > 0 && (set->qp_init > set->qp_max_i ||
758 set->qp_init < set->qp_min_i))) {
759 mpp_loge("invalid qp range: init %d i [%d:%d] p [%d:%d]\n",
760 set->qp_init, set->qp_min_i, set->qp_max_i,
761 set->qp_min, set->qp_max);
762
763 mpp_loge("restore qp range: init %d i [%d:%d] p [%d:%d]\n",
764 set->qp_init, set->qp_min_i, set->qp_max_i,
765 set->qp_min, set->qp_max);
766
767 set->qp_init = cfg->qp_init;
768 set->qp_min_i = cfg->qp_min_i;
769 set->qp_max_i = cfg->qp_max_i;
770 set->qp_min = cfg->qp_min;
771 set->qp_max = cfg->qp_max;
772 }
773
774 if (MPP_ABS(set->qp_delta_ip) > 8) {
775 mpp_loge("invalid qp delta ip %d restore to %d\n",
776 set->qp_delta_ip, cfg->qp_delta_ip);
777 set->qp_delta_ip = cfg->qp_delta_ip;
778 }
779 if (MPP_ABS(set->qp_delta_vi) > 6) {
780 mpp_loge("invalid qp delta vi %d restore to %d\n",
781 set->qp_delta_vi, cfg->qp_delta_vi);
782 set->qp_delta_vi = cfg->qp_delta_vi;
783 }
784 if (set->qp_max_step < 0) {
785 mpp_loge("invalid qp max step %d restore to %d\n",
786 set->qp_max_step, cfg->qp_max_step);
787 set->qp_max_step = cfg->qp_max_step;
788 }
789 if (set->stats_time && set->stats_time > 60) {
790 mpp_loge("warning: bitrate statistic time %d is larger than 60s\n",
791 set->stats_time);
792 }
793
794 /* 2. check rc cfg done now check rc cfg change */
795 if (set->rc_mode != cfg->rc_mode)
796 change |= RC_CHANGE_MODE;
797 if (set->bps_target != cfg->bps_target ||
798 set->bps_max != cfg->bps_max ||
799 set->bps_min != cfg->bps_min)
800 change |= RC_CHANGE_BPS;
801 if (set->fps_in_num != cfg->fps_in_num ||
802 set->fps_in_denom != cfg->fps_in_denom ||
803 set->fps_in_flex != cfg->fps_in_flex)
804 change |= RC_CHANGE_FPS_IN;
805 if (set->fps_out_num != cfg->fps_out_num ||
806 set->fps_out_denom != cfg->fps_out_denom ||
807 set->fps_out_flex != cfg->fps_out_flex)
808 change |= RC_CHANGE_FPS_OUT;
809 if (set->gop != cfg->gop)
810 change |= RC_CHANGE_GOP;
811
812 if (change & (RC_CHANGE_MODE | RC_CHANGE_FPS_IN | RC_CHANGE_FPS_OUT | RC_CHANGE_GOP))
813 enc_set_resend_hdr(enc, "change rc_mode/fps/gop");
814
815 /* NOTE: some rc change no need to (quality) */
816 if (flag)
817 enc_set_rc_updated(enc, "rc cfg changed");
818
819 show_rc_update(cfg, set, change);
820 memcpy(cfg, set, sizeof(*cfg));
821
822 if (change & RC_CHANGE_GOP)
823 mpp_enc_refs_set_rc_igop(enc->refs, cfg->gop);
824
825 if (set->ref_cfg)
826 mpp_enc_control_set_ref_cfg(enc, set->ref_cfg);
827 }
828
proc_split_cfg(MppEncSliceSplit * cfg,MppEncSliceSplit * set)829 static void proc_split_cfg(MppEncSliceSplit *cfg, MppEncSliceSplit *set)
830 {
831 if (set->split_mode >= MPP_ENC_SPLIT_MODE_BUTT) {
832 mpp_loge("invalid split mode %d should be in range [%d:%d]\n",
833 set->split_mode, MPP_ENC_SPLIT_NONE, MPP_ENC_SPLIT_MODE_BUTT);
834 mpp_loge("restore split mode %d\n", cfg->split_mode);
835 set->split_mode = cfg->split_mode;
836 }
837
838 if (!set->split_mode) {
839 set->split_arg = 0;
840 set->split_out = 0;
841 }
842
843 memcpy(cfg, set, sizeof(*cfg));
844 }
845
proc_hw_cfg(MppEncImpl * enc)846 static void proc_hw_cfg(MppEncImpl *enc)
847 {
848 MppEncHwCfg *cfg = &enc->cfg->hw;
849 MppEncHwCfg *set = &enc->set->hw;
850 rk_u32 flag = *mpp_enc_cfg_hw_change(enc->set);
851
852 enc_dbg_cfg("hw cfg change 0x%x\n", flag);
853
854 if (!flag)
855 return;
856
857 if (set->qp_delta_row < 0 || set->qp_delta_row_i < 0) {
858 mpp_loge("invalid hw qp delta row [%d:%d] restore to [%d:%d]\n",
859 set->qp_delta_row_i, set->qp_delta_row,
860 cfg->qp_delta_row_i, cfg->qp_delta_row);
861 set->qp_delta_row = cfg->qp_delta_row;
862 set->qp_delta_row_i = cfg->qp_delta_row_i;
863 }
864
865 if (set->qbias_en < 0) {
866 mpp_loge("invalid hw qbias_en %d restore to %d\n",
867 set->qbias_en, cfg->qbias_en);
868 set->qbias_en = cfg->qbias_en;
869 }
870
871 if (set->qbias_i < 0 || set->qbias_p < 0) {
872 mpp_loge("invalid hw qp bias [%d:%d] restore to [%d:%d]\n",
873 set->qbias_i, set->qbias_p, cfg->qbias_i, cfg->qbias_p);
874 set->qbias_i = cfg->qbias_i;
875 }
876
877 if (set->flt_str_i < 0 || set->flt_str_p < 0) {
878 mpp_loge("invalid filter strength [%d:%d] restore to [%d:%d]\n",
879 set->flt_str_i, set->flt_str_p,
880 cfg->flt_str_i, cfg->flt_str_p);
881 set->flt_str_i = cfg->flt_str_i;
882 }
883
884 memcpy(cfg, set, sizeof(*cfg));
885 }
886
proc_tune_cfg(MppEncImpl * enc)887 static void proc_tune_cfg(MppEncImpl *enc)
888 {
889 MppEncFineTuneCfg *cfg = &enc->cfg->tune;
890 MppEncFineTuneCfg *set = &enc->set->tune;
891 rk_u32 flag = *mpp_enc_cfg_tune_change(enc->set);
892
893 enc_dbg_cfg("tune cfg change 0x%x\n", flag);
894
895 if (!flag)
896 return;
897
898 if (set->scene_mode < MPP_ENC_SCENE_MODE_DEFAULT ||
899 set->scene_mode >= MPP_ENC_SCENE_MODE_BUTT) {
900 mpp_loge("invalid scene mode %d not in range [%d:%d]\n", set->scene_mode,
901 MPP_ENC_SCENE_MODE_DEFAULT, MPP_ENC_SCENE_MODE_BUTT - 1);
902 mpp_loge("restore scene mode %d\n", cfg->scene_mode);
903 set->scene_mode = cfg->scene_mode;
904 }
905
906 if (set->motion_static_switch_enable < 0 || set->motion_static_switch_enable > 1) {
907 mpp_loge("invalid motion static switch enable not in range [%d : %d]\n", 0, 1);
908 mpp_loge("restore motion static switch enable %d\n", cfg->motion_static_switch_enable);
909 set->motion_static_switch_enable = cfg->motion_static_switch_enable;
910 }
911
912 if (set->deblur_str < 0 || set->deblur_str > 7) {
913 mpp_loge("invalid deblur strength not in range [0 : 7]\n");
914 mpp_loge("restore deblur strength %d\n", cfg->deblur_str);
915 set->deblur_str = cfg->deblur_str;
916 }
917
918 if (set->atr_str_i < 0 || set->atr_str_i > 3) {
919 mpp_loge("invalid anti ring strength of I frame not in range [0 : 3]\n");
920 mpp_loge("restore anti ring strength of I frame %d\n", cfg->atr_str_i);
921 set->atr_str_i = cfg->atr_str_i;
922 }
923
924 if (set->atr_str_p < 0 || set->atr_str_p > 3) {
925 mpp_loge("invalid anti ring strength of P frame not in range [0 : 3]\n");
926 mpp_loge("restore anti ring strength of P frame %d\n", cfg->atr_str_p);
927 set->atr_str_p = cfg->atr_str_p;
928 }
929
930 if (set->atl_str < 0 || set->atl_str > 3) {
931 mpp_loge("invalid anti line strength not in range [0 : 3]\n");
932 mpp_loge("restore anti line strength %d\n", cfg->atl_str);
933 set->atl_str = cfg->atl_str;
934 }
935
936 if (set->lambda_idx_p < 0 || set->lambda_idx_p > 8) {
937 mpp_loge("invalid lambda idx not in range [0 : 8]\n");
938 mpp_loge("restore lambda idx %d\n", cfg->lambda_idx_p);
939 set->lambda_idx_p = cfg->lambda_idx_p;
940 }
941
942 if (set->lambda_idx_i < 0 || set->lambda_idx_i > 8) {
943 mpp_loge("invalid I frame lambda idx not in range [0 : 8]\n");
944 mpp_loge("restore I frame lambda idx %d\n", cfg->lambda_idx_i);
945 set->lambda_idx_i = cfg->lambda_idx_i;
946 }
947
948 if (set->atf_str < 0 || set->atf_str > 3) {
949 mpp_loge("invalid anti flick strength not in range [0 : 3]\n");
950 mpp_loge("restore anti flick strength %d\n", cfg->atf_str);
951 set->atf_str = cfg->atf_str;
952 }
953
954 if (set->lgt_chg_lvl < 0 || set->lgt_chg_lvl > 7) {
955 mpp_loge("invalid lgt_chg_lvl %d not in range [0, 7]\n", set->lgt_chg_lvl);
956 mpp_loge("restore lgt_chg_lvl %d\n", cfg->lgt_chg_lvl);
957 set->lgt_chg_lvl = cfg->lgt_chg_lvl;
958 }
959
960 if (set->static_frm_num < 0 || set->static_frm_num > 7) {
961 mpp_loge("invalid static_frm_num %d not in range [0, 7]\n", set->static_frm_num);
962 mpp_loge("restore static_frm_num %d\n", cfg->static_frm_num);
963 set->static_frm_num = cfg->static_frm_num;
964 }
965
966 if (set->madp16_th < 0 || set->madp16_th > 63) {
967 mpp_loge("invalid madp16_th %d not in range [0, 255]\n", set->madp16_th);
968 mpp_loge("restore madp16_th %d\n", cfg->madp16_th);
969 set->madp16_th = cfg->madp16_th;
970 }
971
972 if (!(set->skip16_wgt == 0 || (set->skip16_wgt >= 3 && set->skip16_wgt <= 8))) {
973 mpp_loge("invalid skip16_wgt %d not in range [3, 8] or 0\n", set->skip16_wgt);
974 mpp_loge("restore skip16_wgt %d\n", cfg->skip16_wgt);
975 set->skip16_wgt = cfg->skip16_wgt;
976 }
977
978 if (!(set->skip32_wgt == 0 || (set->skip32_wgt >= 3 && set->skip32_wgt <= 8))) {
979 mpp_loge("invalid skip32_wgt %d not in range [3, 8] or 0\n", set->skip32_wgt);
980 mpp_loge("restore skip32_wgt %d\n", cfg->skip32_wgt);
981 set->skip32_wgt = cfg->skip32_wgt;
982 }
983
984 set->bmap_qpmin_i = mpp_clip(set->bmap_qpmin_i, 1, 51);
985 set->bmap_qpmin_p = mpp_clip(set->bmap_qpmin_p, 1, 51);
986 set->bmap_qpmax_i = mpp_clip(set->bmap_qpmax_i, 1, 51);
987 set->bmap_qpmax_p = mpp_clip(set->bmap_qpmax_p, 1, 51);
988 set->min_bg_fqp = mpp_clip(set->min_bg_fqp, 1, 51);
989 set->max_bg_fqp = mpp_clip(set->max_bg_fqp, 1, 51);
990 set->min_fg_fqp = mpp_clip(set->min_fg_fqp, 1, 51);
991 set->max_fg_fqp = mpp_clip(set->max_fg_fqp, 1, 51);
992 set->bg_delta_qp_i = mpp_clip(set->bg_delta_qp_i, -32, 32);
993 set->bg_delta_qp_p = mpp_clip(set->bg_delta_qp_p, -32, 32);
994 set->fg_delta_qp_i = mpp_clip(set->fg_delta_qp_i, -32, 32);
995 set->fg_delta_qp_p = mpp_clip(set->fg_delta_qp_p, -32, 32);
996 set->fg_area = mpp_clip(set->fg_area, -1, 100);
997
998 if (set->scene_mode != cfg->scene_mode ||
999 set->motion_static_switch_enable != cfg->motion_static_switch_enable ||
1000 set->deblur_str != cfg->deblur_str)
1001 enc_set_rc_updated(enc, "tune cfg changed");
1002
1003 memcpy(cfg, set, sizeof(*cfg));
1004 }
1005
proc_h264_cfg(MppEncImpl * enc)1006 static void proc_h264_cfg(MppEncImpl *enc)
1007 {
1008 MppEncH264Cfg *cfg = &enc->cfg->h264;
1009 MppEncH264Cfg *set = &enc->set->h264;
1010 rk_u32 flag = *mpp_enc_cfg_h264_change(enc->set);
1011 rk_s32 profile = set->profile;
1012 rk_s32 entropy_coding_mode = set->entropy_coding_mode_ex;
1013 rk_s32 cabac_init_idc = set->cabac_init_idc_ex;
1014 rk_s32 transform8x8_mode = set->transform8x8_mode_ex;
1015 rk_s32 disable_cabac = (H264_PROFILE_FREXT_CAVLC444 == profile ||
1016 H264_PROFILE_BASELINE == profile ||
1017 H264_PROFILE_EXTENDED == profile);
1018
1019 enc_dbg_cfg("h264 cfg change 0x%x\n", flag);
1020
1021 if (enc->cfg->rc.refresh_en) {
1022 RK_U32 mb_rows;
1023
1024 if (!enc->cfg->rc.refresh_mode)
1025 mb_rows = MPP_ALIGN(enc->cfg->prep.height, 16) / 16;
1026 else
1027 mb_rows = MPP_ALIGN(enc->cfg->prep.width, 16) / 16;
1028
1029 enc->cfg->rc.refresh_length = (mb_rows + enc->cfg->rc.refresh_num - 1) /
1030 enc->cfg->rc.refresh_num;
1031 if (enc->cfg->rc.gop < enc->cfg->rc.refresh_length)
1032 enc->cfg->rc.refresh_length = enc->cfg->rc.gop;
1033 }
1034
1035 if (!flag)
1036 return;
1037
1038 /* 1. check input h264 config */
1039 if (disable_cabac) {
1040 if (entropy_coding_mode) {
1041 mpp_loge("Warning: invalid cabac_en %d for h264 profile %d, set to 0.\n",
1042 entropy_coding_mode, profile);
1043 entropy_coding_mode = 0;
1044 }
1045
1046 if (cabac_init_idc >= 0) {
1047 mpp_loge("Warning: invalid cabac_init_idc %d for h264 profile %d, set to -1.\n",
1048 cabac_init_idc, profile);
1049
1050 cabac_init_idc = -1;
1051 }
1052 }
1053
1054 if (profile < H264_PROFILE_HIGH && transform8x8_mode) {
1055 mpp_loge("Warning: invalid transform8x8_mode %d for h264 profile %d, set to 0.\n",
1056 transform8x8_mode, profile);
1057
1058 transform8x8_mode = 0;
1059 }
1060
1061 set->entropy_coding_mode = entropy_coding_mode;
1062 set->cabac_init_idc = cabac_init_idc;
1063 set->transform8x8_mode = transform8x8_mode;
1064
1065 memcpy(cfg, set, sizeof(*cfg));
1066 enc_set_resend_hdr(enc, "h264 cfg changed");
1067 }
1068
proc_h265_cfg(MppEncImpl * enc)1069 static void proc_h265_cfg(MppEncImpl *enc)
1070 {
1071 MppEncH265Cfg *cfg = &enc->cfg->h265;
1072 MppEncH265Cfg *set = &enc->set->h265;
1073 rk_u32 flag = *mpp_enc_cfg_h265_change(enc->set);
1074
1075 enc_dbg_cfg("h265 cfg change 0x%x\n", flag);
1076
1077 if (enc->cfg->rc.refresh_en) {
1078 RK_U32 mb_rows;
1079
1080 if (!enc->cfg->rc.refresh_mode)
1081 mb_rows = MPP_ALIGN(enc->cfg->prep.height, 32) / 32;
1082 else
1083 mb_rows = MPP_ALIGN(enc->cfg->prep.width, 32) / 32;
1084
1085 enc->cfg->rc.refresh_length = (mb_rows + enc->cfg->rc.refresh_num - 1) /
1086 enc->cfg->rc.refresh_num;
1087 if (enc->cfg->rc.gop < enc->cfg->rc.refresh_length)
1088 enc->cfg->rc.refresh_length = enc->cfg->rc.gop;
1089 }
1090
1091 if (!flag)
1092 return;
1093
1094 if (set->const_intra_pred) {
1095 RockchipSocType soc_type = mpp_get_soc_type();
1096
1097 if (soc_type >= ROCKCHIP_SOC_RK3576) {
1098 set->const_intra_pred = 0;
1099
1100 mpp_logw("warning: Only rk3576's HEVC encoder support constraint intra prediction flag = 1.");
1101 }
1102 }
1103
1104 if (set->trans_cfg.cb_qp_offset != set->trans_cfg.cr_qp_offset) {
1105 mpp_loge("h265 cr_qp_offset %d MUST equal to cb_qp_offset %d. FORCE to same value\n",
1106 set->trans_cfg.cb_qp_offset, set->trans_cfg.cr_qp_offset);
1107
1108 set->trans_cfg.cr_qp_offset = set->trans_cfg.cb_qp_offset;
1109 }
1110
1111 if (set->trans_cfg.diff_cu_qp_delta_depth > 2 || set->trans_cfg.diff_cu_qp_delta_depth < 0) {
1112 mpp_loge("h265 diff_cu_qp_delta_depth must be in [0, 2] restore to 1\n");
1113 set->trans_cfg.diff_cu_qp_delta_depth = 1;
1114 }
1115
1116 memcpy(cfg, set, sizeof(*cfg));
1117 enc_set_resend_hdr(enc, "h265 cfg changed");
1118 }
1119
proc_jpeg_cfg(MppEncImpl * enc)1120 static void proc_jpeg_cfg(MppEncImpl *enc)
1121 {
1122 MppEncRcCfg *rc_cfg = &enc->cfg->rc;
1123 MppEncRcCfg *rc_set = &enc->set->rc;
1124 MppEncJpegCfg *cfg = &enc->cfg->jpeg;
1125 MppEncJpegCfg *set = &enc->set->jpeg;
1126 rk_u32 flag = *mpp_enc_cfg_jpeg_change(enc->set);
1127 rk_u32 update = 1;
1128 rk_u32 update_rc = 0;
1129
1130 enc_dbg_cfg("jpeg cfg change 0x%x\n", flag);
1131
1132 if (!flag)
1133 return;
1134
1135 /* check input change then check validity */
1136 if (set->quant != set->quant_ext) {
1137 /* quant is set */
1138 if (set->quant_ext < 0 || set->quant_ext > 10) {
1139 mpp_loge("invalid quant %d not in range [0, 10] restore to 10 (best quality)\n", set->quant_ext);
1140 set->quant_ext = 10;
1141 }
1142
1143 rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP;
1144 update_rc = 1;
1145 set->quant = set->quant_ext;
1146 set->q_mode = JPEG_QUANT;
1147 mpp_logi("set jpeg quant %d\n", set->quant);
1148 } else if (set->q_factor != set->q_factor_ext ||
1149 set->qf_max != set->qf_max_ext ||
1150 set->qf_min != set->qf_min_ext) {
1151 if (set->q_factor_ext < 1 || set->q_factor_ext > 99) {
1152 mpp_loge("invalid q_factor %d out of range [1, 99] restore to 80\n", set->q_factor_ext);
1153 set->q_factor_ext = 80;
1154 }
1155 if (set->qf_min_ext < 1 || set->qf_min_ext > 99) {
1156 mpp_loge("invalid qf_min %d out of range [1, 99] restore to 1\n", set->qf_min_ext);
1157 set->qf_min_ext = 1;
1158 }
1159 if (set->qf_max_ext < 1 || set->qf_max_ext > 99) {
1160 mpp_loge("invalid qf_max %d out of range [1, 99] restore to 99\n", set->qf_max_ext);
1161 set->qf_max_ext = 99;
1162 }
1163
1164 /* generate q_factor */
1165 set->q_factor = set->q_factor_ext;
1166 set->qf_max = set->qf_max_ext;
1167 set->qf_min = set->qf_min_ext;
1168 set->q_mode = JPEG_QFACTOR;
1169 mpp_logi("set jpeg qfactor [%d:%d:%d]\n", set->q_factor, set->qf_min, set->qf_max);
1170 } else {
1171 /* check qtable direct update */
1172 static KmppObjDef def = NULL;
1173 static KmppEntry *tbl_qtable = NULL;
1174 static rk_s32 once = 1;
1175
1176 if (!tbl_qtable && once) {
1177 def = kmpp_obj_to_objdef(enc->set_obj);
1178 kmpp_objdef_get_entry(def, "jpeg:qtable_y", &tbl_qtable);
1179
1180 if (!tbl_qtable)
1181 mpp_loge("failed to get jpeg qtable update flag\n");
1182
1183 once = 0;
1184 }
1185
1186 if (kmpp_obj_tbl_test(enc->set_obj, tbl_qtable)) {
1187 rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP;
1188 update_rc = 1;
1189 set->q_mode = JPEG_QTABLE;
1190 mpp_logi("set jpeg qtable\n");
1191 } else {
1192 update = 0;
1193 }
1194 }
1195
1196 if (!update) {
1197 set->q_mode = JPEG_QUANT;
1198 set->quant = 10;
1199 rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP;
1200 update_rc = 1;
1201
1202 mpp_loge("set jpeg invalid cfg, use default quant 10\n");
1203 }
1204 memcpy(cfg, set, sizeof(*cfg));
1205
1206 if (update_rc)
1207 rc_cfg->rc_mode = rc_set->rc_mode;
1208 cfg->update = 1;
1209 }
1210
proc_vp8_cfg(MppEncImpl * enc)1211 static void proc_vp8_cfg(MppEncImpl *enc)
1212 {
1213 MppEncH265Cfg *cfg = &enc->cfg->h265;
1214 MppEncH265Cfg *set = &enc->set->h265;
1215 rk_u32 flag = *mpp_enc_cfg_vp8_change(enc->set);
1216
1217 enc_dbg_cfg("vp8 cfg change 0x%x\n", flag);
1218
1219 if (!flag)
1220 return;
1221
1222 memcpy(cfg, set, sizeof(*cfg));
1223 }
1224
mpp_enc_control_set_ref_cfg(MppEncImpl * enc,void * param)1225 static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param)
1226 {
1227 MPP_RET ret = MPP_OK;
1228 MppEncRefCfg src = (MppEncRefCfg)param;
1229 MppEncRefCfg dst = enc->cfg->ref_cfg;
1230
1231 if (NULL == src)
1232 src = mpp_enc_ref_default();
1233
1234 if (NULL == dst) {
1235 mpp_enc_ref_cfg_init(&dst);
1236 enc->cfg->ref_cfg = dst;
1237 }
1238
1239 ret = mpp_enc_ref_cfg_copy(dst, src);
1240 if (ret) {
1241 mpp_err_f("failed to copy ref cfg ret %d\n", ret);
1242 }
1243
1244 ret = mpp_enc_refs_set_cfg(enc->refs, dst);
1245 if (ret) {
1246 mpp_err_f("failed to set ref cfg ret %d\n", ret);
1247 }
1248
1249 if (mpp_enc_refs_update_hdr(enc->refs))
1250 enc->hdr_status.val = 0;
1251
1252 return ret;
1253 }
1254
mpp_enc_proc_cfg(MppEncImpl * enc,MpiCmd cmd,void * param)1255 MPP_RET mpp_enc_proc_cfg(MppEncImpl *enc, MpiCmd cmd, void *param)
1256 {
1257 MppEncCfgSet *cfg = enc->cfg;
1258 MPP_RET ret = MPP_OK;
1259
1260 switch (cmd) {
1261 case MPP_ENC_SET_CFG : {
1262 KmppObj in_obj = (KmppObj)param;
1263 MppEncCfgSet *set = enc->set;
1264 MPP_RET ret_tmp = MPP_OK;
1265
1266 /* update all element to temporal storage */
1267 ret = (MPP_RET)kmpp_obj_update(enc->set_obj, in_obj);
1268 if (ret) {
1269 mpp_loge_f("failed to update set_obj\n");
1270 break;
1271 }
1272
1273 /* fix for cfg not setup coding */
1274 if (set->base.coding != enc->coding) {
1275 set->base.coding = enc->coding;
1276 }
1277
1278 /* check all date status in set_obj */
1279 /* 1. base cfg -> no check */
1280 memcpy(&cfg->base, &set->base, sizeof(cfg->base));
1281
1282 /* 2. prep cfg -> chech and show resolution update */
1283 proc_prep_cfg(enc);
1284
1285 /* 3. rc cfg -> check and show bps update */
1286 proc_rc_cfg(enc);
1287
1288 /* 4. split cfg -> check with restore */
1289 proc_split_cfg(&cfg->split, &set->split);
1290
1291 /* 5. hw cfg -> check with restore */
1292 proc_hw_cfg(enc);
1293
1294 /* 6. tune cfg -> check with restore */
1295 proc_tune_cfg(enc);
1296
1297 /* 7. codec config */
1298 switch (enc->coding) {
1299 case MPP_VIDEO_CodingAVC : {
1300 proc_h264_cfg(enc);
1301 } break;
1302 case MPP_VIDEO_CodingHEVC : {
1303 proc_h265_cfg(enc);
1304 } break;
1305 case MPP_VIDEO_CodingMJPEG : {
1306 proc_jpeg_cfg(enc);
1307 } break;
1308 case MPP_VIDEO_CodingVP8 : {
1309 proc_vp8_cfg(enc);
1310 } break;
1311 default : {
1312 mpp_loge_f("unsupport coding %d\n", enc->coding);
1313 } break;
1314 }
1315
1316 if (enc->cfg->rc.refresh_en)
1317 mpp_enc_refs_set_refresh_length(enc->refs, enc->cfg->rc.refresh_length);
1318
1319 /* Then process the rest config */
1320 ret_tmp = enc_impl_proc_cfg(enc->impl, cmd, param);
1321 if (ret_tmp != MPP_OK)
1322 ret = ret_tmp;
1323 } break;
1324 case MPP_ENC_SET_IDR_FRAME : {
1325 enc->frm_cfg.force_idr++;
1326 } break;
1327 case MPP_ENC_GET_HDR_SYNC :
1328 case MPP_ENC_GET_EXTRA_INFO : {
1329 /*
1330 * NOTE: get stream header should use user's MppPacket
1331 * If we provide internal MppPacket to external user
1332 * we do not known when the buffer usage is finished.
1333 * So encoder always write its header to external buffer
1334 * which is provided by user.
1335 */
1336 if (!enc->hdr_status.ready) {
1337 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
1338 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
1339 enc->hdr_status.ready = 1;
1340 }
1341
1342 if (cmd == MPP_ENC_GET_EXTRA_INFO) {
1343 mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n");
1344 mpp_err("NOTE: MPP_ENC_GET_HDR_SYNC needs MppPacket input\n");
1345
1346 *(MppPacket *)param = enc->hdr_pkt;
1347 } else {
1348 mpp_packet_copy((MppPacket)param, enc->hdr_pkt);
1349 }
1350
1351 if (enc->hdr_pkt) {
1352 Mpp *mpp = (Mpp *)enc->mpp;
1353 // dump output
1354 mpp_ops_enc_get_pkt(mpp->mDump, enc->hdr_pkt);
1355 }
1356
1357 enc->hdr_status.added_by_ctrl = 1;
1358 } break;
1359 case MPP_ENC_PRE_ALLOC_BUFF : {
1360 /* deprecated control */
1361 mpp_log("deprecated MPP_ENC_PRE_ALLOC_BUFF control\n");
1362 } break;
1363 case MPP_ENC_GET_RC_API_ALL : {
1364 RcApiQueryAll *query = (RcApiQueryAll *)param;
1365
1366 rc_brief_get_all(query);
1367 } break;
1368 case MPP_ENC_GET_RC_API_BY_TYPE : {
1369 RcApiQueryType *query = (RcApiQueryType *)param;
1370
1371 rc_brief_get_by_type(query);
1372 } break;
1373 case MPP_ENC_SET_RC_API_CFG : {
1374 const RcImplApi *api = (const RcImplApi *)param;
1375
1376 rc_api_add(api);
1377 } break;
1378 case MPP_ENC_GET_RC_API_CURRENT : {
1379 RcApiBrief *dst = (RcApiBrief *)param;
1380
1381 *dst = enc->rc_brief;
1382 } break;
1383 case MPP_ENC_SET_RC_API_CURRENT : {
1384 RcApiBrief *src = (RcApiBrief *)param;
1385
1386 mpp_assert(src->type == enc->coding);
1387 enc->rc_brief = *src;
1388 enc->rc_status.rc_api_user_cfg = 1;
1389 enc->rc_status.rc_api_updated = 1;
1390 } break;
1391 case MPP_ENC_SET_HEADER_MODE : {
1392 if (param) {
1393 MppEncHeaderMode mode = *((MppEncHeaderMode *)param);
1394
1395 if (mode < MPP_ENC_HEADER_MODE_BUTT) {
1396 enc->hdr_mode = mode;
1397 enc_dbg_ctrl("header mode set to %d\n", mode);
1398 } else {
1399 mpp_err_f("invalid header mode %d\n", mode);
1400 ret = MPP_NOK;
1401 }
1402 } else {
1403 mpp_err_f("invalid NULL ptr on setting header mode\n");
1404 ret = MPP_NOK;
1405 }
1406 } break;
1407 case MPP_ENC_SET_SEI_CFG : {
1408 if (param) {
1409 MppEncSeiMode mode = *((MppEncSeiMode *)param);
1410
1411 if (mode <= MPP_ENC_SEI_MODE_ONE_FRAME) {
1412 enc->sei_mode = mode;
1413 enc_dbg_ctrl("sei mode set to %d\n", mode);
1414 } else {
1415 mpp_err_f("invalid sei mode %d\n", mode);
1416 ret = MPP_NOK;
1417 }
1418 } else {
1419 mpp_err_f("invalid NULL ptr on setting header mode\n");
1420 ret = MPP_NOK;
1421 }
1422 } break;
1423 case MPP_ENC_SET_REF_CFG : {
1424 ret = mpp_enc_control_set_ref_cfg(enc, param);
1425 enc_set_rc_updated(enc, "ref cfg update");
1426 } break;
1427 case MPP_ENC_SET_OSD_PLT_CFG : {
1428 MppEncOSDPltCfg *src = (MppEncOSDPltCfg *)param;
1429 MppEncOSDPltCfg *dst = &enc->cfg->plt_cfg;
1430 RK_U32 change = src->change;
1431
1432 if (change) {
1433 RK_S32 cfg_err = 0;
1434
1435 if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_MODE) {
1436 if (src->type >= MPP_ENC_OSD_PLT_TYPE_BUTT) {
1437 mpp_err_f("invalid osd plt type %d\n", src->type);
1438 cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_MODE;
1439 } else
1440 dst->type = src->type;
1441 }
1442
1443 if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL) {
1444 if (src->plt == NULL) {
1445 mpp_err_f("invalid osd plt NULL pointer\n");
1446 cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL;
1447 } else {
1448 memcpy(dst->plt, src->plt, sizeof(MppEncOSDPlt));
1449 }
1450 }
1451
1452 dst->change = cfg_err ? 0 : change;
1453 enc_dbg_ctrl("plt type %d data %p\n", dst->type, src->plt);
1454 }
1455 } break;
1456 default : {
1457 ret = enc_impl_proc_cfg(enc->impl, cmd, param);
1458 } break;
1459 }
1460
1461 if (check_hal_info_update(cmd))
1462 enc->hal_info_updated = 0;
1463
1464 check_low_delay_part_mode(enc);
1465 check_low_delay_output(enc);
1466
1467 return ret;
1468 }
1469
1470 static const char *name_of_rc_mode[] = {
1471 "vbr",
1472 "cbr",
1473 "fixqp",
1474 "avbr",
1475 "smtrc",
1476 "sp_enc"
1477 };
1478
update_rc_cfg_log(MppEncImpl * impl,const char * fmt,...)1479 static void update_rc_cfg_log(MppEncImpl *impl, const char* fmt, ...)
1480 {
1481 va_list args;
1482 va_start(args, fmt);
1483
1484 RK_S32 size = impl->rc_cfg_size;
1485 RK_S32 length = impl->rc_cfg_length;
1486 char *base = impl->rc_cfg_info + length;
1487
1488 length += vsnprintf(base, size - length, fmt, args);
1489 if (length >= size)
1490 mpp_log_f("rc cfg log is full\n");
1491
1492 impl->rc_cfg_length = length;
1493
1494 va_end(args);
1495 }
1496
update_user_datas(EncImpl impl,MppPacket packet,MppFrame frame,HalEncTask * hal_task)1497 static void update_user_datas(EncImpl impl, MppPacket packet, MppFrame frame, HalEncTask *hal_task)
1498 {
1499 MppMeta frm_meta = mpp_frame_get_meta(frame);
1500 MppEncUserData *user_data = NULL;
1501 MppEncUserDataSet *user_datas = NULL;
1502 RK_S32 length = 0;
1503
1504 mpp_meta_get_ptr(frm_meta, KEY_USER_DATA, (void**)&user_data);
1505 if (user_data) {
1506 if (user_data->pdata && user_data->len) {
1507 enc_impl_add_prefix(impl, packet, &length, uuid_usr_data,
1508 user_data->pdata, user_data->len);
1509
1510 hal_task->sei_length += length;
1511 hal_task->length += length;
1512 } else
1513 mpp_err_f("failed to insert user data %p len %d\n",
1514 user_data->pdata, user_data->len);
1515 }
1516
1517 mpp_meta_get_ptr(frm_meta, KEY_USER_DATAS, (void**)&user_datas);
1518 if (user_datas && user_datas->count) {
1519 RK_U32 i = 0;
1520
1521 for (i = 0; i < user_datas->count; i++) {
1522 MppEncUserDataFull *user_data_v2 = &user_datas->datas[i];
1523 if (user_data_v2->pdata && user_data_v2->len) {
1524 if (user_data_v2->uuid)
1525 enc_impl_add_prefix(impl, packet, &length, user_data_v2->uuid,
1526 user_data_v2->pdata, user_data_v2->len);
1527 else
1528 enc_impl_add_prefix(impl, packet, &length, uuid_debug_info,
1529 user_data_v2->pdata, user_data_v2->len);
1530
1531 hal_task->sei_length += length;
1532 hal_task->length += length;
1533 }
1534 }
1535 }
1536 }
1537
set_rc_cfg(RcCfg * cfg,MppEncCfgSet * cfg_set)1538 static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set)
1539 {
1540 MppEncRcCfg *rc = &cfg_set->rc;
1541 MppEncPrepCfg *prep = &cfg_set->prep;
1542 MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg;
1543 MppEncCpbInfo *info = &ref->cpb_info;
1544 MppCodingType coding = cfg_set->base.coding;
1545
1546 cfg->width = prep->width;
1547 cfg->height = prep->height;
1548
1549 switch (rc->rc_mode) {
1550 case MPP_ENC_RC_MODE_CBR : {
1551 cfg->mode = RC_CBR;
1552 } break;
1553 case MPP_ENC_RC_MODE_VBR : {
1554 cfg->mode = RC_VBR;
1555 } break;
1556 case MPP_ENC_RC_MODE_AVBR : {
1557 cfg->mode = RC_AVBR;
1558 } break;
1559 case MPP_ENC_RC_MODE_FIXQP: {
1560 cfg->mode = RC_FIXQP;
1561 } break;
1562 case MPP_ENC_RC_MODE_SMTRC: {
1563 cfg->mode = RC_SMT;
1564 } break;
1565 case MPP_ENC_RC_MODE_SE: {
1566 cfg->mode = RC_SE;
1567 } break;
1568 default : {
1569 cfg->mode = RC_AVBR;
1570 } break;
1571 }
1572
1573 cfg->fps.fps_in_flex = rc->fps_in_flex;
1574 cfg->fps.fps_in_num = rc->fps_in_num;
1575 cfg->fps.fps_in_denom = rc->fps_in_denom;
1576 cfg->fps.fps_out_flex = rc->fps_out_flex;
1577 cfg->fps.fps_out_num = rc->fps_out_num;
1578 cfg->fps.fps_out_denom = rc->fps_out_denom;
1579 cfg->igop = rc->gop;
1580 cfg->max_i_bit_prop = rc->max_i_prop;
1581 cfg->min_i_bit_prop = rc->min_i_prop;
1582 cfg->init_ip_ratio = rc->init_ip_ratio;
1583
1584 cfg->bps_target = rc->bps_target;
1585 cfg->bps_max = rc->bps_max;
1586 cfg->bps_min = rc->bps_min;
1587 cfg->scene_mode = cfg_set->tune.scene_mode;
1588 cfg->rc_container = cfg_set->tune.rc_container;
1589
1590 cfg->hier_qp_cfg.hier_qp_en = rc->hier_qp_en;
1591 memcpy(cfg->hier_qp_cfg.hier_frame_num, rc->hier_frame_num, sizeof(rc->hier_frame_num));
1592 memcpy(cfg->hier_qp_cfg.hier_qp_delta, rc->hier_qp_delta, sizeof(rc->hier_qp_delta));
1593
1594 mpp_assert(rc->fps_out_num);
1595 cfg->stats_time = rc->stats_time ? rc->stats_time : 3;
1596 cfg->stats_time = mpp_clip(cfg->stats_time, 1, 60);
1597
1598 /* quality configure */
1599 switch (coding) {
1600 case MPP_VIDEO_CodingAVC :
1601 case MPP_VIDEO_CodingHEVC :
1602 case MPP_VIDEO_CodingVP8 : {
1603 cfg->init_quality = rc->qp_init;
1604 cfg->max_quality = rc->qp_max;
1605 cfg->min_quality = rc->qp_min;
1606 cfg->max_i_quality = rc->qp_max_i ? rc->qp_max_i : rc->qp_max;
1607 cfg->min_i_quality = rc->qp_min_i ? rc->qp_min_i : rc->qp_min;
1608 cfg->i_quality_delta = rc->qp_delta_ip;
1609 cfg->vi_quality_delta = rc->qp_delta_vi;
1610 cfg->fqp_min_p = rc->fqp_min_p == INT_MAX ? cfg->min_quality : rc->fqp_min_p;
1611 cfg->fqp_min_i = rc->fqp_min_i == INT_MAX ? cfg->min_i_quality : rc->fqp_min_i;
1612 cfg->fqp_max_p = rc->fqp_max_p == INT_MAX ? cfg->max_quality : rc->fqp_max_p;
1613 cfg->fqp_max_i = rc->fqp_max_i == INT_MAX ? cfg->max_i_quality : rc->fqp_max_i;
1614 } break;
1615 case MPP_VIDEO_CodingMJPEG : {
1616 MppEncJpegCfg *jpeg = &cfg_set->jpeg;
1617
1618 cfg->init_quality = 100 - jpeg->q_factor;
1619 cfg->max_quality = 100 - jpeg->qf_max;
1620 cfg->min_quality = 100 - jpeg->qf_min;
1621 cfg->max_i_quality = 100 - jpeg->qf_max;
1622 cfg->min_i_quality = 100 - jpeg->qf_min;
1623 cfg->fqp_min_i = 100 - jpeg->qf_max;
1624 cfg->fqp_max_i = 100 - jpeg->qf_min;
1625 cfg->fqp_min_p = 100 - jpeg->qf_max;
1626 cfg->fqp_max_p = 100 - jpeg->qf_min;
1627 } break;
1628 default : {
1629 mpp_err_f("unsupport coding type %d\n", coding);
1630 } break;
1631 }
1632
1633 cfg->layer_bit_prop[0] = 256;
1634 cfg->layer_bit_prop[1] = 0;
1635 cfg->layer_bit_prop[2] = 0;
1636 cfg->layer_bit_prop[3] = 0;
1637
1638 cfg->max_reencode_times = rc->max_reenc_times;
1639 cfg->drop_mode = rc->drop_mode;
1640 cfg->drop_thd = rc->drop_threshold;
1641 cfg->drop_gap = rc->drop_gap;
1642
1643 cfg->super_cfg.rc_priority = rc->rc_priority;
1644 cfg->super_cfg.super_mode = rc->super_mode;
1645 cfg->super_cfg.super_i_thd = rc->super_i_thd;
1646 cfg->super_cfg.super_p_thd = rc->super_p_thd;
1647
1648 cfg->debreath_cfg.enable = rc->debreath_en;
1649 cfg->debreath_cfg.strength = rc->debre_strength;
1650
1651 cfg->refresh_len = rc->refresh_length;
1652
1653 if (info->st_gop) {
1654 cfg->vgop = info->st_gop;
1655 if (cfg->vgop >= rc->fps_out_num / rc->fps_out_denom &&
1656 cfg->vgop < cfg->igop ) {
1657 cfg->gop_mode = SMART_P;
1658 if (!cfg->vi_quality_delta)
1659 cfg->vi_quality_delta = 2;
1660 }
1661 }
1662
1663 if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC) {
1664 mpp_log("mode %s bps [%d:%d:%d] fps %s [%d/%d] -> %s [%d/%d] gop i [%d] v [%d]\n",
1665 name_of_rc_mode[cfg->mode],
1666 rc->bps_min, rc->bps_target, rc->bps_max,
1667 cfg->fps.fps_in_flex ? "flex" : "fix",
1668 cfg->fps.fps_in_num, cfg->fps.fps_in_denom,
1669 cfg->fps.fps_out_flex ? "flex" : "fix",
1670 cfg->fps.fps_out_num, cfg->fps.fps_out_denom,
1671 cfg->igop, cfg->vgop);
1672 }
1673 }
1674
mpp_enc_proc_rc_update(MppEncImpl * enc)1675 MPP_RET mpp_enc_proc_rc_update(MppEncImpl *enc)
1676 {
1677 MPP_RET ret = MPP_OK;
1678
1679 // check and update rate control api
1680 if (!enc->rc_status.rc_api_inited || enc->rc_status.rc_api_updated) {
1681 RcApiBrief *brief = &enc->rc_brief;
1682
1683 if (enc->rc_ctx) {
1684 enc_dbg_detail("rc deinit %p\n", enc->rc_ctx);
1685 rc_deinit(enc->rc_ctx);
1686 enc->rc_ctx = NULL;
1687 }
1688
1689 /* NOTE: default name is NULL */
1690 ret = rc_init(&enc->rc_ctx, enc->coding, &brief->name);
1691 if (ret)
1692 mpp_err("enc %p fail to init rc %s\n", enc, brief->name);
1693 else
1694 enc->rc_status.rc_api_inited = 1;
1695
1696 enc_dbg_detail("rc init %p name %s ret %d\n", enc->rc_ctx, brief->name, ret);
1697 enc->rc_status.rc_api_updated = 0;
1698
1699 enc->rc_cfg_length = 0;
1700 update_rc_cfg_log(enc, "%s:", brief->name);
1701 enc->rc_cfg_pos = enc->rc_cfg_length;
1702 }
1703
1704 // check and update rate control config
1705 if (enc->rc_status.rc_api_user_cfg) {
1706 MppEncCfgSet *cfg = enc->cfg;
1707 RcCfg usr_cfg;
1708
1709 enc_dbg_detail("rc update cfg start\n");
1710
1711 memset(&usr_cfg, 0 , sizeof(usr_cfg));
1712 set_rc_cfg(&usr_cfg, cfg);
1713 ret = rc_update_usr_cfg(enc->rc_ctx, &usr_cfg);
1714
1715 enc_dbg_detail("rc update cfg done\n");
1716 enc->rc_status.rc_api_user_cfg = 0;
1717
1718 enc->rc_cfg_length = enc->rc_cfg_pos;
1719 update_rc_cfg_log(enc, "%s-b:%d[%d:%d]-g:%d-q:%d:[%d:%d]:[%d:%d]:%d\n",
1720 name_of_rc_mode[usr_cfg.mode],
1721 usr_cfg.bps_target,
1722 usr_cfg.bps_min, usr_cfg.bps_max, usr_cfg.igop,
1723 usr_cfg.init_quality,
1724 usr_cfg.min_quality, usr_cfg.max_quality,
1725 usr_cfg.min_i_quality, usr_cfg.max_i_quality,
1726 usr_cfg.i_quality_delta);
1727 }
1728
1729 return ret;
1730 }
1731
1732 #define ENC_RUN_FUNC2(func, ctx, task, mpp, ret) \
1733 ret = func(ctx, task); \
1734 if (ret) { \
1735 mpp_err("mpp %p "#func":%-4d failed return %d", \
1736 mpp, __LINE__, ret); \
1737 goto TASK_DONE; \
1738 }
1739
mpp_enc_check_frm_pkt(MppEncImpl * enc)1740 static MPP_RET mpp_enc_check_frm_pkt(MppEncImpl *enc)
1741 {
1742 enc->frm_buf = NULL;
1743 enc->pkt_buf = NULL;
1744
1745 if (enc->packet)
1746 enc->pkt_buf = mpp_packet_get_buffer(enc->packet);
1747 else
1748 mpp_packet_new(&enc->packet);
1749
1750 if (enc->frame) {
1751 RK_S64 pts = mpp_frame_get_pts(enc->frame);
1752 MppBuffer frm_buf = mpp_frame_get_buffer(enc->frame);
1753
1754 enc->task_pts = pts;
1755 enc->frm_buf = frm_buf;
1756
1757 mpp_packet_set_pts(enc->packet, pts);
1758 mpp_packet_set_dts(enc->packet, mpp_frame_get_dts(enc->frame));
1759
1760 if (mpp_frame_get_eos(enc->frame))
1761 mpp_packet_set_eos(enc->packet);
1762 else
1763 mpp_packet_clr_eos(enc->packet);
1764 }
1765
1766 return (NULL == enc->frame || NULL == enc->frm_buf) ? MPP_NOK : MPP_OK;
1767 }
1768
mpp_enc_check_pkt_buf(MppEncImpl * enc)1769 static MPP_RET mpp_enc_check_pkt_buf(MppEncImpl *enc)
1770 {
1771 if (NULL == enc->pkt_buf) {
1772 /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
1773 Mpp *mpp = (Mpp *)enc->mpp;
1774 MppEncPrepCfg *prep = &enc->cfg->prep;
1775 RK_U32 width = MPP_ALIGN(prep->width, 16);
1776 RK_U32 height = MPP_ALIGN(prep->height, 16);
1777 RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
1778 (width * height * 3 / 2) : (width * height);
1779 MppPacketImpl *pkt = (MppPacketImpl *)enc->packet;
1780 MppBuffer buffer = NULL;
1781
1782 mpp_assert(size);
1783 mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
1784 mpp_buffer_attach_dev(buffer, enc->dev);
1785 mpp_assert(buffer);
1786 enc->pkt_buf = buffer;
1787 pkt->data = mpp_buffer_get_ptr(buffer);
1788 pkt->pos = pkt->data;
1789 pkt->size = mpp_buffer_get_size(buffer);
1790 pkt->length = 0;
1791 pkt->buffer = buffer;
1792
1793 enc_dbg_detail("create output pkt %p buf %p\n", enc->packet, buffer);
1794 } else {
1795 enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
1796 enc->packet, enc->pkt_buf,
1797 mpp_packet_get_pos(enc->packet),
1798 mpp_packet_get_length(enc->packet));
1799 }
1800
1801 return MPP_OK;
1802 }
1803
mpp_enc_proc_two_pass(Mpp * mpp,EncAsyncTaskInfo * task)1804 static MPP_RET mpp_enc_proc_two_pass(Mpp *mpp, EncAsyncTaskInfo *task)
1805 {
1806 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1807 MPP_RET ret = MPP_OK;
1808
1809 if (mpp_enc_refs_next_frm_is_intra(enc->refs)) {
1810 EncRcTask *rc_task = &task->rc;
1811 EncFrmStatus frm_bak = rc_task->frm;
1812 EncRcTaskInfo rc_info = rc_task->info;
1813 EncCpbStatus *cpb = &rc_task->cpb;
1814 EncFrmStatus *frm = &rc_task->frm;
1815 HalEncTask *hal_task = &task->task;
1816 EncImpl impl = enc->impl;
1817 MppEncHal hal = enc->enc_hal;
1818 MppPacket packet = hal_task->packet;
1819 RK_S32 task_len = hal_task->length;
1820 RK_S32 hw_len = hal_task->hw_length;
1821 RK_S32 pkt_len = mpp_packet_get_length(packet);
1822
1823 enc_dbg_detail("task %d two pass mode enter\n", frm->seq_idx);
1824 rc_task->info = enc->rc_info_prev;
1825 hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
1826
1827 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1828 mpp_enc_refs_get_cpb_pass1(enc->refs, cpb);
1829
1830 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1831 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1832
1833 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1834 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
1835
1836 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1837 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1838
1839 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1840 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1841
1842 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1843 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1844
1845 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1846 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
1847
1848 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1849 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1850
1851 //recover status & packet
1852 mpp_packet_set_length(packet, pkt_len);
1853 mpp_packet_set_segment_nb(packet, hal_task->segment_nb);
1854 hal_task->hw_length = hw_len;
1855 hal_task->length = task_len;
1856
1857 *frm = frm_bak;
1858 rc_task->info = rc_info;
1859
1860 enc_dbg_detail("task %d two pass mode leave\n", frm->seq_idx);
1861 }
1862 TASK_DONE:
1863 return ret;
1864 }
1865
mpp_enc_rc_info_backup(MppEncImpl * enc,EncAsyncTaskInfo * task)1866 static void mpp_enc_rc_info_backup(MppEncImpl *enc, EncAsyncTaskInfo *task)
1867 {
1868 if (!enc->support_hw_deflicker || !enc->cfg->rc.debreath_en)
1869 return;
1870
1871 enc->rc_info_prev = task->rc.info;
1872 }
1873
mpp_enc_force_pskip_check(Mpp * mpp,EncAsyncTaskInfo * task)1874 static MPP_RET mpp_enc_force_pskip_check(Mpp *mpp, EncAsyncTaskInfo *task)
1875 {
1876 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1877 EncRcTask *rc_task = &task->rc;
1878 EncCpbStatus *cpb = &rc_task->cpb;
1879 EncFrmStatus *frm = &rc_task->frm;
1880 MppEncCpbInfo cpb_info;
1881 RK_U32 max_tid = 0;
1882 MPP_RET ret = MPP_OK;
1883
1884 mpp_enc_refs_get_cpb_info(enc->refs, &cpb_info);
1885 max_tid = cpb_info.max_st_tid;
1886
1887 if (task->usr.force_flag & ENC_FORCE_IDR) {
1888 enc_dbg_detail("task %d, FORCE IDR should not be set as pskip frames", frm->seq_idx);
1889 ret = MPP_NOK;
1890 }
1891 if (cpb->curr.is_idr) {
1892 enc_dbg_detail("task %d, IDR frames should not be set as pskip frames", frm->seq_idx);
1893 ret = MPP_NOK;
1894 }
1895 if (cpb->curr.is_lt_ref) {
1896 enc_dbg_detail("task %d, LTR frames should not be set as pskip frames", frm->seq_idx);
1897 ret = MPP_NOK;
1898 }
1899 if (cpb->curr.temporal_id != max_tid) {
1900 enc_dbg_detail("task %d, Only top-layer frames can be set as pskip frames in TSVC mode", frm->seq_idx);
1901 ret = MPP_NOK;
1902 }
1903 if (cpb->curr.ref_mode != REF_TO_PREV_REF_FRM) {
1904 enc_dbg_detail("task %d, Only frames with reference mode set to prev_ref can be set as pskip frames", frm->seq_idx);
1905 ret = MPP_NOK;
1906 }
1907
1908 return ret;
1909 }
1910
mpp_enc_force_pskip(Mpp * mpp,EncAsyncTaskInfo * task)1911 static MPP_RET mpp_enc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task)
1912 {
1913 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1914 EncImpl impl = enc->impl;
1915 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
1916 EncRcTask *rc_task = &task->rc;
1917 EncCpbStatus *cpb = &rc_task->cpb;
1918 EncFrmStatus *frm = &rc_task->frm;
1919 HalEncTask *hal_task = &task->task;
1920 MPP_RET ret = MPP_OK;
1921
1922 enc_dbg_func("enter\n");
1923
1924 frm_cfg->force_pskip++;
1925 if (frm->force_pskip)
1926 frm_cfg->force_flag |= ENC_FORCE_PSKIP_NON_REF;
1927 else if (frm->force_pskip_is_ref)
1928 frm_cfg->force_flag |= ENC_FORCE_PSKIP_IS_REF;
1929
1930 /* NOTE: in some condition the pskip should not happen */
1931 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1932
1933 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1934 mpp_enc_refs_get_cpb(enc->refs, cpb);
1935
1936 ret = mpp_enc_force_pskip_check(mpp, task);
1937
1938 if (ret) {
1939 mpp_enc_refs_rollback(enc->refs);
1940 frm_cfg->force_pskip--;
1941 if (frm->force_pskip)
1942 frm_cfg->force_flag &= ~ENC_FORCE_PSKIP_NON_REF;
1943 else if (frm->force_pskip_is_ref)
1944 frm_cfg->force_flag &= ~ENC_FORCE_PSKIP_IS_REF;
1945 return MPP_NOK;
1946 }
1947
1948 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1949 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1950
1951 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
1952 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
1953
1954 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
1955 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
1956
1957 enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx);
1958 ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret);
1959
1960 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
1961 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
1962
1963 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
1964 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
1965
1966 TASK_DONE:
1967 enc_dbg_func("leave\n");
1968 return ret;
1969 }
1970
mpp_enc_get_pskip_mode(Mpp * mpp,EncAsyncTaskInfo * task,MppPskipMode * skip_mode)1971 static MPP_RET mpp_enc_get_pskip_mode(Mpp *mpp, EncAsyncTaskInfo *task, MppPskipMode *skip_mode)
1972 {
1973 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1974 EncRcTask *rc_task = &task->rc;
1975 EncFrmStatus *frm = &rc_task->frm;
1976 HalEncTask *hal_task = &task->task;
1977 MPP_RET ret = MPP_OK;
1978
1979 skip_mode->pskip_is_ref = 0;
1980 skip_mode->pskip_is_non_ref = 0;
1981 enc->frame = hal_task->frame;
1982
1983 if (mpp_frame_has_meta(enc->frame)) {
1984 MppMeta frm_meta = mpp_frame_get_meta(enc->frame);
1985 if (frm_meta) {
1986 mpp_meta_get_s32(frm_meta, KEY_INPUT_PSKIP, &skip_mode->pskip_is_ref);
1987 mpp_meta_get_s32(frm_meta, KEY_INPUT_PSKIP_NON_REF, &skip_mode->pskip_is_non_ref);
1988 }
1989 }
1990
1991 if (skip_mode->pskip_is_ref == 1 && skip_mode->pskip_is_non_ref == 1) {
1992 mpp_err("task %d, Don't cfg pskip frame to be both a ref and non-ref at the same time");
1993 ret = MPP_NOK;
1994 } else {
1995 frm->force_pskip = skip_mode->pskip_is_non_ref;
1996 frm->force_pskip_is_ref = skip_mode->pskip_is_ref;
1997 ret = MPP_OK;
1998 }
1999
2000 return ret;
2001 }
2002
2003
mpp_enc_add_sw_header(MppEncImpl * enc,HalEncTask * hal_task)2004 static void mpp_enc_add_sw_header(MppEncImpl *enc, HalEncTask *hal_task)
2005 {
2006 EncImpl impl = enc->impl;
2007 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
2008 EncRcTask *rc_task = hal_task->rc_task;
2009 EncFrmStatus *frm = &rc_task->frm;
2010 MppPacket packet = hal_task->packet;
2011 MppFrame frame = hal_task->frame;
2012
2013 if (!(hdr_status->val & HDR_ADDED_MASK)) {
2014 RK_U32 add_header = 0;
2015
2016 if (enc->hdr_mode == MPP_ENC_HEADER_MODE_EACH_IDR && frm->is_intra)
2017 add_header |= 1;
2018
2019 if (enc->cfg->rc.refresh_en && frm->is_i_recovery && !frm->is_idr)
2020 add_header |= 2;
2021
2022 if (add_header) {
2023 enc_dbg_detail("task %d IDR header length %d\n",
2024 frm->seq_idx, enc->hdr_len);
2025
2026 mpp_packet_append(packet, enc->hdr_pkt);
2027
2028 hal_task->header_length = enc->hdr_len;
2029 hal_task->length += enc->hdr_len;
2030 hdr_status->added_by_mode = 1;
2031 }
2032
2033 if ((add_header & 2) && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
2034 RK_S32 length = 0;
2035
2036 enc_impl_add_prefix(impl, packet, &length, uuid_refresh_cfg,
2037 &enc->cfg->rc.refresh_length, 0);
2038
2039 if (length) {
2040 enc_dbg_detail("task %d refresh header length %d\n",
2041 frm->seq_idx, enc->hdr_len);
2042
2043 hal_task->sei_length += length;
2044 hal_task->length += length;
2045 }
2046 }
2047 }
2048
2049 // check for header adding
2050 check_hal_task_pkt_len(hal_task, "header adding");
2051
2052 /* 17. Add all prefix info before encoding */
2053 if (frm->is_idr && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
2054 RK_S32 length = 0;
2055
2056 enc_impl_add_prefix(impl, packet, &length, uuid_version,
2057 enc->version_info, enc->version_length);
2058
2059 hal_task->sei_length += length;
2060 hal_task->length += length;
2061
2062 length = 0;
2063 enc_impl_add_prefix(impl, packet, &length, uuid_rc_cfg,
2064 enc->rc_cfg_info, enc->rc_cfg_length);
2065
2066 hal_task->sei_length += length;
2067 hal_task->length += length;
2068 }
2069
2070 if (mpp_frame_has_meta(frame)) {
2071 update_user_datas(impl, packet, frame, hal_task);
2072 }
2073
2074 // check for user data adding
2075 check_hal_task_pkt_len(hal_task, "user data adding");
2076 }
2077
mpp_enc_normal(Mpp * mpp,EncAsyncTaskInfo * task)2078 static MPP_RET mpp_enc_normal(Mpp *mpp, EncAsyncTaskInfo *task)
2079 {
2080 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2081 EncImpl impl = enc->impl;
2082 MppEncHal hal = enc->enc_hal;
2083 EncRcTask *rc_task = &task->rc;
2084 EncCpbStatus *cpb = &rc_task->cpb;
2085 EncFrmStatus *frm = &rc_task->frm;
2086 HalEncTask *hal_task = &task->task;
2087 MPP_RET ret = MPP_OK;
2088 EncAsyncStatus *status = &task->status;
2089
2090 if (enc->support_hw_deflicker && enc->cfg->rc.debreath_en) {
2091 ret = mpp_enc_proc_two_pass(mpp, task);
2092 if (ret)
2093 return ret;
2094 }
2095
2096 enc_dbg_detail("task %d check force pskip start\n", frm->seq_idx);
2097 if (!status->check_frm_pskip) {
2098 MppPskipMode skip_mode;
2099 status->check_frm_pskip = 1;
2100
2101 mpp_enc_get_pskip_mode((Mpp*)enc->mpp, task, &skip_mode);
2102 if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) {
2103 ret = mpp_enc_force_pskip((Mpp*)enc->mpp, task);
2104 if (ret)
2105 enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx);
2106 else
2107 goto TASK_DONE;
2108 }
2109 }
2110
2111 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
2112 mpp_enc_refs_get_cpb(enc->refs, cpb);
2113
2114 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
2115 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2116
2117 enc_dbg_frm_status("frm %d compare\n", cpb->curr.seq_idx);
2118 enc_dbg_frm_status("seq_idx %d vs %d\n", frm->seq_idx, cpb->curr.seq_idx);
2119 enc_dbg_frm_status("is_idr %d vs %d\n", frm->is_idr, cpb->curr.is_idr);
2120 enc_dbg_frm_status("is_intra %d vs %d\n", frm->is_intra, cpb->curr.is_intra);
2121 enc_dbg_frm_status("is_non_ref %d vs %d\n", frm->is_non_ref, cpb->curr.is_non_ref);
2122 enc_dbg_frm_status("is_lt_ref %d vs %d\n", frm->is_lt_ref, cpb->curr.is_lt_ref);
2123 enc_dbg_frm_status("lt_idx %d vs %d\n", frm->lt_idx, cpb->curr.lt_idx);
2124 enc_dbg_frm_status("temporal_id %d vs %d\n", frm->temporal_id, cpb->curr.temporal_id);
2125 enc_dbg_frm_status("frm %d done ***********************************\n", cpb->curr.seq_idx);
2126
2127 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2128 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2129
2130 // 16. generate header before hardware stream
2131 mpp_enc_add_sw_header(enc, hal_task);
2132
2133 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2134 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2135
2136 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2137 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2138
2139 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2140 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2141
2142 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2143 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2144
2145 hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
2146 mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
2147 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2148 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
2149
2150 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2151 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
2152
2153 mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
2154
2155 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2156 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2157
2158 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2159 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2160
2161 enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
2162 ENC_RUN_FUNC2(rc_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
2163
2164 TASK_DONE:
2165 return ret;
2166 }
2167
mpp_enc_clr_rc_cb_info(EncRcTask * rc_task)2168 static void mpp_enc_clr_rc_cb_info(EncRcTask *rc_task)
2169 {
2170 EncRcTaskInfo *hal_rc = (EncRcTaskInfo *) &rc_task->info;
2171 EncRcTaskInfo bak = rc_task->info;
2172
2173 memset(hal_rc, 0, sizeof(rc_task->info));
2174
2175 hal_rc->frame_type = bak.frame_type;
2176 hal_rc->bit_target = bak.bit_target;
2177 hal_rc->bit_max = bak.bit_max;
2178 hal_rc->bit_min = bak.bit_min;
2179 hal_rc->quality_target = bak.quality_target;
2180 hal_rc->quality_max = bak.quality_max;
2181 hal_rc->quality_min = bak.quality_min;
2182 }
2183
mpp_enc_reenc_simple(Mpp * mpp,EncAsyncTaskInfo * task)2184 static MPP_RET mpp_enc_reenc_simple(Mpp *mpp, EncAsyncTaskInfo *task)
2185 {
2186 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2187 MppEncHal hal = enc->enc_hal;
2188 EncRcTask *rc_task = &task->rc;
2189 EncFrmStatus *frm = &rc_task->frm;
2190 HalEncTask *hal_task = &task->task;
2191 MPP_RET ret = MPP_OK;
2192
2193 enc_dbg_func("enter\n");
2194
2195 mpp_enc_clr_rc_cb_info(rc_task);
2196
2197 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2198 ENC_RUN_FUNC2(enc_impl_proc_hal, enc->impl, hal_task, mpp, ret);
2199
2200 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2201 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2202
2203 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2204 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2205
2206 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2207 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2208
2209 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2210 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
2211
2212 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2213 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
2214
2215 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2216 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2217
2218 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2219 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2220
2221 enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
2222 ENC_RUN_FUNC2(rc_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
2223
2224 enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
2225 enc_dbg_func("leave\n");
2226
2227 TASK_DONE:
2228 return ret;
2229 }
2230
mpp_enc_reenc_drop(Mpp * mpp,EncAsyncTaskInfo * task)2231 static MPP_RET mpp_enc_reenc_drop(Mpp *mpp, EncAsyncTaskInfo *task)
2232 {
2233 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2234 EncRcTask *rc_task = &task->rc;
2235 EncRcTaskInfo *info = &rc_task->info;
2236 EncFrmStatus *frm = &rc_task->frm;
2237 HalEncTask *hal_task = &task->task;
2238 MPP_RET ret = MPP_OK;
2239
2240 enc_dbg_func("enter\n");
2241 mpp_enc_refs_rollback(enc->refs);
2242
2243 info->bit_real = hal_task->length;
2244 info->quality_real = info->quality_target;
2245
2246 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2247 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2248
2249 TASK_DONE:
2250 enc_dbg_func("leave\n");
2251 return ret;
2252 }
2253
mpp_enc_reenc_force_pskip(Mpp * mpp,EncAsyncTaskInfo * task)2254 static MPP_RET mpp_enc_reenc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task)
2255 {
2256 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2257 EncImpl impl = enc->impl;
2258 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
2259 EncRcTask *rc_task = &task->rc;
2260 EncCpbStatus *cpb = &rc_task->cpb;
2261 EncFrmStatus *frm = &rc_task->frm;
2262 HalEncTask *hal_task = &task->task;
2263 MPP_RET ret = MPP_OK;
2264
2265 enc_dbg_func("enter\n");
2266
2267 frm_cfg->force_pskip++;
2268 frm_cfg->force_flag |= ENC_FORCE_PSKIP_NON_REF;
2269
2270 /* NOTE: in some condition the pskip should not happen */
2271
2272 mpp_enc_refs_rollback(enc->refs);
2273 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
2274
2275 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
2276 mpp_enc_refs_get_cpb(enc->refs, cpb);
2277
2278 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
2279 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2280
2281 enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx);
2282 ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret);
2283
2284 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2285 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2286
2287 TASK_DONE:
2288 enc_dbg_func("leave\n");
2289 return ret;
2290 }
2291
mpp_enc_terminate_task(MppEncImpl * enc,EncAsyncTaskInfo * task)2292 static void mpp_enc_terminate_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
2293 {
2294 HalEncTask *hal_task = &task->task;
2295 EncFrmStatus *frm = &task->rc.frm;
2296
2297 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2298
2299 if (enc->packet) {
2300 /* setup output packet and meta data */
2301 mpp_packet_set_length(enc->packet, hal_task->length);
2302
2303 /*
2304 * First return output packet.
2305 * Then enqueue task back to input port.
2306 * Final user will release the mpp_frame they had input.
2307 */
2308 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2309
2310 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, enc->packet);
2311 mpp_port_enqueue(enc->output, enc->task_out);
2312 }
2313
2314 if (enc->task_in) {
2315 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2316
2317 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2318 mpp_port_enqueue(enc->input, enc->task_in);
2319 }
2320
2321 reset_enc_task(enc);
2322 task->status.val = 0;
2323 }
2324
try_get_enc_task(MppEncImpl * enc,EncAsyncTaskInfo * task,EncAsyncWait * wait)2325 static MPP_RET try_get_enc_task(MppEncImpl *enc, EncAsyncTaskInfo *task, EncAsyncWait *wait)
2326 {
2327 EncRcTask *rc_task = &task->rc;
2328 EncFrmStatus *frm = &rc_task->frm;
2329 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
2330 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
2331 EncAsyncStatus *status = &task->status;
2332 HalEncTask *hal_task = &task->task;
2333 MppStopwatch stopwatch = NULL;
2334 MPP_RET ret = MPP_OK;
2335
2336 if (!status->task_in_rdy) {
2337 ret = mpp_port_poll(enc->input, MPP_POLL_NON_BLOCK);
2338 if (ret < 0) {
2339 wait->enc_frm_in = 1;
2340 return ret;
2341 }
2342
2343 status->task_in_rdy = 1;
2344 wait->enc_frm_in = 0;
2345 enc_dbg_detail("task in ready\n");
2346 }
2347
2348 // 5. check output task
2349 if (!status->task_out_rdy) {
2350 ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
2351 if (ret < 0) {
2352 wait->enc_pkt_out = 1;
2353 return ret;
2354 }
2355
2356 status->task_out_rdy = 1;
2357 wait->enc_pkt_out = 0;
2358 enc_dbg_detail("task out ready\n");
2359 }
2360
2361 /*
2362 * 6. get frame and packet for one task
2363 * If there is no input frame just return empty packet task
2364 */
2365 if (!status->frm_pkt_rdy) {
2366 // get tasks from both input and output
2367 ret = mpp_port_dequeue(enc->input, &enc->task_in);
2368 mpp_assert(enc->task_in);
2369
2370 ret = mpp_port_dequeue(enc->output, &enc->task_out);
2371 mpp_assert(enc->task_out);
2372
2373 /*
2374 * frame will be return to input.
2375 * packet will be sent to output.
2376 */
2377 mpp_task_meta_get_frame (enc->task_in, KEY_INPUT_FRAME, &enc->frame);
2378 mpp_task_meta_get_packet(enc->task_in, KEY_OUTPUT_PACKET, &enc->packet);
2379 mpp_task_meta_get_buffer(enc->task_in, KEY_MOTION_INFO, &enc->md_info);
2380
2381 enc_dbg_detail("task dequeue done frm %p pkt %p\n", enc->frame, enc->packet);
2382
2383 stopwatch = mpp_frame_get_stopwatch(enc->frame);
2384 mpp_stopwatch_record(stopwatch, "encode task start");
2385
2386 if (mpp_enc_check_frm_pkt(enc)) {
2387 mpp_stopwatch_record(stopwatch, "invalid on check frm pkt");
2388 reset_hal_enc_task(hal_task);
2389 ret = MPP_NOK;
2390 goto TASK_DONE;
2391 }
2392
2393 status->frm_pkt_rdy = 1;
2394 enc_dbg_detail("task frame packet ready\n");
2395 }
2396
2397 // 8. all task ready start encoding one frame
2398 if (!status->hal_task_reset_rdy) {
2399 reset_hal_enc_task(hal_task);
2400 reset_enc_rc_task(rc_task);
2401 task->usr = enc->frm_cfg;
2402 enc->frm_cfg.force_flag = 0;
2403
2404 hal_task->rc_task = rc_task;
2405 hal_task->frm_cfg = frm_cfg;
2406 hal_task->frame = enc->frame;
2407 hal_task->input = enc->frm_buf;
2408 hal_task->packet = enc->packet;
2409 hal_task->output = enc->pkt_buf;
2410 hal_task->md_info = enc->md_info;
2411 hal_task->stopwatch = stopwatch;
2412
2413 frm->seq_idx = task->seq_idx++;
2414 rc_task->frame = enc->frame;
2415 enc_dbg_detail("task seq idx %d start\n", frm->seq_idx);
2416 }
2417
2418 // 9. check frame drop by frame rate conversion
2419 if (!status->rc_check_frm_drop) {
2420 ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
2421 status->rc_check_frm_drop = 1;
2422 enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop);
2423
2424 hal_task->valid = 1;
2425 // when the frame should be dropped just return empty packet
2426 if (frm->drop) {
2427 mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
2428 hal_task->length = 0;
2429 hal_task->flags.drop_by_fps = 1;
2430 status->enc_start = 1;
2431 if (!status->refs_force_update) {
2432 if (frm_cfg->force_flag)
2433 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
2434
2435 status->refs_force_update = 1;
2436 }
2437 ret = MPP_OK;
2438 goto TASK_DONE;
2439 }
2440 }
2441
2442 // start encoder task process here
2443 mpp_assert(hal_task->valid);
2444
2445 // 10. check and create packet for output
2446 if (!status->pkt_buf_rdy) {
2447 mpp_enc_check_pkt_buf(enc);
2448 status->pkt_buf_rdy = 1;
2449
2450 hal_task->output = enc->pkt_buf;
2451 }
2452 mpp_assert(enc->packet);
2453 mpp_assert(enc->pkt_buf);
2454
2455 // 11. check hal info update
2456 if (!enc->hal_info_updated) {
2457 update_enc_hal_info(enc);
2458 enc->hal_info_updated = 1;
2459 }
2460
2461 // 12. generate header before hardware stream
2462 if (!hdr_status->ready) {
2463 /* config cpb before generating header */
2464 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
2465 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
2466 hdr_status->ready = 1;
2467
2468 enc_dbg_detail("task %d update header length %d\n",
2469 frm->seq_idx, enc->hdr_len);
2470
2471 mpp_packet_append(enc->packet, enc->hdr_pkt);
2472 hal_task->header_length = enc->hdr_len;
2473 hal_task->length += enc->hdr_len;
2474 hdr_status->added_by_change = 1;
2475 }
2476
2477 check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
2478
2479 // 13. check frm_meta data force key in input frame and start one frame
2480 if (!status->enc_start) {
2481 enc_dbg_detail("task %d enc start\n", frm->seq_idx);
2482 ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
2483 status->enc_start = 1;
2484 }
2485
2486 // 14. setup user_cfg to dpb
2487 if (!status->refs_force_update) {
2488 if (frm_cfg->force_flag)
2489 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
2490
2491 status->refs_force_update = 1;
2492 }
2493
2494 // 15. backup dpb
2495 if (!status->enc_backup) {
2496 mpp_enc_refs_stash(enc->refs);
2497 status->enc_backup = 1;
2498 }
2499
2500 TASK_DONE:
2501 if (ret)
2502 mpp_enc_terminate_task(enc, task);
2503 return ret;
2504 }
2505
try_proc_low_deley_task(Mpp * mpp,EncAsyncTaskInfo * task,EncAsyncWait * wait)2506 static MPP_RET try_proc_low_deley_task(Mpp *mpp, EncAsyncTaskInfo *task, EncAsyncWait *wait)
2507 {
2508 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2509 EncImpl impl = enc->impl;
2510 MppEncHal hal = enc->enc_hal;
2511 EncRcTask *rc_task = &task->rc;
2512 EncCpbStatus *cpb = &rc_task->cpb;
2513 EncFrmStatus *frm = &rc_task->frm;
2514 EncAsyncStatus *status = &task->status;
2515 HalEncTask *hal_task = &task->task;
2516 MppPacket packet = hal_task->packet;
2517 MPP_RET ret = MPP_OK;
2518
2519 if (hal_task->flags.drop_by_fps)
2520 goto TASK_DONE;
2521
2522 if (status->low_delay_again)
2523 goto GET_OUTPUT_TASK;
2524
2525 enc_dbg_detail("task %d check force pskip start\n", frm->seq_idx);
2526 if (!status->check_frm_pskip) {
2527 MppPskipMode skip_mode;
2528 status->check_frm_pskip = 1;
2529
2530 mpp_enc_get_pskip_mode((Mpp*)enc->mpp, task, &skip_mode);
2531 if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) {
2532 ret = mpp_enc_force_pskip((Mpp*)enc->mpp, task);
2533 if (ret)
2534 enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx);
2535 else
2536 goto TASK_DONE;
2537 }
2538 }
2539
2540 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
2541 mpp_enc_refs_get_cpb(enc->refs, cpb);
2542
2543 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
2544 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2545
2546 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2547 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2548
2549 // 16. generate header before hardware stream
2550 mpp_enc_add_sw_header(enc, hal_task);
2551
2552 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2553 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2554
2555 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2556 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2557
2558 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2559 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2560
2561 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2562 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2563
2564 hal_task->part_first = 0;
2565 hal_task->part_last = 0;
2566
2567 do {
2568 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2569 ENC_RUN_FUNC2(mpp_enc_hal_part_start, hal, hal_task, mpp, ret);
2570
2571 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2572 ENC_RUN_FUNC2(mpp_enc_hal_part_wait, hal, hal_task, mpp, ret);
2573
2574 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2575 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2576
2577 if (hal_task->part_first) {
2578 hal_task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2579 hal_task->part_length = 0;
2580 }
2581
2582 mpp_packet_set_length(packet, hal_task->length);
2583
2584 enc_dbg_detail("task %d task_out %p\n", frm->seq_idx, enc->task_out);
2585
2586 GET_OUTPUT_TASK:
2587 /* output task as soon as */
2588 if (NULL == enc->task_out) {
2589 enc_dbg_detail("task %d poll new task for part output\n", frm->seq_idx);
2590 ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
2591 if (ret < 0) {
2592 wait->enc_pkt_out = 1;
2593 status->low_delay_again = 1;
2594 return MPP_NOK;
2595 }
2596
2597 status->task_out_rdy = 1;
2598 wait->enc_pkt_out = 0;
2599 enc_dbg_detail("task out ready\n");
2600
2601 ret = mpp_port_dequeue(enc->output, &enc->task_out);
2602 }
2603
2604 mpp_assert(enc->task_out);
2605
2606 /* copy new packet for multiple packet output */
2607 if (!hal_task->part_last) {
2608 RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2609 RK_U32 part_length = hal_task->length;
2610 RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2611 RK_U32 pkt_len = 0;
2612 MppPacketImpl *part_pkt = NULL;
2613
2614 enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2615 last_pos, part_pos, part_length);
2616
2617 part_pos += part_length;
2618 pkt_len = (RK_U32)(part_pos - last_pos);
2619
2620 mpp_packet_copy_init((MppPacket *)&part_pkt, packet);
2621 part_pkt->pos = last_pos;
2622 part_pkt->length = pkt_len;
2623 part_pkt->status.val = 0;
2624 part_pkt->status.partition = 1;
2625 part_pkt->status.soi = hal_task->part_first;
2626 part_pkt->status.eoi = hal_task->part_last;
2627
2628 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2629 last_pos, pkt_len);
2630
2631 hal_task->part_pos = part_pos;
2632
2633 enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2634 frm->seq_idx, enc->task_pts, hal_task->part_count);
2635 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, part_pkt);
2636 mpp_port_enqueue(enc->output, enc->task_out);
2637 enc->task_out = NULL;
2638 hal_task->part_count++;
2639 }
2640 } while (!hal_task->part_last);
2641
2642 TASK_DONE:
2643 /* output last task */
2644 {
2645 RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2646 size_t part_length = hal_task->length;
2647 RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2648 RK_U32 pkt_len = 0;
2649 MppPacketImpl *pkt = (MppPacketImpl *)packet;
2650
2651 enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2652 last_pos, part_pos, part_length);
2653
2654 part_pos += part_length;
2655 pkt_len = part_pos - last_pos;
2656
2657 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2658 last_pos, pkt_len);
2659
2660 pkt->length = pkt_len;
2661 pkt->pos = last_pos;
2662 pkt->status.val = 0;
2663 pkt->status.partition = 1;
2664 pkt->status.soi = hal_task->part_first;
2665 pkt->status.eoi = hal_task->part_last;
2666
2667 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2668 last_pos, pkt_len);
2669
2670 hal_task->part_pos = part_pos;
2671
2672 enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2673 frm->seq_idx, enc->task_pts, hal_task->part_count);
2674 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2675 mpp_port_enqueue(enc->output, enc->task_out);
2676 enc->task_out = NULL;
2677 hal_task->part_count = 0;
2678 }
2679 status->low_delay_again = 0;
2680
2681 enc->time_end = mpp_time();
2682 enc->frame_count++;
2683
2684 if (enc->dev && enc->time_base && enc->time_end &&
2685 ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2686 update_hal_info_fps(enc);
2687
2688 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2689 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2690
2691 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2692
2693 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2694 mpp_port_enqueue(enc->input, enc->task_in);
2695
2696 reset_enc_task(enc);
2697 status->val = 0;
2698 task->usr.force_flag = 0;
2699
2700 return ret;
2701 }
2702
set_enc_info_to_packet(MppEncImpl * enc,HalEncTask * hal_task)2703 static MPP_RET set_enc_info_to_packet(MppEncImpl *enc, HalEncTask *hal_task)
2704 {
2705 Mpp *mpp = (Mpp*)enc->mpp;
2706 EncRcTask *rc_task = hal_task->rc_task;
2707 EncFrmStatus *frm = &rc_task->frm;
2708 MppPacket packet = hal_task->packet;
2709 MppMeta meta = mpp_packet_get_meta(packet);
2710
2711 if (!meta) {
2712 mpp_err_f("failed to get meta from packet\n");
2713 return MPP_NOK;
2714 }
2715
2716 if (enc->coding == MPP_VIDEO_CodingHEVC || enc->coding == MPP_VIDEO_CodingAVC) {
2717 RK_U32 is_pskip = !(rc_task->info.lvl64_inter_num ||
2718 rc_task->info.lvl32_inter_num ||
2719 rc_task->info.lvl16_inter_num ||
2720 rc_task->info.lvl8_inter_num ||
2721 rc_task->info.lvl32_intra_num ||
2722 rc_task->info.lvl16_intra_num ||
2723 rc_task->info.lvl8_intra_num ||
2724 rc_task->info.lvl4_intra_num);
2725
2726 /* num of inter different size predicted block */
2727 mpp_meta_set_s32(meta, KEY_LVL64_INTER_NUM, rc_task->info.lvl64_inter_num);
2728 mpp_meta_set_s32(meta, KEY_LVL32_INTER_NUM, rc_task->info.lvl32_inter_num);
2729 mpp_meta_set_s32(meta, KEY_LVL16_INTER_NUM, rc_task->info.lvl16_inter_num);
2730 mpp_meta_set_s32(meta, KEY_LVL8_INTER_NUM, rc_task->info.lvl8_inter_num);
2731 /* num of intra different size predicted block */
2732 mpp_meta_set_s32(meta, KEY_LVL32_INTRA_NUM, rc_task->info.lvl32_intra_num);
2733 mpp_meta_set_s32(meta, KEY_LVL16_INTRA_NUM, rc_task->info.lvl16_intra_num);
2734 mpp_meta_set_s32(meta, KEY_LVL8_INTRA_NUM, rc_task->info.lvl8_intra_num);
2735 mpp_meta_set_s32(meta, KEY_LVL4_INTRA_NUM, rc_task->info.lvl4_intra_num);
2736
2737 mpp_meta_set_s64(meta, KEY_ENC_SSE, rc_task->info.sse);
2738 mpp_meta_set_s32(meta, KEY_OUTPUT_PSKIP, frm->force_pskip || is_pskip);
2739 mpp_meta_set_s32(meta, KEY_ENC_BPS_RT, rc_task->info.rt_bits);
2740
2741 if (rc_task->info.frame_type == INTER_VI_FRAME)
2742 mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, rc_task->cpb.refr.lt_idx);
2743 }
2744 /* frame type */
2745 mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra);
2746
2747 /* start qp and average qp */
2748 mpp_meta_set_s32(meta, KEY_ENC_START_QP, rc_task->info.quality_target);
2749 mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real);
2750
2751 if (hal_task->md_info)
2752 mpp_meta_set_buffer(meta, KEY_MOTION_INFO, hal_task->md_info);
2753
2754 if (mpp->mEncAyncIo)
2755 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, hal_task->frame);
2756
2757 return MPP_OK;
2758 }
2759
try_proc_normal_task(MppEncImpl * enc,EncAsyncTaskInfo * task)2760 static MPP_RET try_proc_normal_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
2761 {
2762 Mpp *mpp = (Mpp*)enc->mpp;
2763 EncRcTask *rc_task = &task->rc;
2764 EncFrmStatus *frm = &rc_task->frm;
2765 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
2766 HalEncTask *hal_task = &task->task;
2767 MppPacket packet = hal_task->packet;
2768 MPP_RET ret = MPP_OK;
2769
2770 if (hal_task->flags.drop_by_fps)
2771 goto TASK_DONE;
2772
2773 // 17. normal encode
2774 ENC_RUN_FUNC2(mpp_enc_normal, mpp, task, mpp, ret);
2775
2776 // 18. drop, force pskip and reencode process
2777 while (frm->reencode && frm->reencode_times < enc->cfg->rc.max_reenc_times) {
2778 hal_task->length -= hal_task->hw_length;
2779 hal_task->hw_length = 0;
2780
2781 mpp_packet_set_segment_nb(hal_task->packet, hal_task->segment_nb);
2782
2783 enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
2784
2785 if (frm->drop) {
2786 mpp_enc_reenc_drop(mpp, task);
2787 break;
2788 }
2789
2790 if (frm->force_pskip && !frm->is_idr && !frm->is_lt_ref) {
2791 mpp_enc_reenc_force_pskip(mpp, task);
2792 break;
2793 }
2794 frm->force_pskip = 0;
2795 mpp_enc_reenc_simple(mpp, task);
2796 }
2797 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2798 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2799
2800 enc->time_end = mpp_time();
2801 enc->frame_count++;
2802
2803 if (enc->dev && enc->time_base && enc->time_end &&
2804 ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2805 update_hal_info_fps(enc);
2806
2807 frm->reencode = 0;
2808 frm->reencode_times = 0;
2809 frm_cfg->force_flag = 0;
2810
2811 TASK_DONE:
2812 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2813
2814 if (!mpp_packet_is_partition(packet)) {
2815 /* setup output packet and meta data */
2816 mpp_packet_set_length(packet, hal_task->length);
2817 }
2818
2819 /* enc failed force idr */
2820 if (ret) {
2821 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2822 enc->hdr_status.val = 0;
2823 mpp_packet_set_length(packet, 0);
2824 mpp_err_f("enc failed force idr!\n");
2825 } else
2826 set_enc_info_to_packet(enc, hal_task);
2827 /*
2828 * First return output packet.
2829 * Then enqueue task back to input port.
2830 * Final user will release the mpp_frame they had input.
2831 */
2832 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2833
2834 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2835 mpp_port_enqueue(enc->output, enc->task_out);
2836
2837 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2838
2839 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2840 mpp_port_enqueue(enc->input, enc->task_in);
2841
2842 mpp_enc_rc_info_backup(enc, task);
2843 reset_enc_task(enc);
2844 task->status.val = 0;
2845
2846 return ret;
2847 }
2848
mpp_enc_thread(void * data)2849 void *mpp_enc_thread(void *data)
2850 {
2851 Mpp *mpp = (Mpp*)data;
2852 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2853 MppThread *thd_enc = enc->thread_enc;
2854 EncAsyncTaskInfo task;
2855 EncAsyncWait wait;
2856 EncAsyncStatus *status = &task.status;
2857 MPP_RET ret = MPP_OK;
2858
2859 memset(&task, 0, sizeof(task));
2860 wait.val = 0;
2861
2862 enc->time_base = mpp_time();
2863
2864 while (1) {
2865 mpp_thread_lock(thd_enc, THREAD_WORK);
2866
2867 if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_enc, THREAD_WORK)) {
2868 mpp_thread_unlock(thd_enc, THREAD_WORK);
2869 break;
2870 }
2871
2872 if (check_enc_task_wait(enc, &wait))
2873 mpp_thread_wait(thd_enc, THREAD_WORK);
2874
2875 mpp_thread_unlock(thd_enc, THREAD_WORK);
2876
2877 // When encoder is not on encoding process external config and reset
2878 if (!status->enc_start) {
2879 // 1. process user control
2880 if (enc->cmd_send != enc->cmd_recv) {
2881 enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
2882 sem_wait(&enc->cmd_start);
2883 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
2884 if (ret)
2885 *enc->cmd_ret = ret;
2886 enc->cmd_recv++;
2887 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
2888 enc->cmd_send);
2889 mpp_assert(enc->cmd_send == enc->cmd_send);
2890 enc->param = NULL;
2891 enc->cmd = (MpiCmd)0;
2892 sem_post(&enc->cmd_done);
2893
2894 // async cfg update process for hal
2895 // mainly for buffer prepare
2896 mpp_enc_hal_prepare(enc->enc_hal);
2897
2898 /* NOTE: here will clear change flag of rc and prep cfg */
2899 mpp_enc_proc_rc_update(enc);
2900 wait.val = 0;
2901 continue;
2902 }
2903
2904 // 2. process reset
2905 if (enc->reset_flag) {
2906 enc_dbg_detail("thread reset start\n");
2907
2908 mpp_thread_lock(thd_enc, THREAD_WORK);
2909 enc->status_flag = 0;
2910 mpp_thread_unlock(thd_enc, THREAD_WORK);
2911
2912 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2913 enc->frm_cfg.force_idr++;
2914
2915 mpp_thread_lock(thd_enc, THREAD_CONTROL);
2916 enc->reset_flag = 0;
2917 sem_post(&enc->enc_reset);
2918 enc_dbg_detail("thread reset done\n");
2919 wait.val = 0;
2920 mpp_thread_unlock(thd_enc, THREAD_CONTROL);
2921 continue;
2922 }
2923
2924 // 3. try get a task to encode
2925 ret = try_get_enc_task(enc, &task, &wait);
2926 if (ret)
2927 continue;
2928 }
2929
2930 mpp_assert(status->enc_start);
2931 if (!status->enc_start)
2932 continue;
2933
2934 // check partition low delay encoding
2935 /*
2936 * NOTE: Only when both split encoding and low delay mode are set then
2937 * use special low delay path
2938 */
2939 if (enc->low_delay_part_mode)
2940 try_proc_low_deley_task(mpp, &task, &wait);
2941 else
2942 try_proc_normal_task(enc, &task);
2943 }
2944
2945 // clear remain task in enc->output port
2946 release_task_in_port(enc->input);
2947 release_task_in_port(mpp->mUsrOutPort);
2948
2949 return NULL;
2950 }
2951
async_task_reset(EncAsyncTaskInfo * task)2952 static void async_task_reset(EncAsyncTaskInfo *task)
2953 {
2954 memset(task, 0, sizeof(*task));
2955 task->task.rc_task = &task->rc;
2956 task->task.frm_cfg = &task->usr;
2957 task->usr.force_flag = 0;
2958 }
2959
async_task_terminate(MppEncImpl * enc,EncAsyncTaskInfo * async)2960 static void async_task_terminate(MppEncImpl *enc, EncAsyncTaskInfo *async)
2961 {
2962 HalEncTask *hal_task = &async->task;
2963 EncFrmStatus *frm = &async->rc.frm;
2964 Mpp *mpp = (Mpp *)enc->mpp;
2965
2966 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2967
2968 if (hal_task->packet) {
2969 MppPacket pkt = hal_task->packet;
2970
2971 /* setup output packet and meta data */
2972 mpp_packet_set_length(pkt, hal_task->length);
2973
2974 /*
2975 * First return output packet.
2976 * Then enqueue task back to input port.
2977 * Final user will release the mpp_frame they had input.
2978 */
2979 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2980
2981 if (mpp->mPktOut) {
2982 MppList *pkt_out = mpp->mPktOut;
2983
2984 if (enc->frame) {
2985 MppMeta meta = mpp_packet_get_meta(pkt);
2986 MppStopwatch stopwatch = mpp_frame_get_stopwatch(enc->frame);
2987
2988 mpp_stopwatch_record(stopwatch, "encode task terminate");
2989
2990 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame);
2991 enc->frame = NULL;
2992 }
2993
2994 mpp_mutex_cond_lock(&pkt_out->cond_lock);
2995
2996 mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt));
2997 mpp->mPacketPutCount++;
2998 mpp_list_signal(pkt_out);
2999 mpp_assert(pkt);
3000
3001 mpp_mutex_cond_unlock(&pkt_out->cond_lock);
3002 enc_dbg_detail("packet out ready\n");
3003 }
3004 }
3005
3006 async_task_reset(async);
3007 }
3008
async_task_skip(MppEncImpl * enc)3009 static void async_task_skip(MppEncImpl *enc)
3010 {
3011 Mpp *mpp = (Mpp*)enc->mpp;
3012 MppStopwatch stopwatch = NULL;
3013 MppMeta meta = NULL;
3014 MppFrame frm = NULL;
3015 MppPacket pkt = NULL;
3016
3017 mpp_list_del_at_head(mpp->mFrmIn, &frm, sizeof(frm));
3018 mpp->mFrameGetCount++;
3019
3020 mpp_assert(frm);
3021
3022 enc_dbg_detail("skip input frame start\n");
3023
3024 stopwatch = mpp_frame_get_stopwatch(frm);
3025 mpp_stopwatch_record(stopwatch, "skip task start");
3026
3027 if (mpp_frame_has_meta(frm)) {
3028 meta = mpp_frame_get_meta(frm);
3029 if (meta)
3030 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &pkt);
3031 }
3032
3033 if (NULL == pkt)
3034 mpp_packet_new(&pkt);
3035
3036 mpp_assert(pkt);
3037
3038 mpp_packet_set_length(pkt, 0);
3039 mpp_packet_set_pts(pkt, mpp_frame_get_pts(frm));
3040 mpp_packet_set_dts(pkt, mpp_frame_get_dts(frm));
3041
3042 if (mpp_frame_get_eos(frm))
3043 mpp_packet_set_eos(pkt);
3044 else
3045 mpp_packet_clr_eos(pkt);
3046
3047 meta = mpp_packet_get_meta(pkt);
3048 mpp_assert(meta);
3049
3050 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, frm);
3051
3052 if (mpp->mPktOut) {
3053 MppList *pkt_out = mpp->mPktOut;
3054
3055 mpp_mutex_cond_lock(&pkt_out->cond_lock);
3056 mpp_stopwatch_record(stopwatch, "skip task output");
3057 mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt));
3058 mpp->mPacketPutCount++;
3059 mpp_list_signal(pkt_out);
3060 mpp_mutex_cond_unlock(&pkt_out->cond_lock);
3061 }
3062
3063 enc_dbg_detail("packet skip ready\n");
3064 }
3065
check_async_frm_pkt(EncAsyncTaskInfo * async)3066 static MPP_RET check_async_frm_pkt(EncAsyncTaskInfo *async)
3067 {
3068 HalEncTask *hal_task = &async->task;
3069 MppPacket packet = hal_task->packet;
3070 MppFrame frame = hal_task->frame;
3071
3072 hal_task->input = NULL;
3073 hal_task->output = NULL;
3074
3075 if (packet)
3076 hal_task->output = mpp_packet_get_buffer(packet);
3077 else {
3078 mpp_packet_new(&packet);
3079 hal_task->packet = packet;
3080 }
3081
3082 if (frame) {
3083 RK_S64 pts = mpp_frame_get_pts(frame);
3084 MppBuffer frm_buf = mpp_frame_get_buffer(frame);
3085
3086 hal_task->input = frm_buf;
3087
3088 mpp_packet_set_pts(packet, pts);
3089 mpp_packet_set_dts(packet, mpp_frame_get_dts(frame));
3090
3091 if (mpp_frame_get_eos(frame))
3092 mpp_packet_set_eos(packet);
3093 else
3094 mpp_packet_clr_eos(packet);
3095 }
3096
3097 return (NULL == frame || NULL == hal_task->input) ? MPP_NOK : MPP_OK;
3098 }
3099
check_async_pkt_buf(MppEncImpl * enc,EncAsyncTaskInfo * async)3100 static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTaskInfo *async)
3101 {
3102 HalEncTask *hal_task = &async->task;
3103
3104 if (NULL == hal_task->output) {
3105 /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
3106 Mpp *mpp = (Mpp *)enc->mpp;
3107 MppEncPrepCfg *prep = &enc->cfg->prep;
3108 RK_U32 width = MPP_ALIGN(prep->width, 16);
3109 RK_U32 height = MPP_ALIGN(prep->height, 16);
3110 RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
3111 (width * height * 3 / 2) : (width * height);
3112 MppPacketImpl *pkt = (MppPacketImpl *)hal_task->packet;
3113 MppBuffer buffer = NULL;
3114
3115 mpp_assert(size);
3116 mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
3117 mpp_buffer_attach_dev(buffer, enc->dev);
3118 mpp_assert(buffer);
3119 enc->pkt_buf = buffer;
3120 pkt->data = mpp_buffer_get_ptr(buffer);
3121 pkt->pos = pkt->data;
3122 pkt->size = mpp_buffer_get_size(buffer);
3123 pkt->length = 0;
3124 pkt->buffer = buffer;
3125 hal_task->output = buffer;
3126
3127 enc_dbg_detail("create output pkt %p buf %p\n", hal_task->packet, buffer);
3128 } else {
3129 enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
3130 hal_task->packet, hal_task->output,
3131 mpp_packet_get_pos(hal_task->packet),
3132 mpp_packet_get_length(hal_task->packet));
3133 }
3134
3135 return MPP_OK;
3136 }
3137
try_get_async_task(MppEncImpl * enc,EncAsyncWait * wait)3138 static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncWait *wait)
3139 {
3140 Mpp *mpp = (Mpp *)enc->mpp;
3141 EncAsyncTaskInfo *async = enc->async;
3142 EncRcTask *rc_task = NULL;
3143 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
3144 HalEncTask *hal_task = NULL;
3145 EncAsyncStatus *status = NULL;
3146 MppStopwatch stopwatch = NULL;
3147 MppPacket packet = NULL;
3148 MppFrame frame = NULL;
3149 RK_U32 seq_idx = 0;
3150 MPP_RET ret = MPP_OK;
3151
3152 if (NULL == enc->hnd) {
3153 hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd);
3154 if (enc->hnd) {
3155 wait->task_hnd = 0;
3156 enc_dbg_detail("get hnd success\n");
3157
3158 mpp_assert(enc->async == NULL);
3159 async = (EncAsyncTaskInfo *)hal_task_hnd_get_data(enc->hnd);
3160 async_task_reset(async);
3161 enc->async = async;
3162 } else {
3163 wait->task_hnd = 1;
3164 enc_dbg_detail("get hnd failed\n");
3165 return MPP_NOK;
3166 }
3167 }
3168
3169 mpp_assert(enc->hnd);
3170 mpp_assert(enc->async);
3171
3172 hal_task = &async->task;
3173 rc_task = &async->rc;
3174 status = &async->status;
3175 packet = hal_task->packet;
3176 frame = hal_task->frame;
3177
3178 if (NULL == frame) {
3179 if (mpp->mFrmIn) {
3180 MppList *frm_in = mpp->mFrmIn;
3181
3182 mpp_mutex_cond_lock(&frm_in->cond_lock);
3183
3184 if (mpp_list_size(frm_in)) {
3185 mpp_list_del_at_head(frm_in, &frame, sizeof(frame));
3186 mpp_list_signal(frm_in);
3187
3188 mpp->mFrameGetCount++;
3189
3190 mpp_assert(frame);
3191
3192 status->task_in_rdy = 1;
3193 wait->enc_frm_in = 0;
3194
3195 enc_dbg_detail("get input frame success\n");
3196
3197 stopwatch = mpp_frame_get_stopwatch(frame);
3198 mpp_stopwatch_record(stopwatch, "encode task start");
3199
3200 hal_task->frame = frame;
3201 }
3202
3203 mpp_mutex_cond_unlock(&frm_in->cond_lock);
3204 }
3205
3206 if (NULL == frame) {
3207 enc_dbg_detail("get input frame failed\n");
3208 wait->enc_frm_in = 1;
3209 return MPP_NOK;
3210 }
3211 }
3212
3213 if (NULL == packet) {
3214 if (mpp_frame_has_meta(frame)) {
3215 MppMeta meta = mpp_frame_get_meta(frame);
3216
3217 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet);
3218 }
3219
3220 if (packet) {
3221 status->task_out_rdy = 1;
3222 wait->enc_pkt_out = 0;
3223
3224 enc_dbg_detail("get output packet success\n");
3225
3226 hal_task->packet = packet;
3227 }
3228 }
3229
3230 mpp_assert(frame);
3231
3232 stopwatch = mpp_frame_get_stopwatch(frame);
3233
3234 /*
3235 * 6. get frame and packet for one task
3236 * If there is no input frame just return empty packet task
3237 */
3238 if (!status->frm_pkt_rdy) {
3239 async->seq_idx = enc->task_idx++;
3240 async->pts = mpp_frame_get_pts(hal_task->frame);
3241
3242 hal_task->stopwatch = stopwatch;
3243 rc_task->frame = async->task.frame;
3244
3245 enc_dbg_detail("task seq idx %d start\n", seq_idx);
3246
3247 if (check_async_frm_pkt(async)) {
3248 mpp_stopwatch_record(stopwatch, "empty frame on check frm pkt");
3249 hal_task->valid = 1;
3250 hal_task->length = 0;
3251 hal_task->flags.drop_by_fps = 1;
3252 ret = MPP_OK;
3253 goto TASK_DONE;
3254 }
3255
3256 status->frm_pkt_rdy = 1;
3257 enc_dbg_detail("task frame packet ready\n");
3258 }
3259
3260 seq_idx = async->seq_idx;
3261
3262 // 9. check frame drop by frame rate conversion
3263 if (!status->rc_check_frm_drop) {
3264 EncFrmStatus *frm = &rc_task->frm;
3265
3266 ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
3267 status->rc_check_frm_drop = 1;
3268 enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop);
3269
3270 // when the frame should be dropped just return empty packet
3271 hal_task->valid = 1;
3272 if (frm->drop) {
3273 mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
3274 hal_task->length = 0;
3275 hal_task->flags.drop_by_fps = 1;
3276 ret = MPP_OK;
3277 goto TASK_DONE;
3278 }
3279
3280 *hal_task->frm_cfg = enc->frm_cfg;
3281 enc->frm_cfg.force_flag = 0;
3282 }
3283
3284 // start encoder task process here
3285 mpp_assert(hal_task->valid);
3286
3287 // 10. check and create packet for output
3288 if (!status->pkt_buf_rdy) {
3289 check_async_pkt_buf(enc, async);
3290 status->pkt_buf_rdy = 1;
3291
3292 enc_dbg_detail("task %d check pkt buffer success\n", seq_idx);
3293 }
3294 mpp_assert(hal_task->packet);
3295 mpp_assert(hal_task->output);
3296
3297 // 11. check hal info update
3298 if (!enc->hal_info_updated) {
3299 update_enc_hal_info(enc);
3300 enc->hal_info_updated = 1;
3301
3302 enc_dbg_detail("task %d update enc hal info success\n", seq_idx);
3303 }
3304
3305 // 12. generate header before hardware stream
3306 if (!hdr_status->ready) {
3307 /* config cpb before generating header */
3308 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
3309 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
3310 hdr_status->ready = 1;
3311
3312 enc_dbg_detail("task %d update header length %d\n",
3313 seq_idx, enc->hdr_len);
3314
3315 mpp_packet_append(hal_task->packet, enc->hdr_pkt);
3316 hal_task->header_length = enc->hdr_len;
3317 hal_task->length += enc->hdr_len;
3318 hdr_status->added_by_change = 1;
3319 }
3320
3321 check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
3322
3323 // 13. check frm_meta data force key in input frame and start one frame
3324 if (!status->enc_start) {
3325 enc_dbg_detail("task %d enc start\n", seq_idx);
3326 ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
3327 status->enc_start = 1;
3328 }
3329
3330 // 14. setup user_cfg to dpb
3331 if (!status->refs_force_update) {
3332 MppEncRefFrmUsrCfg *frm_cfg = &async->usr;
3333
3334 if (frm_cfg->force_flag) {
3335 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
3336 frm_cfg->force_flag = 0;
3337 }
3338
3339 enc_dbg_detail("task %d refs force update success\n", seq_idx);
3340 status->refs_force_update = 1;
3341 }
3342
3343 // 15. backup dpb
3344 if (!status->enc_backup) {
3345 mpp_enc_refs_stash(enc->refs);
3346 enc_dbg_detail("task %d refs stash success\n", seq_idx);
3347 status->enc_backup = 1;
3348 }
3349
3350 TASK_DONE:
3351 if (ret) {
3352 enc_dbg_detail("task %d terminate\n", seq_idx);
3353 async_task_terminate(enc, async);
3354 }
3355
3356 return ret;
3357 }
3358
try_proc_processing_task(MppEncImpl * enc,EncAsyncWait * wait)3359 static MPP_RET try_proc_processing_task(MppEncImpl *enc, EncAsyncWait *wait)
3360 {
3361 HalTaskHnd hnd = NULL;
3362 EncAsyncTaskInfo *info = NULL;
3363 MPP_RET ret = MPP_NOK;
3364
3365 ret = hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd);
3366 if (ret)
3367 return ret;
3368
3369 info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
3370
3371 mpp_assert(!info->status.enc_done);
3372
3373 enc_async_wait_task(enc, info);
3374 hal_task_hnd_set_status(hnd, TASK_IDLE);
3375 wait->task_hnd = 0;
3376
3377 return MPP_OK;
3378 }
3379
proc_async_task(MppEncImpl * enc,EncAsyncWait * wait)3380 static MPP_RET proc_async_task(MppEncImpl *enc, EncAsyncWait *wait)
3381 {
3382 Mpp *mpp = (Mpp*)enc->mpp;
3383 EncImpl impl = enc->impl;
3384 MppEncHal hal = enc->enc_hal;
3385 EncAsyncTaskInfo *async = enc->async;
3386 EncAsyncStatus *status = &async->status;
3387 HalEncTask *hal_task = &async->task;
3388 EncRcTask *rc_task = hal_task->rc_task;
3389 EncCpbStatus *cpb = &rc_task->cpb;
3390 EncFrmStatus *frm = &rc_task->frm;
3391 RK_U32 seq_idx = async->seq_idx;
3392 MPP_RET ret = MPP_OK;
3393
3394 mpp_assert(hal_task->valid);
3395
3396 if (hal_task->flags.drop_by_fps)
3397 goto SEND_TASK_INFO;
3398
3399 if (!status->check_frm_pskip) {
3400 MppPskipMode skip_mode;
3401 status->check_frm_pskip = 1;
3402
3403 mpp_enc_get_pskip_mode((Mpp*)enc->mpp, async, &skip_mode);
3404 if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) {
3405 ret = mpp_enc_force_pskip((Mpp*)enc->mpp, async);
3406 if (ret)
3407 enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx);
3408 else
3409 goto SEND_TASK_INFO;
3410 }
3411 }
3412
3413 if (enc->support_hw_deflicker && enc->cfg->rc.debreath_en) {
3414 bool two_pass_en = mpp_enc_refs_next_frm_is_intra(enc->refs);
3415
3416 if (two_pass_en) {
3417 /* wait all tasks done */
3418 while (MPP_OK == try_proc_processing_task(enc, wait));
3419
3420 ret = mpp_enc_proc_two_pass(mpp, async);
3421 if (ret)
3422 return ret;
3423 }
3424 }
3425
3426 enc_dbg_detail("task %d enc proc dpb\n", seq_idx);
3427 mpp_enc_refs_get_cpb(enc->refs, cpb);
3428
3429 enc_dbg_frm_status("frm %d start ***********************************\n", seq_idx);
3430 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
3431
3432 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
3433 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
3434
3435 // 16. generate header before hardware stream
3436 mpp_enc_add_sw_header(enc, hal_task);
3437
3438 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
3439 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
3440
3441 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
3442 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
3443
3444 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
3445 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
3446
3447 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
3448 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
3449
3450 mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
3451 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
3452 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
3453
3454 SEND_TASK_INFO:
3455 status->enc_done = 0;
3456 hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING);
3457 enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret);
3458
3459 enc->hnd = NULL;
3460 enc->async = NULL;
3461
3462 TASK_DONE:
3463
3464 /* NOTE: clear add_by flags */
3465 enc->hdr_status.val = enc->hdr_status.ready;
3466
3467 return ret;
3468 }
3469
check_enc_async_wait(MppEncImpl * enc,EncAsyncWait * wait)3470 static MPP_RET check_enc_async_wait(MppEncImpl *enc, EncAsyncWait *wait)
3471 {
3472 MPP_RET ret = MPP_OK;
3473 RK_U32 notify = enc->notify_flag;
3474 RK_U32 last_wait = enc->status_flag;
3475 RK_U32 curr_wait = wait->val;
3476 RK_U32 wait_chg = last_wait & (~curr_wait);
3477 RK_U32 keep_notify = 0;
3478
3479 do {
3480 if (enc->reset_flag)
3481 break;
3482
3483 // NOTE: User control should always be processed
3484 if (notify & MPP_ENC_CONTROL) {
3485 keep_notify = notify & (~MPP_ENC_CONTROL);
3486 break;
3487 }
3488
3489 // NOTE: When condition is not fulfilled check nofify flag again
3490 if (!curr_wait || (curr_wait & notify))
3491 break;
3492
3493 ret = MPP_NOK;
3494 } while (0);
3495
3496 enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
3497 last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
3498
3499 enc->status_flag = wait->val;
3500 enc->notify_flag = keep_notify;
3501
3502 if (ret) {
3503 enc->wait_count++;
3504 } else {
3505 enc->work_count++;
3506 }
3507
3508 return ret;
3509 }
3510
enc_async_wait_task(MppEncImpl * enc,EncAsyncTaskInfo * info)3511 static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info)
3512 {
3513 Mpp *mpp = (Mpp*)enc->mpp;
3514 MppEncHal hal = enc->enc_hal;
3515 HalEncTask *hal_task = &info->task;
3516 EncRcTask *rc_task = hal_task->rc_task;
3517 EncFrmStatus *frm = &info->rc.frm;
3518 MppPacket pkt = hal_task->packet;
3519 MPP_RET ret = MPP_OK;
3520
3521 if (hal_task->flags.drop_by_fps || hal_task->frm_cfg->force_pskip)
3522 goto TASK_DONE;
3523
3524 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
3525 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
3526
3527 mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
3528
3529 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
3530 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
3531
3532 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
3533 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
3534
3535 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
3536 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
3537
3538 TASK_DONE:
3539 if (!mpp_packet_is_partition(pkt)) {
3540 /* setup output packet and meta data */
3541 mpp_packet_set_length(pkt, hal_task->length);
3542
3543 check_hal_task_pkt_len(hal_task, "hw finish");
3544 }
3545
3546 enc_dbg_detail("task %d output packet pts %lld\n", info->seq_idx, info->pts);
3547
3548 /*
3549 * async encode process, there may have multiple frames encoding.
3550 * if last frame enc failed, drop non-idr frames and force idr for next frame.
3551 */
3552 if (enc->enc_failed_drop && !hal_task->rc_task->frm.is_idr) {
3553 mpp_packet_set_length(pkt, 0);
3554 mpp_err_f("last frame enc failed, drop this P frame\n");
3555 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
3556 enc->hdr_status.val = 0;
3557 } else
3558 enc->enc_failed_drop = 0;
3559 /* enc failed, force idr for next frame */
3560 if (ret) {
3561 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
3562 enc->hdr_status.val = 0;
3563 mpp_packet_set_length(pkt, 0);
3564 enc->enc_failed_drop = 1;
3565
3566 mpp_err_f("enc failed force idr!\n");
3567 } else
3568 set_enc_info_to_packet(enc, hal_task);
3569
3570 if (mpp->mPktOut) {
3571 MppList *pkt_out = mpp->mPktOut;
3572
3573 mpp_mutex_cond_lock(&pkt_out->cond_lock);
3574
3575 mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt));
3576 mpp->mPacketPutCount++;
3577 mpp_list_signal(pkt_out);
3578
3579 mpp_mutex_cond_unlock(&pkt_out->cond_lock);
3580 }
3581
3582 return ret;
3583 }
3584
mpp_enc_async_thread(void * data)3585 void *mpp_enc_async_thread(void *data)
3586 {
3587 Mpp *mpp = (Mpp*)data;
3588 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
3589 MppThread *thd_enc = enc->thread_enc;
3590 EncAsyncWait wait;
3591 MPP_RET ret = MPP_OK;
3592
3593 enc_dbg_func("thread start\n");
3594
3595 wait.val = 0;
3596
3597 while (1) {
3598 mpp_thread_lock(thd_enc, THREAD_WORK);
3599 if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_enc, THREAD_WORK)) {
3600 mpp_thread_unlock(thd_enc, THREAD_WORK);
3601 break;
3602 }
3603
3604 if (check_enc_async_wait(enc, &wait)) {
3605 enc_dbg_detail("wait start\n");
3606 mpp_thread_wait(thd_enc, THREAD_WORK);
3607 enc_dbg_detail("wait done\n");
3608 }
3609 mpp_thread_unlock(thd_enc, THREAD_WORK);
3610
3611 // When encoder is not on encoding process external config and reset
3612 // 1. process user control and reset flag
3613 if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) {
3614 MppList *frm_in = mpp->mFrmIn;
3615
3616 /* when process cmd or reset hold frame input */
3617 mpp_mutex_cond_lock(&frm_in->cond_lock);
3618
3619 enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
3620
3621 // wait all tasks done
3622 while (MPP_OK == try_proc_processing_task(enc, &wait));
3623
3624 if (enc->cmd_send != enc->cmd_recv) {
3625 sem_wait(&enc->cmd_start);
3626 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
3627 if (ret)
3628 *enc->cmd_ret = ret;
3629 enc->cmd_recv++;
3630 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
3631 enc->cmd_send);
3632 mpp_assert(enc->cmd_send == enc->cmd_send);
3633 enc->param = NULL;
3634 enc->cmd = (MpiCmd)0;
3635 sem_post(&enc->cmd_done);
3636
3637 // async cfg update process for hal
3638 // mainly for buffer prepare
3639 mpp_enc_hal_prepare(enc->enc_hal);
3640
3641 /* NOTE: here will clear change flag of rc and prep cfg */
3642 mpp_enc_proc_rc_update(enc);
3643 goto SYNC_DONE;
3644 }
3645
3646 if (enc->reset_flag) {
3647 enc_dbg_detail("thread reset start\n");
3648
3649 /* skip the frames in input queue */
3650 while (mpp_list_size(frm_in))
3651 async_task_skip(enc);
3652
3653 {
3654 mpp_thread_lock(thd_enc, THREAD_WORK);
3655 enc->status_flag = 0;
3656 mpp_thread_unlock(thd_enc, THREAD_WORK);
3657 }
3658
3659 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
3660 enc->frm_cfg.force_idr++;
3661
3662 mpp_thread_lock(thd_enc, THREAD_CONTROL);
3663 enc->reset_flag = 0;
3664 sem_post(&enc->enc_reset);
3665 enc_dbg_detail("thread reset done\n");
3666 mpp_thread_unlock(thd_enc, THREAD_CONTROL);
3667 }
3668 SYNC_DONE:
3669 mpp_mutex_cond_unlock(&frm_in->cond_lock);
3670 wait.val = 0;
3671 continue;
3672 }
3673
3674 // 2. try get a task to encode
3675 ret = try_get_async_task(enc, &wait);
3676 enc_dbg_detail("try_get_async_task ret %d\n", ret);
3677 if (ret) {
3678 try_proc_processing_task(enc, &wait);
3679 continue;
3680 }
3681
3682 mpp_assert(enc->async);
3683 mpp_assert(enc->async->task.valid);
3684
3685 proc_async_task(enc, &wait);
3686 }
3687 /* wait all task done */
3688 while (MPP_OK == try_proc_processing_task(enc, &wait));
3689
3690 enc_dbg_func("thread finish\n");
3691
3692 return NULL;
3693 }
3694