xref: /rockchip-linux_mpp/mpp/codec/mpp_enc_impl.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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