xref: /rockchip-linux_mpp/mpp/codec/enc/h264/h264e_api_v2.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /*
2*437bfbebSnyanmisaka  * Copyright 2015 Rockchip Electronics Co. LTD
3*437bfbebSnyanmisaka  *
4*437bfbebSnyanmisaka  * Licensed under the Apache License, Version 2.0 (the "License");
5*437bfbebSnyanmisaka  * you may not use this file except in compliance with the License.
6*437bfbebSnyanmisaka  * You may obtain a copy of the License at
7*437bfbebSnyanmisaka  *
8*437bfbebSnyanmisaka  *      http://www.apache.org/licenses/LICENSE-2.0
9*437bfbebSnyanmisaka  *
10*437bfbebSnyanmisaka  * Unless required by applicable law or agreed to in writing, software
11*437bfbebSnyanmisaka  * distributed under the License is distributed on an "AS IS" BASIS,
12*437bfbebSnyanmisaka  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*437bfbebSnyanmisaka  * See the License for the specific language governing permissions and
14*437bfbebSnyanmisaka  * limitations under the License.
15*437bfbebSnyanmisaka  */
16*437bfbebSnyanmisaka 
17*437bfbebSnyanmisaka #define MODULE_TAG "h264e_api_v2"
18*437bfbebSnyanmisaka 
19*437bfbebSnyanmisaka #include <string.h>
20*437bfbebSnyanmisaka #include <limits.h>
21*437bfbebSnyanmisaka 
22*437bfbebSnyanmisaka #include "mpp_env.h"
23*437bfbebSnyanmisaka #include "mpp_mem.h"
24*437bfbebSnyanmisaka #include "mpp_common.h"
25*437bfbebSnyanmisaka 
26*437bfbebSnyanmisaka #include "mpp_packet_impl.h"
27*437bfbebSnyanmisaka #include "mpp_enc_refs.h"
28*437bfbebSnyanmisaka 
29*437bfbebSnyanmisaka #include "h264e_debug.h"
30*437bfbebSnyanmisaka #include "h264e_syntax.h"
31*437bfbebSnyanmisaka #include "h264e_sps.h"
32*437bfbebSnyanmisaka #include "h264e_pps.h"
33*437bfbebSnyanmisaka #include "h264e_sei.h"
34*437bfbebSnyanmisaka #include "h264e_dpb.h"
35*437bfbebSnyanmisaka #include "h264e_slice.h"
36*437bfbebSnyanmisaka #include "h264e_api_v2.h"
37*437bfbebSnyanmisaka #include "rc.h"
38*437bfbebSnyanmisaka #include "mpp_rc.h"
39*437bfbebSnyanmisaka #include "mpp_soc.h"
40*437bfbebSnyanmisaka 
41*437bfbebSnyanmisaka #include "enc_impl_api.h"
42*437bfbebSnyanmisaka #include "mpp_enc_cfg.h"
43*437bfbebSnyanmisaka #include "mpp_enc_impl.h"
44*437bfbebSnyanmisaka 
45*437bfbebSnyanmisaka RK_U32 h264e_debug = 0;
46*437bfbebSnyanmisaka 
47*437bfbebSnyanmisaka typedef struct {
48*437bfbebSnyanmisaka     /* config from mpp_enc */
49*437bfbebSnyanmisaka     MppClientType       type;
50*437bfbebSnyanmisaka     MppEncCfgSet        *cfg;
51*437bfbebSnyanmisaka     MppEncRefs          refs;
52*437bfbebSnyanmisaka     RK_U32              idr_request;
53*437bfbebSnyanmisaka     RK_U32              pre_ref_idx;
54*437bfbebSnyanmisaka 
55*437bfbebSnyanmisaka     /* H.264 high level syntax */
56*437bfbebSnyanmisaka     H264eSps            sps;
57*437bfbebSnyanmisaka     H264ePps            pps;
58*437bfbebSnyanmisaka 
59*437bfbebSnyanmisaka     /*
60*437bfbebSnyanmisaka      * H.264 low level syntax
61*437bfbebSnyanmisaka      *
62*437bfbebSnyanmisaka      * NOTE: two dpb is for dpb roll-back and reencode
63*437bfbebSnyanmisaka      */
64*437bfbebSnyanmisaka     H264eDpb            dpb;
65*437bfbebSnyanmisaka     H264eDpb            dpb_bak;
66*437bfbebSnyanmisaka     H264eSlice          slice;
67*437bfbebSnyanmisaka     H264eReorderInfo    reorder;
68*437bfbebSnyanmisaka     H264eMarkingInfo    marking;
69*437bfbebSnyanmisaka     /* H.264 frame status syntax */
70*437bfbebSnyanmisaka     H264eFrmInfo        frms;
71*437bfbebSnyanmisaka     /* header generation */
72*437bfbebSnyanmisaka     MppPacket           hdr_pkt;
73*437bfbebSnyanmisaka     void                *hdr_buf;
74*437bfbebSnyanmisaka     size_t              hdr_size;
75*437bfbebSnyanmisaka     size_t              hdr_len;
76*437bfbebSnyanmisaka     RK_S32              sps_offset;
77*437bfbebSnyanmisaka     RK_S32              sps_len;
78*437bfbebSnyanmisaka     RK_S32              pps_offset;
79*437bfbebSnyanmisaka     RK_S32              pps_len;
80*437bfbebSnyanmisaka     RK_S32              prefix_offset;
81*437bfbebSnyanmisaka     RK_S32              prefix_len;
82*437bfbebSnyanmisaka     H264ePrefixNal      prefix;
83*437bfbebSnyanmisaka 
84*437bfbebSnyanmisaka     /* rate control config */
85*437bfbebSnyanmisaka     RcCtx               rc_ctx;
86*437bfbebSnyanmisaka 
87*437bfbebSnyanmisaka     /* output to hal */
88*437bfbebSnyanmisaka     RK_S32              syn_num;
89*437bfbebSnyanmisaka     H264eSyntaxDesc     syntax[H264E_SYN_BUTT];
90*437bfbebSnyanmisaka } H264eCtx;
91*437bfbebSnyanmisaka 
init_h264e_cfg_set(MppEncCfgSet * cfg,MppClientType type)92*437bfbebSnyanmisaka static void init_h264e_cfg_set(MppEncCfgSet *cfg, MppClientType type)
93*437bfbebSnyanmisaka {
94*437bfbebSnyanmisaka     MppEncRcCfg *rc_cfg = &cfg->rc;
95*437bfbebSnyanmisaka     MppEncPrepCfg *prep = &cfg->prep;
96*437bfbebSnyanmisaka     MppEncH264Cfg *h264 = &cfg->h264;
97*437bfbebSnyanmisaka 
98*437bfbebSnyanmisaka     /*
99*437bfbebSnyanmisaka      * default codec:
100*437bfbebSnyanmisaka      * High Profile
101*437bfbebSnyanmisaka      * frame mode
102*437bfbebSnyanmisaka      * all flag enabled
103*437bfbebSnyanmisaka      */
104*437bfbebSnyanmisaka     memset(h264, 0, sizeof(*h264));
105*437bfbebSnyanmisaka     h264->profile = H264_PROFILE_BASELINE;
106*437bfbebSnyanmisaka     h264->level = H264_LEVEL_3_1;
107*437bfbebSnyanmisaka     h264->vui.vui_en = 1;
108*437bfbebSnyanmisaka     cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT;
109*437bfbebSnyanmisaka     cfg->tune.deblur_en = 0;
110*437bfbebSnyanmisaka     cfg->tune.vmaf_opt = 0;
111*437bfbebSnyanmisaka 
112*437bfbebSnyanmisaka     switch (type) {
113*437bfbebSnyanmisaka     case VPU_CLIENT_VEPU1 :
114*437bfbebSnyanmisaka     case VPU_CLIENT_VEPU2 : {
115*437bfbebSnyanmisaka         h264->poc_type = 2;
116*437bfbebSnyanmisaka         h264->log2_max_poc_lsb = 12;
117*437bfbebSnyanmisaka         h264->log2_max_frame_num = 12;
118*437bfbebSnyanmisaka         h264->hw_cfg.hw_poc_type = 2;
119*437bfbebSnyanmisaka         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
120*437bfbebSnyanmisaka         h264->hw_cfg.hw_split_out = 0;
121*437bfbebSnyanmisaka     } break;
122*437bfbebSnyanmisaka     case VPU_CLIENT_RKVENC : {
123*437bfbebSnyanmisaka         h264->poc_type = 0;
124*437bfbebSnyanmisaka         h264->log2_max_poc_lsb = 12;
125*437bfbebSnyanmisaka         h264->log2_max_frame_num = 12;
126*437bfbebSnyanmisaka         h264->chroma_cb_qp_offset = -6;
127*437bfbebSnyanmisaka         h264->chroma_cr_qp_offset = -6;
128*437bfbebSnyanmisaka         h264->hw_cfg.hw_poc_type = 0;
129*437bfbebSnyanmisaka         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
130*437bfbebSnyanmisaka         h264->hw_cfg.hw_split_out = 0;
131*437bfbebSnyanmisaka     } break;
132*437bfbebSnyanmisaka     default : {
133*437bfbebSnyanmisaka         h264->poc_type = 0;
134*437bfbebSnyanmisaka         h264->log2_max_poc_lsb = 12;
135*437bfbebSnyanmisaka         h264->log2_max_frame_num = 12;
136*437bfbebSnyanmisaka         h264->hw_cfg.hw_poc_type = 0;
137*437bfbebSnyanmisaka         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
138*437bfbebSnyanmisaka         h264->hw_cfg.hw_split_out = 0;
139*437bfbebSnyanmisaka     } break;
140*437bfbebSnyanmisaka     }
141*437bfbebSnyanmisaka 
142*437bfbebSnyanmisaka     /*
143*437bfbebSnyanmisaka      * default prep:
144*437bfbebSnyanmisaka      * 720p
145*437bfbebSnyanmisaka      * YUV420SP
146*437bfbebSnyanmisaka      */
147*437bfbebSnyanmisaka     prep->width = 1280;
148*437bfbebSnyanmisaka     prep->height = 720;
149*437bfbebSnyanmisaka     prep->hor_stride = 1280;
150*437bfbebSnyanmisaka     prep->ver_stride = 720;
151*437bfbebSnyanmisaka     prep->format = MPP_FMT_YUV420SP;
152*437bfbebSnyanmisaka     prep->rotation = MPP_ENC_ROT_0;
153*437bfbebSnyanmisaka     prep->rotation_ext = MPP_ENC_ROT_0;
154*437bfbebSnyanmisaka     prep->color = MPP_FRAME_SPC_UNSPECIFIED;
155*437bfbebSnyanmisaka     prep->colorprim = MPP_FRAME_PRI_UNSPECIFIED;
156*437bfbebSnyanmisaka     prep->colortrc = MPP_FRAME_TRC_UNSPECIFIED;
157*437bfbebSnyanmisaka     prep->range = MPP_FRAME_RANGE_UNSPECIFIED;
158*437bfbebSnyanmisaka     prep->mirroring = 0;
159*437bfbebSnyanmisaka     prep->mirroring_ext = 0;
160*437bfbebSnyanmisaka     prep->denoise = 0;
161*437bfbebSnyanmisaka     prep->flip = 0;
162*437bfbebSnyanmisaka 
163*437bfbebSnyanmisaka     /*
164*437bfbebSnyanmisaka      * default rc_cfg:
165*437bfbebSnyanmisaka      * CBR
166*437bfbebSnyanmisaka      * 2Mbps +-25%
167*437bfbebSnyanmisaka      * 30fps
168*437bfbebSnyanmisaka      * gop 60
169*437bfbebSnyanmisaka      */
170*437bfbebSnyanmisaka     rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM;
171*437bfbebSnyanmisaka     rc_cfg->bps_target = 2000 * 1000;
172*437bfbebSnyanmisaka     rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4;
173*437bfbebSnyanmisaka     rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4;
174*437bfbebSnyanmisaka     rc_cfg->fps_in_flex = 0;
175*437bfbebSnyanmisaka     rc_cfg->fps_in_num = 30;
176*437bfbebSnyanmisaka     rc_cfg->fps_in_denom = 1;
177*437bfbebSnyanmisaka     rc_cfg->fps_out_flex = 0;
178*437bfbebSnyanmisaka     rc_cfg->fps_out_num = 30;
179*437bfbebSnyanmisaka     rc_cfg->fps_out_denom = 1;
180*437bfbebSnyanmisaka     rc_cfg->gop = 60;
181*437bfbebSnyanmisaka     rc_cfg->max_reenc_times = 1;
182*437bfbebSnyanmisaka     rc_cfg->max_i_prop = 30;
183*437bfbebSnyanmisaka     rc_cfg->min_i_prop = 10;
184*437bfbebSnyanmisaka     rc_cfg->init_ip_ratio = 160;
185*437bfbebSnyanmisaka     rc_cfg->qp_init = 26;
186*437bfbebSnyanmisaka     rc_cfg->qp_max = 48;
187*437bfbebSnyanmisaka     rc_cfg->qp_min = 8;
188*437bfbebSnyanmisaka     /* default max/min intra qp is not set */
189*437bfbebSnyanmisaka     rc_cfg->qp_max_i = 0;
190*437bfbebSnyanmisaka     rc_cfg->qp_min_i = 0;
191*437bfbebSnyanmisaka     rc_cfg->qp_delta_ip = 2;
192*437bfbebSnyanmisaka     rc_cfg->fqp_min_i = INT_MAX;
193*437bfbebSnyanmisaka     rc_cfg->fqp_min_p = INT_MAX;
194*437bfbebSnyanmisaka     rc_cfg->fqp_max_i = INT_MAX;
195*437bfbebSnyanmisaka     rc_cfg->fqp_max_p = INT_MAX;
196*437bfbebSnyanmisaka 
197*437bfbebSnyanmisaka     cfg->tune.lambda_idx_i = 6;
198*437bfbebSnyanmisaka     cfg->tune.lambda_idx_p = 6;
199*437bfbebSnyanmisaka     cfg->tune.atl_str = 1;
200*437bfbebSnyanmisaka     cfg->tune.atr_str_i = 1;
201*437bfbebSnyanmisaka     cfg->tune.atr_str_p = 1;
202*437bfbebSnyanmisaka     cfg->tune.anti_flicker_str = 1;
203*437bfbebSnyanmisaka     cfg->tune.deblur_str = 3;
204*437bfbebSnyanmisaka 
205*437bfbebSnyanmisaka     /* smart v3 parameters */
206*437bfbebSnyanmisaka     cfg->tune.bg_delta_qp_i = -10;
207*437bfbebSnyanmisaka     cfg->tune.bg_delta_qp_p = -10;
208*437bfbebSnyanmisaka     cfg->tune.fg_delta_qp_i = 3;
209*437bfbebSnyanmisaka     cfg->tune.fg_delta_qp_p = 1;
210*437bfbebSnyanmisaka     cfg->tune.bmap_qpmin_i = 30;
211*437bfbebSnyanmisaka     cfg->tune.bmap_qpmin_p = 30;
212*437bfbebSnyanmisaka     cfg->tune.bmap_qpmax_i = 45;
213*437bfbebSnyanmisaka     cfg->tune.bmap_qpmax_p = 47;
214*437bfbebSnyanmisaka     cfg->tune.min_bg_fqp = 30;
215*437bfbebSnyanmisaka     cfg->tune.max_bg_fqp = 45;
216*437bfbebSnyanmisaka     cfg->tune.min_fg_fqp = 25;
217*437bfbebSnyanmisaka     cfg->tune.max_fg_fqp = 35;
218*437bfbebSnyanmisaka }
219*437bfbebSnyanmisaka 
h264e_add_syntax(H264eCtx * ctx,H264eSyntaxType type,void * p)220*437bfbebSnyanmisaka static void h264e_add_syntax(H264eCtx *ctx, H264eSyntaxType type, void *p)
221*437bfbebSnyanmisaka {
222*437bfbebSnyanmisaka     ctx->syntax[ctx->syn_num].type  = type;
223*437bfbebSnyanmisaka     ctx->syntax[ctx->syn_num].p     = p;
224*437bfbebSnyanmisaka     ctx->syn_num++;
225*437bfbebSnyanmisaka }
226*437bfbebSnyanmisaka 
h264e_init(void * ctx,EncImplCfg * ctrl_cfg)227*437bfbebSnyanmisaka static MPP_RET h264e_init(void *ctx, EncImplCfg *ctrl_cfg)
228*437bfbebSnyanmisaka {
229*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
230*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
231*437bfbebSnyanmisaka 
232*437bfbebSnyanmisaka     mpp_env_get_u32("h264e_debug", &h264e_debug, 0);
233*437bfbebSnyanmisaka 
234*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
235*437bfbebSnyanmisaka 
236*437bfbebSnyanmisaka     p->type = ctrl_cfg->type;
237*437bfbebSnyanmisaka     p->hdr_size = SZ_1K;
238*437bfbebSnyanmisaka     p->hdr_buf = mpp_malloc_size(void, p->hdr_size);
239*437bfbebSnyanmisaka     mpp_assert(p->hdr_buf);
240*437bfbebSnyanmisaka     mpp_packet_init(&p->hdr_pkt, p->hdr_buf, p->hdr_size);
241*437bfbebSnyanmisaka     mpp_assert(p->hdr_pkt);
242*437bfbebSnyanmisaka 
243*437bfbebSnyanmisaka     p->cfg = ctrl_cfg->cfg;
244*437bfbebSnyanmisaka     p->refs = ctrl_cfg->refs;
245*437bfbebSnyanmisaka     p->idr_request = 0;
246*437bfbebSnyanmisaka 
247*437bfbebSnyanmisaka     h264e_reorder_init(&p->reorder);
248*437bfbebSnyanmisaka     h264e_marking_init(&p->marking);
249*437bfbebSnyanmisaka 
250*437bfbebSnyanmisaka     h264e_dpb_init(&p->dpb, &p->reorder, &p->marking);
251*437bfbebSnyanmisaka     h264e_slice_init(&p->slice, &p->reorder, &p->marking);
252*437bfbebSnyanmisaka 
253*437bfbebSnyanmisaka     init_h264e_cfg_set(p->cfg, p->type);
254*437bfbebSnyanmisaka 
255*437bfbebSnyanmisaka     mpp_env_get_u32("h264e_debug", &h264e_debug, 0);
256*437bfbebSnyanmisaka 
257*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
258*437bfbebSnyanmisaka     return ret;
259*437bfbebSnyanmisaka }
260*437bfbebSnyanmisaka 
h264e_deinit(void * ctx)261*437bfbebSnyanmisaka static MPP_RET h264e_deinit(void *ctx)
262*437bfbebSnyanmisaka {
263*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
264*437bfbebSnyanmisaka 
265*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
266*437bfbebSnyanmisaka 
267*437bfbebSnyanmisaka     if (p->hdr_pkt)
268*437bfbebSnyanmisaka         mpp_packet_deinit(&p->hdr_pkt);
269*437bfbebSnyanmisaka 
270*437bfbebSnyanmisaka     MPP_FREE(p->hdr_buf);
271*437bfbebSnyanmisaka 
272*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
273*437bfbebSnyanmisaka     return MPP_OK;
274*437bfbebSnyanmisaka }
275*437bfbebSnyanmisaka 
h264e_check_cfg(MppEncCfgSet * cfg)276*437bfbebSnyanmisaka static void h264e_check_cfg(MppEncCfgSet *cfg)
277*437bfbebSnyanmisaka {
278*437bfbebSnyanmisaka     MppEncRcCfg *rc = &cfg->rc;
279*437bfbebSnyanmisaka     MppEncH264Cfg *h264 = &cfg->h264;
280*437bfbebSnyanmisaka 
281*437bfbebSnyanmisaka     if (rc->drop_mode == MPP_ENC_RC_DROP_FRM_PSKIP &&
282*437bfbebSnyanmisaka         rc->drop_gap == 0 &&
283*437bfbebSnyanmisaka         h264->poc_type == 2) {
284*437bfbebSnyanmisaka         mpp_err("poc type 2 is conflict with successive non-reference pskip mode\n");
285*437bfbebSnyanmisaka         mpp_err("set drop gap to 1\n");
286*437bfbebSnyanmisaka         rc->drop_gap = 1;
287*437bfbebSnyanmisaka     }
288*437bfbebSnyanmisaka }
289*437bfbebSnyanmisaka 
h264e_proc_cfg(void * ctx,MpiCmd cmd,void * param)290*437bfbebSnyanmisaka static MPP_RET h264e_proc_cfg(void *ctx, MpiCmd cmd, void *param)
291*437bfbebSnyanmisaka {
292*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
293*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
294*437bfbebSnyanmisaka     MppEncCfgSet *cfg = p->cfg;
295*437bfbebSnyanmisaka 
296*437bfbebSnyanmisaka     h264e_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param);
297*437bfbebSnyanmisaka 
298*437bfbebSnyanmisaka     switch (cmd) {
299*437bfbebSnyanmisaka     case MPP_ENC_SET_CFG : {
300*437bfbebSnyanmisaka         h264e_check_cfg(cfg);
301*437bfbebSnyanmisaka     } break;
302*437bfbebSnyanmisaka     case MPP_ENC_SET_SEI_CFG : {
303*437bfbebSnyanmisaka     } break;
304*437bfbebSnyanmisaka     case MPP_ENC_SET_SPLIT : {
305*437bfbebSnyanmisaka     } break;
306*437bfbebSnyanmisaka     default:
307*437bfbebSnyanmisaka         mpp_err("No correspond cmd found, and can not config!");
308*437bfbebSnyanmisaka         ret = MPP_NOK;
309*437bfbebSnyanmisaka         break;
310*437bfbebSnyanmisaka     }
311*437bfbebSnyanmisaka 
312*437bfbebSnyanmisaka     h264e_dbg_func("leave ret %d\n", ret);
313*437bfbebSnyanmisaka 
314*437bfbebSnyanmisaka     return ret;
315*437bfbebSnyanmisaka }
316*437bfbebSnyanmisaka 
h264e_gen_hdr(void * ctx,MppPacket pkt)317*437bfbebSnyanmisaka static MPP_RET h264e_gen_hdr(void *ctx, MppPacket pkt)
318*437bfbebSnyanmisaka {
319*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
320*437bfbebSnyanmisaka 
321*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
322*437bfbebSnyanmisaka 
323*437bfbebSnyanmisaka     h264e_sps_update(&p->sps, p->cfg);
324*437bfbebSnyanmisaka     h264e_pps_update(&p->pps, p->cfg);
325*437bfbebSnyanmisaka 
326*437bfbebSnyanmisaka     /*
327*437bfbebSnyanmisaka      * NOTE: When sps/pps is update we need to update dpb and slice info
328*437bfbebSnyanmisaka      */
329*437bfbebSnyanmisaka     if (!p->dpb.total_cnt)
330*437bfbebSnyanmisaka         h264e_dpb_setup(&p->dpb, p->cfg, &p->sps);
331*437bfbebSnyanmisaka 
332*437bfbebSnyanmisaka     mpp_packet_reset(p->hdr_pkt);
333*437bfbebSnyanmisaka 
334*437bfbebSnyanmisaka     h264e_sps_to_packet(&p->sps, p->hdr_pkt, &p->sps_offset, &p->sps_len, p->cfg);
335*437bfbebSnyanmisaka     h264e_pps_to_packet(&p->pps, p->hdr_pkt, &p->pps_offset, &p->pps_len);
336*437bfbebSnyanmisaka     p->hdr_len = mpp_packet_get_length(p->hdr_pkt);
337*437bfbebSnyanmisaka 
338*437bfbebSnyanmisaka     if (pkt) {
339*437bfbebSnyanmisaka         mpp_packet_write(pkt, 0, p->hdr_buf, p->hdr_len);
340*437bfbebSnyanmisaka         mpp_packet_set_length(pkt, p->hdr_len);
341*437bfbebSnyanmisaka 
342*437bfbebSnyanmisaka         mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_SPS,
343*437bfbebSnyanmisaka                                     p->sps_offset, p->sps_len);
344*437bfbebSnyanmisaka         mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_PPS,
345*437bfbebSnyanmisaka                                     p->pps_offset, p->pps_len);
346*437bfbebSnyanmisaka     }
347*437bfbebSnyanmisaka 
348*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
349*437bfbebSnyanmisaka     return MPP_OK;
350*437bfbebSnyanmisaka }
351*437bfbebSnyanmisaka 
h264e_start(void * ctx,HalEncTask * task)352*437bfbebSnyanmisaka static MPP_RET h264e_start(void *ctx, HalEncTask *task)
353*437bfbebSnyanmisaka {
354*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
355*437bfbebSnyanmisaka 
356*437bfbebSnyanmisaka     if (mpp_frame_has_meta(task->frame)) {
357*437bfbebSnyanmisaka         MppEncRefFrmUsrCfg *frm_cfg = task->frm_cfg;
358*437bfbebSnyanmisaka         EncRcForceCfg *rc_force = &task->rc_task->force;
359*437bfbebSnyanmisaka         MppMeta meta = mpp_frame_get_meta(task->frame);
360*437bfbebSnyanmisaka         RK_S32 force_lt_idx = -1;
361*437bfbebSnyanmisaka         RK_S32 force_use_lt_idx = -1;
362*437bfbebSnyanmisaka         RK_S32 force_frame_qp = -1;
363*437bfbebSnyanmisaka         RK_S32 base_layer_pid = -1;
364*437bfbebSnyanmisaka         RK_S32 force_tid = -1;
365*437bfbebSnyanmisaka 
366*437bfbebSnyanmisaka         mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &force_lt_idx);
367*437bfbebSnyanmisaka         mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &force_use_lt_idx);
368*437bfbebSnyanmisaka         mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &force_frame_qp);
369*437bfbebSnyanmisaka         mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &base_layer_pid);
370*437bfbebSnyanmisaka         mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &force_tid);
371*437bfbebSnyanmisaka 
372*437bfbebSnyanmisaka         if (force_lt_idx >= 0) {
373*437bfbebSnyanmisaka             frm_cfg->force_flag |= ENC_FORCE_LT_REF_IDX;
374*437bfbebSnyanmisaka             frm_cfg->force_lt_idx = force_lt_idx;
375*437bfbebSnyanmisaka         }
376*437bfbebSnyanmisaka 
377*437bfbebSnyanmisaka         if (force_use_lt_idx >= 0) {
378*437bfbebSnyanmisaka             frm_cfg->force_flag |= ENC_FORCE_REF_MODE;
379*437bfbebSnyanmisaka             frm_cfg->force_ref_mode = REF_TO_LT_REF_IDX;
380*437bfbebSnyanmisaka             frm_cfg->force_ref_arg = force_use_lt_idx;
381*437bfbebSnyanmisaka         }
382*437bfbebSnyanmisaka 
383*437bfbebSnyanmisaka         if (force_tid >= 0) {
384*437bfbebSnyanmisaka             frm_cfg->force_flag |= ENC_FORCE_TEMPORAL_ID;
385*437bfbebSnyanmisaka             frm_cfg->force_temporal_id = force_tid;
386*437bfbebSnyanmisaka         }
387*437bfbebSnyanmisaka 
388*437bfbebSnyanmisaka         if (force_frame_qp >= 0) {
389*437bfbebSnyanmisaka             rc_force->force_flag = ENC_RC_FORCE_QP;
390*437bfbebSnyanmisaka             rc_force->force_qp = force_frame_qp;
391*437bfbebSnyanmisaka         } else {
392*437bfbebSnyanmisaka             rc_force->force_flag &= (~ENC_RC_FORCE_QP);
393*437bfbebSnyanmisaka             rc_force->force_qp = -1;
394*437bfbebSnyanmisaka         }
395*437bfbebSnyanmisaka 
396*437bfbebSnyanmisaka         if (base_layer_pid >= 0) {
397*437bfbebSnyanmisaka             H264eCtx *p = (H264eCtx *)ctx;
398*437bfbebSnyanmisaka             MppEncH264Cfg *h264 = &p->cfg->h264;
399*437bfbebSnyanmisaka 
400*437bfbebSnyanmisaka             h264->base_layer_pid = base_layer_pid;
401*437bfbebSnyanmisaka         }
402*437bfbebSnyanmisaka     }
403*437bfbebSnyanmisaka 
404*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
405*437bfbebSnyanmisaka 
406*437bfbebSnyanmisaka     return MPP_OK;
407*437bfbebSnyanmisaka }
408*437bfbebSnyanmisaka 
h264e_pskip_ref_check(H264eDpb * dpb,H264eFrmInfo * frms)409*437bfbebSnyanmisaka MPP_RET h264e_pskip_ref_check(H264eDpb *dpb, H264eFrmInfo *frms)
410*437bfbebSnyanmisaka {
411*437bfbebSnyanmisaka     H264eDpbFrm *curr = NULL;
412*437bfbebSnyanmisaka     H264eDpbFrm *refr = NULL;
413*437bfbebSnyanmisaka     RK_U32 i;
414*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
415*437bfbebSnyanmisaka 
416*437bfbebSnyanmisaka     curr = dpb->curr;
417*437bfbebSnyanmisaka     refr = dpb->refr;
418*437bfbebSnyanmisaka 
419*437bfbebSnyanmisaka     if (curr->status.force_pskip_is_ref) {
420*437bfbebSnyanmisaka         H264eDpbFrm *temp_frm;
421*437bfbebSnyanmisaka         for (i = 0; i < H264E_MAX_REFS_CNT; i++) {
422*437bfbebSnyanmisaka             temp_frm = &dpb->frames[i];
423*437bfbebSnyanmisaka             if (temp_frm->slot_idx != frms->refr_idx) {
424*437bfbebSnyanmisaka                 temp_frm->as_pskip_ref = 0;
425*437bfbebSnyanmisaka             } else {
426*437bfbebSnyanmisaka                 temp_frm->as_pskip_ref = 1;
427*437bfbebSnyanmisaka             }
428*437bfbebSnyanmisaka         }
429*437bfbebSnyanmisaka     }
430*437bfbebSnyanmisaka 
431*437bfbebSnyanmisaka     if (!refr->status.force_pskip_is_ref && !curr->status.force_pskip_is_ref) {
432*437bfbebSnyanmisaka         H264eDpbFrm *temp_frm;
433*437bfbebSnyanmisaka         for (i = 0; i < H264E_MAX_REFS_CNT; i++) {
434*437bfbebSnyanmisaka             temp_frm = &dpb->frames[i];
435*437bfbebSnyanmisaka             if (temp_frm) {
436*437bfbebSnyanmisaka                 temp_frm->as_pskip_ref = 0;
437*437bfbebSnyanmisaka             }
438*437bfbebSnyanmisaka         }
439*437bfbebSnyanmisaka     }
440*437bfbebSnyanmisaka 
441*437bfbebSnyanmisaka     return ret;
442*437bfbebSnyanmisaka }
443*437bfbebSnyanmisaka 
h264e_proc_dpb(void * ctx,HalEncTask * task)444*437bfbebSnyanmisaka static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task)
445*437bfbebSnyanmisaka {
446*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
447*437bfbebSnyanmisaka     H264eDpb *dpb = &p->dpb;
448*437bfbebSnyanmisaka     H264eFrmInfo *frms = &p->frms;
449*437bfbebSnyanmisaka     EncCpbStatus *cpb = &task->rc_task->cpb;
450*437bfbebSnyanmisaka     EncFrmStatus *frm = &task->rc_task->frm;
451*437bfbebSnyanmisaka     H264eDpbFrm *curr = NULL;
452*437bfbebSnyanmisaka     H264eDpbFrm *refr = NULL;
453*437bfbebSnyanmisaka     RK_S32 i;
454*437bfbebSnyanmisaka 
455*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
456*437bfbebSnyanmisaka 
457*437bfbebSnyanmisaka     // update dpb
458*437bfbebSnyanmisaka     h264e_dpb_proc(dpb, cpb);
459*437bfbebSnyanmisaka 
460*437bfbebSnyanmisaka     curr = dpb->curr;
461*437bfbebSnyanmisaka     refr = dpb->refr;
462*437bfbebSnyanmisaka 
463*437bfbebSnyanmisaka     // update slice info
464*437bfbebSnyanmisaka     h264e_slice_update(&p->slice, p->cfg, &p->sps, &p->pps, dpb->curr);
465*437bfbebSnyanmisaka 
466*437bfbebSnyanmisaka     // update frame usage
467*437bfbebSnyanmisaka     frms->seq_idx = curr->seq_idx;
468*437bfbebSnyanmisaka     frms->curr_idx = curr->slot_idx;
469*437bfbebSnyanmisaka 
470*437bfbebSnyanmisaka     if (refr) {
471*437bfbebSnyanmisaka         if (refr->status.force_pskip_is_ref)
472*437bfbebSnyanmisaka             frms->refr_idx = refr->prev_ref_idx;
473*437bfbebSnyanmisaka         else
474*437bfbebSnyanmisaka             frms->refr_idx = refr->slot_idx;
475*437bfbebSnyanmisaka     } else {
476*437bfbebSnyanmisaka         frms->refr_idx = curr->slot_idx;
477*437bfbebSnyanmisaka     }
478*437bfbebSnyanmisaka 
479*437bfbebSnyanmisaka     // mark actual refs buf when force pskip is ref
480*437bfbebSnyanmisaka     h264e_pskip_ref_check(dpb, frms);
481*437bfbebSnyanmisaka 
482*437bfbebSnyanmisaka     for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(frms->usage); i++)
483*437bfbebSnyanmisaka         frms->usage[i] = dpb->frames[i].on_used;
484*437bfbebSnyanmisaka 
485*437bfbebSnyanmisaka     // update dpb to after encoding status
486*437bfbebSnyanmisaka     h264e_dpb_check(dpb, cpb);
487*437bfbebSnyanmisaka 
488*437bfbebSnyanmisaka     frm->val = curr->status.val;
489*437bfbebSnyanmisaka 
490*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
491*437bfbebSnyanmisaka 
492*437bfbebSnyanmisaka     return MPP_OK;
493*437bfbebSnyanmisaka }
494*437bfbebSnyanmisaka 
h264e_proc_hal(void * ctx,HalEncTask * task)495*437bfbebSnyanmisaka static MPP_RET h264e_proc_hal(void *ctx, HalEncTask *task)
496*437bfbebSnyanmisaka {
497*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
498*437bfbebSnyanmisaka     MppEncH264Cfg *h264 = &p->cfg->h264;
499*437bfbebSnyanmisaka 
500*437bfbebSnyanmisaka     h264e_dbg_func("enter\n");
501*437bfbebSnyanmisaka 
502*437bfbebSnyanmisaka     p->syn_num = 0;
503*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_CFG, p->cfg);
504*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_SPS, &p->sps);
505*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_PPS, &p->pps);
506*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_DPB, &p->dpb);
507*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_SLICE, &p->slice);
508*437bfbebSnyanmisaka     h264e_add_syntax(p, H264E_SYN_FRAME, &p->frms);
509*437bfbebSnyanmisaka 
510*437bfbebSnyanmisaka     /* check max temporal layer id */
511*437bfbebSnyanmisaka     {
512*437bfbebSnyanmisaka         MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(p->cfg->ref_cfg);
513*437bfbebSnyanmisaka         RK_S32 cpb_max_tid = cpb_info->max_st_tid;
514*437bfbebSnyanmisaka         RK_S32 cfg_max_tid = h264->max_tid;
515*437bfbebSnyanmisaka 
516*437bfbebSnyanmisaka         if (cpb_max_tid != cfg_max_tid) {
517*437bfbebSnyanmisaka             mpp_log("max tid is update to match cpb %d -> %d\n",
518*437bfbebSnyanmisaka                     cfg_max_tid, cpb_max_tid);
519*437bfbebSnyanmisaka             h264->max_tid = cpb_max_tid;
520*437bfbebSnyanmisaka         }
521*437bfbebSnyanmisaka     }
522*437bfbebSnyanmisaka 
523*437bfbebSnyanmisaka     /* NOTE: prefix nal is added after SEI packet and before hw_stream */
524*437bfbebSnyanmisaka     if (h264->prefix_mode || h264->max_tid) {
525*437bfbebSnyanmisaka         H264ePrefixNal *prefix = &p->prefix;
526*437bfbebSnyanmisaka         H264eSlice *slice = &p->slice;
527*437bfbebSnyanmisaka         EncFrmStatus *frm = &task->rc_task->frm;
528*437bfbebSnyanmisaka         MppPacket packet = task->packet;
529*437bfbebSnyanmisaka         MppMeta meta = mpp_packet_get_meta(packet);
530*437bfbebSnyanmisaka 
531*437bfbebSnyanmisaka         prefix->idr_flag = slice->idr_flag;
532*437bfbebSnyanmisaka         prefix->nal_ref_idc = slice->nal_reference_idc;
533*437bfbebSnyanmisaka         prefix->priority_id = h264->base_layer_pid + frm->temporal_id;
534*437bfbebSnyanmisaka         prefix->no_inter_layer_pred_flag = 1;
535*437bfbebSnyanmisaka         prefix->dependency_id = 0;
536*437bfbebSnyanmisaka         prefix->quality_id = 0;
537*437bfbebSnyanmisaka         prefix->temporal_id = frm->temporal_id;
538*437bfbebSnyanmisaka         prefix->use_ref_base_pic_flag = 0;
539*437bfbebSnyanmisaka         prefix->discardable_flag = 0;
540*437bfbebSnyanmisaka         prefix->output_flag = 1;
541*437bfbebSnyanmisaka 
542*437bfbebSnyanmisaka         h264e_add_syntax(p, H264E_SYN_PREFIX, &p->prefix);
543*437bfbebSnyanmisaka         mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, frm->temporal_id);
544*437bfbebSnyanmisaka         if (!frm->is_non_ref && frm->is_lt_ref)
545*437bfbebSnyanmisaka             mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, frm->lt_idx);
546*437bfbebSnyanmisaka     } else
547*437bfbebSnyanmisaka         h264e_add_syntax(p, H264E_SYN_PREFIX, NULL);
548*437bfbebSnyanmisaka 
549*437bfbebSnyanmisaka     task->valid = 1;
550*437bfbebSnyanmisaka     task->syntax.data   = &p->syntax[0];
551*437bfbebSnyanmisaka     task->syntax.number = p->syn_num;
552*437bfbebSnyanmisaka 
553*437bfbebSnyanmisaka     h264e_dbg_func("leave\n");
554*437bfbebSnyanmisaka 
555*437bfbebSnyanmisaka     return MPP_OK;
556*437bfbebSnyanmisaka }
557*437bfbebSnyanmisaka 
h264e_sw_enc(void * ctx,HalEncTask * task)558*437bfbebSnyanmisaka static MPP_RET h264e_sw_enc(void *ctx, HalEncTask *task)
559*437bfbebSnyanmisaka {
560*437bfbebSnyanmisaka     H264eCtx *p = (H264eCtx *)ctx;
561*437bfbebSnyanmisaka     MppEncH264Cfg *h264 = &p->cfg->h264;
562*437bfbebSnyanmisaka     EncRcTaskInfo *rc_info = &task->rc_task->info;
563*437bfbebSnyanmisaka     MppPacket packet = task->packet;
564*437bfbebSnyanmisaka     void *pos = mpp_packet_get_pos(packet);
565*437bfbebSnyanmisaka     void *data = mpp_packet_get_data(packet);
566*437bfbebSnyanmisaka     size_t size = mpp_packet_get_size(packet);
567*437bfbebSnyanmisaka     size_t length = mpp_packet_get_length(packet);
568*437bfbebSnyanmisaka     void *base = pos + length;
569*437bfbebSnyanmisaka     RK_S32 buf_size = (data + size) - (pos + length);
570*437bfbebSnyanmisaka     RK_S32 slice_len = 0;
571*437bfbebSnyanmisaka     RK_S32 final_len = 0;
572*437bfbebSnyanmisaka 
573*437bfbebSnyanmisaka     if (h264->prefix_mode || h264->max_tid) {
574*437bfbebSnyanmisaka         /* add prefix first */
575*437bfbebSnyanmisaka         RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(&p->prefix, base, buf_size);
576*437bfbebSnyanmisaka 
577*437bfbebSnyanmisaka         prefix_bit = (prefix_bit + 7) / 8;
578*437bfbebSnyanmisaka 
579*437bfbebSnyanmisaka         base += prefix_bit;
580*437bfbebSnyanmisaka         buf_size -= prefix_bit;
581*437bfbebSnyanmisaka         final_len += prefix_bit;
582*437bfbebSnyanmisaka     }
583*437bfbebSnyanmisaka 
584*437bfbebSnyanmisaka     /* write slice header */
585*437bfbebSnyanmisaka     slice_len = h264e_slice_write_pskip(&p->slice, base, buf_size);
586*437bfbebSnyanmisaka     slice_len = (slice_len + 7) / 8;
587*437bfbebSnyanmisaka     final_len += slice_len;
588*437bfbebSnyanmisaka 
589*437bfbebSnyanmisaka     task->length += final_len;
590*437bfbebSnyanmisaka 
591*437bfbebSnyanmisaka     rc_info->bit_real = task->length * 8;
592*437bfbebSnyanmisaka     rc_info->quality_real = rc_info->quality_target;
593*437bfbebSnyanmisaka     p->dpb.curr->prev_ref_idx = p->frms.refr_idx;
594*437bfbebSnyanmisaka     mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SLICE, length, final_len);
595*437bfbebSnyanmisaka     mpp_buffer_sync_partial_end(mpp_packet_get_buffer(packet), length, final_len);
596*437bfbebSnyanmisaka 
597*437bfbebSnyanmisaka     return MPP_OK;
598*437bfbebSnyanmisaka }
599*437bfbebSnyanmisaka 
h264e_add_sei(MppPacket pkt,RK_S32 * length,RK_U8 uuid[16],const void * data,RK_S32 size)600*437bfbebSnyanmisaka MPP_RET h264e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16],
601*437bfbebSnyanmisaka                       const void *data, RK_S32 size)
602*437bfbebSnyanmisaka {
603*437bfbebSnyanmisaka     if (uuid == uuid_refresh_cfg) {
604*437bfbebSnyanmisaka         return h264e_sei_recovery_point_to_packet(pkt, length, ((RK_U32 *)data)[0] - 1);
605*437bfbebSnyanmisaka     } else
606*437bfbebSnyanmisaka         return h264e_sei_to_packet(pkt, length, H264_SEI_USER_DATA_UNREGISTERED,
607*437bfbebSnyanmisaka                                    uuid, data, size);
608*437bfbebSnyanmisaka }
609*437bfbebSnyanmisaka 
610*437bfbebSnyanmisaka /*!
611*437bfbebSnyanmisaka ***********************************************************************
612*437bfbebSnyanmisaka * \brief
613*437bfbebSnyanmisaka *   api struct interface
614*437bfbebSnyanmisaka ***********************************************************************
615*437bfbebSnyanmisaka */
616*437bfbebSnyanmisaka const EncImplApi api_h264e = {
617*437bfbebSnyanmisaka     "h264e_control",
618*437bfbebSnyanmisaka     MPP_VIDEO_CodingAVC,
619*437bfbebSnyanmisaka     sizeof(H264eCtx),
620*437bfbebSnyanmisaka     0,
621*437bfbebSnyanmisaka     h264e_init,
622*437bfbebSnyanmisaka     h264e_deinit,
623*437bfbebSnyanmisaka     h264e_proc_cfg,
624*437bfbebSnyanmisaka     h264e_gen_hdr,
625*437bfbebSnyanmisaka     h264e_start,
626*437bfbebSnyanmisaka     h264e_proc_dpb,
627*437bfbebSnyanmisaka     h264e_proc_hal,
628*437bfbebSnyanmisaka     h264e_add_sei,
629*437bfbebSnyanmisaka     h264e_sw_enc,
630*437bfbebSnyanmisaka };
631