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