xref: /OK3568_Linux_fs/external/mpp/mpp/codec/mpp_enc_impl.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define  MODULE_TAG "mpp_enc"
18 
19 #include <string.h>
20 #include <stdarg.h>
21 #include <limits.h>
22 
23 #include "mpp_time.h"
24 #include "mpp_common.h"
25 
26 #include "mpp_frame_impl.h"
27 #include "mpp_packet_impl.h"
28 
29 #include "mpp.h"
30 #include "mpp_enc_debug.h"
31 #include "mpp_enc_cfg_impl.h"
32 #include "mpp_enc_impl.h"
33 #include "mpp_enc_cb_param.h"
34 
35 typedef union EncAsyncWait_u {
36     RK_U32          val;
37     struct {
38         RK_U32      enc_frm_in      : 1;   // 0x0001 MPP_ENC_NOTIFY_FRAME_ENQUEUE
39         RK_U32      reserv0002      : 1;   // 0x0002
40         RK_U32      reserv0004      : 1;   // 0x0004
41         RK_U32      enc_pkt_out     : 1;   // 0x0008 MPP_ENC_NOTIFY_PACKET_ENQUEUE
42 
43         RK_U32      task_hnd        : 1;   // 0x0010
44         RK_U32      reserv0020      : 1;   // 0x0020
45         RK_U32      reserv0040      : 1;   // 0x0040
46         RK_U32      reserv0080      : 1;   // 0x0080
47 
48         RK_U32      reserv0100      : 1;   // 0x0100
49         RK_U32      reserv0200      : 1;   // 0x0200
50         RK_U32      reserv0400      : 1;   // 0x0400
51         RK_U32      reserv0800      : 1;   // 0x0800
52 
53         RK_U32      reserv1000      : 1;   // 0x1000
54         RK_U32      reserv2000      : 1;   // 0x2000
55         RK_U32      reserv4000      : 1;   // 0x4000
56         RK_U32      reserv8000      : 1;   // 0x8000
57     };
58 } EncAsyncWait;
59 
60 static RK_U8 uuid_version[16] = {
61     0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8,
62     0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac,
63 };
64 
65 static RK_U8 uuid_rc_cfg[16] = {
66     0xd7, 0xdc, 0x03, 0xc3, 0xc5, 0x6f, 0x40, 0xe0,
67     0x8e, 0xa9, 0x17, 0x1a, 0xd2, 0xef, 0x5e, 0x23,
68 };
69 
70 static RK_U8 uuid_usr_data[16] = {
71     0xfe, 0x39, 0xac, 0x4c, 0x4a, 0x8e, 0x4b, 0x4b,
72     0x85, 0xd9, 0xb2, 0xa2, 0x4f, 0xa1, 0x19, 0x5b,
73 };
74 
75 static RK_U8 uuid_debug_info[16] = {
76     0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
77     0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
78 };
79 
80 RK_U8 uuid_refresh_cfg[16] = {
81     0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
82     0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x00
83 };
84 
reset_hal_enc_task(HalEncTask * task)85 static void reset_hal_enc_task(HalEncTask *task)
86 {
87     memset(task, 0, sizeof(*task));
88 }
89 
reset_enc_rc_task(EncRcTask * task)90 static void reset_enc_rc_task(EncRcTask *task)
91 {
92     memset(task, 0, sizeof(*task));
93 }
94 
reset_enc_task(MppEncImpl * enc)95 static void reset_enc_task(MppEncImpl *enc)
96 {
97     enc->task_in = NULL;
98     enc->task_out = NULL;
99     enc->packet = NULL;
100     enc->frame = NULL;
101 
102     enc->frm_buf = NULL;
103     enc->pkt_buf = NULL;
104 
105     /* NOTE: clear add_by flags */
106     enc->hdr_status.val = enc->hdr_status.ready;
107 }
108 
update_enc_hal_info(MppEncImpl * enc)109 static void update_enc_hal_info(MppEncImpl *enc)
110 {
111     MppDevInfoCfg data[32];
112     RK_S32 size = sizeof(data);
113     RK_S32 i;
114 
115     if (NULL == enc->hal_info || NULL == enc->dev)
116         return ;
117 
118     hal_info_from_enc_cfg(enc->hal_info, &enc->cfg);
119     hal_info_get(enc->hal_info, data, &size);
120 
121     if (size) {
122         size /= sizeof(data[0]);
123         for (i = 0; i < size; i++)
124             mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &data[i]);
125     }
126 }
127 
update_hal_info_fps(MppEncImpl * enc)128 static void update_hal_info_fps(MppEncImpl *enc)
129 {
130     MppDevInfoCfg cfg;
131 
132     RK_S32 time_diff = ((RK_S32)(enc->time_end - enc->time_base) / 1000);
133     RK_U64 fps = hal_info_to_float(enc->frame_count * 1000, time_diff);
134 
135     cfg.type = ENC_INFO_FPS_CALC;
136     cfg.flag = CODEC_INFO_FLAG_STRING;
137     cfg.data = fps;
138 
139     mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &cfg);
140 
141     enc->time_base = enc->time_end;
142     enc->frame_count = 0;
143 }
144 
release_task_in_port(MppPort port)145 static MPP_RET release_task_in_port(MppPort port)
146 {
147     MPP_RET ret = MPP_OK;
148     MppPacket packet = NULL;
149     MppFrame frame = NULL;
150     MppTask mpp_task;
151 
152     do {
153         ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK);
154         if (ret < 0)
155             break;
156 
157         mpp_port_dequeue(port, &mpp_task);
158         mpp_assert(mpp_task);
159         if (mpp_task) {
160             packet = NULL;
161             frame = NULL;
162             ret = mpp_task_meta_get_frame(mpp_task, KEY_INPUT_FRAME,  &frame);
163             if (frame) {
164                 mpp_frame_deinit(&frame);
165                 frame = NULL;
166             }
167             ret = mpp_task_meta_get_packet(mpp_task, KEY_OUTPUT_PACKET, &packet);
168             if (packet) {
169                 mpp_packet_deinit(&packet);
170                 packet = NULL;
171             }
172 
173             mpp_port_enqueue(port, mpp_task);
174             mpp_task = NULL;
175         } else
176             break;
177     } while (1);
178 
179     return ret;
180 }
181 
check_hal_task_pkt_len(HalEncTask * task,const char * reason)182 static void check_hal_task_pkt_len(HalEncTask *task, const char *reason)
183 {
184     RK_U32 task_length = task->length;
185     RK_U32 packet_length = mpp_packet_get_length(task->packet);
186 
187     if (task_length != packet_length) {
188         mpp_err_f("%s check failed: task length is not match to packet length %d vs %d\n",
189                   reason, task_length, packet_length);
190     }
191 }
192 
check_enc_task_wait(MppEncImpl * enc,EncAsyncWait * wait)193 static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncAsyncWait *wait)
194 {
195     MPP_RET ret = MPP_OK;
196     RK_U32 notify = enc->notify_flag;
197     RK_U32 last_wait = enc->status_flag;
198     RK_U32 curr_wait = wait->val;
199     RK_U32 wait_chg  = last_wait & (~curr_wait);
200     RK_U32 keep_notify = 0;
201 
202     do {
203         if (enc->reset_flag)
204             break;
205 
206         // NOTE: User control should always be processed
207         if (notify & MPP_ENC_CONTROL) {
208             keep_notify = notify & (~MPP_ENC_CONTROL);
209             break;
210         }
211 
212         // NOTE: When condition is not fulfilled check nofify flag again
213         if (!curr_wait || (curr_wait & notify))
214             break;
215 
216         ret = MPP_NOK;
217     } while (0);
218 
219     enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
220                    last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
221 
222     enc->status_flag = wait->val;
223     enc->notify_flag = keep_notify;
224 
225     if (ret) {
226         enc->wait_count++;
227     } else {
228         enc->work_count++;
229     }
230 
231     return ret;
232 }
233 
check_codec_to_resend_hdr(MppEncCodecCfg * codec)234 static RK_S32 check_codec_to_resend_hdr(MppEncCodecCfg *codec)
235 {
236     switch (codec->coding) {
237     case MPP_VIDEO_CodingAVC : {
238         if (codec->h264.change)
239             return 1;
240     } break;
241     case MPP_VIDEO_CodingHEVC : {
242         if (codec->h265.change)
243             return 1;
244     } break;
245     case MPP_VIDEO_CodingVP8 :
246     case MPP_VIDEO_CodingMJPEG :
247     default : {
248     } break;
249     }
250     return 0;
251 }
252 
check_resend_hdr(MpiCmd cmd,void * param,MppEncCfgSet * cfg)253 static RK_S32 check_resend_hdr(MpiCmd cmd, void *param, MppEncCfgSet *cfg)
254 {
255     RK_S32 resend = 0;
256     static const char *resend_reason[] = {
257         "unchanged",
258         "codec/prep cfg change",
259         "rc cfg change rc_mode/fps/gop",
260         "set cfg change input/format/color",
261         "set cfg change rc_mode/fps/gop",
262         "set cfg change codec",
263     };
264 
265     if (cfg->codec.coding == MPP_VIDEO_CodingMJPEG ||
266         cfg->codec.coding == MPP_VIDEO_CodingVP8)
267         return 0;
268 
269     do {
270         if (cmd == MPP_ENC_SET_IDR_FRAME)
271             return 1;
272 
273         if (cmd == MPP_ENC_SET_CODEC_CFG ||
274             cmd == MPP_ENC_SET_PREP_CFG) {
275             resend = 1;
276             break;
277         }
278 
279         if (cmd == MPP_ENC_SET_RC_CFG) {
280             RK_U32 change = *(RK_U32 *)param;
281             RK_U32 check_flag = MPP_ENC_RC_CFG_CHANGE_RC_MODE |
282                                 MPP_ENC_RC_CFG_CHANGE_FPS_IN |
283                                 MPP_ENC_RC_CFG_CHANGE_FPS_OUT |
284                                 MPP_ENC_RC_CFG_CHANGE_GOP;
285 
286             if (change & check_flag) {
287                 resend = 2;
288                 break;
289             }
290         }
291 
292         if (cmd == MPP_ENC_SET_CFG) {
293             RK_U32 change = cfg->prep.change;
294             RK_U32 check_flag = MPP_ENC_PREP_CFG_CHANGE_INPUT |
295                                 MPP_ENC_PREP_CFG_CHANGE_FORMAT |
296                                 MPP_ENC_PREP_CFG_CHANGE_ROTATION |
297                                 MPP_ENC_PREP_CFG_CHANGE_COLOR_RANGE |
298                                 MPP_ENC_PREP_CFG_CHANGE_COLOR_SPACE |
299                                 MPP_ENC_PREP_CFG_CHANGE_COLOR_PRIME |
300                                 MPP_ENC_PREP_CFG_CHANGE_COLOR_TRC;
301 
302             if (change & check_flag) {
303                 resend = 3;
304                 break;
305             }
306 
307             change = cfg->rc.change;
308             check_flag = MPP_ENC_RC_CFG_CHANGE_RC_MODE |
309                          MPP_ENC_RC_CFG_CHANGE_FPS_IN |
310                          MPP_ENC_RC_CFG_CHANGE_FPS_OUT |
311                          MPP_ENC_RC_CFG_CHANGE_GOP;
312 
313             if (change & check_flag) {
314                 resend = 4;
315                 break;
316             }
317             if (check_codec_to_resend_hdr(&cfg->codec)) {
318                 resend = 5;
319                 break;
320             }
321         }
322     } while (0);
323 
324     if (resend)
325         enc_dbg_detail("send header for %s\n", resend_reason[resend]);
326 
327     return resend;
328 }
329 
check_rc_cfg_update(MpiCmd cmd,MppEncCfgSet * cfg)330 static RK_S32 check_rc_cfg_update(MpiCmd cmd, MppEncCfgSet *cfg)
331 {
332     if (cmd == MPP_ENC_SET_RC_CFG ||
333         cmd == MPP_ENC_SET_PREP_CFG ||
334         cmd == MPP_ENC_SET_REF_CFG) {
335         return 1;
336     }
337 
338     if (cmd == MPP_ENC_SET_CFG) {
339         RK_U32 change = cfg->prep.change;
340         RK_U32 check_flag = MPP_ENC_PREP_CFG_CHANGE_INPUT |
341                             MPP_ENC_PREP_CFG_CHANGE_FORMAT;
342 
343         if (change & check_flag)
344             return 1;
345 
346         change = cfg->rc.change;
347         check_flag = MPP_ENC_RC_CFG_CHANGE_ALL &
348                      (~MPP_ENC_RC_CFG_CHANGE_QUALITY);
349 
350         if (change & check_flag)
351             return 1;
352     }
353 
354     return 0;
355 }
356 
check_rc_gop_update(MpiCmd cmd,MppEncCfgSet * cfg)357 static RK_S32 check_rc_gop_update(MpiCmd cmd, MppEncCfgSet *cfg)
358 {
359     if (((cmd == MPP_ENC_SET_RC_CFG) || (cmd == MPP_ENC_SET_CFG)) &&
360         (cfg->rc.change & MPP_ENC_RC_CFG_CHANGE_GOP))
361         return 1;
362 
363     return 0;
364 }
365 
check_hal_info_update(MpiCmd cmd)366 static RK_S32 check_hal_info_update(MpiCmd cmd)
367 {
368     if (cmd == MPP_ENC_SET_CFG ||
369         cmd == MPP_ENC_SET_RC_CFG ||
370         cmd == MPP_ENC_SET_CODEC_CFG ||
371         cmd == MPP_ENC_SET_PREP_CFG ||
372         cmd == MPP_ENC_SET_REF_CFG) {
373         return 1;
374     }
375 
376     return 0;
377 }
378 
check_low_delay_part_mode(MppEncImpl * enc)379 static void check_low_delay_part_mode(MppEncImpl *enc)
380 {
381     MppEncCfgSet *cfg = &enc->cfg;
382 
383     enc->low_delay_part_mode = 0;
384 
385     if (!(cfg->base.low_delay))
386         return;
387 
388     if (!cfg->split.split_mode)
389         return;
390 
391     if (mpp_enc_hal_check_part_mode(enc->enc_hal))
392         return;
393 
394     enc->low_delay_part_mode = 1;
395 }
396 
check_low_delay_output(MppEncImpl * enc)397 static void check_low_delay_output(MppEncImpl *enc)
398 {
399     MppEncCfgSet *cfg = &enc->cfg;
400 
401     enc->low_delay_output = 0;
402 
403     if (!cfg->split.split_mode || !(cfg->split.split_out & MPP_ENC_SPLIT_OUT_LOWDELAY))
404         return;
405 
406     if (cfg->rc.max_reenc_times) {
407         mpp_log_f("can not enable lowdelay output with reencode enabled\n");
408         cfg->rc.max_reenc_times = 0;
409     }
410 
411     if (cfg->rc.drop_mode) {
412         mpp_log_f("can not enable lowdelay output with drop mode enabled\n");
413         cfg->rc.drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED;
414     }
415 
416     if (cfg->rc.super_mode) {
417         mpp_log_f("can not enable lowdelay output with super frame mode enabled\n");
418         cfg->rc.super_mode = MPP_ENC_RC_SUPER_FRM_NONE;
419     }
420 
421     enc->low_delay_output = 1;
422 }
423 
mpp_enc_callback(const char * caller,void * ctx,RK_S32 cmd,void * param)424 MPP_RET mpp_enc_callback(const char *caller, void *ctx, RK_S32 cmd, void *param)
425 {
426     MppEncImpl *enc = (MppEncImpl *)ctx;
427     EncOutParam *out = (EncOutParam *)param;
428     HalEncTask *task = NULL;
429     MppPacket packet = NULL;
430     MppPacketImpl *impl = NULL;
431     RK_U8 *last_pos = NULL;
432     RK_S32 slice_length = 0;
433     RK_U32 part_first = 0;
434     MPP_RET ret = MPP_OK;
435     Mpp *mpp = (Mpp*)enc->mpp;
436     (void) caller;
437 
438     if (!enc->low_delay_output)
439         return ret;
440 
441     task = (HalEncTask *)out->task;
442     mpp_assert(task);
443     part_first = task->part_first;
444     packet = task->packet;
445 
446     if (part_first) {
447         task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
448         task->part_length = mpp_packet_get_length(packet);
449 
450         enc_dbg_slice("first slice previous length %d\n", task->part_length);
451         mpp_assert(task->part_pos);
452         task->part_first = 0;
453         slice_length = task->part_length;
454     }
455 
456     last_pos = (RK_U8 *)task->part_pos;
457     slice_length += out->length;
458 
459     enc_dbg_slice("last_pos %p len %d:%d\n", last_pos, out->length, slice_length);
460 
461     switch (cmd) {
462     case ENC_OUTPUT_FINISH : {
463         enc_dbg_slice("slice pos %p len %5d last\n", last_pos, slice_length);
464 
465         impl = (MppPacketImpl *)packet;
466 
467         impl->pos = last_pos;
468         impl->length = slice_length;
469         impl->status.val = 0;
470         impl->status.partition = 1;
471         impl->status.soi = part_first;
472         impl->status.eoi = 1;
473 
474         task->part_pos += slice_length;
475         task->part_length += slice_length;
476         task->part_count++;
477         task->part_last = 1;
478     } break;
479     case ENC_OUTPUT_SLICE : {
480         enc_dbg_slice("slice pos %p len %5d\n", last_pos, slice_length);
481 
482         mpp_packet_new((MppPacket *)&impl);
483         mpp_assert(impl);
484 
485         /* copy the source data */
486         memcpy(impl, packet, sizeof(*impl));
487 
488         impl->pos = last_pos;
489         impl->length = slice_length;
490         impl->status.val = 0;
491         impl->status.partition = 1;
492         impl->status.soi = part_first;
493         impl->status.eoi = 0;
494 
495         if (impl->buffer)
496             mpp_buffer_inc_ref(impl->buffer);
497 
498         mpp_meta_get(&impl->meta);
499         if (impl->meta) {
500             EncFrmStatus *frm = &task->rc_task->frm;
501 
502             mpp_meta_set_s32(impl->meta, KEY_OUTPUT_INTRA, frm->is_intra);
503         }
504 
505         mpp_packet_copy_segment_info(impl, packet);
506         mpp_packet_reset_segment(packet);
507 
508         enc_dbg_detail("pkt %d new pos %p len %d\n", task->part_count,
509                        last_pos, slice_length);
510 
511         task->part_pos += slice_length;
512         task->part_length += slice_length;
513         task->part_count++;
514         if (!mpp->mEncAyncProc) {
515             mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, impl);
516             mpp_port_enqueue(enc->output, enc->task_out);
517 
518             ret = mpp_port_poll(enc->output, MPP_POLL_BLOCK);
519             mpp_assert(ret > 0);
520             ret = mpp_port_dequeue(enc->output, &enc->task_out);
521             mpp_assert(enc->task_out);
522         } else {
523             if (mpp->mPktOut) {
524                 mpp_list *pkt_out = mpp->mPktOut;
525 
526                 AutoMutex autoLock(pkt_out->mutex());
527 
528                 pkt_out->add_at_tail(&impl, sizeof(impl));
529                 mpp->mPacketPutCount++;
530                 pkt_out->signal();
531             }
532         }
533     } break;
534     default : {
535     } break;
536     }
537 
538     return ret;
539 }
540 
mpp_enc_proc_rc_cfg(MppCodingType coding,MppEncRcCfg * dst,MppEncRcCfg * src)541 MPP_RET mpp_enc_proc_rc_cfg(MppCodingType coding, MppEncRcCfg *dst, MppEncRcCfg *src)
542 {
543     MPP_RET ret = MPP_OK;
544     RK_U32 change = src->change;
545 
546     if (change) {
547         MppEncRcCfg bak = *dst;
548 
549         if (change & MPP_ENC_RC_CFG_CHANGE_RC_MODE)
550             dst->rc_mode = src->rc_mode;
551 
552         if (change & MPP_ENC_RC_CFG_CHANGE_QUALITY)
553             dst->quality = src->quality;
554 
555         if (change & MPP_ENC_RC_CFG_CHANGE_BPS) {
556             dst->bps_target = src->bps_target;
557             dst->bps_max = src->bps_max;
558             dst->bps_min = src->bps_min;
559         }
560 
561         if (change & MPP_ENC_RC_CFG_CHANGE_FPS_IN) {
562             dst->fps_in_flex = src->fps_in_flex;
563             dst->fps_in_num = src->fps_in_num;
564             dst->fps_in_denorm = src->fps_in_denorm;
565         }
566 
567         if (change & MPP_ENC_RC_CFG_CHANGE_FPS_OUT) {
568             dst->fps_out_flex = src->fps_out_flex;
569             dst->fps_out_num = src->fps_out_num;
570             dst->fps_out_denorm = src->fps_out_denorm;
571         }
572 
573         if (change & MPP_ENC_RC_CFG_CHANGE_GOP) {
574             /*
575              * If GOP is changed smaller, disable Intra-Refresh
576              * and User level should reconfig Intra-Refresh
577              */
578             if (dst->gop < src->gop && dst->refresh_en) {
579                 dst->refresh_en = 0;
580             }
581             dst->gop = src->gop;
582         }
583 
584         if (change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG)
585             dst->ref_cfg = src->ref_cfg;
586 
587         if (change & MPP_ENC_RC_CFG_CHANGE_MAX_REENC)
588             dst->max_reenc_times = src->max_reenc_times;
589 
590         if (change & MPP_ENC_RC_CFG_CHANGE_DROP_FRM) {
591             dst->drop_mode = src->drop_mode;
592             dst->drop_threshold = src->drop_threshold;
593             dst->drop_gap = src->drop_gap;
594         }
595 
596         if (change & MPP_ENC_RC_CFG_CHANGE_PRIORITY) {
597             if (src->rc_priority >= MPP_ENC_RC_PRIORITY_BUTT) {
598                 mpp_err("invalid rc_priority %d should be[%d, %d] \n",
599                         src->rc_priority, MPP_ENC_RC_BY_BITRATE_FIRST, MPP_ENC_RC_PRIORITY_BUTT);
600                 ret = MPP_ERR_VALUE;
601             }
602             dst->rc_priority = src->rc_priority;
603         }
604 
605         if (change & MPP_ENC_RC_CFG_CHANGE_SUPER_FRM) {
606             if (src->super_mode >= MPP_ENC_RC_SUPER_FRM_BUTT) {
607                 mpp_err("invalid super_mode %d should be[%d, %d] \n",
608                         src->super_mode, MPP_ENC_RC_SUPER_FRM_NONE, MPP_ENC_RC_SUPER_FRM_BUTT);
609                 ret = MPP_ERR_VALUE;
610             }
611             dst->super_mode = src->super_mode;
612             dst->super_i_thd = src->super_i_thd;
613             dst->super_p_thd = src->super_p_thd;
614         }
615 
616         if (change & MPP_ENC_RC_CFG_CHANGE_DEBREATH) {
617             dst->debreath_en    = src->debreath_en;
618             dst->debre_strength = src->debre_strength;
619             if (dst->debreath_en && dst->debre_strength > 35) {
620                 mpp_err("invalid debre_strength should be[%d, %d] \n", 0, 35);
621                 ret = MPP_ERR_VALUE;
622             }
623         }
624 
625         if (change & MPP_ENC_RC_CFG_CHANGE_MAX_I_PROP)
626             dst->max_i_prop = src->max_i_prop;
627 
628         if (change & MPP_ENC_RC_CFG_CHANGE_MIN_I_PROP)
629             dst->min_i_prop = src->min_i_prop;
630 
631         if (change & MPP_ENC_RC_CFG_CHANGE_INIT_IP_RATIO)
632             dst->init_ip_ratio = src->init_ip_ratio;
633 
634         if (change & MPP_ENC_RC_CFG_CHANGE_QP_INIT)
635             dst->qp_init = src->qp_init;
636 
637         if (change & MPP_ENC_RC_CFG_CHANGE_QP_RANGE) {
638             dst->qp_min = src->qp_min;
639             dst->qp_max = src->qp_max;
640         }
641 
642         if (change & MPP_ENC_RC_CFG_CHANGE_QP_RANGE_I) {
643             dst->qp_min_i = src->qp_min_i;
644             dst->qp_max_i = src->qp_max_i;
645         }
646 
647         if (change & MPP_ENC_RC_CFG_CHANGE_QP_MAX_STEP)
648             dst->qp_max_step = src->qp_max_step;
649 
650         if (change & MPP_ENC_RC_CFG_CHANGE_QP_IP)
651             dst->qp_delta_ip = src->qp_delta_ip;
652 
653         if (change & MPP_ENC_RC_CFG_CHANGE_QP_VI)
654             dst->qp_delta_vi = src->qp_delta_vi;
655 
656         if (change & MPP_ENC_RC_CFG_CHANGE_HIER_QP) {
657             dst->hier_qp_en = src->hier_qp_en;
658             memcpy(dst->hier_qp_delta, src->hier_qp_delta, sizeof(src->hier_qp_delta));
659             memcpy(dst->hier_frame_num, src->hier_frame_num, sizeof(src->hier_frame_num));
660         }
661 
662         if (change & MPP_ENC_RC_CFG_CHANGE_ST_TIME)
663             dst->stats_time = src->stats_time;
664 
665         if (change & MPP_ENC_RC_CFG_CHANGE_REFRESH) {
666             if (dst->debreath_en) {
667                 mpp_err_f("Turn off Debreath first.");
668                 ret = MPP_ERR_VALUE;
669             }
670             dst->refresh_en = src->refresh_en;
671             dst->refresh_mode = src->refresh_mode;
672             // Make sure refresh_num is legal
673             dst->refresh_num = src->refresh_num;
674         }
675 
676         // parameter checking
677         if (dst->rc_mode >= MPP_ENC_RC_MODE_BUTT) {
678             mpp_err("invalid rc mode %d should be RC_MODE_VBR or RC_MODE_CBR\n",
679                     src->rc_mode);
680             ret = MPP_ERR_VALUE;
681         }
682         if (dst->quality >= MPP_ENC_RC_QUALITY_BUTT) {
683             mpp_err("invalid quality %d should be from QUALITY_WORST to QUALITY_BEST\n",
684                     dst->quality);
685             ret = MPP_ERR_VALUE;
686         }
687 
688         if (dst->rc_mode != MPP_ENC_RC_MODE_FIXQP) {
689             RK_S32 bps_min = MPP_ENC_MIN_BPS;
690             RK_S32 bps_max = MPP_ENC_MAX_BPS;
691 
692             if (coding == MPP_VIDEO_CodingMJPEG) {
693                 bps_min *= 4;
694                 bps_max *= 4;
695                 if (bps_max < 0)
696                     bps_max = INT_MAX;
697             }
698 
699             if ((dst->bps_target >= bps_max || dst->bps_target <= bps_min) ||
700                 (dst->bps_max    >= bps_max || dst->bps_max    <= bps_min) ||
701                 (dst->bps_min    >= bps_max || dst->bps_min    <= bps_min)) {
702                 mpp_err("invalid bit per second %x:%u min %x:%u max %x:%u out of range %dK~%dM\n",
703                         dst->bps_target, dst->bps_target, dst->bps_min,
704                         dst->bps_min, dst->bps_max, dst->bps_max,
705                         bps_min / SZ_1K,  bps_max / SZ_1M);
706                 ret = MPP_ERR_VALUE;
707             }
708         }
709 
710         if (dst->fps_in_num < 0 || dst->fps_in_denorm < 0 ||
711             dst->fps_out_num < 0 || dst->fps_out_denorm < 0) {
712             mpp_err("invalid fps cfg [number:denorm:flex]: in [%d:%d:%d] out [%d:%d:%d]\n",
713                     dst->fps_in_num, dst->fps_in_denorm, dst->fps_in_flex,
714                     dst->fps_out_num, dst->fps_out_denorm, dst->fps_out_flex);
715             ret = MPP_ERR_VALUE;
716         }
717 
718         // if I frame min/max is not set use normal case
719         if (dst->qp_min_i <= 0)
720             dst->qp_min_i = dst->qp_min;
721         if (dst->qp_max_i <= 0)
722             dst->qp_max_i = dst->qp_max;
723         if (dst->qp_min < 0 || dst->qp_max < 0 || dst->qp_min > dst->qp_max ||
724             dst->qp_min_i < 0 || dst->qp_max_i < 0 ||
725             dst->qp_min_i > dst->qp_max_i ||
726             (dst->qp_init > 0 &&
727              (dst->qp_init > dst->qp_max_i || dst->qp_init < dst->qp_min_i))) {
728             mpp_err("invalid qp range: init %d i [%d:%d] p [%d:%d]\n",
729                     dst->qp_init, dst->qp_min_i, dst->qp_max_i,
730                     dst->qp_min, dst->qp_max);
731 
732             dst->qp_init  = bak.qp_init;
733             dst->qp_min_i = bak.qp_min_i;
734             dst->qp_max_i = bak.qp_max_i;
735             dst->qp_min   = bak.qp_min;
736             dst->qp_max   = bak.qp_max;
737 
738             mpp_err("restore qp range: init %d i [%d:%d] p [%d:%d]\n",
739                     dst->qp_init, dst->qp_min_i, dst->qp_max_i,
740                     dst->qp_min, dst->qp_max);
741         }
742         if (MPP_ABS(dst->qp_delta_ip) > 8) {
743             mpp_err("invalid qp delta ip %d restore to %d\n",
744                     dst->qp_delta_ip, bak.qp_delta_ip);
745             dst->qp_delta_ip = bak.qp_delta_ip;
746         }
747         if (MPP_ABS(dst->qp_delta_vi) > 6) {
748             mpp_err("invalid qp delta vi %d restore to %d\n",
749                     dst->qp_delta_vi, bak.qp_delta_vi);
750             dst->qp_delta_vi = bak.qp_delta_vi;
751         }
752         if (dst->qp_max_step < 0) {
753             mpp_err("invalid qp max step %d restore to %d\n",
754                     dst->qp_max_step, bak.qp_max_step);
755             dst->qp_max_step = bak.qp_max_step;
756         }
757         if (dst->stats_time && dst->stats_time > 60) {
758             mpp_err("warning: bitrate statistic time %d is larger than 60s\n",
759                     dst->stats_time);
760         }
761 
762         dst->change |= change;
763 
764         if (ret) {
765             mpp_err_f("failed to accept new rc config\n");
766             *dst = bak;
767         } else {
768             mpp_log("MPP_ENC_SET_RC_CFG bps %d [%d : %d] fps [%d:%d] gop %d\n",
769                     dst->bps_target, dst->bps_min, dst->bps_max,
770                     dst->fps_in_num, dst->fps_out_num, dst->gop);
771         }
772     }
773 
774     return ret;
775 }
776 
mpp_enc_proc_hw_cfg(MppEncHwCfg * dst,MppEncHwCfg * src)777 MPP_RET mpp_enc_proc_hw_cfg(MppEncHwCfg *dst, MppEncHwCfg *src)
778 {
779     MPP_RET ret = MPP_OK;
780     RK_U32 change = src->change;
781 
782     if (change) {
783         MppEncHwCfg bak = *dst;
784 
785         if (change & MPP_ENC_HW_CFG_CHANGE_QP_ROW)
786             dst->qp_delta_row = src->qp_delta_row;
787 
788         if (change & MPP_ENC_HW_CFG_CHANGE_QP_ROW_I)
789             dst->qp_delta_row_i = src->qp_delta_row_i;
790 
791         if (change & MPP_ENC_HW_CFG_CHANGE_AQ_THRD_I)
792             memcpy(dst->aq_thrd_i, src->aq_thrd_i, sizeof(dst->aq_thrd_i));
793 
794         if (change & MPP_ENC_HW_CFG_CHANGE_AQ_THRD_P)
795             memcpy(dst->aq_thrd_p, src->aq_thrd_p, sizeof(dst->aq_thrd_p));
796 
797         if (change & MPP_ENC_HW_CFG_CHANGE_AQ_STEP_I)
798             memcpy(dst->aq_step_i, src->aq_step_i, sizeof(dst->aq_step_i));
799 
800         if (change & MPP_ENC_HW_CFG_CHANGE_AQ_STEP_P)
801             memcpy(dst->aq_step_p, src->aq_step_p, sizeof(dst->aq_step_p));
802 
803         if (change & MPP_ENC_HW_CFG_CHANGE_MB_RC)
804             dst->mb_rc_disable = src->mb_rc_disable;
805 
806         if (change & MPP_ENC_HW_CFG_CHANGE_CU_MODE_BIAS)
807             memcpy(dst->mode_bias, src->mode_bias, sizeof(dst->mode_bias));
808 
809         if (change & MPP_ENC_HW_CFG_CHANGE_CU_SKIP_BIAS) {
810             dst->skip_bias_en = src->skip_bias_en;
811             dst->skip_sad = src->skip_sad;
812             dst->skip_bias = src->skip_bias;
813         }
814 
815         if (dst->qp_delta_row < 0 || dst->qp_delta_row_i < 0) {
816             mpp_err("invalid hw qp delta row [%d:%d]\n",
817                     dst->qp_delta_row_i, dst->qp_delta_row);
818             ret = MPP_ERR_VALUE;
819         }
820 
821         dst->change |= change;
822 
823         if (ret) {
824             mpp_err_f("failed to accept new hw config\n");
825             *dst = bak;
826         }
827     }
828 
829     return ret;
830 }
831 
mpp_enc_proc_tune_cfg(MppEncFineTuneCfg * dst,MppEncFineTuneCfg * src)832 MPP_RET mpp_enc_proc_tune_cfg(MppEncFineTuneCfg *dst, MppEncFineTuneCfg *src)
833 {
834     MPP_RET ret = MPP_OK;
835     RK_U32 change = src->change;
836 
837     if (change) {
838         MppEncFineTuneCfg bak = *dst;
839 
840         if (change & MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE)
841             dst->scene_mode = src->scene_mode;
842 
843         if (dst->scene_mode < MPP_ENC_SCENE_MODE_DEFAULT ||
844             dst->scene_mode >= MPP_ENC_SCENE_MODE_BUTT) {
845             mpp_err("invalid scene mode %d not in range [%d:%d]\n", dst->scene_mode,
846                     MPP_ENC_SCENE_MODE_DEFAULT, MPP_ENC_SCENE_MODE_BUTT - 1);
847             ret = MPP_ERR_VALUE;
848         }
849 
850         dst->change |= change;
851 
852         if (ret) {
853             mpp_err_f("failed to accept new tuning config\n");
854             *dst = bak;
855         }
856     }
857 
858     return ret;
859 }
860 
mpp_enc_control_set_ref_cfg(MppEncImpl * enc,void * param)861 static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param)
862 {
863     MPP_RET ret = MPP_OK;
864     MppEncRefCfg src = (MppEncRefCfg)param;
865     MppEncRefCfg dst = enc->cfg.ref_cfg;
866 
867     if (NULL == src)
868         src = mpp_enc_ref_default();
869 
870     if (NULL == dst) {
871         mpp_enc_ref_cfg_init(&dst);
872         enc->cfg.ref_cfg = dst;
873     }
874 
875     ret = mpp_enc_ref_cfg_copy(dst, src);
876     if (ret) {
877         mpp_err_f("failed to copy ref cfg ret %d\n", ret);
878     }
879 
880     ret = mpp_enc_refs_set_cfg(enc->refs, dst);
881     if (ret) {
882         mpp_err_f("failed to set ref cfg ret %d\n", ret);
883     }
884 
885     if (mpp_enc_refs_update_hdr(enc->refs))
886         enc->hdr_status.val = 0;
887 
888     return ret;
889 }
890 
mpp_enc_proc_cfg(MppEncImpl * enc,MpiCmd cmd,void * param)891 MPP_RET mpp_enc_proc_cfg(MppEncImpl *enc, MpiCmd cmd, void *param)
892 {
893     MPP_RET ret = MPP_OK;
894 
895     switch (cmd) {
896     case MPP_ENC_SET_CFG : {
897         MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
898         MppEncCfgSet *src = &impl->cfg;
899         RK_U32 change = src->base.change;
900 
901         /* get base cfg here */
902         if (change) {
903             MppEncCfgSet *dst = &enc->cfg;
904 
905             if (change & MPP_ENC_BASE_CFG_CHANGE_LOW_DELAY)
906                 dst->base.low_delay = src->base.low_delay;
907 
908             src->base.change = 0;
909         }
910 
911         /* process rc cfg at mpp_enc module */
912         if (src->rc.change) {
913             ret = mpp_enc_proc_rc_cfg(enc->coding, &enc->cfg.rc, &src->rc);
914 
915             // update ref cfg
916             if ((enc->cfg.rc.change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG) &&
917                 (enc->cfg.rc.gop > 0))
918                 mpp_enc_control_set_ref_cfg(enc, enc->cfg.rc.ref_cfg);
919 
920             src->rc.change = 0;
921         }
922 
923         /* process hardware cfg at mpp_enc module */
924         if (src->hw.change) {
925             ret = mpp_enc_proc_hw_cfg(&enc->cfg.hw, &src->hw);
926             src->hw.change = 0;
927         }
928 
929         /* process hardware cfg at mpp_enc module */
930         if (src->tune.change) {
931             ret = mpp_enc_proc_tune_cfg(&enc->cfg.tune, &src->tune);
932             src->tune.change = 0;
933         }
934 
935         /* Then process the rest config */
936         ret = enc_impl_proc_cfg(enc->impl, cmd, param);
937     } break;
938     case MPP_ENC_SET_RC_CFG : {
939         MppEncRcCfg *src = (MppEncRcCfg *)param;
940         if (src) {
941             ret = mpp_enc_proc_rc_cfg(enc->coding, &enc->cfg.rc, src);
942 
943             // update ref cfg
944             if ((enc->cfg.rc.change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG) &&
945                 (enc->cfg.rc.gop > 0))
946                 mpp_enc_control_set_ref_cfg(enc, enc->cfg.rc.ref_cfg);
947         }
948     } break;
949     case MPP_ENC_SET_IDR_FRAME : {
950         enc->frm_cfg.force_idr++;
951     } break;
952     case MPP_ENC_GET_HDR_SYNC :
953     case MPP_ENC_GET_EXTRA_INFO : {
954         /*
955          * NOTE: get stream header should use user's MppPacket
956          * If we provide internal MppPacket to external user
957          * we do not known when the buffer usage is finished.
958          * So encoder always write its header to external buffer
959          * which is provided by user.
960          */
961         if (!enc->hdr_status.ready) {
962             enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
963             enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
964             enc->hdr_status.ready = 1;
965         }
966 
967         if (cmd == MPP_ENC_GET_EXTRA_INFO) {
968             mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n");
969             mpp_err("NOTE: MPP_ENC_GET_HDR_SYNC needs MppPacket input\n");
970 
971             *(MppPacket *)param = enc->hdr_pkt;
972         } else {
973             mpp_packet_copy((MppPacket)param, enc->hdr_pkt);
974         }
975 
976         if (enc->hdr_pkt) {
977             Mpp *mpp = (Mpp *)enc->mpp;
978             // dump output
979             mpp_ops_enc_get_pkt(mpp->mDump, enc->hdr_pkt);
980         }
981 
982         enc->hdr_status.added_by_ctrl = 1;
983     } break;
984     case MPP_ENC_PRE_ALLOC_BUFF : {
985         /* deprecated control */
986         mpp_log("deprecated MPP_ENC_PRE_ALLOC_BUFF control\n");
987     } break;
988     case MPP_ENC_GET_RC_API_ALL : {
989         RcApiQueryAll *query = (RcApiQueryAll *)param;
990 
991         rc_brief_get_all(query);
992     } break;
993     case MPP_ENC_GET_RC_API_BY_TYPE : {
994         RcApiQueryType *query = (RcApiQueryType *)param;
995 
996         rc_brief_get_by_type(query);
997     } break;
998     case MPP_ENC_SET_RC_API_CFG : {
999         const RcImplApi *api = (const RcImplApi *)param;
1000 
1001         rc_api_add(api);
1002     } break;
1003     case MPP_ENC_GET_RC_API_CURRENT : {
1004         RcApiBrief *dst = (RcApiBrief *)param;
1005 
1006         *dst = enc->rc_brief;
1007     } break;
1008     case MPP_ENC_SET_RC_API_CURRENT : {
1009         RcApiBrief *src = (RcApiBrief *)param;
1010 
1011         mpp_assert(src->type == enc->coding);
1012         enc->rc_brief = *src;
1013         enc->rc_status.rc_api_user_cfg = 1;
1014         enc->rc_status.rc_api_updated = 1;
1015     } break;
1016     case MPP_ENC_SET_HEADER_MODE : {
1017         if (param) {
1018             MppEncHeaderMode mode = *((MppEncHeaderMode *)param);
1019 
1020             if (mode < MPP_ENC_HEADER_MODE_BUTT) {
1021                 enc->hdr_mode = mode;
1022                 enc_dbg_ctrl("header mode set to %d\n", mode);
1023             } else {
1024                 mpp_err_f("invalid header mode %d\n", mode);
1025                 ret = MPP_NOK;
1026             }
1027         } else {
1028             mpp_err_f("invalid NULL ptr on setting header mode\n");
1029             ret = MPP_NOK;
1030         }
1031     } break;
1032     case MPP_ENC_SET_SEI_CFG : {
1033         if (param) {
1034             MppEncSeiMode mode = *((MppEncSeiMode *)param);
1035 
1036             if (mode <= MPP_ENC_SEI_MODE_ONE_FRAME) {
1037                 enc->sei_mode = mode;
1038                 enc_dbg_ctrl("sei mode set to %d\n", mode);
1039             } else {
1040                 mpp_err_f("invalid sei mode %d\n", mode);
1041                 ret = MPP_NOK;
1042             }
1043         } else {
1044             mpp_err_f("invalid NULL ptr on setting header mode\n");
1045             ret = MPP_NOK;
1046         }
1047     } break;
1048     case MPP_ENC_SET_REF_CFG : {
1049         ret = mpp_enc_control_set_ref_cfg(enc, param);
1050     } break;
1051     case MPP_ENC_SET_OSD_PLT_CFG : {
1052         MppEncOSDPltCfg *src = (MppEncOSDPltCfg *)param;
1053         MppEncOSDPltCfg *dst = &enc->cfg.plt_cfg;
1054         RK_U32 change = src->change;
1055 
1056         if (change) {
1057             RK_S32 cfg_err = 0;
1058 
1059             if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_MODE) {
1060                 if (src->type >= MPP_ENC_OSD_PLT_TYPE_BUTT) {
1061                     mpp_err_f("invalid osd plt type %d\n", src->type);
1062                     cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_MODE;
1063                 } else
1064                     dst->type = src->type;
1065             }
1066 
1067             if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL) {
1068                 if (src->plt == NULL) {
1069                     mpp_err_f("invalid osd plt NULL pointer\n");
1070                     cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL;
1071                 } else {
1072                     memcpy(dst->plt, src->plt, sizeof(MppEncOSDPlt));
1073                 }
1074             }
1075 
1076             dst->change = cfg_err ? 0 : change;
1077             enc_dbg_ctrl("plt type %d data %p\n", dst->type, src->plt);
1078         }
1079     } break;
1080     default : {
1081         ret = enc_impl_proc_cfg(enc->impl, cmd, param);
1082     } break;
1083     }
1084 
1085     if (check_resend_hdr(cmd, param, &enc->cfg)) {
1086         enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
1087         enc->hdr_status.val = 0;
1088     }
1089     if (check_rc_cfg_update(cmd, &enc->cfg))
1090         enc->rc_status.rc_api_user_cfg = 1;
1091     if (check_rc_gop_update(cmd, &enc->cfg))
1092         mpp_enc_refs_set_rc_igop(enc->refs, enc->cfg.rc.gop);
1093 
1094     if (enc->cfg.rc.refresh_en)
1095         mpp_enc_refs_set_refresh_length(enc->refs, enc->cfg.rc.refresh_length);
1096 
1097     if (check_hal_info_update(cmd))
1098         enc->hal_info_updated = 0;
1099 
1100     check_low_delay_part_mode(enc);
1101     check_low_delay_output(enc);
1102 
1103     return ret;
1104 }
1105 
1106 static const char *name_of_rc_mode[] = {
1107     "vbr",
1108     "cbr",
1109     "fixqp",
1110     "avbr",
1111 };
1112 
update_rc_cfg_log(MppEncImpl * impl,const char * fmt,...)1113 static void update_rc_cfg_log(MppEncImpl *impl, const char* fmt, ...)
1114 {
1115     va_list args;
1116     va_start(args, fmt);
1117 
1118     RK_S32 size = impl->rc_cfg_size;
1119     RK_S32 length = impl->rc_cfg_length;
1120     char *base = impl->rc_cfg_info + length;
1121 
1122     length += vsnprintf(base, size - length, fmt, args);
1123     if (length >= size)
1124         mpp_log_f("rc cfg log is full\n");
1125 
1126     impl->rc_cfg_length = length;
1127 
1128     va_end(args);
1129 }
1130 
update_user_datas(EncImpl impl,MppPacket packet,MppFrame frame,HalEncTask * hal_task)1131 static void update_user_datas(EncImpl impl, MppPacket packet, MppFrame frame, HalEncTask *hal_task)
1132 {
1133     MppMeta frm_meta = mpp_frame_get_meta(frame);
1134     MppEncUserData *user_data = NULL;
1135     MppEncUserDataSet *user_datas = NULL;
1136     RK_S32 length = 0;
1137 
1138     mpp_meta_get_ptr(frm_meta, KEY_USER_DATA, (void**)&user_data);
1139     if (user_data) {
1140         if (user_data->pdata && user_data->len) {
1141             enc_impl_add_prefix(impl, packet, &length, uuid_usr_data,
1142                                 user_data->pdata, user_data->len);
1143 
1144             hal_task->sei_length += length;
1145             hal_task->length += length;
1146         } else
1147             mpp_err_f("failed to insert user data %p len %d\n",
1148                       user_data->pdata, user_data->len);
1149     }
1150 
1151     mpp_meta_get_ptr(frm_meta, KEY_USER_DATAS, (void**)&user_datas);
1152     if (user_datas && user_datas->count) {
1153         RK_U32 i = 0;
1154 
1155         for (i = 0; i < user_datas->count; i++) {
1156             MppEncUserDataFull *user_data_v2 = &user_datas->datas[i];
1157             if (user_data_v2->pdata && user_data_v2->len) {
1158                 if (user_data_v2->uuid)
1159                     enc_impl_add_prefix(impl, packet, &length, user_data_v2->uuid,
1160                                         user_data_v2->pdata, user_data_v2->len);
1161                 else
1162                     enc_impl_add_prefix(impl, packet, &length, uuid_debug_info,
1163                                         user_data_v2->pdata, user_data_v2->len);
1164 
1165                 hal_task->sei_length += length;
1166                 hal_task->length += length;
1167             }
1168         }
1169     }
1170 }
1171 
set_rc_cfg(RcCfg * cfg,MppEncCfgSet * cfg_set)1172 static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set)
1173 {
1174     MppEncRcCfg *rc = &cfg_set->rc;
1175     MppEncPrepCfg *prep = &cfg_set->prep;
1176     MppEncCodecCfg *codec = &cfg_set->codec;
1177     MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg;
1178     MppEncCpbInfo *info = &ref->cpb_info;
1179 
1180     cfg->width = prep->width;
1181     cfg->height = prep->height;
1182 
1183     switch (rc->rc_mode) {
1184     case MPP_ENC_RC_MODE_CBR : {
1185         cfg->mode = RC_CBR;
1186     } break;
1187     case MPP_ENC_RC_MODE_VBR : {
1188         cfg->mode = RC_VBR;
1189     } break;
1190     case MPP_ENC_RC_MODE_AVBR : {
1191         cfg->mode = RC_AVBR;
1192     } break;
1193     case MPP_ENC_RC_MODE_FIXQP: {
1194         cfg->mode = RC_FIXQP;
1195     } break;
1196     default : {
1197         cfg->mode = RC_AVBR;
1198     } break;
1199     }
1200 
1201     cfg->fps.fps_in_flex    = rc->fps_in_flex;
1202     cfg->fps.fps_in_num     = rc->fps_in_num;
1203     cfg->fps.fps_in_denorm  = rc->fps_in_denorm;
1204     cfg->fps.fps_out_flex   = rc->fps_out_flex;
1205     cfg->fps.fps_out_num    = rc->fps_out_num;
1206     cfg->fps.fps_out_denorm = rc->fps_out_denorm;
1207     cfg->igop               = rc->gop;
1208     cfg->max_i_bit_prop     = rc->max_i_prop;
1209     cfg->min_i_bit_prop     = rc->min_i_prop;
1210     cfg->init_ip_ratio      = rc->init_ip_ratio;
1211 
1212     cfg->bps_target = rc->bps_target;
1213     cfg->bps_max    = rc->bps_max;
1214     cfg->bps_min    = rc->bps_min;
1215 
1216     cfg->hier_qp_cfg.hier_qp_en = rc->hier_qp_en;
1217     memcpy(cfg->hier_qp_cfg.hier_frame_num, rc->hier_frame_num, sizeof(rc->hier_frame_num));
1218     memcpy(cfg->hier_qp_cfg.hier_qp_delta, rc->hier_qp_delta, sizeof(rc->hier_qp_delta));
1219 
1220     mpp_assert(rc->fps_out_num);
1221     cfg->stats_time = rc->stats_time ? rc->stats_time : 3;
1222     cfg->stats_time = mpp_clip(cfg->stats_time, 1, 60);
1223 
1224     /* quality configure */
1225     switch (codec->coding) {
1226     case MPP_VIDEO_CodingAVC :
1227     case MPP_VIDEO_CodingHEVC :
1228     case MPP_VIDEO_CodingVP8 : {
1229         cfg->init_quality = rc->qp_init;
1230         cfg->max_quality = rc->qp_max;
1231         cfg->min_quality = rc->qp_min;
1232         cfg->max_i_quality = rc->qp_max_i ? rc->qp_max_i : rc->qp_max;
1233         cfg->min_i_quality = rc->qp_min_i ? rc->qp_min_i : rc->qp_min;
1234         cfg->i_quality_delta = rc->qp_delta_ip;
1235         cfg->vi_quality_delta = rc->qp_delta_vi;
1236     } break;
1237     case MPP_VIDEO_CodingMJPEG : {
1238         MppEncJpegCfg *jpeg = &codec->jpeg;
1239 
1240         cfg->init_quality = jpeg->q_factor;
1241         cfg->max_quality = jpeg->qf_max;
1242         cfg->min_quality = jpeg->qf_min;
1243         cfg->max_i_quality = jpeg->qf_max;
1244         cfg->min_i_quality = jpeg->qf_min;
1245     } break;
1246     default : {
1247         mpp_err_f("unsupport coding type %d\n", codec->coding);
1248     } break;
1249     }
1250 
1251     cfg->layer_bit_prop[0] = 256;
1252     cfg->layer_bit_prop[1] = 0;
1253     cfg->layer_bit_prop[2] = 0;
1254     cfg->layer_bit_prop[3] = 0;
1255 
1256     cfg->max_reencode_times = rc->max_reenc_times;
1257     cfg->drop_mode = rc->drop_mode;
1258     cfg->drop_thd = rc->drop_threshold;
1259     cfg->drop_gap = rc->drop_gap;
1260 
1261     cfg->super_cfg.rc_priority = rc->rc_priority;
1262     cfg->super_cfg.super_mode = rc->super_mode;
1263     cfg->super_cfg.super_i_thd = rc->super_i_thd;
1264     cfg->super_cfg.super_p_thd = rc->super_p_thd;
1265 
1266     cfg->debreath_cfg.enable   = rc->debreath_en;
1267     cfg->debreath_cfg.strength = rc->debre_strength;
1268 
1269     cfg->refresh_len = rc->refresh_length;
1270 
1271     if (info->st_gop) {
1272         cfg->vgop = info->st_gop;
1273         if (cfg->vgop >= rc->fps_out_num / rc->fps_out_denorm &&
1274             cfg->vgop < cfg->igop ) {
1275             cfg->gop_mode = SMART_P;
1276             if (!cfg->vi_quality_delta)
1277                 cfg->vi_quality_delta = 2;
1278         }
1279     }
1280 
1281     if (codec->coding == MPP_VIDEO_CodingAVC ||
1282         codec->coding == MPP_VIDEO_CodingHEVC) {
1283         mpp_log("mode %s bps [%d:%d:%d] fps %s [%d/%d] -> %s [%d/%d] gop i [%d] v [%d]\n",
1284                 name_of_rc_mode[cfg->mode],
1285                 rc->bps_min, rc->bps_target, rc->bps_max,
1286                 cfg->fps.fps_in_flex ? "flex" : "fix",
1287                 cfg->fps.fps_in_num, cfg->fps.fps_in_denorm,
1288                 cfg->fps.fps_out_flex ? "flex" : "fix",
1289                 cfg->fps.fps_out_num, cfg->fps.fps_out_denorm,
1290                 cfg->igop, cfg->vgop);
1291     }
1292 }
1293 
mpp_enc_proc_rc_update(MppEncImpl * enc)1294 MPP_RET mpp_enc_proc_rc_update(MppEncImpl *enc)
1295 {
1296     MPP_RET ret = MPP_OK;
1297 
1298     // check and update rate control api
1299     if (!enc->rc_status.rc_api_inited || enc->rc_status.rc_api_updated) {
1300         RcApiBrief *brief = &enc->rc_brief;
1301 
1302         if (enc->rc_ctx) {
1303             enc_dbg_detail("rc deinit %p\n", enc->rc_ctx);
1304             rc_deinit(enc->rc_ctx);
1305             enc->rc_ctx = NULL;
1306         }
1307 
1308         /* NOTE: default name is NULL */
1309         ret = rc_init(&enc->rc_ctx, enc->coding, &brief->name);
1310         if (ret)
1311             mpp_err("enc %p fail to init rc %s\n", enc, brief->name);
1312         else
1313             enc->rc_status.rc_api_inited = 1;
1314 
1315         enc_dbg_detail("rc init %p name %s ret %d\n", enc->rc_ctx, brief->name, ret);
1316         enc->rc_status.rc_api_updated = 0;
1317 
1318         enc->rc_cfg_length = 0;
1319         update_rc_cfg_log(enc, "%s:", brief->name);
1320         enc->rc_cfg_pos = enc->rc_cfg_length;
1321     }
1322 
1323     // check and update rate control config
1324     if (enc->rc_status.rc_api_user_cfg) {
1325         MppEncCfgSet *cfg = &enc->cfg;
1326         MppEncRcCfg *rc_cfg = &cfg->rc;
1327         MppEncPrepCfg *prep_cfg = &cfg->prep;
1328         RcCfg usr_cfg;
1329 
1330         enc_dbg_detail("rc update cfg start\n");
1331 
1332         memset(&usr_cfg, 0 , sizeof(usr_cfg));
1333         set_rc_cfg(&usr_cfg, cfg);
1334         ret = rc_update_usr_cfg(enc->rc_ctx, &usr_cfg);
1335         rc_cfg->change = 0;
1336         prep_cfg->change = 0;
1337 
1338         enc_dbg_detail("rc update cfg done\n");
1339         enc->rc_status.rc_api_user_cfg = 0;
1340 
1341         enc->rc_cfg_length = enc->rc_cfg_pos;
1342         update_rc_cfg_log(enc, "%s-b:%d[%d:%d]-g:%d-q:%d:[%d:%d]:[%d:%d]:%d\n",
1343                           name_of_rc_mode[usr_cfg.mode],
1344                           usr_cfg.bps_target,
1345                           usr_cfg.bps_min, usr_cfg.bps_max, usr_cfg.igop,
1346                           usr_cfg.init_quality,
1347                           usr_cfg.min_quality, usr_cfg.max_quality,
1348                           usr_cfg.min_i_quality, usr_cfg.max_i_quality,
1349                           usr_cfg.i_quality_delta);
1350     }
1351 
1352     return ret;
1353 }
1354 
1355 #define ENC_RUN_FUNC2(func, ctx, task, mpp, ret)        \
1356     ret = func(ctx, task);                              \
1357     if (ret) {                                          \
1358         mpp_err("mpp %p "#func":%-4d failed return %d", \
1359                 mpp, __LINE__, ret);                    \
1360         goto TASK_DONE;                                 \
1361     }
1362 
mpp_enc_check_frm_pkt(MppEncImpl * enc)1363 static MPP_RET mpp_enc_check_frm_pkt(MppEncImpl *enc)
1364 {
1365     enc->frm_buf = NULL;
1366     enc->pkt_buf = NULL;
1367 
1368     if (enc->packet)
1369         enc->pkt_buf = mpp_packet_get_buffer(enc->packet);
1370     else
1371         mpp_packet_new(&enc->packet);
1372 
1373     if (enc->frame) {
1374         RK_S64 pts = mpp_frame_get_pts(enc->frame);
1375         MppBuffer frm_buf = mpp_frame_get_buffer(enc->frame);
1376 
1377         enc->task_pts = pts;
1378         enc->frm_buf = frm_buf;
1379 
1380         mpp_packet_set_pts(enc->packet, pts);
1381         mpp_packet_set_dts(enc->packet, mpp_frame_get_dts(enc->frame));
1382 
1383         if (mpp_frame_get_eos(enc->frame))
1384             mpp_packet_set_eos(enc->packet);
1385         else
1386             mpp_packet_clr_eos(enc->packet);
1387     }
1388 
1389     return (NULL == enc->frame || NULL == enc->frm_buf) ? MPP_NOK : MPP_OK;
1390 }
1391 
mpp_enc_check_pkt_buf(MppEncImpl * enc)1392 static MPP_RET mpp_enc_check_pkt_buf(MppEncImpl *enc)
1393 {
1394     if (NULL == enc->pkt_buf) {
1395         /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
1396         Mpp *mpp = (Mpp *)enc->mpp;
1397         MppEncPrepCfg *prep = &enc->cfg.prep;
1398         RK_U32 width  = MPP_ALIGN(prep->width, 16);
1399         RK_U32 height = MPP_ALIGN(prep->height, 16);
1400         RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
1401                       (width * height * 3 / 2) : (width * height);
1402         MppPacketImpl *pkt = (MppPacketImpl *)enc->packet;
1403         MppBuffer buffer = NULL;
1404 
1405         mpp_assert(size);
1406         mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
1407         mpp_assert(buffer);
1408         enc->pkt_buf = buffer;
1409         pkt->data   = mpp_buffer_get_ptr(buffer);
1410         pkt->pos    = pkt->data;
1411         pkt->size   = mpp_buffer_get_size(buffer);
1412         pkt->length = 0;
1413         pkt->buffer = buffer;
1414 
1415         enc_dbg_detail("create output pkt %p buf %p\n", enc->packet, buffer);
1416     } else {
1417         enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
1418                        enc->packet, enc->pkt_buf,
1419                        mpp_packet_get_pos(enc->packet),
1420                        mpp_packet_get_length(enc->packet));
1421     }
1422 
1423     return MPP_OK;
1424 }
1425 
mpp_enc_proc_two_pass(Mpp * mpp,EncAsyncTaskInfo * task)1426 static MPP_RET mpp_enc_proc_two_pass(Mpp *mpp, EncAsyncTaskInfo *task)
1427 {
1428     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1429     MPP_RET ret = MPP_OK;
1430 
1431     if (mpp_enc_refs_next_frm_is_intra(enc->refs)) {
1432         EncRcTask *rc_task = &task->rc;
1433         EncFrmStatus frm_bak = rc_task->frm;
1434         EncRcTaskInfo rc_info = rc_task->info;
1435         EncCpbStatus *cpb = &rc_task->cpb;
1436         EncFrmStatus *frm = &rc_task->frm;
1437         HalEncTask *hal_task = &task->task;
1438         EncImpl impl = enc->impl;
1439         MppEncHal hal = enc->enc_hal;
1440         MppPacket packet = hal_task->packet;
1441         RK_S32 task_len = hal_task->length;
1442         RK_S32 hw_len = hal_task->hw_length;
1443         RK_S32 pkt_len = mpp_packet_get_length(packet);
1444 
1445         enc_dbg_detail("task %d two pass mode enter\n", frm->seq_idx);
1446         rc_task->info = enc->rc_info_prev;
1447         hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
1448 
1449         enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1450         mpp_enc_refs_get_cpb_pass1(enc->refs, cpb);
1451 
1452         enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1453         ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1454 
1455         enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1456         ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
1457 
1458         enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1459         ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1460 
1461         enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1462         ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1463 
1464         enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1465         ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1466 
1467         enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1468         ENC_RUN_FUNC2(mpp_enc_hal_wait,  hal, hal_task, mpp, ret);
1469 
1470         enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1471         ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1472 
1473         //recover status & packet
1474         mpp_packet_set_length(packet, pkt_len);
1475         mpp_packet_set_segment_nb(packet, hal_task->segment_nb);
1476         hal_task->hw_length = hw_len;
1477         hal_task->length = task_len;
1478 
1479         *frm = frm_bak;
1480         rc_task->info = rc_info;
1481 
1482         enc_dbg_detail("task %d two pass mode leave\n", frm->seq_idx);
1483     }
1484 TASK_DONE:
1485     return ret;
1486 }
1487 
mpp_enc_rc_info_backup(MppEncImpl * enc,EncAsyncTaskInfo * task)1488 static void mpp_enc_rc_info_backup(MppEncImpl *enc, EncAsyncTaskInfo *task)
1489 {
1490     if (!enc->support_hw_deflicker || !enc->cfg.rc.debreath_en)
1491         return;
1492 
1493     enc->rc_info_prev = task->rc.info;
1494 }
1495 
mpp_enc_add_sw_header(MppEncImpl * enc,HalEncTask * hal_task)1496 static void mpp_enc_add_sw_header(MppEncImpl *enc, HalEncTask *hal_task)
1497 {
1498     EncImpl impl = enc->impl;
1499     MppEncHeaderStatus *hdr_status = &enc->hdr_status;
1500     EncRcTask *rc_task = hal_task->rc_task;
1501     EncFrmStatus *frm = &rc_task->frm;
1502     MppPacket packet = hal_task->packet;
1503     MppFrame frame = hal_task->frame;
1504 
1505     if (!(hdr_status->val & HDR_ADDED_MASK)) {
1506         RK_U32 add_header = 0;
1507 
1508         if (enc->hdr_mode == MPP_ENC_HEADER_MODE_EACH_IDR && frm->is_intra)
1509             add_header |= 1;
1510 
1511         if (enc->cfg.rc.refresh_en && frm->is_i_recovery && !frm->is_idr)
1512             add_header |= 2;
1513 
1514         if (add_header) {
1515             enc_dbg_detail("task %d IDR header length %d\n",
1516                            frm->seq_idx, enc->hdr_len);
1517 
1518             mpp_packet_append(packet, enc->hdr_pkt);
1519 
1520             hal_task->header_length = enc->hdr_len;
1521             hal_task->length += enc->hdr_len;
1522             hdr_status->added_by_mode = 1;
1523         }
1524 
1525         if ((add_header & 2) && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
1526             RK_S32 length = 0;
1527 
1528             enc_impl_add_prefix(impl, packet, &length, uuid_refresh_cfg,
1529                                 &enc->cfg.rc.refresh_length, 0);
1530 
1531             if (length) {
1532                 enc_dbg_detail("task %d refresh header length %d\n",
1533                                frm->seq_idx, enc->hdr_len);
1534 
1535                 hal_task->sei_length += length;
1536                 hal_task->length += length;
1537             }
1538         }
1539     }
1540 
1541     // check for header adding
1542     check_hal_task_pkt_len(hal_task, "header adding");
1543 
1544     /* 17. Add all prefix info before encoding */
1545     if (frm->is_idr && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
1546         RK_S32 length = 0;
1547 
1548         enc_impl_add_prefix(impl, packet, &length, uuid_version,
1549                             enc->version_info, enc->version_length);
1550 
1551         hal_task->sei_length += length;
1552         hal_task->length += length;
1553 
1554         length = 0;
1555         enc_impl_add_prefix(impl, packet, &length, uuid_rc_cfg,
1556                             enc->rc_cfg_info, enc->rc_cfg_length);
1557 
1558         hal_task->sei_length += length;
1559         hal_task->length += length;
1560     }
1561 
1562     if (mpp_frame_has_meta(frame)) {
1563         update_user_datas(impl, packet, frame, hal_task);
1564     }
1565 
1566     // check for user data adding
1567     check_hal_task_pkt_len(hal_task, "user data adding");
1568 }
1569 
mpp_enc_normal(Mpp * mpp,EncAsyncTaskInfo * task)1570 static MPP_RET mpp_enc_normal(Mpp *mpp, EncAsyncTaskInfo *task)
1571 {
1572     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1573     EncImpl impl = enc->impl;
1574     MppEncHal hal = enc->enc_hal;
1575     EncRcTask *rc_task = &task->rc;
1576     EncCpbStatus *cpb = &rc_task->cpb;
1577     EncFrmStatus *frm = &rc_task->frm;
1578     HalEncTask *hal_task = &task->task;
1579     MPP_RET ret = MPP_OK;
1580 
1581     if (enc->support_hw_deflicker && enc->cfg.rc.debreath_en) {
1582         ret = mpp_enc_proc_two_pass(mpp, task);
1583         if (ret)
1584             return ret;
1585     }
1586 
1587     enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1588     mpp_enc_refs_get_cpb(enc->refs, cpb);
1589 
1590     enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1591     ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1592 
1593     enc_dbg_frm_status("frm %d compare\n", cpb->curr.seq_idx);
1594     enc_dbg_frm_status("seq_idx      %d vs %d\n", frm->seq_idx, cpb->curr.seq_idx);
1595     enc_dbg_frm_status("is_idr       %d vs %d\n", frm->is_idr, cpb->curr.is_idr);
1596     enc_dbg_frm_status("is_intra     %d vs %d\n", frm->is_intra, cpb->curr.is_intra);
1597     enc_dbg_frm_status("is_non_ref   %d vs %d\n", frm->is_non_ref, cpb->curr.is_non_ref);
1598     enc_dbg_frm_status("is_lt_ref    %d vs %d\n", frm->is_lt_ref, cpb->curr.is_lt_ref);
1599     enc_dbg_frm_status("lt_idx       %d vs %d\n", frm->lt_idx, cpb->curr.lt_idx);
1600     enc_dbg_frm_status("temporal_id  %d vs %d\n", frm->temporal_id, cpb->curr.temporal_id);
1601     enc_dbg_frm_status("frm %d done  ***********************************\n", cpb->curr.seq_idx);
1602 
1603     enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
1604     ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
1605 
1606     // 16. generate header before hardware stream
1607     mpp_enc_add_sw_header(enc, hal_task);
1608 
1609     enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1610     ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
1611 
1612     enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1613     ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1614 
1615     enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
1616     ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
1617 
1618     enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1619     ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1620 
1621     hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
1622     mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
1623     enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1624     ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1625 
1626     enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1627     ENC_RUN_FUNC2(mpp_enc_hal_wait,  hal, hal_task, mpp, ret);
1628 
1629     mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
1630 
1631     enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
1632     ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
1633 
1634     enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1635     ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1636 
1637     enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
1638     ENC_RUN_FUNC2(rc_frm_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
1639 
1640 TASK_DONE:
1641     return ret;
1642 }
1643 
mpp_enc_clr_rc_cb_info(EncRcTask * rc_task)1644 static void mpp_enc_clr_rc_cb_info(EncRcTask *rc_task)
1645 {
1646     EncRcTaskInfo *hal_rc = (EncRcTaskInfo *) &rc_task->info;
1647     EncRcTaskInfo bak = rc_task->info;
1648 
1649     memset(hal_rc, 0, sizeof(rc_task->info));
1650 
1651     hal_rc->frame_type = bak.frame_type;
1652     hal_rc->bit_target = bak.bit_target;
1653     hal_rc->bit_max = bak.bit_max;
1654     hal_rc->bit_min = bak.bit_min;
1655     hal_rc->quality_target = bak.quality_target;
1656     hal_rc->quality_max = bak.quality_max;
1657     hal_rc->quality_min = bak.quality_min;
1658 }
1659 
mpp_enc_reenc_simple(Mpp * mpp,EncAsyncTaskInfo * task)1660 static MPP_RET mpp_enc_reenc_simple(Mpp *mpp, EncAsyncTaskInfo *task)
1661 {
1662     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1663     MppEncHal hal = enc->enc_hal;
1664     EncRcTask *rc_task = &task->rc;
1665     EncFrmStatus *frm = &rc_task->frm;
1666     HalEncTask *hal_task = &task->task;
1667     MPP_RET ret = MPP_OK;
1668 
1669     enc_dbg_func("enter\n");
1670 
1671     mpp_enc_clr_rc_cb_info(rc_task);
1672 
1673     enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1674     ENC_RUN_FUNC2(enc_impl_proc_hal, enc->impl, hal_task, mpp, ret);
1675 
1676     enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1677     ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1678 
1679     enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
1680     ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
1681 
1682     enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1683     ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1684 
1685     enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1686     ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1687 
1688     enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1689     ENC_RUN_FUNC2(mpp_enc_hal_wait,  hal, hal_task, mpp, ret);
1690 
1691     enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
1692     ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
1693 
1694     enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1695     ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1696 
1697     enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
1698     ENC_RUN_FUNC2(rc_frm_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
1699 
1700     enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
1701     enc_dbg_func("leave\n");
1702 
1703 TASK_DONE:
1704     return ret;
1705 }
1706 
mpp_enc_reenc_drop(Mpp * mpp,EncAsyncTaskInfo * task)1707 static MPP_RET mpp_enc_reenc_drop(Mpp *mpp, EncAsyncTaskInfo *task)
1708 {
1709     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1710     EncRcTask *rc_task = &task->rc;
1711     EncRcTaskInfo *info = &rc_task->info;
1712     EncFrmStatus *frm = &rc_task->frm;
1713     HalEncTask *hal_task = &task->task;
1714     MPP_RET ret = MPP_OK;
1715 
1716     enc_dbg_func("enter\n");
1717     mpp_enc_refs_rollback(enc->refs);
1718 
1719     info->bit_real = hal_task->length;
1720     info->quality_real = info->quality_target;
1721 
1722     enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
1723     ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
1724 
1725 TASK_DONE:
1726     enc_dbg_func("leave\n");
1727     return ret;
1728 }
1729 
mpp_enc_reenc_force_pskip(Mpp * mpp,EncAsyncTaskInfo * task)1730 static MPP_RET mpp_enc_reenc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task)
1731 {
1732     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1733     EncImpl impl = enc->impl;
1734     MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
1735     EncRcTask *rc_task = &task->rc;
1736     EncCpbStatus *cpb = &rc_task->cpb;
1737     EncFrmStatus *frm = &rc_task->frm;
1738     HalEncTask *hal_task = &task->task;
1739     MPP_RET ret = MPP_OK;
1740 
1741     enc_dbg_func("enter\n");
1742 
1743     frm_cfg->force_pskip++;
1744     frm_cfg->force_flag |= ENC_FORCE_PSKIP;
1745 
1746     /* NOTE: in some condition the pskip should not happen */
1747 
1748     mpp_enc_refs_rollback(enc->refs);
1749     mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1750 
1751     enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1752     mpp_enc_refs_get_cpb(enc->refs, cpb);
1753 
1754     enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1755     ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1756 
1757     enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx);
1758     ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret);
1759 
1760     enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
1761     ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
1762 
1763 TASK_DONE:
1764     enc_dbg_func("leave\n");
1765     return ret;
1766 }
1767 
mpp_enc_terminate_task(MppEncImpl * enc,EncAsyncTaskInfo * task)1768 static void mpp_enc_terminate_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
1769 {
1770     HalEncTask *hal_task = &task->task;
1771     EncFrmStatus *frm = &task->rc.frm;
1772 
1773     mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
1774 
1775     if (enc->packet) {
1776         /* setup output packet and meta data */
1777         mpp_packet_set_length(enc->packet, hal_task->length);
1778 
1779         /*
1780          * First return output packet.
1781          * Then enqueue task back to input port.
1782          * Final user will release the mpp_frame they had input.
1783          */
1784         enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
1785 
1786         mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, enc->packet);
1787         mpp_port_enqueue(enc->output, enc->task_out);
1788     }
1789 
1790     if (enc->task_in) {
1791         enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
1792 
1793         mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
1794         mpp_port_enqueue(enc->input, enc->task_in);
1795     }
1796 
1797     reset_enc_task(enc);
1798     task->status.val = 0;
1799 }
1800 
try_get_enc_task(MppEncImpl * enc,EncAsyncTaskInfo * task,EncAsyncWait * wait)1801 static MPP_RET try_get_enc_task(MppEncImpl *enc, EncAsyncTaskInfo *task, EncAsyncWait *wait)
1802 {
1803     EncRcTask *rc_task = &task->rc;
1804     EncFrmStatus *frm = &rc_task->frm;
1805     MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
1806     MppEncHeaderStatus *hdr_status = &enc->hdr_status;
1807     EncAsyncStatus *status = &task->status;
1808     HalEncTask *hal_task = &task->task;
1809     MppStopwatch stopwatch = NULL;
1810     MPP_RET ret = MPP_OK;
1811 
1812     if (!status->task_in_rdy) {
1813         ret = mpp_port_poll(enc->input, MPP_POLL_NON_BLOCK);
1814         if (ret < 0) {
1815             wait->enc_frm_in = 1;
1816             return ret;
1817         }
1818 
1819         status->task_in_rdy = 1;
1820         wait->enc_frm_in = 0;
1821         enc_dbg_detail("task in ready\n");
1822     }
1823 
1824     // 5. check output task
1825     if (!status->task_out_rdy) {
1826         ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
1827         if (ret < 0) {
1828             wait->enc_pkt_out = 1;
1829             return ret;
1830         }
1831 
1832         status->task_out_rdy = 1;
1833         wait->enc_pkt_out = 0;
1834         enc_dbg_detail("task out ready\n");
1835     }
1836 
1837     /*
1838      * 6. get frame and packet for one task
1839      * If there is no input frame just return empty packet task
1840      */
1841     if (!status->frm_pkt_rdy) {
1842         // get tasks from both input and output
1843         ret = mpp_port_dequeue(enc->input, &enc->task_in);
1844         mpp_assert(enc->task_in);
1845 
1846         ret = mpp_port_dequeue(enc->output, &enc->task_out);
1847         mpp_assert(enc->task_out);
1848 
1849         /*
1850          * frame will be return to input.
1851          * packet will be sent to output.
1852          */
1853         mpp_task_meta_get_frame (enc->task_in, KEY_INPUT_FRAME,  &enc->frame);
1854         mpp_task_meta_get_packet(enc->task_in, KEY_OUTPUT_PACKET, &enc->packet);
1855         mpp_task_meta_get_buffer(enc->task_in, KEY_MOTION_INFO, &enc->md_info);
1856 
1857         enc_dbg_detail("task dequeue done frm %p pkt %p\n", enc->frame, enc->packet);
1858 
1859         stopwatch = mpp_frame_get_stopwatch(enc->frame);
1860         mpp_stopwatch_record(stopwatch, "encode task start");
1861 
1862         if (mpp_enc_check_frm_pkt(enc)) {
1863             mpp_stopwatch_record(stopwatch, "invalid on check frm pkt");
1864             reset_hal_enc_task(hal_task);
1865             ret = MPP_NOK;
1866             goto TASK_DONE;
1867         }
1868 
1869         status->frm_pkt_rdy = 1;
1870         enc_dbg_detail("task frame packet ready\n");
1871     }
1872 
1873     // 8. all task ready start encoding one frame
1874     if (!status->hal_task_reset_rdy) {
1875         reset_hal_enc_task(hal_task);
1876         reset_enc_rc_task(rc_task);
1877         task->usr = enc->frm_cfg;
1878         enc->frm_cfg.force_flag = 0;
1879 
1880         hal_task->rc_task   = rc_task;
1881         hal_task->frm_cfg   = frm_cfg;
1882         hal_task->frame     = enc->frame;
1883         hal_task->input     = enc->frm_buf;
1884         hal_task->packet    = enc->packet;
1885         hal_task->output    = enc->pkt_buf;
1886         hal_task->md_info   = enc->md_info;
1887         hal_task->stopwatch = stopwatch;
1888 
1889         frm->seq_idx = task->seq_idx++;
1890         rc_task->frame = enc->frame;
1891         enc_dbg_detail("task seq idx %d start\n", frm->seq_idx);
1892     }
1893 
1894     // 9. check frame drop by frame rate conversion
1895     if (!status->rc_check_frm_drop) {
1896         ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
1897         status->rc_check_frm_drop = 1;
1898         enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop);
1899 
1900         hal_task->valid = 1;
1901         // when the frame should be dropped just return empty packet
1902         if (frm->drop) {
1903             mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
1904             hal_task->length = 0;
1905             hal_task->flags.drop_by_fps = 1;
1906             status->enc_start = 1;
1907             if (!status->refs_force_update) {
1908                 if (frm_cfg->force_flag)
1909                     mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1910 
1911                 status->refs_force_update = 1;
1912             }
1913             ret = MPP_OK;
1914             goto TASK_DONE;
1915         }
1916     }
1917 
1918     // start encoder task process here
1919     mpp_assert(hal_task->valid);
1920 
1921     // 10. check and create packet for output
1922     if (!status->pkt_buf_rdy) {
1923         mpp_enc_check_pkt_buf(enc);
1924         status->pkt_buf_rdy = 1;
1925 
1926         hal_task->output = enc->pkt_buf;
1927     }
1928     mpp_assert(enc->packet);
1929     mpp_assert(enc->pkt_buf);
1930 
1931     // 11. check hal info update
1932     if (!enc->hal_info_updated) {
1933         update_enc_hal_info(enc);
1934         enc->hal_info_updated = 1;
1935     }
1936 
1937     // 12. generate header before hardware stream
1938     if (!hdr_status->ready) {
1939         /* config cpb before generating header */
1940         enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
1941         enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
1942         hdr_status->ready = 1;
1943 
1944         enc_dbg_detail("task %d update header length %d\n",
1945                        frm->seq_idx, enc->hdr_len);
1946 
1947         mpp_packet_append(enc->packet, enc->hdr_pkt);
1948         hal_task->header_length = enc->hdr_len;
1949         hal_task->length += enc->hdr_len;
1950         hdr_status->added_by_change = 1;
1951     }
1952 
1953     check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
1954 
1955     // 13. check frm_meta data force key in input frame and start one frame
1956     if (!status->enc_start) {
1957         enc_dbg_detail("task %d enc start\n", frm->seq_idx);
1958         ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
1959         status->enc_start = 1;
1960     }
1961 
1962     // 14. setup user_cfg to dpb
1963     if (!status->refs_force_update) {
1964         if (frm_cfg->force_flag)
1965             mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1966 
1967         status->refs_force_update = 1;
1968     }
1969 
1970     // 15. backup dpb
1971     if (!status->enc_backup) {
1972         mpp_enc_refs_stash(enc->refs);
1973         status->enc_backup = 1;
1974     }
1975 
1976 TASK_DONE:
1977     if (ret)
1978         mpp_enc_terminate_task(enc, task);
1979     return ret;
1980 }
1981 
try_proc_low_deley_task(Mpp * mpp,EncAsyncTaskInfo * task,EncAsyncWait * wait)1982 static MPP_RET try_proc_low_deley_task(Mpp *mpp, EncAsyncTaskInfo *task, EncAsyncWait *wait)
1983 {
1984     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1985     EncImpl impl = enc->impl;
1986     MppEncHal hal = enc->enc_hal;
1987     EncRcTask *rc_task = &task->rc;
1988     EncCpbStatus *cpb = &rc_task->cpb;
1989     EncFrmStatus *frm = &rc_task->frm;
1990     EncAsyncStatus *status = &task->status;
1991     HalEncTask *hal_task = &task->task;
1992     MppPacket packet = hal_task->packet;
1993     MPP_RET ret = MPP_OK;
1994 
1995     if (hal_task->flags.drop_by_fps)
1996         goto TASK_DONE;
1997 
1998     if (status->low_delay_again)
1999         goto GET_OUTPUT_TASK;
2000 
2001     enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
2002     mpp_enc_refs_get_cpb(enc->refs, cpb);
2003 
2004     enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
2005     ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2006 
2007     enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2008     ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2009 
2010     // 16. generate header before hardware stream
2011     mpp_enc_add_sw_header(enc, hal_task);
2012 
2013     enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2014     ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2015 
2016     enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2017     ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2018 
2019     enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2020     ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2021 
2022     enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2023     ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2024 
2025     hal_task->part_first = 0;
2026     hal_task->part_last = 0;
2027 
2028     do {
2029         enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2030         ENC_RUN_FUNC2(mpp_enc_hal_part_start, hal, hal_task, mpp, ret);
2031 
2032         enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2033         ENC_RUN_FUNC2(mpp_enc_hal_part_wait,  hal, hal_task, mpp, ret);
2034 
2035         enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2036         ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2037 
2038         if (hal_task->part_first) {
2039             hal_task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2040             hal_task->part_length = 0;
2041         }
2042 
2043         mpp_packet_set_length(packet, hal_task->length);
2044 
2045         enc_dbg_detail("task %d task_out %p\n", frm->seq_idx, enc->task_out);
2046 
2047     GET_OUTPUT_TASK:
2048         /* output task as soon as  */
2049         if (NULL == enc->task_out) {
2050             enc_dbg_detail("task %d poll new task for part output\n", frm->seq_idx);
2051             ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
2052             if (ret < 0) {
2053                 wait->enc_pkt_out = 1;
2054                 status->low_delay_again = 1;
2055                 return MPP_NOK;
2056             }
2057 
2058             status->task_out_rdy = 1;
2059             wait->enc_pkt_out = 0;
2060             enc_dbg_detail("task out ready\n");
2061 
2062             ret = mpp_port_dequeue(enc->output, &enc->task_out);
2063         }
2064 
2065         mpp_assert(enc->task_out);
2066 
2067         /* copy new packet for multiple packet output */
2068         if (!hal_task->part_last) {
2069             RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2070             RK_U32 part_length = hal_task->length;
2071             RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2072             RK_U32 pkt_len = 0;
2073             MppPacketImpl *part_pkt = NULL;
2074 
2075             enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2076                            last_pos, part_pos, part_length);
2077 
2078             part_pos += part_length;
2079             pkt_len = (RK_U32)(part_pos - last_pos);
2080 
2081             mpp_packet_copy_init((MppPacket *)&part_pkt, packet);
2082             part_pkt->pos = last_pos;
2083             part_pkt->length = pkt_len;
2084             part_pkt->status.val = 0;
2085             part_pkt->status.partition = 1;
2086             part_pkt->status.soi = hal_task->part_first;
2087             part_pkt->status.eoi = hal_task->part_last;
2088 
2089             enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2090                            last_pos, pkt_len);
2091 
2092             hal_task->part_pos = part_pos;
2093 
2094             enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2095                            frm->seq_idx, enc->task_pts, hal_task->part_count);
2096             mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, part_pkt);
2097             mpp_port_enqueue(enc->output, enc->task_out);
2098             enc->task_out = NULL;
2099             hal_task->part_count++;
2100         }
2101     } while (!hal_task->part_last);
2102 
2103 TASK_DONE:
2104     /* output last task */
2105     {
2106         RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2107         size_t part_length = hal_task->length;
2108         RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2109         RK_U32 pkt_len = 0;
2110         MppPacketImpl *pkt = (MppPacketImpl *)packet;
2111 
2112         enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2113                        last_pos, part_pos, part_length);
2114 
2115         part_pos += part_length;
2116         pkt_len = part_pos - last_pos;
2117 
2118         enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2119                        last_pos, pkt_len);
2120 
2121         pkt->length = pkt_len;
2122         pkt->pos = last_pos;
2123         pkt->status.val = 0;
2124         pkt->status.partition = 1;
2125         pkt->status.soi = hal_task->part_first;
2126         pkt->status.eoi = hal_task->part_last;
2127 
2128         enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2129                        last_pos, pkt_len);
2130 
2131         hal_task->part_pos = part_pos;
2132 
2133         enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2134                        frm->seq_idx, enc->task_pts, hal_task->part_count);
2135         mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2136         mpp_port_enqueue(enc->output, enc->task_out);
2137         enc->task_out = NULL;
2138         hal_task->part_count = 0;
2139     }
2140     status->low_delay_again = 0;
2141 
2142     enc->time_end = mpp_time();
2143     enc->frame_count++;
2144 
2145     if (enc->dev && enc->time_base && enc->time_end &&
2146         ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2147         update_hal_info_fps(enc);
2148 
2149     enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2150     ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2151 
2152     enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2153 
2154     mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2155     mpp_port_enqueue(enc->input, enc->task_in);
2156 
2157     reset_enc_task(enc);
2158     status->val = 0;
2159     task->usr.force_flag = 0;
2160 
2161     return ret;
2162 }
2163 
try_proc_normal_task(MppEncImpl * enc,EncAsyncTaskInfo * task)2164 static MPP_RET try_proc_normal_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
2165 {
2166     Mpp *mpp = (Mpp*)enc->mpp;
2167     EncRcTask *rc_task = &task->rc;
2168     EncFrmStatus *frm = &rc_task->frm;
2169     MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
2170     HalEncTask *hal_task = &task->task;
2171     MppPacket packet = hal_task->packet;
2172     MPP_RET ret = MPP_OK;
2173 
2174     if (hal_task->flags.drop_by_fps)
2175         goto TASK_DONE;
2176 
2177     // 17. normal encode
2178     ENC_RUN_FUNC2(mpp_enc_normal, mpp, task, mpp, ret);
2179 
2180     // 18. drop, force pskip and reencode  process
2181     while (frm->reencode && frm->reencode_times < enc->cfg.rc.max_reenc_times) {
2182         hal_task->length -= hal_task->hw_length;
2183         hal_task->hw_length = 0;
2184 
2185         mpp_packet_set_segment_nb(hal_task->packet, hal_task->segment_nb);
2186 
2187         enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
2188 
2189         if (frm->drop) {
2190             mpp_enc_reenc_drop(mpp, task);
2191             break;
2192         }
2193 
2194         if (frm->force_pskip && !frm->is_idr && !frm->is_lt_ref) {
2195             mpp_enc_reenc_force_pskip(mpp, task);
2196             break;
2197         }
2198 
2199         mpp_enc_reenc_simple(mpp, task);
2200     }
2201     enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2202     ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2203 
2204     enc->time_end = mpp_time();
2205     enc->frame_count++;
2206 
2207     if (enc->dev && enc->time_base && enc->time_end &&
2208         ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2209         update_hal_info_fps(enc);
2210 
2211     frm->reencode = 0;
2212     frm->reencode_times = 0;
2213     frm_cfg->force_flag = 0;
2214 
2215 TASK_DONE:
2216     mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2217 
2218     if (!mpp_packet_is_partition(packet)) {
2219         /* setup output packet and meta data */
2220         mpp_packet_set_length(packet, hal_task->length);
2221     }
2222 
2223     {
2224         MppMeta meta = mpp_packet_get_meta(packet);
2225 
2226         if (hal_task->md_info)
2227             mpp_meta_set_buffer(meta, KEY_MOTION_INFO, hal_task->md_info);
2228 
2229         mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra);
2230         if (rc_task->info.quality_real)
2231             mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real);
2232 
2233         if (mpp->mEncAyncIo)
2234             mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame);
2235     }
2236 
2237     /* enc failed force idr */
2238     if (ret) {
2239         enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2240         enc->hdr_status.val = 0;
2241         mpp_packet_set_length(packet, 0);
2242         mpp_err_f("enc failed force idr!\n");
2243     }
2244     /*
2245      * First return output packet.
2246      * Then enqueue task back to input port.
2247      * Final user will release the mpp_frame they had input.
2248      */
2249     enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2250 
2251     mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2252     mpp_port_enqueue(enc->output, enc->task_out);
2253 
2254     enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2255 
2256     mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2257     mpp_port_enqueue(enc->input, enc->task_in);
2258 
2259     mpp_enc_rc_info_backup(enc, task);
2260     reset_enc_task(enc);
2261     task->status.val = 0;
2262 
2263     return ret;
2264 }
2265 
mpp_enc_thread(void * data)2266 void *mpp_enc_thread(void *data)
2267 {
2268     Mpp *mpp = (Mpp*)data;
2269     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2270     MppThread *thd_enc  = enc->thread_enc;
2271     EncAsyncTaskInfo task;
2272     EncAsyncWait wait;
2273     EncAsyncStatus *status = &task.status;
2274     MPP_RET ret = MPP_OK;
2275 
2276     memset(&task, 0, sizeof(task));
2277     wait.val = 0;
2278 
2279     enc->time_base = mpp_time();
2280 
2281     while (1) {
2282         {
2283             AutoMutex autolock(thd_enc->mutex());
2284             if (MPP_THREAD_RUNNING != thd_enc->get_status())
2285                 break;
2286 
2287             if (check_enc_task_wait(enc, &wait))
2288                 thd_enc->wait();
2289         }
2290 
2291         // When encoder is not on encoding process external config and reset
2292         if (!status->enc_start) {
2293             // 1. process user control
2294             if (enc->cmd_send != enc->cmd_recv) {
2295                 enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
2296                 sem_wait(&enc->cmd_start);
2297                 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
2298                 if (ret)
2299                     *enc->cmd_ret = ret;
2300                 enc->cmd_recv++;
2301                 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
2302                                enc->cmd_send);
2303                 mpp_assert(enc->cmd_send == enc->cmd_send);
2304                 enc->param = NULL;
2305                 enc->cmd = (MpiCmd)0;
2306                 sem_post(&enc->cmd_done);
2307 
2308                 // async cfg update process for hal
2309                 // mainly for buffer prepare
2310                 mpp_enc_hal_prepare(enc->enc_hal);
2311 
2312                 /* NOTE: here will clear change flag of rc and prep cfg */
2313                 mpp_enc_proc_rc_update(enc);
2314                 wait.val = 0;
2315                 continue;
2316             }
2317 
2318             // 2. process reset
2319             if (enc->reset_flag) {
2320                 enc_dbg_detail("thread reset start\n");
2321                 {
2322                     AutoMutex autolock(thd_enc->mutex());
2323                     enc->status_flag = 0;
2324                 }
2325 
2326                 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2327                 enc->frm_cfg.force_idr++;
2328 
2329                 AutoMutex autolock(thd_enc->mutex(THREAD_CONTROL));
2330                 enc->reset_flag = 0;
2331                 sem_post(&enc->enc_reset);
2332                 enc_dbg_detail("thread reset done\n");
2333                 wait.val = 0;
2334                 continue;
2335             }
2336 
2337             // 3. try get a task to encode
2338             ret = try_get_enc_task(enc, &task, &wait);
2339             if (ret)
2340                 continue;
2341         }
2342 
2343         mpp_assert(status->enc_start);
2344         if (!status->enc_start)
2345             continue;
2346 
2347         // check partition low delay encoding
2348         /*
2349          * NOTE: Only when both split encoding and low delay mode are set then
2350          *       use special low delay path
2351          */
2352         if (enc->low_delay_part_mode)
2353             try_proc_low_deley_task(mpp, &task, &wait);
2354         else
2355             try_proc_normal_task(enc, &task);
2356     }
2357 
2358     // clear remain task in enc->output port
2359     release_task_in_port(enc->input);
2360     release_task_in_port(mpp->mUsrOutPort);
2361 
2362     return NULL;
2363 }
2364 
async_task_reset(EncAsyncTaskInfo * task)2365 static void async_task_reset(EncAsyncTaskInfo *task)
2366 {
2367     memset(task, 0, sizeof(*task));
2368     task->task.rc_task = &task->rc;
2369     task->task.frm_cfg = &task->usr;
2370     task->usr.force_flag = 0;
2371 }
2372 
async_task_terminate(MppEncImpl * enc,EncAsyncTaskInfo * async)2373 static void async_task_terminate(MppEncImpl *enc, EncAsyncTaskInfo *async)
2374 {
2375     HalEncTask *hal_task = &async->task;
2376     EncFrmStatus *frm = &async->rc.frm;
2377     Mpp *mpp = (Mpp *)enc->mpp;
2378 
2379     mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2380 
2381     if (hal_task->packet) {
2382         MppPacket pkt = hal_task->packet;
2383 
2384         /* setup output packet and meta data */
2385         mpp_packet_set_length(pkt, hal_task->length);
2386 
2387         /*
2388          * First return output packet.
2389          * Then enqueue task back to input port.
2390          * Final user will release the mpp_frame they had input.
2391          */
2392         enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2393 
2394         if (mpp->mPktOut) {
2395             mpp_list *pkt_out = mpp->mPktOut;
2396 
2397             if (enc->frame) {
2398                 MppMeta meta = mpp_packet_get_meta(pkt);
2399                 MppStopwatch stopwatch = mpp_frame_get_stopwatch(enc->frame);
2400 
2401                 mpp_stopwatch_record(stopwatch, "encode task terminate");
2402 
2403                 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame);
2404                 enc->frame = NULL;
2405             }
2406 
2407             AutoMutex autolock(pkt_out->mutex());
2408 
2409             pkt_out->add_at_tail(&pkt, sizeof(pkt));
2410             mpp->mPacketPutCount++;
2411             pkt_out->signal();
2412             mpp_assert(pkt);
2413 
2414             enc_dbg_detail("packet out ready\n");
2415         }
2416     }
2417 
2418     async_task_reset(async);
2419 }
2420 
async_task_skip(MppEncImpl * enc)2421 static void async_task_skip(MppEncImpl *enc)
2422 {
2423     Mpp *mpp = (Mpp*)enc->mpp;
2424     MppStopwatch stopwatch = NULL;
2425     MppMeta meta = NULL;
2426     MppFrame frm = NULL;
2427     MppPacket pkt = NULL;
2428 
2429     mpp->mFrmIn->del_at_head(&frm, sizeof(frm));
2430     mpp->mFrameGetCount++;
2431 
2432     mpp_assert(frm);
2433 
2434     enc_dbg_detail("skip input frame start\n");
2435 
2436     stopwatch = mpp_frame_get_stopwatch(frm);
2437     mpp_stopwatch_record(stopwatch, "skip task start");
2438 
2439     if (mpp_frame_has_meta(frm)) {
2440         meta = mpp_frame_get_meta(frm);
2441         if (meta)
2442             mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &pkt);
2443     }
2444 
2445     if (NULL == pkt)
2446         mpp_packet_new(&pkt);
2447 
2448     mpp_assert(pkt);
2449 
2450     mpp_packet_set_length(pkt, 0);
2451     mpp_packet_set_pts(pkt, mpp_frame_get_pts(frm));
2452     mpp_packet_set_dts(pkt, mpp_frame_get_dts(frm));
2453 
2454     if (mpp_frame_get_eos(frm))
2455         mpp_packet_set_eos(pkt);
2456     else
2457         mpp_packet_clr_eos(pkt);
2458 
2459     meta = mpp_packet_get_meta(pkt);
2460     mpp_assert(meta);
2461 
2462     mpp_meta_set_frame(meta, KEY_INPUT_FRAME, frm);
2463 
2464     if (mpp->mPktOut) {
2465         mpp_list *pkt_out = mpp->mPktOut;
2466 
2467         pkt_out->lock();
2468         mpp_stopwatch_record(stopwatch, "skip task output");
2469         pkt_out->add_at_tail(&pkt, sizeof(pkt));
2470         mpp->mPacketPutCount++;
2471         pkt_out->signal();
2472         pkt_out->unlock();
2473     }
2474 
2475     enc_dbg_detail("packet skip ready\n");
2476 }
2477 
check_async_frm_pkt(EncAsyncTaskInfo * async)2478 static MPP_RET check_async_frm_pkt(EncAsyncTaskInfo *async)
2479 {
2480     HalEncTask *hal_task = &async->task;
2481     MppPacket packet = hal_task->packet;
2482     MppFrame frame = hal_task->frame;
2483 
2484     hal_task->input = NULL;
2485     hal_task->output = NULL;
2486 
2487     if (packet)
2488         hal_task->output = mpp_packet_get_buffer(packet);
2489     else {
2490         mpp_packet_new(&packet);
2491         hal_task->packet = packet;
2492     }
2493 
2494     if (frame) {
2495         RK_S64 pts = mpp_frame_get_pts(frame);
2496         MppBuffer frm_buf = mpp_frame_get_buffer(frame);
2497 
2498         hal_task->input = frm_buf;
2499 
2500         mpp_packet_set_pts(packet, pts);
2501         mpp_packet_set_dts(packet, mpp_frame_get_dts(frame));
2502 
2503         if (mpp_frame_get_eos(frame))
2504             mpp_packet_set_eos(packet);
2505         else
2506             mpp_packet_clr_eos(packet);
2507     }
2508 
2509     return (NULL == frame || NULL == hal_task->input) ? MPP_NOK : MPP_OK;
2510 }
2511 
check_async_pkt_buf(MppEncImpl * enc,EncAsyncTaskInfo * async)2512 static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTaskInfo *async)
2513 {
2514     HalEncTask *hal_task = &async->task;
2515 
2516     if (NULL == hal_task->output) {
2517         /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
2518         Mpp *mpp = (Mpp *)enc->mpp;
2519         MppEncPrepCfg *prep = &enc->cfg.prep;
2520         RK_U32 width  = MPP_ALIGN(prep->width, 16);
2521         RK_U32 height = MPP_ALIGN(prep->height, 16);
2522         RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
2523                       (width * height * 3 / 2) : (width * height);
2524         MppPacketImpl *pkt = (MppPacketImpl *)hal_task->packet;
2525         MppBuffer buffer = NULL;
2526 
2527         mpp_assert(size);
2528         mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
2529         mpp_assert(buffer);
2530         enc->pkt_buf = buffer;
2531         pkt->data   = mpp_buffer_get_ptr(buffer);
2532         pkt->pos    = pkt->data;
2533         pkt->size   = mpp_buffer_get_size(buffer);
2534         pkt->length = 0;
2535         pkt->buffer = buffer;
2536         hal_task->output = buffer;
2537 
2538         enc_dbg_detail("create output pkt %p buf %p\n", hal_task->packet, buffer);
2539     } else {
2540         enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
2541                        hal_task->packet, hal_task->output,
2542                        mpp_packet_get_pos(hal_task->packet),
2543                        mpp_packet_get_length(hal_task->packet));
2544     }
2545 
2546     return MPP_OK;
2547 }
2548 
try_get_async_task(MppEncImpl * enc,EncAsyncWait * wait)2549 static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncWait *wait)
2550 {
2551     Mpp *mpp = (Mpp *)enc->mpp;
2552     EncAsyncTaskInfo *async = enc->async;
2553     EncRcTask *rc_task = NULL;
2554     MppEncHeaderStatus *hdr_status = &enc->hdr_status;
2555     HalEncTask *hal_task = NULL;
2556     EncAsyncStatus *status = NULL;
2557     MppStopwatch stopwatch = NULL;
2558     MppPacket packet = NULL;
2559     MppFrame frame = NULL;
2560     RK_U32 seq_idx = 0;
2561     MPP_RET ret = MPP_OK;
2562 
2563     if (NULL == enc->hnd) {
2564         hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd);
2565         if (enc->hnd) {
2566             wait->task_hnd = 0;
2567             enc_dbg_detail("get hnd success\n");
2568 
2569             mpp_assert(enc->async == NULL);
2570             async = (EncAsyncTaskInfo *)hal_task_hnd_get_data(enc->hnd);
2571             async_task_reset(async);
2572             enc->async = async;
2573         } else {
2574             wait->task_hnd = 1;
2575             enc_dbg_detail("get hnd failed\n");
2576             return MPP_NOK;
2577         }
2578     }
2579 
2580     mpp_assert(enc->hnd);
2581     mpp_assert(enc->async);
2582 
2583     hal_task = &async->task;
2584     rc_task = &async->rc;
2585     status = &async->status;
2586     packet = hal_task->packet;
2587     frame = hal_task->frame;
2588 
2589     if (NULL == frame) {
2590         if (mpp->mFrmIn) {
2591             mpp_list *frm_in = mpp->mFrmIn;
2592             AutoMutex autolock(frm_in->mutex());
2593 
2594             if (frm_in->list_size()) {
2595                 frm_in->del_at_head(&frame, sizeof(frame));
2596                 frm_in->signal();
2597                 mpp->mFrameGetCount++;
2598 
2599                 mpp_assert(frame);
2600 
2601                 status->task_in_rdy = 1;
2602                 wait->enc_frm_in = 0;
2603 
2604                 enc_dbg_detail("get input frame success\n");
2605 
2606                 stopwatch = mpp_frame_get_stopwatch(frame);
2607                 mpp_stopwatch_record(stopwatch, "encode task start");
2608 
2609                 hal_task->frame = frame;
2610             }
2611         }
2612 
2613         if (NULL == frame) {
2614             enc_dbg_detail("get input frame failed\n");
2615             wait->enc_frm_in = 1;
2616             return MPP_NOK;
2617         }
2618     }
2619 
2620     if (NULL == packet) {
2621         if (mpp_frame_has_meta(frame)) {
2622             MppMeta meta = mpp_frame_get_meta(frame);
2623 
2624             mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet);
2625         }
2626 
2627         if (packet) {
2628             status->task_out_rdy = 1;
2629             wait->enc_pkt_out = 0;
2630 
2631             enc_dbg_detail("get output packet success\n");
2632 
2633             hal_task->packet = packet;
2634         }
2635     }
2636 
2637     mpp_assert(frame);
2638 
2639     stopwatch = mpp_frame_get_stopwatch(frame);
2640 
2641     /*
2642      * 6. get frame and packet for one task
2643      * If there is no input frame just return empty packet task
2644      */
2645     if (!status->frm_pkt_rdy) {
2646         async->seq_idx = enc->task_idx++;
2647         async->pts = mpp_frame_get_pts(hal_task->frame);
2648 
2649         hal_task->stopwatch = stopwatch;
2650         rc_task->frame = async->task.frame;
2651 
2652         enc_dbg_detail("task seq idx %d start\n", seq_idx);
2653 
2654         if (check_async_frm_pkt(async)) {
2655             mpp_stopwatch_record(stopwatch, "empty frame on check frm pkt");
2656             hal_task->valid = 1;
2657             hal_task->length = 0;
2658             hal_task->flags.drop_by_fps = 1;
2659             ret = MPP_OK;
2660             goto TASK_DONE;
2661         }
2662 
2663         status->frm_pkt_rdy = 1;
2664         enc_dbg_detail("task frame packet ready\n");
2665     }
2666 
2667     seq_idx = async->seq_idx;
2668 
2669     // 9. check frame drop by frame rate conversion
2670     if (!status->rc_check_frm_drop) {
2671         EncFrmStatus *frm = &rc_task->frm;
2672 
2673         ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
2674         status->rc_check_frm_drop = 1;
2675         enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop);
2676 
2677         // when the frame should be dropped just return empty packet
2678         hal_task->valid = 1;
2679         if (frm->drop) {
2680             mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
2681             hal_task->length = 0;
2682             hal_task->flags.drop_by_fps = 1;
2683             ret = MPP_OK;
2684             goto TASK_DONE;
2685         }
2686 
2687         *hal_task->frm_cfg = enc->frm_cfg;
2688         enc->frm_cfg.force_flag = 0;
2689     }
2690 
2691     // start encoder task process here
2692     mpp_assert(hal_task->valid);
2693 
2694     // 10. check and create packet for output
2695     if (!status->pkt_buf_rdy) {
2696         check_async_pkt_buf(enc, async);
2697         status->pkt_buf_rdy = 1;
2698 
2699         enc_dbg_detail("task %d check pkt buffer success\n", seq_idx);
2700     }
2701     mpp_assert(hal_task->packet);
2702     mpp_assert(hal_task->output);
2703 
2704     // 11. check hal info update
2705     if (!enc->hal_info_updated) {
2706         update_enc_hal_info(enc);
2707         enc->hal_info_updated = 1;
2708 
2709         enc_dbg_detail("task %d update enc hal info success\n", seq_idx);
2710     }
2711 
2712     // 12. generate header before hardware stream
2713     if (!hdr_status->ready) {
2714         /* config cpb before generating header */
2715         enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
2716         enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
2717         hdr_status->ready = 1;
2718 
2719         enc_dbg_detail("task %d update header length %d\n",
2720                        seq_idx, enc->hdr_len);
2721 
2722         mpp_packet_append(hal_task->packet, enc->hdr_pkt);
2723         hal_task->header_length = enc->hdr_len;
2724         hal_task->length += enc->hdr_len;
2725         hdr_status->added_by_change = 1;
2726     }
2727 
2728     check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
2729 
2730     // 13. check frm_meta data force key in input frame and start one frame
2731     if (!status->enc_start) {
2732         enc_dbg_detail("task %d enc start\n", seq_idx);
2733         ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
2734         status->enc_start = 1;
2735     }
2736 
2737     // 14. setup user_cfg to dpb
2738     if (!status->refs_force_update) {
2739         MppEncRefFrmUsrCfg *frm_cfg = &async->usr;
2740 
2741         if (frm_cfg->force_flag) {
2742             mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
2743             frm_cfg->force_flag = 0;
2744         }
2745 
2746         enc_dbg_detail("task %d refs force update success\n", seq_idx);
2747         status->refs_force_update = 1;
2748     }
2749 
2750     // 15. backup dpb
2751     if (!status->enc_backup) {
2752         mpp_enc_refs_stash(enc->refs);
2753         enc_dbg_detail("task %d refs stash success\n", seq_idx);
2754         status->enc_backup = 1;
2755     }
2756 
2757 TASK_DONE:
2758     if (ret) {
2759         enc_dbg_detail("task %d terminate\n", seq_idx);
2760         async_task_terminate(enc, async);
2761     }
2762 
2763     return ret;
2764 }
2765 
proc_async_task(MppEncImpl * enc)2766 static MPP_RET proc_async_task(MppEncImpl *enc)
2767 {
2768     Mpp *mpp = (Mpp*)enc->mpp;
2769     EncImpl impl = enc->impl;
2770     MppEncHal hal = enc->enc_hal;
2771     EncAsyncTaskInfo *async = enc->async;
2772     EncAsyncStatus *status = &async->status;
2773     HalEncTask *hal_task = &async->task;
2774     EncRcTask *rc_task = hal_task->rc_task;
2775     EncCpbStatus *cpb = &rc_task->cpb;
2776     EncFrmStatus *frm = &rc_task->frm;
2777     RK_U32 seq_idx = async->seq_idx;
2778     MPP_RET ret = MPP_OK;
2779 
2780     mpp_assert(hal_task->valid);
2781 
2782     if (hal_task->flags.drop_by_fps)
2783         goto SEND_TASK_INFO;
2784 
2785     enc_dbg_detail("task %d enc proc dpb\n", seq_idx);
2786     mpp_enc_refs_get_cpb(enc->refs, cpb);
2787 
2788     enc_dbg_frm_status("frm %d start ***********************************\n", seq_idx);
2789     ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2790 
2791     enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2792     ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2793 
2794     // 16. generate header before hardware stream
2795     mpp_enc_add_sw_header(enc, hal_task);
2796 
2797     enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2798     ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2799 
2800     enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2801     ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2802 
2803     enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2804     ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2805 
2806     enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2807     ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2808 
2809     mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
2810     enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2811     ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
2812 
2813 SEND_TASK_INFO:
2814     status->enc_done = 0;
2815     hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING);
2816     enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret);
2817 
2818     enc->hnd = NULL;
2819     enc->async = NULL;
2820 
2821 TASK_DONE:
2822 
2823     /* NOTE: clear add_by flags */
2824     enc->hdr_status.val = enc->hdr_status.ready;
2825 
2826     return ret;
2827 }
2828 
check_enc_async_wait(MppEncImpl * enc,EncAsyncWait * wait)2829 static MPP_RET check_enc_async_wait(MppEncImpl *enc, EncAsyncWait *wait)
2830 {
2831     MPP_RET ret = MPP_OK;
2832     RK_U32 notify = enc->notify_flag;
2833     RK_U32 last_wait = enc->status_flag;
2834     RK_U32 curr_wait = wait->val;
2835     RK_U32 wait_chg  = last_wait & (~curr_wait);
2836     RK_U32 keep_notify = 0;
2837 
2838     do {
2839         if (enc->reset_flag)
2840             break;
2841 
2842         // NOTE: User control should always be processed
2843         if (notify & MPP_ENC_CONTROL) {
2844             keep_notify = notify & (~MPP_ENC_CONTROL);
2845             break;
2846         }
2847 
2848         // NOTE: When condition is not fulfilled check nofify flag again
2849         if (!curr_wait || (curr_wait & notify))
2850             break;
2851 
2852         ret = MPP_NOK;
2853     } while (0);
2854 
2855     enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
2856                    last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
2857 
2858     enc->status_flag = wait->val;
2859     enc->notify_flag = keep_notify;
2860 
2861     if (ret) {
2862         enc->wait_count++;
2863     } else {
2864         enc->work_count++;
2865     }
2866 
2867     return ret;
2868 }
2869 
enc_async_wait_task(MppEncImpl * enc,EncAsyncTaskInfo * info)2870 static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info)
2871 {
2872     Mpp *mpp = (Mpp*)enc->mpp;
2873     MppEncHal hal = enc->enc_hal;
2874     HalEncTask *hal_task = &info->task;
2875     EncRcTask *rc_task = hal_task->rc_task;
2876     EncFrmStatus *frm = &info->rc.frm;
2877     MppPacket pkt = hal_task->packet;
2878     MppMeta meta = mpp_packet_get_meta(pkt);
2879     MPP_RET ret = MPP_OK;
2880 
2881     if (hal_task->flags.drop_by_fps)
2882         goto TASK_DONE;
2883 
2884     enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2885     ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
2886 
2887     mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
2888 
2889     enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2890     ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2891 
2892     enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2893     ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2894 
2895     enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2896     ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2897 
2898 TASK_DONE:
2899     if (!mpp_packet_is_partition(pkt)) {
2900         /* setup output packet and meta data */
2901         mpp_packet_set_length(pkt, hal_task->length);
2902 
2903         check_hal_task_pkt_len(hal_task, "hw finish");
2904     }
2905 
2906     mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra);
2907     if (rc_task->info.quality_real)
2908         mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real);
2909 
2910     mpp_meta_set_frame(meta, KEY_INPUT_FRAME, hal_task->frame);
2911 
2912     enc_dbg_detail("task %d output packet pts %lld\n", info->seq_idx, info->pts);
2913 
2914     /*
2915      * async encode process, there may have multiple frames encoding.
2916      * if last frame enc failed, drop non-idr frames and force idr for next frame.
2917      */
2918     if (enc->enc_failed_drop && !hal_task->rc_task->frm.is_idr) {
2919         mpp_packet_set_length(pkt, 0);
2920         mpp_err_f("last frame enc failed, drop this P frame\n");
2921         enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2922         enc->hdr_status.val = 0;
2923     } else
2924         enc->enc_failed_drop = 0;
2925     /* enc failed, force idr for next frame */
2926     if (ret) {
2927         enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2928         enc->hdr_status.val = 0;
2929         mpp_packet_set_length(pkt, 0);
2930         enc->enc_failed_drop = 1;
2931 
2932         mpp_err_f("enc failed force idr!\n");
2933     }
2934 
2935     if (mpp->mPktOut) {
2936         mpp_list *pkt_out = mpp->mPktOut;
2937 
2938         AutoMutex autoLock(pkt_out->mutex());
2939 
2940         pkt_out->add_at_tail(&pkt, sizeof(pkt));
2941         mpp->mPacketPutCount++;
2942         pkt_out->signal();
2943     }
2944 
2945     return ret;
2946 }
2947 
mpp_enc_async_thread(void * data)2948 void *mpp_enc_async_thread(void *data)
2949 {
2950     Mpp *mpp = (Mpp*)data;
2951     MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2952     MppThread *thd_enc = enc->thread_enc;
2953     EncAsyncWait wait;
2954     MPP_RET ret = MPP_OK;
2955 
2956     enc_dbg_func("thread start\n");
2957 
2958     wait.val = 0;
2959 
2960     while (1) {
2961         {
2962             AutoMutex autolock(thd_enc->mutex());
2963             if (MPP_THREAD_RUNNING != thd_enc->get_status())
2964                 break;
2965 
2966             if (check_enc_async_wait(enc, &wait)) {
2967                 enc_dbg_detail("wait start\n");
2968                 thd_enc->wait();
2969                 enc_dbg_detail("wait done\n");
2970             }
2971         }
2972 
2973         // When encoder is not on encoding process external config and reset
2974         // 1. process user control and reset flag
2975         if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) {
2976             mpp_list *frm_in = mpp->mFrmIn;
2977             HalTaskHnd hnd = NULL;
2978             EncAsyncTaskInfo *info = NULL;
2979 
2980             /* when process cmd or reset hold frame input */
2981             frm_in->lock();
2982 
2983             enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
2984 
2985             // wait all tasks done
2986             while (MPP_OK == hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd)) {
2987                 info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
2988 
2989                 mpp_assert(!info->status.enc_done);
2990 
2991                 enc_async_wait_task(enc, info);
2992                 hal_task_hnd_set_status(hnd, TASK_IDLE);
2993                 wait.task_hnd = 0;
2994             }
2995 
2996             if (enc->cmd_send != enc->cmd_recv) {
2997                 sem_wait(&enc->cmd_start);
2998                 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
2999                 if (ret)
3000                     *enc->cmd_ret = ret;
3001                 enc->cmd_recv++;
3002                 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
3003                                enc->cmd_send);
3004                 mpp_assert(enc->cmd_send == enc->cmd_send);
3005                 enc->param = NULL;
3006                 enc->cmd = (MpiCmd)0;
3007                 sem_post(&enc->cmd_done);
3008 
3009                 // async cfg update process for hal
3010                 // mainly for buffer prepare
3011                 mpp_enc_hal_prepare(enc->enc_hal);
3012 
3013                 /* NOTE: here will clear change flag of rc and prep cfg */
3014                 mpp_enc_proc_rc_update(enc);
3015                 goto SYNC_DONE;
3016             }
3017 
3018             if (enc->reset_flag) {
3019                 enc_dbg_detail("thread reset start\n");
3020 
3021                 /* skip the frames in input queue */
3022                 while (frm_in->list_size())
3023                     async_task_skip(enc);
3024 
3025                 {
3026                     AutoMutex autolock(thd_enc->mutex());
3027                     enc->status_flag = 0;
3028                 }
3029 
3030                 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
3031                 enc->frm_cfg.force_idr++;
3032 
3033                 AutoMutex autolock(thd_enc->mutex(THREAD_CONTROL));
3034                 enc->reset_flag = 0;
3035                 sem_post(&enc->enc_reset);
3036                 enc_dbg_detail("thread reset done\n");
3037             }
3038         SYNC_DONE:
3039             frm_in->unlock();
3040             wait.val = 0;
3041             continue;
3042         }
3043 
3044         // 2. try get a task to encode
3045         ret = try_get_async_task(enc, &wait);
3046         enc_dbg_detail("try_get_async_task ret %d\n", ret);
3047         if (ret) {
3048             HalTaskHnd hnd = NULL;
3049             EncAsyncTaskInfo *info = NULL;
3050 
3051             hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd);
3052             if (hnd) {
3053                 info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
3054 
3055                 mpp_assert(!info->status.enc_done);
3056 
3057                 enc_async_wait_task(enc, info);
3058                 hal_task_hnd_set_status(hnd, TASK_IDLE);
3059                 wait.task_hnd = 0;
3060             }
3061 
3062             continue;
3063         }
3064 
3065         mpp_assert(enc->async);
3066         mpp_assert(enc->async->task.valid);
3067 
3068         proc_async_task(enc);
3069     }
3070 
3071     enc_dbg_func("thread finish\n");
3072 
3073     return NULL;
3074 }
3075