xref: /OK3568_Linux_fs/external/mpp/mpp/codec/enc/h264/h264e_api_v2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "h264e_api_v2"
18 
19 #include <string.h>
20 
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_common.h"
24 
25 #include "mpp_packet_impl.h"
26 #include "mpp_enc_refs.h"
27 
28 #include "h264e_debug.h"
29 #include "h264e_syntax.h"
30 #include "h264e_sps.h"
31 #include "h264e_pps.h"
32 #include "h264e_sei.h"
33 #include "h264e_dpb.h"
34 #include "h264e_slice.h"
35 #include "h264e_api_v2.h"
36 #include "rc.h"
37 #include "mpp_rc.h"
38 
39 #include "enc_impl_api.h"
40 #include "mpp_enc_cfg_impl.h"
41 
42 RK_U32 h264e_debug = 0;
43 
44 typedef struct {
45     /* config from mpp_enc */
46     MppClientType       type;
47     MppEncCfgSet        *cfg;
48     MppEncRefs          refs;
49     RK_U32              idr_request;
50 
51     /* H.264 high level syntax */
52     H264eSps            sps;
53     H264ePps            pps;
54 
55     /*
56      * H.264 low level syntax
57      *
58      * NOTE: two dpb is for dpb roll-back and reencode
59      */
60     H264eDpb            dpb;
61     H264eDpb            dpb_bak;
62     H264eSlice          slice;
63     H264eReorderInfo    reorder;
64     H264eMarkingInfo    marking;
65     /* H.264 frame status syntax */
66     H264eFrmInfo        frms;
67     /* header generation */
68     MppPacket           hdr_pkt;
69     void                *hdr_buf;
70     size_t              hdr_size;
71     size_t              hdr_len;
72     RK_S32              sps_offset;
73     RK_S32              sps_len;
74     RK_S32              pps_offset;
75     RK_S32              pps_len;
76     RK_S32              prefix_offset;
77     RK_S32              prefix_len;
78     H264ePrefixNal      prefix;
79 
80     /* rate control config */
81     RcCtx               rc_ctx;
82 
83     /* output to hal */
84     RK_S32              syn_num;
85     H264eSyntaxDesc     syntax[H264E_SYN_BUTT];
86 } H264eCtx;
87 
init_h264e_cfg_set(MppEncCfgSet * cfg,MppClientType type)88 static void init_h264e_cfg_set(MppEncCfgSet *cfg, MppClientType type)
89 {
90     MppEncRcCfg *rc_cfg = &cfg->rc;
91     MppEncPrepCfg *prep = &cfg->prep;
92     MppEncH264Cfg *h264 = &cfg->codec.h264;
93 
94     /*
95      * default codec:
96      * High Profile
97      * frame mode
98      * all flag enabled
99      */
100     memset(h264, 0, sizeof(*h264));
101     h264->profile = H264_PROFILE_BASELINE;
102     h264->level = H264_LEVEL_3_1;
103 
104     switch (type) {
105     case VPU_CLIENT_VEPU1 :
106     case VPU_CLIENT_VEPU2 : {
107         h264->poc_type = 2;
108         h264->log2_max_poc_lsb = 12;
109         h264->log2_max_frame_num = 12;
110         h264->hw_cfg.hw_poc_type = 2;
111         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
112     } break;
113     case VPU_CLIENT_RKVENC : {
114         h264->poc_type = 0;
115         h264->log2_max_poc_lsb = 12;
116         h264->log2_max_frame_num = 12;
117         h264->chroma_cb_qp_offset = -6;
118         h264->chroma_cr_qp_offset = -6;
119         h264->hw_cfg.hw_poc_type = 0;
120         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
121     } break;
122     default : {
123         h264->poc_type = 0;
124         h264->log2_max_poc_lsb = 12;
125         h264->log2_max_frame_num = 12;
126         h264->hw_cfg.hw_poc_type = 0;
127         h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12;
128     } break;
129     }
130 
131     /*
132      * default prep:
133      * 720p
134      * YUV420SP
135      */
136     prep->change = 0;
137     prep->width = 1280;
138     prep->height = 720;
139     prep->hor_stride = 1280;
140     prep->ver_stride = 720;
141     prep->format = MPP_FMT_YUV420SP;
142     prep->rotation = MPP_ENC_ROT_0;
143     prep->rotation_ext = MPP_ENC_ROT_0;
144     prep->color = MPP_FRAME_SPC_UNSPECIFIED;
145     prep->colorprim = MPP_FRAME_PRI_UNSPECIFIED;
146     prep->colortrc = MPP_FRAME_TRC_UNSPECIFIED;
147     prep->range = MPP_FRAME_RANGE_UNSPECIFIED;
148     prep->mirroring = 0;
149     prep->mirroring_ext = 0;
150     prep->denoise = 0;
151     prep->flip = 0;
152 
153     /*
154      * default rc_cfg:
155      * CBR
156      * 2Mbps +-25%
157      * 30fps
158      * gop 60
159      */
160     rc_cfg->change = 0;
161     rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM;
162     rc_cfg->bps_target = 2000 * 1000;
163     rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4;
164     rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4;
165     rc_cfg->fps_in_flex = 0;
166     rc_cfg->fps_in_num = 30;
167     rc_cfg->fps_in_denorm = 1;
168     rc_cfg->fps_out_flex = 0;
169     rc_cfg->fps_out_num = 30;
170     rc_cfg->fps_out_denorm = 1;
171     rc_cfg->gop = 60;
172     rc_cfg->max_reenc_times = 1;
173     rc_cfg->max_i_prop = 30;
174     rc_cfg->min_i_prop = 10;
175     rc_cfg->init_ip_ratio = 160;
176     rc_cfg->qp_init = 26;
177     rc_cfg->qp_max = 48;
178     rc_cfg->qp_min = 8;
179     /* default max/min intra qp is not set */
180     rc_cfg->qp_max_i = 0;
181     rc_cfg->qp_min_i = 0;
182     rc_cfg->qp_delta_ip = 2;
183 }
184 
h264e_add_syntax(H264eCtx * ctx,H264eSyntaxType type,void * p)185 static void h264e_add_syntax(H264eCtx *ctx, H264eSyntaxType type, void *p)
186 {
187     ctx->syntax[ctx->syn_num].type  = type;
188     ctx->syntax[ctx->syn_num].p     = p;
189     ctx->syn_num++;
190 }
191 
h264e_init(void * ctx,EncImplCfg * ctrl_cfg)192 static MPP_RET h264e_init(void *ctx, EncImplCfg *ctrl_cfg)
193 {
194     MPP_RET ret = MPP_OK;
195     H264eCtx *p = (H264eCtx *)ctx;
196 
197     mpp_env_get_u32("h264e_debug", &h264e_debug, 0);
198 
199     h264e_dbg_func("enter\n");
200 
201     p->type = ctrl_cfg->type;
202     p->hdr_size = SZ_1K;
203     p->hdr_buf = mpp_malloc_size(void, p->hdr_size);
204     mpp_assert(p->hdr_buf);
205     mpp_packet_init(&p->hdr_pkt, p->hdr_buf, p->hdr_size);
206     mpp_assert(p->hdr_pkt);
207 
208     p->cfg = ctrl_cfg->cfg;
209     p->refs = ctrl_cfg->refs;
210     p->idr_request = 0;
211 
212     h264e_reorder_init(&p->reorder);
213     h264e_marking_init(&p->marking);
214 
215     h264e_dpb_init(&p->dpb, &p->reorder, &p->marking);
216     h264e_slice_init(&p->slice, &p->reorder, &p->marking);
217 
218     init_h264e_cfg_set(p->cfg, p->type);
219 
220     mpp_env_get_u32("h264e_debug", &h264e_debug, 0);
221 
222     h264e_dbg_func("leave\n");
223     return ret;
224 }
225 
h264e_deinit(void * ctx)226 static MPP_RET h264e_deinit(void *ctx)
227 {
228     H264eCtx *p = (H264eCtx *)ctx;
229 
230     h264e_dbg_func("enter\n");
231 
232     if (p->hdr_pkt)
233         mpp_packet_deinit(&p->hdr_pkt);
234 
235     MPP_FREE(p->hdr_buf);
236 
237     h264e_dbg_func("leave\n");
238     return MPP_OK;
239 }
240 
h264e_proc_prep_cfg(MppEncPrepCfg * dst,MppEncPrepCfg * src)241 static MPP_RET h264e_proc_prep_cfg(MppEncPrepCfg *dst, MppEncPrepCfg *src)
242 {
243     MPP_RET ret = MPP_OK;
244     RK_U32 change = src->change;
245 
246     mpp_assert(change);
247     if (change) {
248         RK_S32 mirroring;
249         RK_S32 rotation;
250         MppEncPrepCfg bak = *dst;
251 
252         if (change & MPP_ENC_PREP_CFG_CHANGE_FORMAT)
253             dst->format = src->format;
254 
255         if (change & MPP_ENC_PREP_CFG_CHANGE_COLOR_RANGE)
256             dst->range = src->range;
257 
258         if (change & MPP_ENC_PREP_CFG_CHANGE_COLOR_SPACE)
259             dst->color = src->color;
260 
261         if (change & MPP_ENC_PREP_CFG_CHANGE_COLOR_PRIME)
262             dst->colorprim = src->colorprim;
263 
264         if (change & MPP_ENC_PREP_CFG_CHANGE_COLOR_TRC)
265             dst->colortrc = src->colortrc;
266 
267         if (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)
268             dst->rotation_ext = src->rotation_ext;
269 
270         if (change & MPP_ENC_PREP_CFG_CHANGE_MIRRORING)
271             dst->mirroring_ext = src->mirroring_ext;
272 
273         if (change & MPP_ENC_PREP_CFG_CHANGE_FLIP)
274             dst->flip = src->flip;
275 
276         if (change & MPP_ENC_PREP_CFG_CHANGE_DENOISE)
277             dst->denoise = src->denoise;
278 
279         if (change & MPP_ENC_PREP_CFG_CHANGE_SHARPEN)
280             dst->sharpen = src->sharpen;
281 
282         // parameter checking
283         if (dst->rotation_ext >= MPP_ENC_ROT_BUTT || dst->rotation_ext < 0 ||
284             dst->mirroring_ext < 0 || dst->flip < 0) {
285             mpp_err("invalid trans: rotation %d, mirroring %d\n", dst->rotation_ext, dst->mirroring_ext);
286             ret = MPP_ERR_VALUE;
287         }
288 
289         /* For unifying the encoder's params used by CFG_SET and CFG_GET command,
290          * there is distinction between user's set and set in hal.
291          * User can externally set rotation_ext, mirroring_ext and flip,
292          * which should be transformed to mirroring and rotation in hal.
293          */
294         mirroring = dst->mirroring_ext;
295         rotation = dst->rotation_ext;
296 
297         if (dst->flip) {
298             mirroring = !mirroring;
299             rotation += MPP_ENC_ROT_180;
300             rotation &= MPP_ENC_ROT_270;
301         }
302 
303         dst->mirroring = mirroring;
304         dst->rotation = rotation;
305 
306         if ((change & MPP_ENC_PREP_CFG_CHANGE_INPUT) ||
307             (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)) {
308             if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
309                 dst->width = src->height;
310                 dst->height = src->width;
311             } else {
312                 dst->width = src->width;
313                 dst->height = src->height;
314             }
315             dst->hor_stride = src->hor_stride;
316             dst->ver_stride = src->ver_stride;
317         }
318 
319         dst->change |= change;
320 
321         // parameter checking
322         if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
323             if (dst->height > dst->hor_stride || dst->width > dst->ver_stride) {
324                 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
325                         dst->width, dst->height, dst->hor_stride, dst->ver_stride);
326                 ret = MPP_ERR_VALUE;
327             }
328         } else {
329             if (dst->width > dst->hor_stride || dst->height > dst->ver_stride) {
330                 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
331                         dst->width, dst->height, dst->hor_stride, dst->ver_stride);
332                 ret = MPP_ERR_VALUE;
333             }
334         }
335 
336         if (MPP_FRAME_FMT_IS_FBC(dst->format) && (dst->mirroring || dst->rotation || dst->flip)) {
337             // rk3588 rkvenc support fbc with rotation
338             if (!strstr(mpp_get_soc_name(), "rk3588")) {
339                 mpp_err("invalid cfg fbc data no support mirror %d, rotation %d, or flip %d",
340                         dst->mirroring, dst->rotation, dst->flip);
341                 ret = MPP_ERR_VALUE;
342             }
343         }
344 
345         if (dst->range >= MPP_FRAME_RANGE_NB ||
346             dst->color >= MPP_FRAME_SPC_NB ||
347             dst->colorprim >= MPP_FRAME_PRI_NB ||
348             dst->colortrc >= MPP_FRAME_TRC_NB) {
349             mpp_err("invalid color range %d colorspace %d primaries %d transfer characteristic %d\n",
350                     dst->range, dst->color, dst->colorprim, dst->colortrc);
351             ret = MPP_ERR_VALUE;
352         }
353 
354         if (ret) {
355             mpp_err_f("failed to accept new prep config\n");
356             *dst = bak;
357         } else {
358             mpp_log("MPP_ENC_SET_PREP_CFG w:h [%d:%d] stride [%d:%d]\n",
359                     dst->width, dst->height,
360                     dst->hor_stride, dst->ver_stride);
361         }
362     }
363 
364     src->change = 0;
365     return ret;
366 }
367 
h264e_proc_h264_cfg(MppEncH264Cfg * dst,MppEncH264Cfg * src)368 static MPP_RET h264e_proc_h264_cfg(MppEncH264Cfg *dst, MppEncH264Cfg *src)
369 {
370     MPP_RET ret = MPP_OK;
371     RK_U32 change = src->change;
372 
373     // TODO: do codec check first
374     if (change) {
375         RK_S32 entropy_coding_mode;
376         RK_S32 cabac_init_idc;
377         RK_S32 transform8x8_mode;
378         RK_U32 disable_cabac;
379 
380         if (change & MPP_ENC_H264_CFG_STREAM_TYPE)
381             dst->stream_type = src->stream_type;
382 
383         if ((change & MPP_ENC_H264_CFG_CHANGE_PROFILE) &&
384             ((dst->profile != src->profile) || (dst->level != src->level))) {
385             dst->profile = src->profile;
386             dst->level = src->level;
387             dst->change |= MPP_ENC_H264_CFG_CHANGE_PROFILE;
388         }
389 
390         if ((change & MPP_ENC_H264_CFG_CHANGE_POC_TYPE) &&
391             (dst->poc_type != src->poc_type)) {
392             dst->poc_type = src->poc_type;
393             dst->change |= MPP_ENC_H264_CFG_CHANGE_POC_TYPE;
394         }
395 
396         if ((change & MPP_ENC_H264_CFG_CHANGE_MAX_POC_LSB) &&
397             (dst->log2_max_poc_lsb != src->log2_max_poc_lsb)) {
398             dst->log2_max_poc_lsb = src->log2_max_poc_lsb;
399             dst->change |= MPP_ENC_H264_CFG_CHANGE_MAX_POC_LSB;
400         }
401 
402         if ((change & MPP_ENC_H264_CFG_CHANGE_MAX_FRM_NUM) &&
403             (dst->log2_max_frame_num != src->log2_max_frame_num)) {
404             dst->log2_max_frame_num = src->log2_max_frame_num;
405             dst->change |= MPP_ENC_H264_CFG_CHANGE_MAX_FRM_NUM;
406         }
407 
408         if ((change & MPP_ENC_H264_CFG_CHANGE_GAPS_IN_FRM_NUM) &&
409             (dst->gaps_not_allowed != src->gaps_not_allowed)) {
410             dst->gaps_not_allowed = src->gaps_not_allowed;
411             dst->change |= MPP_ENC_H264_CFG_CHANGE_GAPS_IN_FRM_NUM;
412         }
413 
414         if ((change & MPP_ENC_H264_CFG_CHANGE_ENTROPY) &&
415             ((dst->entropy_coding_mode_ex != src->entropy_coding_mode_ex) ||
416              (dst->cabac_init_idc_ex != src->cabac_init_idc_ex))) {
417             dst->entropy_coding_mode_ex = src->entropy_coding_mode_ex;
418             dst->cabac_init_idc_ex = src->cabac_init_idc_ex;
419             dst->change |= MPP_ENC_H264_CFG_CHANGE_ENTROPY;
420         }
421 
422         if ((change & MPP_ENC_H264_CFG_CHANGE_TRANS_8x8) &&
423             (dst->transform8x8_mode_ex != src->transform8x8_mode_ex)) {
424             dst->transform8x8_mode_ex = src->transform8x8_mode_ex;
425             dst->change |= MPP_ENC_H264_CFG_CHANGE_TRANS_8x8;
426         }
427 
428         if ((change & MPP_ENC_H264_CFG_CHANGE_CONST_INTRA) &&
429             (dst->constrained_intra_pred_mode != src->constrained_intra_pred_mode)) {
430             dst->constrained_intra_pred_mode = src->constrained_intra_pred_mode;
431             dst->change |= MPP_ENC_H264_CFG_CHANGE_CONST_INTRA;
432         }
433 
434         if ((change & MPP_ENC_H264_CFG_CHANGE_CHROMA_QP) &&
435             (dst->chroma_cb_qp_offset != src->chroma_cb_qp_offset ||
436              dst->chroma_cr_qp_offset != src->chroma_cr_qp_offset)) {
437             dst->chroma_cb_qp_offset = src->chroma_cb_qp_offset;
438             dst->chroma_cr_qp_offset = src->chroma_cr_qp_offset;
439             dst->change |= MPP_ENC_H264_CFG_CHANGE_CHROMA_QP;
440         }
441 
442         if ((change & MPP_ENC_H264_CFG_CHANGE_DEBLOCKING) &&
443             ((dst->deblock_disable != src->deblock_disable) ||
444              (dst->deblock_offset_alpha != src->deblock_offset_alpha) ||
445              (dst->deblock_offset_beta != src->deblock_offset_beta))) {
446             dst->deblock_disable = src->deblock_disable;
447             dst->deblock_offset_alpha = src->deblock_offset_alpha;
448             dst->deblock_offset_beta = src->deblock_offset_beta;
449             dst->change |= MPP_ENC_H264_CFG_CHANGE_DEBLOCKING;
450         }
451 
452         if (change & MPP_ENC_H264_CFG_CHANGE_LONG_TERM)
453             dst->use_longterm = src->use_longterm;
454 
455         if ((change & MPP_ENC_H264_CFG_CHANGE_SCALING_LIST) &&
456             (dst->scaling_list_mode != src->scaling_list_mode)) {
457             dst->scaling_list_mode = src->scaling_list_mode;
458             dst->change |= MPP_ENC_H264_CFG_CHANGE_SCALING_LIST;
459         }
460 
461         if ((change & MPP_ENC_H264_CFG_CHANGE_INTRA_REFRESH) &&
462             ((dst->intra_refresh_mode != src->intra_refresh_mode) ||
463              (dst->intra_refresh_arg != src->intra_refresh_arg))) {
464             dst->intra_refresh_mode = src->intra_refresh_mode;
465             dst->intra_refresh_arg = src->intra_refresh_arg;
466             dst->change |= MPP_ENC_H264_CFG_CHANGE_INTRA_REFRESH;
467         }
468 
469         if ((change & MPP_ENC_H264_CFG_CHANGE_MAX_LTR) &&
470             (dst->max_ltr_frames != src->max_ltr_frames)) {
471             dst->max_ltr_frames = src->max_ltr_frames;
472             dst->change |= MPP_ENC_H264_CFG_CHANGE_MAX_LTR;
473         }
474 
475         if ((change & MPP_ENC_H264_CFG_CHANGE_MAX_TID) &&
476             (dst->max_tid != src->max_tid)) {
477             dst->max_tid = src->max_tid;
478             dst->change |= MPP_ENC_H264_CFG_CHANGE_MAX_TID;
479         }
480 
481         if ((change & MPP_ENC_H264_CFG_CHANGE_ADD_PREFIX) &&
482             (dst->prefix_mode != src->prefix_mode)) {
483             dst->prefix_mode = src->prefix_mode;
484             dst->change |= MPP_ENC_H264_CFG_CHANGE_ADD_PREFIX;
485         }
486 
487         if ((change & MPP_ENC_H264_CFG_CHANGE_BASE_LAYER_PID) &&
488             (dst->base_layer_pid != src->base_layer_pid)) {
489             dst->base_layer_pid = src->base_layer_pid;
490             dst->change |= MPP_ENC_H264_CFG_CHANGE_BASE_LAYER_PID;
491         }
492 
493         if ((change & MPP_ENC_H264_CFG_CHANGE_CONSTRAINT_SET) &&
494             (dst->constraint_set != src->constraint_set)) {
495             dst->constraint_set = src->constraint_set;
496             dst->change |= MPP_ENC_H264_CFG_CHANGE_CONSTRAINT_SET;
497         }
498 
499         // check user h.264 config. If valid, set to HAL.
500         entropy_coding_mode = dst->entropy_coding_mode_ex;
501         cabac_init_idc = dst->cabac_init_idc_ex;
502         transform8x8_mode = dst->transform8x8_mode_ex;
503 
504         disable_cabac = (H264_PROFILE_FREXT_CAVLC444 == dst->profile ||
505                          H264_PROFILE_BASELINE == dst->profile ||
506                          H264_PROFILE_EXTENDED == dst->profile);
507 
508         if (disable_cabac && entropy_coding_mode) {
509             mpp_err("Warning: invalid cabac_en %d for profile %d, set to 0.\n",
510                     entropy_coding_mode, dst->profile);
511 
512             entropy_coding_mode = 0;
513         }
514 
515         if (disable_cabac && cabac_init_idc >= 0) {
516             mpp_err("Warning: invalid cabac_init_idc %d for profile %d, set to -1.\n",
517                     cabac_init_idc, dst->profile);
518 
519             cabac_init_idc = -1;
520         }
521 
522         if (dst->profile < H264_PROFILE_HIGH && transform8x8_mode) {
523             mpp_err("Warning: invalid transform8x8_mode %d for profile %d, set to 0.\n",
524                     transform8x8_mode, dst->profile);
525 
526             transform8x8_mode = 0;
527         }
528 
529         dst->entropy_coding_mode = entropy_coding_mode;
530         dst->cabac_init_idc = cabac_init_idc;
531         dst->transform8x8_mode = transform8x8_mode;
532     }
533 
534     src->change = 0;
535     return ret;
536 }
537 
h264e_proc_split_cfg(MppEncSliceSplit * dst,MppEncSliceSplit * src)538 static MPP_RET h264e_proc_split_cfg(MppEncSliceSplit *dst, MppEncSliceSplit *src)
539 {
540     MPP_RET ret = MPP_OK;
541     RK_U32 change = src->change;
542 
543     if (change & MPP_ENC_SPLIT_CFG_CHANGE_MODE) {
544         dst->split_mode = src->split_mode;
545         dst->split_arg = src->split_arg;
546     }
547 
548     if (change & MPP_ENC_SPLIT_CFG_CHANGE_ARG)
549         dst->split_arg = src->split_arg;
550 
551     if (change & MPP_ENC_SPLIT_CFG_CHANGE_OUTPUT)
552         dst->split_out = src->split_out;
553 
554     /* cleanup arg and out when split mode is disabled */
555     if (!dst->split_mode) {
556         dst->split_arg = 0;
557         dst->split_out = 0;
558     }
559 
560     dst->change |= change;
561     src->change = 0;
562 
563     return ret;
564 }
565 
h264e_check_cfg(MppEncCfgSet * cfg)566 static void h264e_check_cfg(MppEncCfgSet *cfg)
567 {
568     MppEncRcCfg *rc = &cfg->rc;
569     MppEncH264Cfg *h264 = &cfg->codec.h264;
570 
571     if (rc->drop_mode == MPP_ENC_RC_DROP_FRM_PSKIP &&
572         rc->drop_gap == 0 &&
573         h264->poc_type == 2) {
574         mpp_err("poc type 2 is ocnflict with successive non-reference pskip mode\n");
575         mpp_err("set drop gap to 1\n");
576         rc->drop_gap = 1;
577     }
578 }
579 
h264e_proc_cfg(void * ctx,MpiCmd cmd,void * param)580 static MPP_RET h264e_proc_cfg(void *ctx, MpiCmd cmd, void *param)
581 {
582     MPP_RET ret = MPP_OK;
583     H264eCtx *p = (H264eCtx *)ctx;
584     MppEncCfgSet *cfg = p->cfg;
585 
586     h264e_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param);
587 
588     switch (cmd) {
589     case MPP_ENC_SET_CFG : {
590         MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
591         MppEncCfgSet *src = &impl->cfg;
592 
593         if (src->prep.change)
594             ret |= h264e_proc_prep_cfg(&cfg->prep, &src->prep);
595 
596         // TODO: rc cfg shouldn't be done here
597         if (cfg->rc.refresh_en) {
598             RK_U32 mb_rows;
599 
600             if (MPP_ENC_RC_INTRA_REFRESH_ROW == cfg->rc.refresh_mode)
601                 mb_rows = MPP_ALIGN(cfg->prep.height, 16) / 16;
602             else
603                 mb_rows = MPP_ALIGN(cfg->prep.width, 16) / 16;
604 
605             cfg->rc.refresh_length = (mb_rows + cfg->rc.refresh_num - 1) / cfg->rc.refresh_num;
606             if (cfg->rc.gop < cfg->rc.refresh_length)
607                 cfg->rc.refresh_length = cfg->rc.gop;
608         }
609 
610         if (src->codec.h264.change)
611             ret |= h264e_proc_h264_cfg(&cfg->codec.h264, &src->codec.h264);
612 
613         if (src->split.change)
614             ret |= h264e_proc_split_cfg(&cfg->split, &src->split);
615     } break;
616     case MPP_ENC_SET_PREP_CFG : {
617         ret = h264e_proc_prep_cfg(&cfg->prep, param);
618     } break;
619     case MPP_ENC_SET_CODEC_CFG : {
620         MppEncCodecCfg *codec = (MppEncCodecCfg *)param;
621         ret = h264e_proc_h264_cfg(&cfg->codec.h264, &codec->h264);
622     } break;
623     case MPP_ENC_SET_SEI_CFG : {
624     } break;
625     case MPP_ENC_SET_SPLIT : {
626         ret = h264e_proc_split_cfg(&cfg->split, param);
627     } break;
628     default:
629         mpp_err("No correspond cmd found, and can not config!");
630         ret = MPP_NOK;
631         break;
632     }
633 
634     h264e_check_cfg(cfg);
635 
636     h264e_dbg_func("leave ret %d\n", ret);
637 
638     return ret;
639 }
640 
h264e_gen_hdr(void * ctx,MppPacket pkt)641 static MPP_RET h264e_gen_hdr(void *ctx, MppPacket pkt)
642 {
643     H264eCtx *p = (H264eCtx *)ctx;
644 
645     h264e_dbg_func("enter\n");
646 
647     h264e_sps_update(&p->sps, p->cfg);
648     h264e_pps_update(&p->pps, p->cfg);
649 
650     /*
651      * NOTE: When sps/pps is update we need to update dpb and slice info
652      */
653     h264e_dpb_setup(&p->dpb, p->cfg, &p->sps);
654 
655     mpp_packet_reset(p->hdr_pkt);
656 
657     h264e_sps_to_packet(&p->sps, p->hdr_pkt, &p->sps_offset, &p->sps_len, p->cfg);
658     h264e_pps_to_packet(&p->pps, p->hdr_pkt, &p->pps_offset, &p->pps_len);
659     p->hdr_len = mpp_packet_get_length(p->hdr_pkt);
660 
661     if (pkt) {
662         mpp_packet_write(pkt, 0, p->hdr_buf, p->hdr_len);
663         mpp_packet_set_length(pkt, p->hdr_len);
664 
665         mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_SPS,
666                                     p->sps_offset, p->sps_len);
667         mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_PPS,
668                                     p->pps_offset, p->pps_len);
669     }
670 
671     h264e_dbg_func("leave\n");
672     return MPP_OK;
673 }
674 
h264e_start(void * ctx,HalEncTask * task)675 static MPP_RET h264e_start(void *ctx, HalEncTask *task)
676 {
677     h264e_dbg_func("enter\n");
678 
679     if (mpp_frame_has_meta(task->frame)) {
680         MppEncRefFrmUsrCfg *frm_cfg = task->frm_cfg;
681         EncRcForceCfg *rc_force = &task->rc_task->force;
682         MppMeta meta = mpp_frame_get_meta(task->frame);
683         RK_S32 force_lt_idx = -1;
684         RK_S32 force_use_lt_idx = -1;
685         RK_S32 force_frame_qp = -1;
686         RK_S32 base_layer_pid = -1;
687 
688         mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &force_lt_idx);
689         mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &force_use_lt_idx);
690         mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &force_frame_qp);
691         mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &base_layer_pid);
692 
693         if (force_lt_idx >= 0) {
694             frm_cfg->force_flag |= ENC_FORCE_LT_REF_IDX;
695             frm_cfg->force_lt_idx = force_lt_idx;
696         }
697 
698         if (force_use_lt_idx >= 0) {
699             frm_cfg->force_flag |= ENC_FORCE_REF_MODE;
700             frm_cfg->force_ref_mode = REF_TO_LT_REF_IDX;
701             frm_cfg->force_ref_arg = force_use_lt_idx;
702         }
703 
704         if (force_frame_qp >= 0) {
705             rc_force->force_flag = ENC_RC_FORCE_QP;
706             rc_force->force_qp = force_frame_qp;
707         } else {
708             rc_force->force_flag &= (~ENC_RC_FORCE_QP);
709             rc_force->force_qp = -1;
710         }
711 
712         if (base_layer_pid >= 0) {
713             H264eCtx *p = (H264eCtx *)ctx;
714             MppEncH264Cfg *h264 = &p->cfg->codec.h264;
715 
716             h264->base_layer_pid = base_layer_pid;
717         }
718     }
719 
720     h264e_dbg_func("leave\n");
721 
722     return MPP_OK;
723 }
724 
h264e_proc_dpb(void * ctx,HalEncTask * task)725 static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task)
726 {
727     H264eCtx *p = (H264eCtx *)ctx;
728     H264eDpb *dpb = &p->dpb;
729     H264eFrmInfo *frms = &p->frms;
730     EncCpbStatus *cpb = &task->rc_task->cpb;
731     EncFrmStatus *frm = &task->rc_task->frm;
732     H264eDpbFrm *curr = NULL;
733     H264eDpbFrm *refr = NULL;
734     RK_S32 i;
735 
736     h264e_dbg_func("enter\n");
737 
738     // update dpb
739     h264e_dpb_proc(dpb, cpb);
740 
741     curr = dpb->curr;
742     refr = dpb->refr;
743 
744     // update slice info
745     h264e_slice_update(&p->slice, p->cfg, &p->sps, &p->pps, dpb->curr);
746 
747     // update frame usage
748     frms->seq_idx = curr->seq_idx;
749     frms->curr_idx = curr->slot_idx;
750     frms->refr_idx = (refr) ? refr->slot_idx : curr->slot_idx;
751 
752     for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(frms->usage); i++)
753         frms->usage[i] = dpb->frames[i].on_used;
754 
755     // update dpb to after encoding status
756     h264e_dpb_check(dpb, cpb);
757 
758     frm->val = curr->status.val;
759 
760     h264e_dbg_func("leave\n");
761 
762     return MPP_OK;
763 }
764 
h264e_proc_hal(void * ctx,HalEncTask * task)765 static MPP_RET h264e_proc_hal(void *ctx, HalEncTask *task)
766 {
767     H264eCtx *p = (H264eCtx *)ctx;
768     MppEncH264Cfg *h264 = &p->cfg->codec.h264;
769 
770     h264e_dbg_func("enter\n");
771 
772     p->syn_num = 0;
773     h264e_add_syntax(p, H264E_SYN_CFG, p->cfg);
774     h264e_add_syntax(p, H264E_SYN_SPS, &p->sps);
775     h264e_add_syntax(p, H264E_SYN_PPS, &p->pps);
776     h264e_add_syntax(p, H264E_SYN_DPB, &p->dpb);
777     h264e_add_syntax(p, H264E_SYN_SLICE, &p->slice);
778     h264e_add_syntax(p, H264E_SYN_FRAME, &p->frms);
779 
780     /* check max temporal layer id */
781     {
782         MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(p->cfg->ref_cfg);
783         RK_S32 cpb_max_tid = cpb_info->max_st_tid;
784         RK_S32 cfg_max_tid = h264->max_tid;
785 
786         if (cpb_max_tid != cfg_max_tid) {
787             mpp_log("max tid is update to match cpb %d -> %d\n",
788                     cfg_max_tid, cpb_max_tid);
789             h264->max_tid = cpb_max_tid;
790         }
791     }
792 
793     /* NOTE: prefix nal is added after SEI packet and before hw_stream */
794     if (h264->prefix_mode || h264->max_tid) {
795         H264ePrefixNal *prefix = &p->prefix;
796         H264eSlice *slice = &p->slice;
797         EncFrmStatus *frm = &task->rc_task->frm;
798         MppPacket packet = task->packet;
799         MppMeta meta = mpp_packet_get_meta(packet);
800 
801         prefix->idr_flag = slice->idr_flag;
802         prefix->nal_ref_idc = slice->nal_reference_idc;
803         prefix->priority_id = h264->base_layer_pid + frm->temporal_id;
804         prefix->no_inter_layer_pred_flag = 1;
805         prefix->dependency_id = 0;
806         prefix->quality_id = 0;
807         prefix->temporal_id = frm->temporal_id;
808         prefix->use_ref_base_pic_flag = 0;
809         prefix->discardable_flag = 0;
810         prefix->output_flag = 1;
811 
812         h264e_add_syntax(p, H264E_SYN_PREFIX, &p->prefix);
813         mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, frm->temporal_id);
814         if (!frm->is_non_ref && frm->is_lt_ref)
815             mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, frm->lt_idx);
816     } else
817         h264e_add_syntax(p, H264E_SYN_PREFIX, NULL);
818 
819     task->valid = 1;
820     task->syntax.data   = &p->syntax[0];
821     task->syntax.number = p->syn_num;
822     h264->change = 0;
823 
824     h264e_dbg_func("leave\n");
825 
826     return MPP_OK;
827 }
828 
h264e_sw_enc(void * ctx,HalEncTask * task)829 static MPP_RET h264e_sw_enc(void *ctx, HalEncTask *task)
830 {
831     H264eCtx *p = (H264eCtx *)ctx;
832     MppEncH264Cfg *h264 = &p->cfg->codec.h264;
833     EncRcTaskInfo *rc_info = &task->rc_task->info;
834     MppPacket packet = task->packet;
835     void *pos = mpp_packet_get_pos(packet);
836     void *data = mpp_packet_get_data(packet);
837     size_t size = mpp_packet_get_size(packet);
838     size_t length = mpp_packet_get_length(packet);
839     void *base = pos + length;
840     RK_S32 buf_size = (data + size) - (pos + length);
841     RK_S32 slice_len = 0;
842     RK_S32 final_len = 0;
843 
844     if (h264->prefix_mode || h264->max_tid) {
845         /* add prefix first */
846         RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(&p->prefix, base, buf_size);
847 
848         prefix_bit = (prefix_bit + 7) / 8;
849 
850         base += prefix_bit;
851         buf_size -= prefix_bit;
852         final_len += prefix_bit;
853     }
854 
855     /* write slice header */
856     slice_len = h264e_slice_write_pskip(&p->slice, base, buf_size);
857     slice_len = (slice_len + 7) / 8;
858     final_len += slice_len;
859 
860     task->length += final_len;
861 
862     rc_info->bit_real = task->length;
863     rc_info->quality_real = rc_info->quality_target;
864 
865     return MPP_OK;
866 }
867 
h264e_add_sei(MppPacket pkt,RK_S32 * length,RK_U8 uuid[16],const void * data,RK_S32 size)868 MPP_RET h264e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16],
869                       const void *data, RK_S32 size)
870 {
871     if (uuid == uuid_refresh_cfg) {
872         return h264e_sei_recovery_point_to_packet(pkt, length, ((RK_U32 *)data)[0] - 1);
873     } else
874         return h264e_sei_to_packet(pkt, length, H264_SEI_USER_DATA_UNREGISTERED,
875                                    uuid, data, size);
876 }
877 
878 /*!
879 ***********************************************************************
880 * \brief
881 *   api struct interface
882 ***********************************************************************
883 */
884 const EncImplApi api_h264e = {
885     "h264e_control",
886     MPP_VIDEO_CodingAVC,
887     sizeof(H264eCtx),
888     0,
889     h264e_init,
890     h264e_deinit,
891     h264e_proc_cfg,
892     h264e_gen_hdr,
893     h264e_start,
894     h264e_proc_dpb,
895     h264e_proc_hal,
896     h264e_add_sei,
897     h264e_sw_enc,
898 };
899