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