xref: /rockchip-linux_mpp/mpp/codec/enc/h265/h265e_api.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "h265e_api"
18 
19 #include <string.h>
20 #include <limits.h>
21 
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 
25 #include "rc.h"
26 #include "mpp_soc.h"
27 #include "mpp_enc_cfg.h"
28 #include "mpp_packet_impl.h"
29 #include "mpp_enc_impl.h"
30 
31 #include "h265e_api.h"
32 #include "h265e_slice.h"
33 #include "h265e_codec.h"
34 #include "h265e_syntax_new.h"
35 #include "h265e_ps.h"
36 #include "h265e_header_gen.h"
37 
38 RK_U32 h265e_debug = 0;
39 
h265e_init(void * ctx,EncImplCfg * ctrlCfg)40 static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg)
41 {
42     H265eCtx *p = (H265eCtx *)ctx;
43     MPP_RET ret = MPP_OK;
44     MppEncRcCfg *rc_cfg = &ctrlCfg->cfg->rc;
45     MppEncPrepCfg *prep = &ctrlCfg->cfg->prep;
46     MppEncH265Cfg *h265 = NULL;
47     RockchipSocType soc_type;
48 
49     if (ctx == NULL) {
50         mpp_err_f("invalid NULL ctx\n");
51         return MPP_ERR_NULL_PTR;
52     }
53 
54     mpp_env_get_u32("h265e_debug", &h265e_debug, 0);
55     h265e_dbg_func("enter ctx %p\n", ctx);
56 
57     mpp_assert(ctrlCfg->coding == MPP_VIDEO_CodingHEVC);
58     p->cfg = ctrlCfg->cfg;
59 
60     memset(&p->syntax, 0, sizeof(p->syntax));
61 
62     p->extra_info = mpp_calloc(H265eExtraInfo, 1);
63 
64     h265e_init_extra_info(p->extra_info);
65     /* set defualt value of codec */
66     h265 = &p->cfg->h265;
67     h265->intra_qp = 26;
68     h265->qpmap_mode = 1;
69 
70     h265->profile = MPP_PROFILE_HEVC_MAIN;
71     h265->level = 120;
72     h265->const_intra_pred = 0;           /* constraint intra prediction flag */
73 
74     soc_type = mpp_get_soc_type();
75     if (soc_type == ROCKCHIP_SOC_RK3528 ||
76         soc_type == ROCKCHIP_SOC_RK3576 ||
77         soc_type == ROCKCHIP_SOC_RV1126B)
78         h265->max_cu_size = 32;
79     else
80         h265->max_cu_size = 64;
81 
82     h265->tmvp_enable = 0;
83     h265->amp_enable = 0;
84     h265->sao_enable = 1;
85 
86     h265->num_ref = 1;
87 
88     h265->slice_cfg.split_enable = 0;
89     h265->entropy_cfg.cabac_init_flag = 1;
90     h265->sao_cfg.slice_sao_chroma_disable = 0;
91     h265->sao_cfg.slice_sao_luma_disable = 0;
92     h265->dblk_cfg.slice_deblocking_filter_disabled_flag = 0;
93     h265->cu_cfg.strong_intra_smoothing_enabled_flag = 1;
94     h265->merge_cfg.max_mrg_cnd = 2;
95     h265->merge_cfg.merge_left_flag = 1;
96     h265->merge_cfg.merge_up_flag = 1;
97     h265->trans_cfg.diff_cu_qp_delta_depth = 0;
98     h265->vui.vui_en = 1;
99     p->cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT;
100     p->cfg->tune.lambda_idx_i = 2;
101     p->cfg->tune.lambda_idx_p = 4;
102     p->cfg->tune.anti_flicker_str = 2;
103     p->cfg->tune.atr_str_i = 3;
104     p->cfg->tune.atr_str_p = 0;
105     p->cfg->tune.atl_str = 1;
106     p->cfg->tune.sao_str_i = 0;
107     p->cfg->tune.sao_str_p = 1;
108     p->cfg->tune.deblur_str = 3;
109     p->cfg->tune.deblur_en = 0;
110     p->cfg->tune.rc_container = 0;
111     p->cfg->tune.vmaf_opt = 0;
112 
113     /* smart v3 parameters */
114     p->cfg->tune.bg_delta_qp_i = -10;
115     p->cfg->tune.bg_delta_qp_p = -10;
116     p->cfg->tune.fg_delta_qp_i = 3;
117     p->cfg->tune.fg_delta_qp_p = 1;
118     p->cfg->tune.bmap_qpmin_i = 30;
119     p->cfg->tune.bmap_qpmin_p = 30;
120     p->cfg->tune.bmap_qpmax_i = 45;
121     p->cfg->tune.bmap_qpmax_p = 47;
122     p->cfg->tune.min_bg_fqp = 30;
123     p->cfg->tune.max_bg_fqp = 45;
124     p->cfg->tune.min_fg_fqp = 25;
125     p->cfg->tune.max_fg_fqp = 35;
126 
127     /*
128      * default prep:
129      * 720p
130      * YUV420SP
131      */
132     prep->width = 1280;
133     prep->height = 720;
134     prep->hor_stride = 1280;
135     prep->ver_stride = 720;
136     prep->format = MPP_FMT_YUV420SP;
137     prep->color = MPP_FRAME_SPC_UNSPECIFIED;
138     prep->colorprim = MPP_FRAME_PRI_UNSPECIFIED;
139     prep->colortrc = MPP_FRAME_TRC_UNSPECIFIED;
140     prep->range = MPP_FRAME_RANGE_UNSPECIFIED;
141     prep->rotation = MPP_ENC_ROT_0;
142     prep->rotation_ext = MPP_ENC_ROT_0;
143     prep->mirroring = 0;
144     prep->mirroring_ext = 0;
145     prep->denoise = 0;
146     prep->flip = 0;
147 
148     /*
149      * default rc_cfg:
150      * CBR
151      * 2Mbps +-25%
152      * 30fps
153      * gop 60
154      */
155     rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM;
156     rc_cfg->bps_target = 2000 * 1000;
157     rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4;
158     rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4;
159     rc_cfg->fps_in_flex = 0;
160     rc_cfg->fps_in_num = 30;
161     rc_cfg->fps_in_denom = 1;
162     rc_cfg->fps_out_flex = 0;
163     rc_cfg->fps_out_num = 30;
164     rc_cfg->fps_out_denom = 1;
165     rc_cfg->gop = 60;
166     rc_cfg->max_reenc_times = 1;
167     rc_cfg->max_i_prop = 30;
168     rc_cfg->min_i_prop = 10;
169     rc_cfg->init_ip_ratio = 160;
170     rc_cfg->qp_init = 26;
171     rc_cfg->qp_max = 51;
172     rc_cfg->qp_min = 10;
173     rc_cfg->qp_max_i = 51;
174     rc_cfg->qp_min_i = 15;
175     rc_cfg->qp_delta_ip = 4;
176     rc_cfg->qp_delta_vi = 2;
177     rc_cfg->fqp_min_i = INT_MAX;
178     rc_cfg->fqp_min_p = INT_MAX;
179     rc_cfg->fqp_max_i = INT_MAX;
180     rc_cfg->fqp_max_p = INT_MAX;
181     INIT_LIST_HEAD(&p->rc_list);
182 
183     h265e_dbg_func("leave ctx %p\n", ctx);
184     return ret;
185 }
186 
h265e_deinit(void * ctx)187 static MPP_RET h265e_deinit(void *ctx)
188 {
189     H265eCtx *p = (H265eCtx *)ctx;
190 
191     h265e_dbg_func("enter ctx %p\n", ctx);
192 
193     if (ctx == NULL) {
194         mpp_err_f("invalid NULL ctx\n");
195         return MPP_ERR_NULL_PTR;
196     }
197 
198     h265e_deinit_extra_info(p->extra_info);
199 
200     MPP_FREE(p->extra_info);
201 
202     h265e_dpb_deinit(p->dpb);
203 
204     h265e_dbg_func("leave ctx %p\n", ctx);
205     return MPP_OK;
206 }
207 
h265e_gen_hdr(void * ctx,MppPacket pkt)208 static MPP_RET h265e_gen_hdr(void *ctx, MppPacket pkt)
209 {
210     H265eCtx *p = (H265eCtx *)ctx;
211 
212     h265e_dbg_func("enter ctx %p\n", ctx);
213 
214     h265e_set_extra_info(p);
215     h265e_get_extra_info(p, pkt);
216 
217     if (NULL == p->dpb)
218         h265e_dpb_init(&p->dpb);
219 
220     h265e_dbg_func("leave ctx %p\n", ctx);
221 
222     return MPP_OK;
223 }
224 
h265e_start(void * ctx,HalEncTask * task)225 static MPP_RET h265e_start(void *ctx, HalEncTask *task)
226 {
227     h265e_dbg_func("enter\n");
228 
229     if (mpp_frame_has_meta(task->frame)) {
230         MppEncRefFrmUsrCfg *frm_cfg = task->frm_cfg;
231         EncRcForceCfg *rc_force = &task->rc_task->force;
232         MppMeta meta = mpp_frame_get_meta(task->frame);
233         RK_S32 force_lt_idx = -1;
234         RK_S32 force_use_lt_idx = -1;
235         RK_S32 force_frame_qp = -1;
236         RK_S32 base_layer_pid = -1;
237         RK_S32 force_tid = -1;
238 
239         mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &force_lt_idx);
240         mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &force_use_lt_idx);
241         mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &force_frame_qp);
242         mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &base_layer_pid);
243         mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &force_tid);
244 
245         if (force_lt_idx >= 0) {
246             frm_cfg->force_flag |= ENC_FORCE_LT_REF_IDX;
247             frm_cfg->force_lt_idx = force_lt_idx;
248         }
249 
250         if (force_use_lt_idx >= 0) {
251             frm_cfg->force_flag |= ENC_FORCE_REF_MODE;
252             frm_cfg->force_ref_mode = REF_TO_LT_REF_IDX;
253             frm_cfg->force_ref_arg = force_use_lt_idx;
254         }
255 
256         if (force_tid >= 0) {
257             frm_cfg->force_flag |= ENC_FORCE_TEMPORAL_ID;
258             frm_cfg->force_temporal_id = force_tid;
259         }
260 
261         if (force_frame_qp >= 0) {
262             rc_force->force_flag = ENC_RC_FORCE_QP;
263             rc_force->force_qp = force_frame_qp;
264         } else {
265             rc_force->force_flag &= (~ENC_RC_FORCE_QP);
266             rc_force->force_qp = -1;
267         }
268 
269         if (base_layer_pid >= 0) {
270             H265eCtx *p = (H265eCtx *)ctx;
271             MppEncH265Cfg *h265 = &p->cfg->h265;
272 
273             h265->base_layer_pid = base_layer_pid;
274         }
275     }
276 
277     /*
278      * Step 2: Fps conversion
279      *
280      * Determine current frame which should be encoded or not according to
281      * input and output frame rate.
282      */
283 
284     if (!task->valid)
285         mpp_log_f("drop one frame\n");
286 
287     /*
288      * Step 3: Backup dpb for reencode
289      */
290     //h265e_dpb_copy(&p->dpb_bak, p->dpb);
291     h265e_dbg_func("leave\n");
292 
293     return MPP_OK;
294 }
295 
h265e_proc_dpb(void * ctx,HalEncTask * task)296 static MPP_RET h265e_proc_dpb(void *ctx, HalEncTask *task)
297 {
298     H265eCtx *p = (H265eCtx *)ctx;
299     EncRcTask    *rc_task = task->rc_task;
300     EncCpbStatus *cpb = &task->rc_task->cpb;
301 
302     h265e_dbg_func("enter\n");
303     h265e_dpb_proc_cpb(p->dpb, cpb);
304     h265e_dpb_get_curr(p->dpb);
305     h265e_slice_init(ctx, cpb->curr);
306     h265e_dpb_build_list(p->dpb, cpb);
307 
308     rc_task->frm  = p->dpb->curr->status;
309 
310     h265e_dbg_func("leave\n");
311     return MPP_OK;
312 }
313 
h265e_proc_hal(void * ctx,HalEncTask * task)314 static MPP_RET h265e_proc_hal(void *ctx, HalEncTask *task)
315 {
316     H265eCtx *p = (H265eCtx *)ctx;
317     MppEncH265Cfg *h265 = &p->cfg->h265;
318 
319     if (ctx == NULL) {
320         mpp_err_f("invalid NULL ctx\n");
321         return MPP_ERR_NULL_PTR;
322     }
323 
324     /* check max temporal layer id */
325     {
326         MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(p->cfg->ref_cfg);
327         RK_S32 cpb_max_tid = cpb_info->max_st_tid;
328         RK_S32 cfg_max_tid = h265->max_tid;
329 
330         if (cpb_max_tid != cfg_max_tid) {
331             mpp_log("max tid is update to match cpb %d -> %d\n",
332                     cfg_max_tid, cpb_max_tid);
333             h265->max_tid = cpb_max_tid;
334         }
335     }
336 
337     if (h265->max_tid) {
338         EncFrmStatus *frm = &task->rc_task->frm;
339         MppPacket packet = task->packet;
340         MppMeta meta = mpp_packet_get_meta(packet);
341 
342         mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, frm->temporal_id);
343         if (!frm->is_non_ref && frm->is_lt_ref)
344             mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, frm->lt_idx);
345     }
346 
347     h265e_dbg_func("enter ctx %p \n", ctx);
348 
349     h265e_syntax_fill(ctx);
350 
351     task->valid = 1;
352     task->syntax.number = 1;
353     task->syntax.data = &p->syntax;
354 
355     h265e_dbg_func("leave ctx %p \n", ctx);
356     return MPP_OK;
357 }
358 
h265e_proc_enc_skip(void * ctx,HalEncTask * task)359 static MPP_RET h265e_proc_enc_skip(void *ctx, HalEncTask *task)
360 {
361     H265eCtx *p = (H265eCtx *)ctx;
362     MppPacket pkt = task->packet;
363     H265eSyntax_new *syntax = &p->syntax;
364     RK_U8 *ptr = mpp_packet_get_pos(pkt);
365     RK_U32 offset = mpp_packet_get_length(pkt);
366     RK_U32 len    = mpp_packet_get_size(pkt) - offset;
367     RK_U32 new_length = 0;
368 
369     h265e_dbg_func("enter\n");
370     ptr += offset;
371     p->slice->m_sliceQp = task->rc_task->info.quality_target;
372     new_length = h265e_code_slice_skip_frame(ctx, p->slice, ptr, len);
373     task->length = new_length;
374     task->rc_task->info.bit_real = 8 * new_length;
375     p->dpb->curr->prev_ref_idx = syntax->sp.recon_pic.slot_idx;
376     mpp_packet_add_segment_info(pkt, NAL_TRAIL_R, offset, new_length);
377     mpp_buffer_sync_partial_end(mpp_packet_get_buffer(pkt), offset, new_length);
378 
379     h265e_dbg_func("leave\n");
380     return MPP_OK;
381 }
382 
h265e_add_sei(MppPacket pkt,RK_S32 * length,RK_U8 uuid[16],const void * data,RK_S32 size)383 static MPP_RET h265e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16],
384                              const void *data, RK_S32 size)
385 {
386     RK_U8 *ptr = mpp_packet_get_pos(pkt);
387     RK_U32 offset = mpp_packet_get_length(pkt);
388     RK_U32 new_length = 0;
389 
390     ptr += offset;
391 
392     if (uuid == uuid_refresh_cfg) {
393         RK_U32 recovery_frame_cnt = ((RK_U32 *)data)[0] - 1;
394         new_length = h265e_sei_recovery_point(ptr, uuid, &recovery_frame_cnt, 0);
395     } else {
396         new_length = h265e_data_to_sei(ptr, uuid, data, size);
397     }
398     *length = new_length;
399 
400     mpp_packet_set_length(pkt, offset + new_length);
401     mpp_packet_add_segment_info(pkt, NAL_SEI_PREFIX, offset, new_length);
402 
403     return MPP_OK;
404 }
405 
h265e_proc_cfg(void * ctx,MpiCmd cmd,void * param)406 static MPP_RET h265e_proc_cfg(void *ctx, MpiCmd cmd, void *param)
407 {
408     H265eCtx *p = (H265eCtx *)ctx;
409     MppEncCfgSet *cfg = p->cfg;
410     MPP_RET ret = MPP_OK;
411 
412     h265e_dbg_func("enter ctx %p cmd %08x\n", ctx, cmd);
413 
414     switch (cmd) {
415     case MPP_ENC_SET_CFG : {
416     } break;
417     case MPP_ENC_GET_EXTRA_INFO: {
418         MppPacket pkt_out = (MppPacket )param;
419         h265e_set_extra_info(p);
420         h265e_get_extra_info(p, pkt_out);
421     } break;
422     case MPP_ENC_SET_SEI_CFG: {
423     } break;
424     case MPP_ENC_SET_SPLIT : {
425         MppEncSliceSplit *src = (MppEncSliceSplit *)param;
426         MppEncH265SliceCfg *slice_cfg = &cfg->h265.slice_cfg;
427 
428         if (src->split_mode > MPP_ENC_SPLIT_NONE) {
429             slice_cfg->split_enable = 1;
430             slice_cfg->split_mode = 0;
431             if (src->split_mode == MPP_ENC_SPLIT_BY_CTU)
432                 slice_cfg->split_mode = 1;
433             slice_cfg->slice_size =  src->split_arg;
434         } else {
435             slice_cfg->split_enable = 0;
436         }
437     } break;
438     default:
439         mpp_err("No correspond %08x found, and can not config!\n", cmd);
440         ret = MPP_NOK;
441         break;
442     }
443 
444     h265e_dbg_func("leave ctx %p\n", ctx);
445     return ret;
446 }
447 
448 const EncImplApi api_h265e = {
449     "h265e_control",
450     MPP_VIDEO_CodingHEVC,
451     sizeof(H265eCtx),
452     0,
453     h265e_init,
454     h265e_deinit,
455     h265e_proc_cfg,
456     h265e_gen_hdr,
457     h265e_start,
458     h265e_proc_dpb,
459     h265e_proc_hal,
460     h265e_add_sei,
461     h265e_proc_enc_skip,
462 };
463