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