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