From 44f3604fb12b3699538c58fc47201c0d18086b33 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Tue, 19 Nov 2019 11:05:35 +0800 Subject: [PATCH] [h264e_dpb]: Add H.264 encoder dpb/slice functions 1. Move hal h264e dpb/slice functions to codec. 2. The dpb functions support I frame gop interval, LTR interval, force LTR and generating reorder/marking syntax. Change-Id: I42654f33c9628bb3228afb6acf56c85c984a377e Signed-off-by: Herman Chen --- mpp/codec/enc/h264/CMakeLists.txt | 2 + mpp/codec/enc/h264/h264e_dpb.c | 1013 +++++++++++++++++ .../common => codec/enc}/h264/h264e_dpb.h | 197 ++-- mpp/codec/enc/h264/h264e_slice.c | 634 +++++++++++ mpp/codec/enc/h264/h264e_slice.h | 59 + mpp/hal/common/h264/CMakeLists.txt | 2 - mpp/hal/common/h264/h264e_dpb.c | 815 ------------- mpp/hal/common/h264/h264e_slice.c | 665 ----------- mpp/hal/common/h264/h264e_slice.h | 130 --- 9 files changed, 1796 insertions(+), 1721 deletions(-) create mode 100644 mpp/codec/enc/h264/h264e_dpb.c rename mpp/{hal/common => codec/enc}/h264/h264e_dpb.h (55%) create mode 100644 mpp/codec/enc/h264/h264e_slice.c create mode 100644 mpp/codec/enc/h264/h264e_slice.h delete mode 100644 mpp/hal/common/h264/h264e_dpb.c delete mode 100644 mpp/hal/common/h264/h264e_slice.c delete mode 100644 mpp/hal/common/h264/h264e_slice.h diff --git a/mpp/codec/enc/h264/CMakeLists.txt b/mpp/codec/enc/h264/CMakeLists.txt index a74f68a6..61894346 100644 --- a/mpp/codec/enc/h264/CMakeLists.txt +++ b/mpp/codec/enc/h264/CMakeLists.txt @@ -16,6 +16,8 @@ set(H264E_HDR set(H264E_SRC h264e_sps.c h264e_pps.c + h264e_dpb.c + h264e_slice.c h264e_api.c ) diff --git a/mpp/codec/enc/h264/h264e_dpb.c b/mpp/codec/enc/h264/h264e_dpb.c new file mode 100644 index 00000000..934e62b8 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_dpb.c @@ -0,0 +1,1013 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_dpb" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "h264e_debug.h" +#include "h264e_dpb.h" +#include "h264e_slice.h" + +void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller) +{ + RK_S32 i = 0; + + mpp_log_f("dump dpb frame info in %s\n", caller); + + mpp_log_f("dpb %p total count %d size %d\n", dpb, dpb->total_cnt, dpb->dpb_size); + mpp_log_f("dpb status - use seq gop idx type idr ref lt idx sta cnt\n"); + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *frm = &dpb->frames[i]; + + mpp_log_f("frm slot %2d %-3d %-3d %-3d %-3d %-4d %-3d %-3d %-2d %-3d %-3x %-3d\n", + i, + frm->on_used, + frm->seq_idx, + frm->gop_cnt, + frm->gop_idx, + frm->frame_type, + frm->status.is_idr, + !frm->status.is_non_ref, + frm->status.is_lt_ref, + frm->lt_idx, + frm->ref_status, + frm->ref_count); + } +} + +void h264e_dpb_dump_listX(H264eDpbFrm **list, RK_S32 count) +{ + RK_S32 i; + + for (i = 0; i < count; i++) { + H264eDpbFrm *frm = list[i]; + + mpp_log_f("list slot %d %-3d %-3d %-3d %-4d %-3d %-3d %-2d %-3d %-3x %-3d\n", + i, + frm->on_used, + frm->seq_idx, + frm->gop_idx, + frm->frame_type, + frm->status.is_idr, + !frm->status.is_non_ref, + frm->status.is_lt_ref, + frm->lt_idx, + frm->ref_status, + frm->ref_count); + } +} + +void h264e_dpb_dump_list(H264eDpb *dpb) +{ + mpp_log_f("dump dpb list info\n"); + + mpp_log_f("dpb size %d st size %d lt size %d\n", + dpb->dpb_size, dpb->st_size, dpb->lt_size); + + if (dpb->dpb_size) { + mpp_log_f("list status - use seq gop type idr ref lt idx sta cnt\n", dpb, dpb->total_cnt); + + h264e_dpb_dump_listX(dpb->list, dpb->dpb_size); + } +} + +static void h264e_dpb_mark_one_nonref(H264eDpb *dpb, H264eDpbFrm *ref) +{ + H264eDpbFrm *cur = dpb->curr; + RK_S32 cur_frm_num = cur->frame_num; + RK_S32 unref_frm_num = ref->frame_num; + H264eMmco op; + + h264e_dbg_dpb("cur %d T%d mark ref %d gop [%d:%d] to be unreference dpb size %d\n", + cur->seq_idx, cur->status.temporal_id, + ref->seq_idx, ref->gop_cnt, ref->gop_idx, dpb->dpb_size); + + memset(&op, 0, sizeof(op)); + + if (!ref->status.is_lt_ref) { + RK_S32 difference_of_pic_nums_minus1 = MPP_ABS(unref_frm_num - cur_frm_num) - 1; + + h264e_dbg_mmco("cur_frm_num %d unref_frm_num %d\n", cur_frm_num, unref_frm_num); + h264e_dbg_mmco("add mmco st 1 %d\n", difference_of_pic_nums_minus1); + + op.mmco = 1; + op.difference_of_pic_nums_minus1 = difference_of_pic_nums_minus1; + } else { + h264e_dbg_mmco("add mmco lt 2 %d\n", ref->lt_idx); + + op.mmco = 2; + op.long_term_frame_idx = ref->lt_idx; + } + + h264e_marking_wr_op(dpb->marking, &op); +} + +MPP_RET h264e_dpb_init(H264eDpb *dpb, H264eReorderInfo *reorder, H264eMarkingInfo *marking) +{ + RK_S32 i; + + h264e_dbg_dpb("enter %p\n", dpb); + + memset(dpb, 0, sizeof(*dpb)); + + dpb->reorder = reorder; + dpb->marking = marking; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frames); i++) + dpb->frames[i].slot_idx = i; + + h264e_dbg_dpb("leave %p\n", dpb); + + return MPP_OK; +} + +MPP_RET h264e_dpb_copy(H264eDpb *dst, H264eDpb *src) +{ + h264e_dbg_dpb("enter dst %p src %p\n", dst, src); + + memcpy(dst, src, sizeof(*dst)); + + h264e_dbg_dpb("leave\n"); + + return MPP_OK; +} + +MPP_RET h264e_dpb_set_cfg(H264eDpb *dpb, MppEncCfgSet* cfg, SynH264eSps *sps) +{ + MPP_RET ret = MPP_OK; + RK_S32 i; + + h264e_dbg_dpb("enter %p\n", dpb); + + /* 1. setup reference frame number */ + RK_S32 ref_frm_num = sps->num_ref_frames; + RK_S32 log2_max_frm_num = sps->log2_max_frame_num_minus4 + 4; + RK_S32 log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4; + + h264e_dbg_dpb("max ref frm num %d\n", ref_frm_num); + h264e_dbg_dpb("log2 max frm num %d\n", log2_max_frm_num); + h264e_dbg_dpb("log2 max poc lsb %d\n", log2_max_poc_lsb); + + if (ref_frm_num < 0 || ref_frm_num > H264E_MAX_REFS_CNT || + log2_max_frm_num < 0 || log2_max_frm_num > 16 || + log2_max_poc_lsb < 0 || log2_max_poc_lsb > 16) { + mpp_err_f("invalid config value %d %d %d\n", ref_frm_num, + log2_max_frm_num, log2_max_poc_lsb); + + ref_frm_num = 1; + log2_max_frm_num = 16; + log2_max_poc_lsb = 16; + + mpp_err_f("set to default value %d %d %d\n", ref_frm_num, + log2_max_frm_num, log2_max_poc_lsb); + } + + mpp_assert(ref_frm_num <= H264E_MAX_REFS_CNT); + + dpb->max_frm_num = (1 << log2_max_frm_num) - 1; + dpb->max_poc_lsb = (1 << log2_max_poc_lsb) - 1; + dpb->total_cnt = ref_frm_num + 1; + + /* 2. setup IDR gop (igop) */ + dpb->idr_gop_cnt = 0; + dpb->idr_gop_idx = 0; + dpb->idr_gop_len = cfg->rc.gop; + + /* 3. setup gop ref hierarchy (vgop) */ + MppEncGopRef *ref = &cfg->gop_ref; + + dpb->mode = 0; + if (!ref->gop_cfg_enable) { + /* set default dpb info */ + EncFrmStatus *info = &dpb->ref_inf[0]; + + info[0].is_intra = 1; + info[0].is_idr = 1; + info[0].is_non_ref = 0; + info[0].is_lt_ref = 0; + info[0].lt_idx = -1; + info[0].temporal_id = 0; + info[0].ref_dist = -1; + + info[1].is_intra = 0; + info[1].is_idr = 0; + info[1].is_non_ref = 0; + info[1].is_lt_ref = 0; + info[1].lt_idx = -1; + info[1].temporal_id = 0; + info[1].ref_dist = -1; + + dpb->ref_cnt[0] = 2; + dpb->ref_cnt[1] = 2; + + dpb->ref_dist[0] = -1; + dpb->ref_dist[1] = -1; + + dpb->st_gop_len = 1; + dpb->lt_gop_len = 0; + + goto GOP_CFG_DONE; + } + + memset(dpb->ref_inf, 0, sizeof(dpb->ref_inf)); + memset(dpb->ref_sta, 0, sizeof(dpb->ref_sta)); + memset(dpb->ref_cnt, 0, sizeof(dpb->ref_cnt)); + memset(dpb->ref_dist, 0, sizeof(dpb->ref_dist)); + + RK_S32 st_gop_len = ref->ref_gop_len; + RK_S32 lt_gop_len = ref->lt_ref_interval; + RK_S32 max_layer_id = 0; + + dpb->st_gop_len = st_gop_len; + dpb->lt_gop_len = lt_gop_len; + if (ref->max_lt_ref_cnt) + dpb->max_lt_idx = ref->max_lt_ref_cnt - 1; + else + dpb->max_lt_idx = 0; + + h264e_dbg_dpb("st_gop_len %d lt_gop_len %d max_lt_idx_plus_1 %d\n", + dpb->st_gop_len, dpb->lt_gop_len, + dpb->max_lt_idx); + + if (st_gop_len) + dpb->mode |= H264E_ST_GOP_FLAG; + + if (lt_gop_len) { + dpb->mode |= H264E_LT_GOP_FLAG; + mpp_assert(ref->max_lt_ref_cnt > 0); + } + + RK_S32 max_lt_ref_idx = -1; + + for (i = 0; i < st_gop_len + 1; i++) { + MppGopRefInfo *info = &ref->gop_info[i]; + RK_S32 is_non_ref = info->is_non_ref; + RK_S32 is_lt_ref = info->is_lt_ref; + RK_S32 temporal_id = info->temporal_id; + RK_S32 lt_idx = info->lt_idx; + RK_S32 ref_idx = info->ref_idx; + + dpb->ref_inf[i].is_intra = (i == 0) ? (1) : (0); + dpb->ref_inf[i].is_idr = dpb->ref_inf[i].is_intra; + dpb->ref_inf[i].is_non_ref = is_non_ref; + dpb->ref_inf[i].is_lt_ref = is_lt_ref; + dpb->ref_inf[i].lt_idx = lt_idx; + dpb->ref_inf[i].temporal_id = temporal_id; + dpb->ref_inf[i].ref_dist = ref_idx - i; + dpb->ref_dist[i] = ref_idx - i; + + if (!is_non_ref) { + dpb->ref_sta[i] |= REF_BY_RECN(i); + dpb->ref_cnt[i]++; + } + + if (max_layer_id < temporal_id) + max_layer_id = temporal_id; + + if (is_lt_ref) { + if (lt_idx > max_lt_ref_idx) { + max_lt_ref_idx = lt_idx; + h264e_dbg_dpb("curr %d update lt_idx to %d\n", + i, max_lt_ref_idx); + + if (max_lt_ref_idx > dpb->max_lt_idx) { + mpp_err("mismatch max_lt_ref_idx_p1 %d vs %d\n", + max_lt_ref_idx, dpb->max_lt_idx); + } + } + + dpb->mode |= H264E_ST_GOP_WITH_LT_REF; + + if (lt_gop_len) + mpp_err_f("Can NOT use both lt_ref_interval and gop_info lt_ref at the same time!\n "); + } + + // update the reference frame status and counter only once + if (ref_idx == i) + continue; + + mpp_assert(!dpb->ref_inf[ref_idx].is_non_ref); + dpb->ref_sta[ref_idx] |= REF_BY_REFR(i); + dpb->ref_cnt[ref_idx]++; + + h264e_dbg_dpb("refr %d ref_status 0x%03x count %d\n", + ref_idx, dpb->ref_sta[ref_idx], dpb->ref_cnt[ref_idx]); + } + +GOP_CFG_DONE: + h264e_dbg_dpb("leave %p\n", dpb); + + return ret; +} + +MPP_RET h264e_dpb_set_curr(H264eDpb *dpb, H264eDpbFrmCfg *cfg) +{ + RK_S32 i; + // current st gop info for update + // st_gop_idx_wrap is for reference relationship index + RK_S32 seq_idx = dpb->seq_idx++; + RK_S32 idr_gop_cnt = dpb->idr_gop_cnt; + RK_S32 idr_gop_idx = dpb->idr_gop_idx; + RK_S32 st_gop_cnt = dpb->st_gop_cnt; + RK_S32 st_gop_idx = dpb->st_gop_idx; + RK_S32 st_gop_idx_wrap; + RK_S32 lt_gop_cnt = dpb->lt_gop_cnt; + RK_S32 lt_gop_idx = dpb->lt_gop_idx; + RK_S32 ref_dist; + RK_S32 lt_req; + RK_S32 poc_lsb; + RK_S32 idr_req; + H264eDpbFrm *frm = NULL; + H264eDpbFrm *ref = NULL; + + h264e_dbg_dpb("enter %p\n", dpb); + /* + * Step 1: Generate flag + * + * St gop structure should be reset by idr qop or lt gop. + * It means when user request IDR frame or T0 long-term reference frame + * the st gop struture should be reset to index 0. + */ + if (cfg->force_idr) { + idr_req = 1; + } else { + if (dpb->idr_gop_len == 0) { + idr_req = (seq_idx) ? (0) : (1); + } else if (dpb->idr_gop_len == 1) { + idr_req = 1; + } else { + idr_req = (idr_gop_idx) ? (0) : (1); + } + } + + if ((cfg->force_lt_idx >= 0) || + (dpb->lt_gop_len && !dpb->lt_gop_idx)) + lt_req = 1; + else + lt_req = 0; + + h264e_dbg_dpb("prev %5d - gop i [%d:%d] l [%d:%d] s [%d:%d] -> idr %d lt %d\n", + seq_idx, idr_gop_cnt, idr_gop_idx, lt_gop_cnt, lt_gop_idx, + st_gop_cnt, st_gop_idx, idr_req, lt_req); + + /* + * step 2: Update short-term gop counter and idr gop counter + */ + if (idr_req) { + // update current and next st gop status + // NOTE: st_gop_idx here is for next st_gop_idx and idr_req will reset st_gop_cnt + dpb->st_gop_idx = 1; + dpb->st_gop_cnt = 0; + + st_gop_cnt = 0; + st_gop_idx = 0; + + // update idr gop status + if (seq_idx) + dpb->idr_gop_cnt++; + + idr_gop_idx = 0; + dpb->idr_gop_idx = 1; + + dpb->poc_lsb = 2; + poc_lsb = 0; + } else { + if (lt_req) { + // NOTE: lt_req will not reset st_gop_cnt + dpb->st_gop_idx = 1; + dpb->st_gop_cnt++; + + st_gop_idx = 0; + st_gop_cnt = dpb->st_gop_cnt; + } else { + st_gop_cnt = dpb->st_gop_cnt; + st_gop_idx = dpb->st_gop_idx; + + dpb->st_gop_idx++; + + if (dpb->st_gop_idx >= dpb->st_gop_len) { + dpb->st_gop_idx = 0; + dpb->st_gop_cnt++; + } + } + + dpb->idr_gop_idx++; + if (dpb->idr_gop_idx >= dpb->idr_gop_len) + dpb->idr_gop_idx = 0; + + poc_lsb = dpb->poc_lsb; + dpb->poc_lsb += 2; + if (dpb->poc_lsb >= dpb->max_poc_lsb) + dpb->poc_lsb = 0; + } + + /* + * step 3: Update long-term gop counter and idr gop counter + */ + if (lt_req) { + lt_gop_idx = 0; + dpb->lt_gop_idx = 1; + dpb->lt_gop_cnt++; + } else { + if (dpb->lt_gop_len) { + dpb->lt_gop_idx++; + if (dpb->lt_gop_idx >= dpb->lt_gop_len) { + dpb->lt_gop_idx = 0; + dpb->lt_gop_cnt++; + } + + lt_gop_idx = dpb->lt_gop_idx; + } + } + + /* + * step 4: Get wrapped short-term index for getting frame info in gop + */ + if (!st_gop_idx && st_gop_cnt && !lt_req) + st_gop_idx_wrap = dpb->st_gop_len; + else + st_gop_idx_wrap = st_gop_idx; + + h264e_dbg_dpb("curr %5d - gop i [%d:%d] l [%d:%d] s [%d:%d] -> warp %d poc %d\n", + seq_idx, idr_gop_cnt, idr_gop_idx, lt_gop_cnt, lt_gop_idx, + st_gop_cnt, st_gop_idx, st_gop_idx_wrap, poc_lsb); + + h264e_dbg_dpb("next %5d - gop i [%d:%d] l [%d:%d] s [%d:%d]\n", + dpb->seq_idx, dpb->idr_gop_cnt, dpb->idr_gop_idx, + dpb->lt_gop_cnt, dpb->lt_gop_idx, dpb->st_gop_cnt, + dpb->st_gop_idx); + + /* + * step 5: Get ref_dist from short-term gop info and find reference frame + */ + ref_dist = dpb->ref_dist[st_gop_idx_wrap]; + + if (cfg->force_ref_lt_idx < 0) { + if (!idr_req) { + // normal lt ref loop case + RK_S32 ref_seq_idx = seq_idx + ref_dist; + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (!tmp->on_used) + continue; + + if (tmp->status.is_non_ref) + continue; + + if (tmp->seq_idx == ref_seq_idx) { + ref = tmp; + h264e_dbg_dpb("frm: %5d found dist %d refer frm %d of %p\n", + seq_idx, ref_dist, ref_seq_idx, ref); + break; + } + } + + if (NULL == ref) { + mpp_err_f("failed to find refernce frame %d for current frame %d dist %d\n", + ref_seq_idx, seq_idx, ref_dist); + h264e_dpb_dump_frms(dpb); + } + } + } else { + // force long-term reference frame as reference frame case + /* step 5.1: find the long-term reference frame */ + // init list + // 5.1 found all short term and long term ref + RK_S32 lt_ref_idx = cfg->force_ref_lt_idx; + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (!tmp->on_used) + continue; + + if (tmp->status.is_non_ref) + continue; + + if (tmp->status.is_lt_ref && lt_ref_idx == tmp->status.lt_idx) { + h264e_dbg_dpb("found lt_ref_idx %d frm_cnt %d\n", + lt_ref_idx, tmp->seq_idx); + ref = tmp; + break; + } + } + + if (ref == NULL) + mpp_log_f("failed to find reference frame lt_idx %d\n", lt_ref_idx); + + /* step 5.2: mark all short-term reference frame as non-referenced */ + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (!tmp->on_used) + continue; + + if (tmp->status.is_non_ref) + continue; + + // remove short-term reference frame in last lt_gop + if (!tmp->status.is_lt_ref) { + tmp->ref_status = 0; + tmp->ref_count = 0; + } + } + + /* step 5.3: set current frame as short-term gop start */ + dpb->st_gop_idx = 1; + dpb->st_gop_cnt++; + + st_gop_idx = 0; + st_gop_cnt = dpb->st_gop_cnt; + } + + dpb->refr = ref; + + /* + * step 6: Clear dpb slot for next frame + * + * When IDR frame clear all dpb slots. + * When force idr clear previous short-term reference frame + */ + if (idr_req) { + // init to 0 + dpb->last_frm_num = 0; + + // mmco 5 mark all reference frame to be non-referenced + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + tmp->on_used = 0; + tmp->status.is_intra = 0; + tmp->status.is_idr = 0; + tmp->status.is_non_ref = 1; + tmp->status.is_lt_ref = 0; + tmp->status.lt_idx = 0; + tmp->status.temporal_id = 0; + tmp->status.ref_dist = 0; + + tmp->ref_status = 0; + tmp->ref_count = 0; + } + + dpb->dpb_size = 0; + dpb->lt_size = 0; + dpb->st_size = 0; + } + + /* + * step 7: Find a slot for current frame + */ + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (!tmp->on_used) { + frm = tmp; + dpb->curr = tmp; + + // found empty slot and clear status + frm->on_used = 1; + frm->ref_status = 0; + frm->ref_count = 0; + memset(&frm->status, 0, sizeof(frm->status)); + break; + } + } + + /* + * step 8: Update known info to current frame + */ + frm->seq_idx = seq_idx; + frm->gop_cnt = st_gop_cnt; + frm->gop_idx = st_gop_idx; + // NOTE: info update 1 - update from default ref info + frm->status = dpb->ref_inf[st_gop_idx_wrap]; + frm->ref_status = dpb->ref_sta[st_gop_idx]; + frm->ref_count = dpb->ref_cnt[st_gop_idx]; + frm->ref_dist = dpb->ref_dist[st_gop_idx_wrap]; + frm->poc = poc_lsb; + + // NOTE: current frame info should be updated by previous flag + if (idr_req) { + // NOTE: info update 2 - update by idr frame + frm->status.is_idr = 1; + frm->status.is_intra = 1; + frm->status.is_non_ref = 0; + } + + if (lt_req) { + // NOTE: info update 3 - update by current frame LT request + frm->status.is_non_ref = 0; + frm->status.is_lt_ref = 1; + + if (cfg->force_ref_lt_idx >= 0) { + // force LTR + frm->status.lt_idx = cfg->force_ref_lt_idx; + frm->status.temporal_id = 0; + } else if (dpb->lt_gop_len && !dpb->lt_gop_idx) { + // auto LTR loop + frm->status.lt_idx = dpb->lt_ref_idx; + frm->status.temporal_id = 0; + + dpb->lt_ref_idx++; + if (dpb->lt_ref_idx > dpb->max_lt_idx) + dpb->lt_ref_idx = 0; + } + } + + // update ref_dist for reorder + if (cfg->force_ref_lt_idx >= 0) { + // NOTE: info update 4 - update by force refer to LTR + frm->ref_dist = ref->seq_idx - seq_idx; + } + + // update ref_dist in current frame info + frm->status.ref_dist = frm->ref_dist; + // NOTE: info update all done here + + frm->lt_idx = (frm->status.is_lt_ref) ? (frm->status.lt_idx) : (-1); + frm->frame_num = dpb->last_frm_num; + frm->frame_type = (idr_req) ? (H264_I_SLICE) : (H264_P_SLICE); + + if (!frm->status.is_non_ref) + dpb->last_frm_num++; + + h264e_dbg_dpb("frm: %5d gop [%d:%d] frm_num [%d:%d] poc %d R%dL%d ref %d\n", + frm->seq_idx, frm->gop_cnt, frm->gop_idx, + frm->frame_num, dpb->last_frm_num, frm->poc, + !frm->status.is_non_ref, frm->status.is_lt_ref, frm->ref_dist); + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + h264e_dbg_dpb("leave %p\n", dpb); + + return MPP_OK; +} + +static int cmp_st_list(const void *p0, const void *p1) +{ + H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; + H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; + + if (frm0->frame_num == frm1->frame_num) + return 0; + if (frm0->frame_num < frm1->frame_num) + return 1; + else + return -1; +} + +static int cmp_lt_list(const void *p0, const void *p1) +{ + H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; + H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; + + if (frm0->lt_idx == frm1->lt_idx) + return 0; + if (frm0->lt_idx > frm1->lt_idx) + return 1; + else + return -1; +} + +/* + * Build list function + * + * This function should build the default list for current frame. + * Then check the reference frame is the default one or not. + * Reorder command is need if the reference frame is not match. + */ +void h264e_dpb_build_list(H264eDpb *dpb) +{ + RK_S32 i, j; + RK_S32 st_size = 0; + RK_S32 lt_size = 0; + + if (dpb->curr->status.is_intra) + return ; + + h264e_dbg_dpb("enter %p\n", dpb); + + // init list + // 1. found all short term and long term ref + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *frm = &dpb->frames[i]; + + if (!frm->on_used) + continue; + + if (frm == dpb->curr) + continue; + + if (frm->status.is_non_ref) + continue; + + h264e_dbg_list("idx %d on_used %x ref_status %03x is_non_ref %d lt_ref %d\n", + i, frm->on_used, frm->ref_status, + frm->status.is_non_ref, frm->status.is_lt_ref); + + if (!frm->status.is_non_ref) { + if (!frm->status.is_lt_ref) { + dpb->stref[st_size] = frm; + st_size++; + h264e_dbg_list("found st %d st_size %d %p\n", i, st_size, frm); + } else { + dpb->ltref[lt_size] = frm; + lt_size++; + h264e_dbg_list("found lt %d lt_size %d %p\n", i, lt_size, frm); + } + } + } + + h264e_dbg_dpb("dpb_size %d st_size %d lt_size %d\n", dpb->dpb_size, st_size, lt_size); + + // sort st list + if (st_size > 1) { + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb st list before sort\n"); + h264e_dpb_dump_listX(dpb->stref, st_size); + } + + qsort(dpb->stref, st_size, sizeof(dpb->stref[0]), cmp_st_list); + + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb st list after sort\n"); + h264e_dpb_dump_listX(dpb->stref, st_size); + } + } + + if (lt_size > 1) { + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb lt list before sort\n"); + h264e_dpb_dump_listX(dpb->ltref, lt_size); + } + + qsort(dpb->ltref, lt_size, sizeof(dpb->ltref[0]), cmp_lt_list); + + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb lt list after sort\n"); + h264e_dpb_dump_listX(dpb->ltref, lt_size); + } + } + + // generate list before reorder + memset(dpb->list, 0, sizeof(dpb->list)); + j = 0; + for (i = 0; i < st_size; i++) + dpb->list[j++] = dpb->stref[i]; + + for (i = 0; i < lt_size; i++) + dpb->list[j++] = dpb->ltref[i]; + + dpb->st_size = st_size; + dpb->lt_size = lt_size; + + mpp_assert(dpb->dpb_size == st_size + lt_size); + + if (h264e_debug & H264E_DBG_LIST) + h264e_dpb_dump_list(dpb); + + if (dpb->st_size + dpb->lt_size) { + H264eDpbFrm *curr = dpb->curr; + H264eDpbFrm *refr = dpb->refr; + H264eDpbFrm *def_ref = dpb->list[0]; + + RK_S32 curr_frm_cnt = curr->seq_idx; + RK_S32 def_ref_frm_cnt = def_ref->seq_idx; + RK_S32 set_ref_frm_cnt = curr->seq_idx + curr->ref_dist; + + h264e_dbg_list("refer curr %d def %d set %d reorder %d\n", + curr_frm_cnt, def_ref_frm_cnt, set_ref_frm_cnt, + (def_ref_frm_cnt != set_ref_frm_cnt)); + + if (def_ref_frm_cnt != set_ref_frm_cnt) { + H264eRplmo op; + + h264e_dbg_list("reorder to frm %d gop %d idx %d\n", + refr->seq_idx, refr->gop_cnt, refr->gop_idx); + + mpp_assert(!refr->status.is_non_ref); + + op.modification_of_pic_nums_idc = (refr->status.is_lt_ref) ? (2) : (0); + if (refr->status.is_lt_ref) { + op.modification_of_pic_nums_idc = 2; + op.long_term_pic_idx = refr->lt_idx; + + h264e_dbg_list("reorder lt idx %d \n", op.long_term_pic_idx); + } else { + /* Only support refr pic num less than current pic num case */ + op.modification_of_pic_nums_idc = 0; + op.abs_diff_pic_num_minus1 = MPP_ABS(curr->frame_num - refr->frame_num) - 1; + + h264e_dbg_list("reorder st cur %d refr %d diff - 1 %d\n", + curr->frame_num, refr->frame_num, + op.abs_diff_pic_num_minus1); + } + + h264e_reorder_wr_op(dpb->reorder, &op); + } + } else { + h264e_dbg_list("refer NULL\n"); + } + + h264e_dbg_dpb("leave %p\n", dpb); +} + +void h264e_dpb_build_marking(H264eDpb *dpb) +{ + RK_S32 i; + H264eDpbFrm *frm = dpb->curr; + H264eDpbFrm *ref = dpb->refr; + H264eMarkingInfo *marking = dpb->marking; + + h264e_dbg_dpb("enter %p\n", dpb); + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + // refernce frame can not mark itself as unreferenced. + // So do NOT clear RECN flag here + // clear the ref status and count once + if (ref && frm != ref) { + ref->ref_status &= ~(REF_BY_REFR(frm->gop_idx)); + + if (ref->ref_count > 0) + ref->ref_count--; + + h264e_dbg_dpb("refr %d ref_status %03x count %d\n", + ref->gop_idx, ref->ref_status, ref->ref_count); + } + + if (!frm->status.is_non_ref && frm->status.is_lt_ref) { + h264e_dbg_dpb("found lt idx %d curr max %d\n", frm->lt_idx, dpb->curr_max_lt_idx); + if (frm->lt_idx > dpb->curr_max_lt_idx) { + dpb->next_max_lt_idx = frm->lt_idx; + } + } + + if (frm->status.is_idr) { + marking->idr_flag = 1; + marking->no_output_of_prior_pics = 1; + marking->long_term_reference_flag = frm->status.is_lt_ref; + goto DONE; + } + + marking->idr_flag = 0; + marking->adaptive_ref_pic_buffering = 0; + + h264e_dbg_dpb("curr -- frm %d gop s [%d:%d] ref %d lt %d T%d\n", + frm->seq_idx, frm->gop_cnt, frm->gop_idx, + !frm->status.is_non_ref, frm->status.is_lt_ref, + frm->status.temporal_id); + + if (frm->status.is_non_ref) + goto DONE; + + // When current frame is lt_ref update max_lt_idx + if (frm->status.is_lt_ref) { + H264eMmco op; + + if (dpb->next_max_lt_idx != dpb->curr_max_lt_idx) { + RK_S32 max_lt_idx_p1 = dpb->next_max_lt_idx + 1; + + op.mmco = 4; + op.max_long_term_frame_idx_plus1 = max_lt_idx_p1; + + h264e_marking_wr_op(marking, &op); + h264e_dbg_mmco("add mmco 4 %d\n", max_lt_idx_p1); + + dpb->curr_max_lt_idx = dpb->next_max_lt_idx; + } + + op.mmco = 6; + op.long_term_frame_idx = frm->lt_idx; + + h264e_marking_wr_op(marking, &op); + h264e_dbg_mmco("add mmco 6 %d\n", frm->lt_idx); + } + + // if we are reference frame scan the previous frame to mark + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (!tmp->on_used) + continue; + + if (tmp->status.is_non_ref) + continue; + + /* + * NOTE: In ffmpeg we can not mark reference frame to be + * non-reference frame. But in JM it is valid for mmco execution + * is after frame decoding. So for compatibility consideration + * we do NOT remove current reference frame from dpb. + * That is the reason for frm->gop_index != ref_index + * + * There is a case for the first frame of a new gop which is not + * first frame of the whole sequeuce. On this case we need to + * remove frame in previous gop + * + * Tsvc temporal hierarchy dependency require the reference + * must be marked non-reference frame by the frame with same + * temporal layer id. + */ + if ((tmp == ref) || (tmp == frm)) + continue; + + h264e_dbg_dpb("slot %2d frm %3d gop %3d idx %2d T%d lt %d cnt %d\n", + i, tmp->seq_idx, tmp->gop_cnt, tmp->gop_idx, + tmp->status.temporal_id, tmp->status.is_lt_ref, tmp->ref_count); + + if (tmp->status.is_lt_ref) { + if (frm->status.is_lt_ref && frm->lt_idx == tmp->lt_idx) { + h264e_dbg_dpb("frm %3d lt idx %d replace frm %d dpb size %d\n", + frm->seq_idx, tmp->lt_idx, tmp->seq_idx, + dpb->dpb_size); + } + + continue; + } + + if (!tmp->ref_count && tmp->status.temporal_id == frm->status.temporal_id) { + h264e_dpb_mark_one_nonref(dpb, tmp); + + /* update frame status here */ + tmp->status.is_non_ref = 1; + tmp->on_used = 0; + + h264e_dbg_mmco("set frm %d gop %d idx %d to not used\n", + tmp->seq_idx, tmp->gop_cnt, tmp->gop_idx); + + // decrease dpb size here for sometime frame will be remove later + dpb->dpb_size--; + } + } + +DONE: + h264e_dbg_dpb("dpb size %d\n", dpb->dpb_size); + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + h264e_dbg_dpb("leave %p\n", dpb); +} + +void h264e_dpb_curr_ready(H264eDpb *dpb) +{ + H264eDpbFrm *frm = dpb->curr; + H264eDpbFrm *ref = dpb->refr; + + h264e_dbg_dpb("enter %p\n", dpb); + + if (ref) + h264e_dbg_dpb("curr %d gop %d idx %d refr -> frm %d gop %d idx %d ready\n", + frm->seq_idx, frm->gop_cnt, frm->gop_idx, + ref->seq_idx, ref->gop_cnt, ref->gop_idx, + frm->status.is_non_ref); + else + h264e_dbg_dpb("curr %d gop %d idx %d refr -> non ready\n", + frm->seq_idx, frm->gop_cnt, frm->gop_idx); + + if (!frm->status.is_non_ref) { + frm->ref_status &= ~(REF_BY_RECN(frm->gop_idx)); + frm->ref_count--; + dpb->dpb_size++; + + // FIXME: sliding window marking should be done here + } else + frm->on_used = 0; + + // on swap mode just mark reference frame as not used + if (dpb->mode == 0 && ref) { + ref->on_used = 0; + dpb->dpb_size--; + } + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + dpb->curr = NULL; + dpb->refr = NULL; + + h264e_dbg_dpb("leave %p\n", dpb); +} + diff --git a/mpp/hal/common/h264/h264e_dpb.h b/mpp/codec/enc/h264/h264e_dpb.h similarity index 55% rename from mpp/hal/common/h264/h264e_dpb.h rename to mpp/codec/enc/h264/h264e_dpb.h index f0c31995..b51db8dc 100644 --- a/mpp/hal/common/h264/h264e_dpb.h +++ b/mpp/codec/enc/h264/h264e_dpb.h @@ -17,10 +17,7 @@ #ifndef __H264E_DPB_H__ #define __H264E_DPB_H__ -#include "mpp_buffer.h" - -#include "mpp_enc_refs.h" -#include "h264e_slice.h" +#include "h264e_sps.h" /* * H.264 encoder dpb structure info @@ -38,58 +35,43 @@ * */ -#define H264E_REF_MAX 16 -#define H264E_MAX_BUF_CNT 2 +#define MAX_GOP_SIZE 8 +#define MAX_GOP_FMT_CNT (MAX_GOP_SIZE+1) +#define MAX_GOP_FMT_SIZE 5 +#define MAX_GOP_FMT_BUF_STUFF 16 +#define MAX_GOP_FMT_BUF_SIZE (MAX_GOP_FMT_CNT * MAX_GOP_FMT_SIZE + MAX_GOP_FMT_BUF_STUFF) + +#define H264E_ST_GOP_FLAG (0x00000001) +#define H264E_ST_GOP_WITH_LT_REF (0x00000002) +#define H264E_LT_GOP_FLAG (0x00000010) #define REF_BY_RECN(idx) (0x00000001 << idx) #define REF_BY_REFR(idx) (0x00000001 << idx) -typedef struct H264eDpb_t H264eDpb; -typedef struct H264eDpbFrm_t H264eDpbFrm; -typedef struct H264eFrmBuf_t H264eFrmBuf; -typedef struct H264eFrmBufGrp_t H264eFrmBufGrp; +typedef struct H264eDpbFrmCfg_t { + /* request current frame to be IDR frame */ + RK_S32 force_idr; -/* - * Split reference frame configure to two parts - * The first part is slice depended info like poc / frame_num, and frame - * type and flags. - * The other part is gop structure depended info like gop index, ref_status - * and ref_frm_index. This part is inited from dpb gop hierarchy info. - */ -typedef struct H264eDpbFrmInfo_t { - /* - * 0 - inter frame - * 1 - intra frame - */ - RK_U32 is_intra : 1; + /* request current frame to be a software all PSkip frame */ + RK_S32 force_pskip; /* - * Valid when is_intra is true - * 0 - normal intra frame - * 1 - IDR frame + * request current frame to be mark as a long-reference frame + * -1 - not forced to be marked as long-term reference frame */ - RK_U32 is_idr : 1; + RK_S32 force_lt_idx; /* - * 0 - mark as reference frame - * 1 - mark as non-refernce frame + * request current frame use long-term reference frame as its reference frame + * -1 - not forced to use long-term reference frame as reference frame */ - RK_U32 is_non_ref : 1; - - /* - * Valid when is_non_ref is false - * 0 - mark as short-term reference frame - * 1 - mark as long-term refernce frame - */ - RK_U32 is_lt_ref : 1; - RK_U32 stuff : 28; - -} H264eDpbFrmInfo; + RK_S32 force_ref_lt_idx; +} H264eDpbFrmCfg; typedef struct H264eDpbFrm_t { - H264eDpb *dpb; + RK_S32 slot_idx; // frame index in frames - RK_S32 frm_cnt; + RK_S32 seq_idx; // gop index in one gop structure RK_S32 gop_idx; RK_S32 gop_cnt; @@ -121,17 +103,10 @@ typedef struct H264eDpbFrm_t { RK_S32 ref_dist; /* frame status */ - MppEncFrmStatus info; - /* flag for marking process */ - RK_S32 marked_unref; + EncFrmStatus status; - /* - * ENC_FRAME_TYPE in mpp_rc.h - * 0 - INTER_P_FRAME - * 1 - INTER_B_FRAME - * 2 - INTRA_FRAME - */ - RK_S32 frame_type; + /* H264_I_SLICE / H264_P_SLICE */ + H264SliceType frame_type; /* frame number from H264eSlice */ RK_S32 frame_num; RK_S32 lt_idx; @@ -139,33 +114,8 @@ typedef struct H264eDpbFrm_t { RK_S32 poc; /* pts from input MppFrame */ RK_S64 pts; - - H264eFrmBuf *buf; } H264eDpbFrm; -typedef struct H264eFrmBuf_t { - RK_U32 is_used; - // buf0 for normal pixel buffer - // buf1 for scaled buffer - MppBuffer buf[H264E_MAX_BUF_CNT]; -} H264eFrmBuf; - -typedef struct H264eFrmBufGrp_t { - MppBufferGroup group; - // buffer count for each frame buffers - RK_U32 count; - // buffer size for each buffer in frame buffers - RK_U32 size[H264E_MAX_BUF_CNT]; - // frame buffer set - H264eFrmBuf bufs[H264E_REF_MAX]; -} H264eFrmBufGrp; - -typedef struct H264eDpbCfg_t { - RK_S32 ref_frm_num; - RK_S32 log2_max_frm_num; - RK_S32 log2_max_poc_lsb; -} H264eDpbCfg; - /* * dpb frame arrangement * @@ -177,7 +127,8 @@ typedef struct H264eDpbCfg_t { * next frame encoding. */ typedef struct H264eDpb_t { - H264eDpbCfg cfg; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; /* * ref_frm_num - max reference frame number @@ -190,38 +141,51 @@ typedef struct H264eDpb_t { RK_S32 max_frm_num; RK_S32 max_poc_lsb; - // status and count for one gop structure - RK_S32 seq_cnt; - RK_S32 seq_idx; - RK_S32 gop_len; - RK_S32 gop_cnt; - RK_S32 gop_idx; + /* + * dpb mode + * 0 - Default two frame swap mode. Only use refr and recn frame + * 1 - Dpb with user hierarchy mode + */ + RK_S32 mode; - RK_S32 curr_frm_num; - RK_S32 next_frm_num; + // overall frame counter + RK_S32 seq_idx; + + // status and count for one gop structure + // idr_gop - for intra / IDR frame group of picture + // st_gop - for short-term reference group of picture in TSVC mode + // lt_gop - for long-term reference group of picture in SVC mode + RK_S32 idr_gop_len; + RK_S32 idr_gop_cnt; + RK_S32 idr_gop_idx; + + RK_S32 st_gop_len; + RK_S32 st_gop_cnt; + RK_S32 st_gop_idx; + + RK_S32 lt_gop_len; + RK_S32 lt_gop_cnt; + RK_S32 lt_gop_idx; + + RK_S32 poc_lsb; + RK_S32 last_frm_num; + RK_S32 lt_ref_idx; // slot counter RK_S32 total_cnt; - RK_S32 max_st_cnt; - RK_S32 max_lt_cnt; - RK_S32 curr_idx; // for reference frame list generation RK_S32 dpb_size; RK_S32 st_size; RK_S32 lt_size; H264eDpbFrm *curr; - H264eDpbFrm *list[H264E_REF_MAX]; - H264eDpbFrm *stref[H264E_REF_MAX]; - H264eDpbFrm *ltref[H264E_REF_MAX]; - RK_S32 need_reorder; + H264eDpbFrm *refr; + H264eDpbFrm *list[H264E_MAX_REFS_CNT]; + H264eDpbFrm *stref[H264E_MAX_REFS_CNT]; + H264eDpbFrm *ltref[H264E_MAX_REFS_CNT]; RK_S32 curr_max_lt_idx; RK_S32 next_max_lt_idx; - // for mmco unreferece marking process - RK_U32 unref_cnt; - H264eDpbFrm *unref[H264E_REF_MAX]; - /* * ref_inf bit info: * bit 0 - intra flag @@ -229,36 +193,51 @@ typedef struct H264eDpb_t { * bit 2 - non-ref flag * bit 3 - long-term flag */ - MppEncFrmStatus ref_inf[MAX_GOP_FMT_CNT]; + EncFrmStatus ref_inf[MAX_GOP_FMT_CNT]; RK_U32 ref_sta[MAX_GOP_FMT_CNT]; RK_U32 ref_cnt[MAX_GOP_FMT_CNT]; RK_S32 ref_dist[MAX_GOP_FMT_CNT]; - // buffer management - H264eFrmBufGrp buf_grp; - // frame storage - H264eDpbFrm *frames; + H264eDpbFrm frames[H264E_MAX_REFS_CNT + 1]; } H264eDpb; #ifdef __cplusplus extern "C" { #endif -MPP_RET h264e_dpb_init(H264eDpb **dpb, H264eDpbCfg *cfg); +MPP_RET h264e_dpb_init(H264eDpb *dpb, H264eReorderInfo *reorder, H264eMarkingInfo *marking); MPP_RET h264e_dpb_deinit(H264eDpb *dpb); -MPP_RET h264e_dpb_setup_buf_size(H264eDpb *dpb, RK_U32 size[], RK_U32 count); -MPP_RET h264e_dpb_setup_hier(H264eDpb *dpb, MppEncHierCfg *cfg); +/* copy function is for dpb backup and restore */ +MPP_RET h264e_dpb_copy(H264eDpb *dst, H264eDpb *src); -H264eDpbFrm *h264e_dpb_get_curr(H264eDpb *dpb, RK_S32 new_seq); -H264eDpbFrm *h264e_dpb_get_refr(H264eDpbFrm *frm); +/* + * Setup gop group config using MppEncCfgSet and SynH264eSps + * This config function will be called on the following cases: + * + * 1. sps reference number changed which will change totol dpb slot count + * 2. gop size changed which will change the max frame number and max poc lsb + * 3. gop ref relation changed will change tsvc / vgop setup + */ +MPP_RET h264e_dpb_set_cfg(H264eDpb *dpb, MppEncCfgSet* cfg, SynH264eSps *sps); + +/* + * Setup current frame config using flags + * This config function will be called before each frame is encoded: + * + * idr - current frame is force to IDR or not + * lt_ref - current frame is marked as longterm reference + */ +MPP_RET h264e_dpb_set_curr(H264eDpb *dpb, H264eDpbFrmCfg *cfg); + +/* + * Setup current frame and reference frame + */ void h264e_dpb_build_list(H264eDpb *dpb); void h264e_dpb_build_marking(H264eDpb *dpb); void h264e_dpb_curr_ready(H264eDpb *dpb); -MppBuffer h264e_dpb_frm_get_buf(H264eDpbFrm *frm, RK_S32 index); - #define h264e_dpb_dump_frms(dpb) h264e_dpb_dump_frm(dpb, __FUNCTION__) void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller); diff --git a/mpp/codec/enc/h264/h264e_slice.c b/mpp/codec/enc/h264/h264e_slice.c new file mode 100644 index 00000000..937de8a5 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_slice.c @@ -0,0 +1,634 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_slice" + +#include + +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitwrite.h" + +#include "h264e_debug.h" +#include "h264e_slice.h" + +#define FP_FIFO_IS_FULL + +void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder, + H264eMarkingInfo *marking) +{ + memset(slice, 0, sizeof(*slice)); + + slice->num_ref_idx_active = 1; + + slice->reorder = reorder; + slice->marking = marking; +} + +RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg, + SynH264eSps *sps, H264eDpbFrm *frm) +{ + MppEncH264Cfg *h264 = &cfg->codec.h264; + + slice->log2_max_frame_num = sps->log2_max_frame_num_minus4 + 4; + slice->log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4; + slice->entropy_coding_mode = h264->entropy_coding_mode; + + slice->nal_reference_idc = H264_NALU_PRIORITY_HIGH;; + slice->nalu_type = H264_NALU_TYPE_IDR; + + slice->first_mb_in_slice = 0; + slice->slice_type = (frm->status.is_idr) ? (H264_I_SLICE) : (H264_P_SLICE); + slice->pic_parameter_set_id = 0; + slice->frame_num = frm->frame_num; + slice->num_ref_idx_override = 0; + slice->qp_delta = 0; + slice->cabac_init_idc = h264->entropy_coding_mode ? h264->cabac_init_idc : -1; + slice->disable_deblocking_filter_idc = h264->deblock_disable; + slice->slice_alpha_c0_offset_div2 = h264->deblock_offset_alpha; + slice->slice_beta_offset_div2 = h264->deblock_offset_beta; + + slice->idr_flag = frm->status.is_idr; + + if (slice->idr_flag) { + slice->idr_pic_id = slice->next_idr_pic_id; + slice->next_idr_pic_id++; + if (slice->next_idr_pic_id >= 16) + slice->next_idr_pic_id = 0; + } + + slice->pic_order_cnt_lsb = frm->poc; + slice->num_ref_idx_active = 1; + + return MPP_OK; +} + +MPP_RET h264e_reorder_init(H264eReorderInfo *reorder) +{ + reorder->size = H264E_MAX_REFS_CNT; + reorder->pos_wr = 0; + reorder->pos_rd = reorder->size; + + return MPP_OK; +} + +MPP_RET h264e_reorder_wr_op(H264eReorderInfo *info, H264eRplmo *op) +{ + if (info->pos_rd == info->pos_wr) + return MPP_NOK; + + RK_S32 pos_wr = info->pos_wr; + + if (pos_wr >= info->size) + pos_wr -= info->size; + + info->ops[pos_wr] = *op; + + info->pos_wr++; + if (info->pos_wr >= info->size * 2) + info->pos_wr = 0; + + return MPP_OK; +} + +MPP_RET h264e_reorder_rd_op(H264eReorderInfo *info, H264eRplmo *op) +{ + if (info->pos_rd - info->pos_wr == info->size || + info->pos_wr - info->pos_rd == info->size) + return MPP_NOK; + + RK_S32 pos_rd = info->pos_rd; + + if (pos_rd >= info->size) + pos_rd -= info->size; + + *op = info->ops[pos_rd]; + + info->pos_rd++; + if (info->pos_rd >= info->size * 2) + info->pos_rd = 0; + + return MPP_OK; +} + +MPP_RET h264e_marking_init(H264eMarkingInfo *marking) +{ + marking->idr_flag = 0; + marking->no_output_of_prior_pics = 1; + marking->long_term_reference_flag = 0; + marking->adaptive_ref_pic_buffering = 0; + marking->size = MAX_H264E_MMCO_CNT; + marking->pos_wr = 0; + marking->pos_rd = marking->size; + marking->count = 0; + + return MPP_OK; +} + +RK_S32 h264e_marking_is_empty(H264eMarkingInfo *info) +{ + return (info->pos_rd - info->pos_wr == info->size || + info->pos_wr - info->pos_rd == info->size) ? (1) : (0); +} + +RK_S32 h264e_marking_is_full(H264eMarkingInfo *info) +{ + return (info->pos_rd == info->pos_wr) ? (1) : (0); +} + +MPP_RET h264e_marking_wr_op(H264eMarkingInfo *info, H264eMmco *op) +{ + if (h264e_marking_is_full(info)) + return MPP_NOK; + + RK_S32 pos_wr = info->pos_wr; + + if (pos_wr >= info->size) + pos_wr -= info->size; + + info->ops[pos_wr] = *op; + + info->pos_wr++; + if (info->pos_wr >= info->size * 2) + info->pos_wr = 0; + + info->count++; + + return MPP_OK; +} + +MPP_RET h264e_marking_rd_op(H264eMarkingInfo *info, H264eMmco *op) +{ + if (h264e_marking_is_empty(info)) + return MPP_NOK; + + RK_S32 pos_rd = info->pos_rd; + + if (pos_rd >= info->size) + pos_rd -= info->size; + + *op = info->ops[pos_rd]; + + info->pos_rd++; + if (info->pos_rd >= info->size * 2) + info->pos_rd = 0; + + info->count--; + + return MPP_OK; +} + +void write_marking(MppWriteCtx *s, H264eMarkingInfo *marking) +{ + if (marking->idr_flag) { + /* no_output_of_prior_pics_flag */ + mpp_writer_put_bits(s, marking->no_output_of_prior_pics, 1); + + /* long_term_reference_flag */ + mpp_writer_put_bits(s, marking->long_term_reference_flag, 1); + + // clear long_term_reference_flag flag + marking->long_term_reference_flag = 0; + } else { + h264e_dbg_mmco("mmco count %d\n", marking->count); + + if (!h264e_marking_is_empty(marking)) { + /* adaptive_ref_pic_marking_mode_flag */ + mpp_writer_put_bits(s, 1, 1); + + while (marking->count) { + H264eMmco mmco; + + h264e_marking_rd_op(marking, &mmco); + + /* memory_management_control_operation */ + mpp_writer_put_ue(s, mmco.mmco); + + switch (mmco.mmco) { + case 1 : { + /* difference_of_pic_nums_minus1 */ + mpp_writer_put_ue(s, mmco.difference_of_pic_nums_minus1); + } break; + case 2 : { + /* long_term_pic_num */ + mpp_writer_put_ue(s, mmco.long_term_pic_num ); + } break; + case 3 : { + /* difference_of_pic_nums_minus1 */ + mpp_writer_put_ue(s, mmco.difference_of_pic_nums_minus1); + + /* long_term_frame_idx */ + mpp_writer_put_ue(s, mmco.long_term_frame_idx ); + } break; + case 4 : { + /* max_long_term_frame_idx_plus1 */ + mpp_writer_put_ue(s, mmco.max_long_term_frame_idx_plus1); + } break; + case 5 : { + } break; + case 6 : { + /* long_term_frame_idx */ + mpp_writer_put_ue(s, mmco.long_term_frame_idx); + } break; + default : { + mpp_err_f("invalid mmco %d\n", mmco.mmco); + } break; + } + + marking->count--; + } + + /* memory_management_control_operation */ + mpp_writer_put_ue(s, 0); + } else { + /* adaptive_ref_pic_marking_mode_flag */ + mpp_writer_put_bits(s, 0, 1); + } + } +} + +RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size) +{ + BitReadCtx_t bit; + RK_S32 ret = 0; + RK_S32 val = 0; + RK_S32 bit_cnt = 0; + + mpp_set_bitread_ctx(&bit, p, size); + + /* start_code */ + ret |= mpp_read_longbits(&bit, 32, (RK_U32 *)&val); + + /* forbidden_zero_bit */ + ret |= mpp_read_bits(&bit, 1, &val); + + /* nal_ref_idc */ + ret |= mpp_read_bits(&bit, 2, &slice->nal_reference_idc); + + /* nal_unit_type */ + ret |= mpp_read_bits(&bit, 5, &slice->nalu_type); + + /* first_mb_nr */ + ret = mpp_read_ue(&bit, &slice->first_mb_in_slice); + + /* slice_type */ + ret |= mpp_read_ue(&bit, &slice->slice_type); + + /* pic_parameter_set_id */ + ret |= mpp_read_ue(&bit, &slice->pic_parameter_set_id); + + /* frame_num */ + /* NOTE: vpu hardware fix 16 bit frame_num */ + ret |= mpp_read_bits(&bit, 16, &slice->frame_num); + + slice->idr_flag = (slice->nalu_type == 5); + if (slice->idr_flag) { + /* idr_pic_id */ + ret |= mpp_read_ue(&bit, &slice->idr_pic_id); + } + + // pic_order_cnt_type here + // vpu hardware is always zero. Just ignore + + // NOTE: Only P slice has num_ref_idx_override flag and ref_pic_list_modification flag + if (slice->slice_type == 0) { + /* num_ref_idx_override */ + ret |= mpp_read_bits(&bit, 1, &slice->num_ref_idx_override); + + /* ref_pic_list_modification_flag */ + ret |= mpp_read_bits(&bit, 1, &slice->ref_pic_list_modification_flag); + } + + // NOTE: vpu hardware is always zero + slice->ref_pic_list_modification_flag = 0; + + if (slice->nal_reference_idc) { + if (slice->idr_flag) { + /* no_output_of_prior_pics */ + ret |= mpp_read_bits(&bit, 1, &slice->no_output_of_prior_pics); + + /* long_term_reference_flag */ + ret |= mpp_read_bits(&bit, 1, &slice->long_term_reference_flag); + } else { + /* adaptive_ref_pic_buffering */ + ret |= mpp_read_bits(&bit, 1, &slice->adaptive_ref_pic_buffering); + + mpp_assert(slice->adaptive_ref_pic_buffering == 0); + } + } + + if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { + /* cabac_init_idc */ + ret |= mpp_read_ue(&bit, &slice->cabac_init_idc); + } + + /* qp_delta */ + ret |= mpp_read_se(&bit, &slice->qp_delta); + + /* disable_deblocking_filter_idc */ + ret |= mpp_read_ue(&bit, &slice->disable_deblocking_filter_idc); + + /* slice_alpha_c0_offset_div2 */ + ret |= mpp_read_se(&bit, &slice->slice_alpha_c0_offset_div2); + + /* slice_beta_offset_div2 */ + ret |= mpp_read_se(&bit, &slice->slice_beta_offset_div2); + + h264e_dbg_slice("non-aligned used bit %d\n", bit.used_bits); + + if (slice->entropy_coding_mode) { + if (bit.num_remaining_bits_in_curr_byte_) { + RK_U32 tmp = bit.num_remaining_bits_in_curr_byte_; + + /* cabac_aligned_bit */ + ret |= mpp_read_bits(&bit, tmp, &val); + } + } + bit_cnt = bit.used_bits; + + h264e_dbg_slice("total aligned used bit %d\n", bit_cnt); + + return bit_cnt; +} + +RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size) +{ + MppWriteCtx stream; + MppWriteCtx *s = &stream; + RK_S32 i; + RK_S32 bitCnt = 0; + H264eMarkingInfo *marking = slice->marking; + H264eRplmo rplmo; + MPP_RET ret; + + mpp_writer_init(s, p, size); + + RK_U8 *tmp = (RK_U8 *)s->buffer; + + /* nal header */ + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(s, 0, 24); + mpp_writer_put_raw_bits(s, 1, 8); + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(s, 0, 1); + + /* nal_reference_idc */ + mpp_writer_put_raw_bits(s, slice->nal_reference_idc, 2); + /* nalu_type */ + mpp_writer_put_raw_bits(s, slice->nalu_type, 5); + + /* slice header */ + /* start_mb_nr */ + mpp_writer_put_ue(s, slice->first_mb_in_slice); + + /* slice_type */ + mpp_writer_put_ue(s, slice->slice_type); + + /* pic_parameter_set_id */ + mpp_writer_put_ue(s, slice->pic_parameter_set_id); + + /* frame_num */ + mpp_writer_put_bits(s, slice->frame_num, 16); + + if (slice->nalu_type == 5) { + /* idr_pic_id */ + mpp_writer_put_ue(s, slice->idr_pic_id); + marking->idr_flag = 1; + } else + marking->idr_flag = 0; + + // Force to use poc type 0 here + { + RK_S32 pic_order_cnt_lsb = slice->pic_order_cnt_lsb; + RK_S32 max_poc_lsb = (1 << slice->log2_max_poc_lsb) - 1; + + + if (pic_order_cnt_lsb >= max_poc_lsb) + pic_order_cnt_lsb -= max_poc_lsb; + + /* pic_order_cnt_lsb */ + mpp_writer_put_bits(s, pic_order_cnt_lsb, 16); + } + + /* read reorder and check */ + ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (slice->slice_type == H264_P_SLICE && !ret) { + /* num_ref_idx_override */ + mpp_writer_put_bits(s, slice->num_ref_idx_override, 1); + + /* ref_pic_list_reordering */ + mpp_writer_put_bits(s, 1, 1); + + slice->ref_pic_list_modification_flag = 1; + } else + slice->ref_pic_list_modification_flag = 0; + + if (slice->slice_type == H264_I_SLICE) + mpp_assert(slice->ref_pic_list_modification_flag == 0); + + if (slice->ref_pic_list_modification_flag) { + mpp_assert(ret == MPP_OK); + /* modification_of_pic_nums_idc */ + mpp_writer_put_ue(s, rplmo.modification_of_pic_nums_idc); + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + /* abs_diff_pic_num_minus1 */ + mpp_writer_put_ue(s, rplmo.abs_diff_pic_num_minus1); + } break; + case 2 : { + /* long_term_pic_idx */ + mpp_writer_put_ue(s, rplmo.long_term_pic_idx); + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + + /* modification_of_pic_nums_idc */ + mpp_writer_put_ue(s, 3); + } + + // NOTE: ignore nal ref idc here + h264e_dbg_mmco("nal_reference_idc %d idr_flag %d\n", + slice->nal_reference_idc, slice->idr_flag); + + if (slice->nal_reference_idc) + write_marking(s, marking); + + if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { + /* cabac_init_idc */ + mpp_writer_put_ue(s, slice->cabac_init_idc); + } + + /* qp_delta */ + mpp_writer_put_se(s, slice->qp_delta); + + /* disable_deblocking_filter_idc */ + mpp_writer_put_ue(s, 0); + + /* slice_alpha_c0_offset_div2 */ + mpp_writer_put_se(s, 0); + + /* slice_beta_offset_div2 */ + mpp_writer_put_se(s, 0); + + bitCnt = s->buffered_bits + s->byte_cnt * 8; + + if (s->buffered_bits) { + // NOTE: only have aligned bit on cabac mode but cavlc also need to write byte cache to memory + RK_S32 left = (8 - s->buffered_bits); + for (i = 0; i < left; i++) { + /* align_bit */ + mpp_writer_put_bits(s, 1, 1); + } + } + + // update on cabac mode + if (slice->entropy_coding_mode) + bitCnt = s->buffered_bits + s->byte_cnt * 8; + + RK_S32 pos = 0; + char log[256]; + + pos = sprintf(log + pos, "sw stream: "); + for (i = 0; i < 16; i ++) { + pos += sprintf(log + pos, "%02x ", tmp[i]); + } + pos += sprintf(log + pos, "\n"); + h264e_dbg_slice(log); + + return bitCnt; +} + +static RK_S32 frame_no = 0; + +RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, RK_S32 src_size) +{ + RK_S32 dst_byte = dst_bit / 8; + RK_S32 src_byte = src_bit / 8; + RK_S32 dst_bit_r = dst_bit & 7; + RK_S32 src_bit_r = src_bit & 7; + RK_S32 src_len = src_size - src_byte; + RK_S32 diff_len = 0; + + if (src_bit_r == 0 && dst_bit_r == 0) { + // direct copy + if (h264e_debug & H264E_DBG_SLICE) + mpp_log_f("direct copy %p -> %p %d\n", src, dst, src_len); + + memcpy(dst + dst_byte, src + src_byte, src_len); + return diff_len; + } + + RK_U8 *psrc = src + src_byte; + RK_U8 *pdst = dst + dst_byte; + + RK_U16 tmp16a, tmp16b, tmp16c, last_tmp; + RK_U8 tmp0, tmp1; + RK_U32 loop = src_len; + RK_U32 i = 0; + RK_U32 src_zero_cnt = 0; + RK_U32 dst_zero_cnt = 0; + RK_U32 dst_len = 0; + + if (h264e_debug & H264E_DBG_SLICE) + mpp_log("bit [%d %d] [%d %d] loop %d\n", src_bit, dst_bit, + src_bit_r, dst_bit_r, loop); + + last_tmp = pdst[0] >> (8 - dst_bit_r) << (8 - dst_bit_r); + + for (i = 0; i < loop; i++) { + if (psrc[0] == 0) { + src_zero_cnt++; + } else { + src_zero_cnt = 0; + } + + // tmp0 tmp1 is next two non-aligned bytes from src + tmp0 = psrc[0]; + tmp1 = (i < loop - 1) ? psrc[1] : 0; + + if (src_zero_cnt >= 2 && tmp1 == 3) { + if (h264e_debug & H264E_DBG_SLICE) + mpp_log("found 03 at src pos %d %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, psrc[-2], psrc[-1], psrc[0], psrc[1], psrc[2], + psrc[3], psrc[4], psrc[5]); + + psrc++; + i++; + tmp1 = psrc[1]; + src_zero_cnt = 0; + diff_len--; + } + // get U16 data + tmp16a = ((RK_U16)tmp0 << 8) | (RK_U16)tmp1; + + if (src_bit_r) { + tmp16b = tmp16a << src_bit_r; + } else { + tmp16b = tmp16a; + } + + if (dst_bit_r) + tmp16c = tmp16b >> dst_bit_r | (last_tmp >> (8 - dst_bit_r) << (16 - dst_bit_r)); + else + tmp16c = tmp16b; + + pdst[0] = (tmp16c >> 8) & 0xFF; + pdst[1] = tmp16c & 0xFF; + + if (h264e_debug & H264E_DBG_SLICE) { + if (i < 10) { + mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); + } + if (i >= loop - 10) { + mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); + } + } + + if (dst_zero_cnt == 2 && pdst[0] <= 0x3) { + if (h264e_debug & H264E_DBG_SLICE) + mpp_log("found 03 at dst frame %d pos %d\n", frame_no, dst_len); + + pdst[2] = pdst[1]; + pdst[1] = pdst[0]; + pdst[0] = 0x3; + pdst++; + diff_len++; + dst_len++; + dst_zero_cnt = 0; + } + + if (pdst[0] == 0) + dst_zero_cnt++; + else + dst_zero_cnt = 0; + + last_tmp = tmp16c; + + psrc++; + pdst++; + dst_len++; + } + + frame_no++; + + return diff_len; +} diff --git a/mpp/codec/enc/h264/h264e_slice.h b/mpp/codec/enc/h264/h264e_slice.h new file mode 100644 index 00000000..e4c54031 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_slice.h @@ -0,0 +1,59 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __H264E_SLICE_H__ +#define __H264E_SLICE_H__ + +#include "mpp_enc_cfg.h" + +#include "h264e_syntax_new.h" +#include "h264e_dpb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h264e_reorder_init(H264eReorderInfo *reorder); +MPP_RET h264e_marking_init(H264eMarkingInfo *marking); + +/* + * h264e_slice_update is called only on cfg is update. + * When cfg has no changes just use slice next to setup + */ +void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder, + H264eMarkingInfo *marking); +RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg, + SynH264eSps *sps, H264eDpbFrm *frm); + +/* reorder context for dpb */ +MPP_RET h264e_reorder_wr_op(H264eReorderInfo *info, H264eRplmo *op); +MPP_RET h264e_reorder_rd_op(H264eReorderInfo *info, H264eRplmo *op); + +/* mmco context for dpb */ +MPP_RET h264e_marking_wr_op(H264eMarkingInfo *info, H264eMmco *op); +MPP_RET h264e_marking_rd_op(H264eMarkingInfo *info, H264eMmco *op); + + +RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size); +RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size); +RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, + RK_S32 src_size); + +#ifdef __cplusplus +} +#endif + +#endif /* __H264E_SLICE_H__ */ diff --git a/mpp/hal/common/h264/CMakeLists.txt b/mpp/hal/common/h264/CMakeLists.txt index 1aa95ed4..63325761 100644 --- a/mpp/hal/common/h264/CMakeLists.txt +++ b/mpp/hal/common/h264/CMakeLists.txt @@ -11,8 +11,6 @@ set(HAL_H264E_HDR # hal h264 encoder sourse set(HAL_H264E_SRC - h264e_dpb.c - h264e_slice.c h264e_stream.c hal_h264e_com.c hal_h264e_api.c diff --git a/mpp/hal/common/h264/h264e_dpb.c b/mpp/hal/common/h264/h264e_dpb.c deleted file mode 100644 index a1bbc110..00000000 --- a/mpp/hal/common/h264/h264e_dpb.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright 2015 Rockchip Electronics Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "h264e_dpb" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_common.h" - -#include "hal_h264e_com.h" -#include "h264e_dpb.h" - -H264eFrmBuf *h264e_dpb_frm_buf_get(H264eFrmBufGrp *grp) -{ - RK_U32 i; - - for (i = 0; i < H264E_REF_MAX; i++) { - if (!grp->bufs[i].is_used) { - grp->bufs[i].is_used = 1; - return &grp->bufs[i]; - } - } - - mpp_err_f("failed to get buffer for dpb frame\n"); - - return NULL; -} - -MPP_RET h264e_dpb_frm_buf_put(H264eFrmBufGrp *grp, H264eFrmBuf *buf) -{ - mpp_assert(buf->is_used); - buf->is_used = 0; - - (void)grp; - - return MPP_OK; -} - -/* get buffer at init */ -MPP_RET h264e_dpb_init_curr(H264eDpb *dpb, H264eDpbFrm *frm) -{ - H264eFrmBufGrp *buf_grp = &dpb->buf_grp; - - mpp_assert(!frm->on_used); - - frm->dpb = dpb; - frm->ref_status = 0; - frm->ref_count = 0; - - memset(&frm->info, 0, sizeof(frm->info)); - - if (!frm->buf) { - RK_U32 i; - H264eFrmBuf *buf = h264e_dpb_frm_buf_get(buf_grp); - - for (i = 0; i < buf_grp->count; i++) { - mpp_buffer_get(buf_grp->group, &buf->buf[i], buf_grp->size[i]); - mpp_assert(buf->buf[i]); - } - - frm->buf = buf; - } - - frm->inited = 1; - - return MPP_OK; -} - -/* put buffer at deinit */ -MPP_RET h264e_dpb_frm_deinit(H264eDpbFrm *frm) -{ - RK_U32 i; - H264eDpb *dpb = frm->dpb; - H264eFrmBufGrp *buf_grp = &dpb->buf_grp; - H264eFrmBuf *buf = frm->buf; - - h264e_dpb_dbg_f("enter %d\n", frm->frm_cnt); - - for (i = 0; i < buf_grp->count; i++) { - mpp_assert(buf->buf[i]); - mpp_buffer_put(buf->buf[i]); - buf->buf[i] = NULL; - } - - h264e_dpb_frm_buf_put(buf_grp, buf); - frm->inited = 0; - - return MPP_OK; -} - -MppBuffer h264e_dpb_frm_get_buf(H264eDpbFrm *frm, RK_S32 index) -{ - H264eFrmBuf *buf = frm->buf; - - if (NULL == buf) - return NULL; - - mpp_assert(buf->is_used); - mpp_assert(index >= 0 && index < H264E_MAX_BUF_CNT); - mpp_assert(buf->buf[index]); - return buf->buf[index]; -} - -static void h264e_dpb_dump_hier(H264eDpb *dpb) -{ - RK_S32 i = 0; - - mpp_log_f("dpb %p gop length %d\n", dpb, dpb->gop_len); - - for (i = 0; i < dpb->gop_len + 1; i++) { - mpp_log_f("hier %d cnt %2d status 0x%03x dist %d\n", i, - dpb->ref_cnt[i], dpb->ref_sta[i], dpb->ref_dist[i]); - } -} - -void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller) -{ - RK_S32 i = 0; - - mpp_log_f("dump dpb frame info in %s\n", caller); - - mpp_log_f("dpb %p total count %d\n", dpb, dpb->total_cnt); - mpp_log_f("dpb status - init use cnt gop idx type idr ref lt idx sta cnt\n", dpb, dpb->total_cnt); - - for (i = 0; i < dpb->total_cnt; i++) { - H264eDpbFrm *frm = &dpb->frames[i]; - - if (i == 0) { - mpp_log_f("short-term reference frame:\n"); - } else if (i == dpb->max_st_cnt) { - mpp_log_f("long-term reference frame:\n"); - } else if (i == dpb->curr_idx) { - mpp_log_f("current frame:\n"); - } - - if (!frm->inited) - continue; - - mpp_log_f("frm slot %2d %-4d %-3d %-3d %-3d %-3d %-4d %-3d %-3d %-2d %-3d %-3x %-3d\n", - i, - frm->inited, - frm->on_used, - frm->frm_cnt, - frm->gop_cnt, - frm->gop_idx, - frm->frame_type, - frm->info.is_idr, - !frm->info.is_non_ref, - frm->info.is_lt_ref, - frm->lt_idx, - frm->ref_status, - frm->ref_count); - } -} - -void h264e_dpb_dump_listX(H264eDpbFrm **list, RK_S32 count) -{ - RK_S32 i; - - for (i = 0; i < count; i++) { - H264eDpbFrm *frm = list[i]; - - mpp_log_f("list slot %d %-4d %-3d %-3d %-3d %-4d %-3d %-3d %-2d %-3d %-3x %-3d\n", - i, - frm->inited, - frm->on_used, - frm->frm_cnt, - frm->gop_idx, - frm->frame_type, - frm->info.is_idr, - !frm->info.is_non_ref, - frm->info.is_lt_ref, - frm->lt_idx, - frm->ref_status, - frm->ref_count); - } -} - -void h264e_dpb_dump_list(H264eDpb *dpb) -{ - mpp_log_f("dump dpb list info\n"); - - mpp_log_f("dpb size %d st size %d lt size %d\n", - dpb->dpb_size, dpb->st_size, dpb->lt_size); - - if (dpb->dpb_size) { - mpp_log_f("list status - init use cnt gop type idr ref lt idx sta cnt\n", dpb, dpb->total_cnt); - - h264e_dpb_dump_listX(dpb->list, dpb->dpb_size); - } -} - -MPP_RET h264e_dpb_init(H264eDpb **dpb, H264eDpbCfg *cfg) -{ - MPP_RET ret = MPP_OK; - H264eDpb *p = NULL; - if (NULL == dpb || NULL == cfg) { - mpp_err_f("invalid parameter %p %p\n", dpb, cfg); - return MPP_ERR_VALUE; - } - - h264e_dpb_dbg_f("enter\n"); - h264e_dpb_dbg_f("max ref frm num %d\n", cfg->ref_frm_num); - h264e_dpb_dbg_f("log2 max frm num %d\n", cfg->log2_max_frm_num); - h264e_dpb_dbg_f("log2 max poc lsb %d\n", cfg->log2_max_poc_lsb); - - if (cfg->ref_frm_num < 0 || cfg->ref_frm_num > H264E_REF_MAX || - cfg->log2_max_frm_num < 0 || cfg->log2_max_frm_num > 16 || - cfg->log2_max_poc_lsb < 0 || cfg->log2_max_poc_lsb > 16) { - mpp_err_f("invalid config value %d %d %d\n", cfg->ref_frm_num, - cfg->log2_max_frm_num, cfg->log2_max_poc_lsb); - return MPP_ERR_VALUE; - } - - RK_S32 max_st_cnt = cfg->ref_frm_num; - RK_S32 max_lt_cnt = cfg->ref_frm_num; - RK_S32 total_cnt = max_st_cnt + max_lt_cnt + 1; - - p = mpp_calloc_size(H264eDpb, sizeof(H264eDpb) + - total_cnt * sizeof(H264eDpbFrm)); - - if (NULL == p) - return MPP_ERR_MALLOC; - - p->cfg = *cfg; - - p->ref_frm_num = max_st_cnt; - p->max_frm_num = (1 << cfg->log2_max_frm_num) - 1; - p->max_poc_lsb = (1 << cfg->log2_max_poc_lsb) - 1; - - p->total_cnt = total_cnt; - p->max_st_cnt = max_st_cnt; - p->max_lt_cnt = max_lt_cnt; - p->curr_idx = total_cnt - 1; - - p->frames = (H264eDpbFrm *)(p + 1); - - ret = mpp_buffer_group_get_internal(&p->buf_grp.group, MPP_BUFFER_TYPE_ION); - mpp_assert(ret == MPP_OK); - mpp_assert(p->buf_grp.group); - mpp_assert(dpb); - *dpb = p; - - h264e_dpb_dbg_f("leave %p\n", p); - - return ret; -} - -MPP_RET h264e_dpb_deinit(H264eDpb *dpb) -{ - RK_S32 i; - - h264e_dpb_dbg_f("enter %p\n", dpb); - - for (i = 0; i < dpb->total_cnt; i++) { - if (dpb->frames[i].inited) - h264e_dpb_frm_deinit(&dpb->frames[i]); - } - - if (dpb->buf_grp.group) - mpp_buffer_group_put(dpb->buf_grp.group); - - MPP_FREE(dpb); - - h264e_dpb_dbg_f("leave\n"); - - return MPP_OK; -} - -MPP_RET h264e_dpb_setup_buf_size(H264eDpb *dpb, RK_U32 size[], RK_U32 count) -{ - RK_U32 i; - H264eFrmBufGrp *buf_grp = &dpb->buf_grp; - - if (count > H264E_MAX_BUF_CNT) { - mpp_err_f("invalid count %d\n", count); - return MPP_NOK; - } - - for (i = 0; i < count; i++) { - buf_grp->size[i] = size[i]; - h264e_dpb_dbg_f("size[%d] %d\n", i, size[i]); - } - - buf_grp->count = count; - - return MPP_OK; -} - -MPP_RET h264e_dpb_setup_hier(H264eDpb *dpb, MppEncHierCfg *cfg) -{ - // update gop hierarchy reference status and each frame counter - RK_S32 i; - MppEncFrmRefInfo *info; - MppEncFrmRefInfo *base; - - memset(dpb->ref_inf, 0, sizeof(dpb->ref_inf)); - memset(dpb->ref_sta, 0, sizeof(dpb->ref_sta)); - memset(dpb->ref_cnt, 0, sizeof(dpb->ref_cnt)); - memset(dpb->ref_dist, 0, sizeof(dpb->ref_dist)); - - dpb->gop_len = cfg->length; - dpb->max_lt_idx = 0; - - mpp_enc_get_hier_info(&info, cfg); - base = info; - - for (i = 0; i < cfg->length + 1; i++, info++) { - RK_S32 ref_idx = info->ref_gop_idx; - - // setup ref_status and ref_idx for new frame - dpb->ref_inf[i] = info->status; - dpb->ref_dist[i] = ref_idx - i; - - if (!info->status.is_non_ref) { - dpb->ref_sta[i] |= REF_BY_RECN(i); - dpb->ref_cnt[i]++; - } - - if (!info->status.is_non_ref && info->status.is_lt_ref) { - if (info->status.lt_idx > dpb->max_lt_idx) { - dpb->max_lt_idx = info->status.lt_idx; - h264e_dpb_dbg_f("curr %d update lt_idx to %d\n", - i, dpb->max_lt_idx); - } - } - - h264e_dpb_dbg_f("curr %d ref_status 0x%03x count %d -> %d dist %d\n", - i, dpb->ref_sta[i], dpb->ref_cnt[i], - ref_idx, dpb->ref_dist[i]); - - // update the reference frame status and counter only once - if (ref_idx == i) - continue; - - dpb->ref_sta[ref_idx] |= REF_BY_REFR(i); - dpb->ref_cnt[ref_idx]++; - - h264e_dpb_dbg_f("refr %d ref_status 0x%03x count %d\n", - ref_idx, dpb->ref_sta[ref_idx], dpb->ref_cnt[ref_idx]); - } - - mpp_enc_put_hier_info(base); - - if (hal_h264e_debug & H264E_DBG_DPB) - h264e_dpb_dump_hier(dpb); - - return MPP_OK; -} - -static void h264e_dpb_frm_swap(H264eDpb *dpb, RK_S32 a, RK_S32 b) -{ - H264eDpbFrm tmp; - - tmp = dpb->frames[a]; - dpb->frames[a] = dpb->frames[b]; - dpb->frames[b] = tmp; -} - -H264eDpbFrm *h264e_dpb_get_curr(H264eDpb *dpb, RK_S32 new_seq) -{ - RK_S32 gop_cnt = 0; - RK_S32 gop_idx = 0; - RK_S32 gop_idx_wrap = 0; - - H264eDpbFrm *frm = &dpb->frames[dpb->curr_idx]; - - h264e_dpb_dbg_f("try get curr %d new_seq %d gop cnt %d idx %d\n", - dpb->seq_idx, new_seq, dpb->gop_cnt, dpb->gop_idx); - - if (!frm->inited) - h264e_dpb_init_curr(dpb, frm); - - mpp_assert(!frm->on_used); - mpp_assert(!dpb->curr); - - if (new_seq) { - // NOTE: gop_idx here is for next gop_idx - dpb->gop_idx = 1; - dpb->gop_cnt = 0; - - if (dpb->seq_idx) - dpb->seq_cnt++; - - dpb->seq_idx = 0; - - gop_cnt = 0; - gop_idx = 0; - } else { - gop_cnt = dpb->gop_cnt; - gop_idx = dpb->gop_idx++; - } - - h264e_dpb_dbg_f("A frm cnt %d gop %d idx %d dpb gop %d idx %d\n", - frm->frm_cnt, gop_cnt, gop_idx, - dpb->gop_cnt, dpb->gop_idx); - - if (dpb->gop_idx >= dpb->gop_len) { - dpb->gop_idx = 0; - dpb->gop_cnt++; - } - - frm->frm_cnt = dpb->seq_idx++; - frm->gop_cnt = gop_cnt; - frm->gop_idx = gop_idx; - - h264e_dpb_dbg_f("B frm cnt %d gop %d idx %d dpb gop %d idx %d\n", - frm->frm_cnt, gop_cnt, gop_idx, - dpb->gop_cnt, dpb->gop_idx); - - gop_idx_wrap = gop_idx; - - if (!gop_idx && gop_cnt) - gop_idx_wrap = dpb->gop_len; - - frm->info = dpb->ref_inf[gop_idx_wrap]; - frm->ref_status = dpb->ref_sta[gop_idx]; - frm->ref_count = dpb->ref_cnt[gop_idx]; - frm->ref_dist = dpb->ref_dist[gop_idx_wrap]; - frm->poc = frm->frm_cnt * 2; - frm->lt_idx = frm->info.lt_idx; - frm->on_used = 1; - - h264e_dpb_dbg_f("setup frm %d gop %d idx %d wrap %d ref dist %d\n", - frm->frm_cnt, frm->gop_cnt, frm->gop_idx, gop_idx_wrap, frm->ref_dist); - - dpb->curr = frm; - - h264e_dpb_dbg_f("frm %d old frm num %d next %d\n", - frm->frm_cnt, dpb->curr_frm_num, dpb->next_frm_num); - - // new_seq is for dpb reset and IDR frame - if (new_seq) { - RK_S32 i; - - frm->info.is_idr = 1; - frm->info.is_intra = 1; - - // init to 0 - dpb->curr_frm_num = 0; - dpb->next_frm_num = 1; - frm->frame_num = 0; - frm->poc = 0; - - // mmco 5 mark all reference frame to be non-referenced - for (i = 0; i < dpb->curr_idx; i++) { - H264eDpbFrm *tmp = &dpb->frames[i]; - - tmp->on_used = 0; - tmp->info.is_non_ref = 1; - tmp->info.is_lt_ref = 0; - tmp->ref_status = 0; - tmp->ref_count = 0; - tmp->marked_unref = 0; - } - - dpb->dpb_size = 0; - dpb->lt_size = 0; - dpb->st_size = 0; - dpb->unref_cnt = 0; - } else - dpb->curr_frm_num = dpb->next_frm_num; - - frm->frame_num = dpb->curr_frm_num; - - dpb->next_frm_num = dpb->curr_frm_num + !frm->info.is_non_ref; - h264e_dpb_dbg_f("frm %d new frm num %d next %d\n", - frm->frm_cnt, dpb->curr_frm_num, dpb->next_frm_num); - - - if (hal_h264e_debug & H264E_DBG_DPB) - h264e_dpb_dump_frms(dpb); - - return frm; -} - -H264eDpbFrm *h264e_dpb_get_refr(H264eDpbFrm *frm) -{ - RK_S32 i; - H264eDpbFrm *ref = NULL; - H264eDpb *dpb = frm->dpb; - RK_S32 frm_cnt = frm->frm_cnt; - RK_S32 ref_dist = frm->ref_dist; - RK_S32 ref_frm_cnt = frm_cnt + ref_dist; - - for (i = 0; i < dpb->curr_idx; i++) { - H264eDpbFrm *tmp = &dpb->frames[i]; - - if (tmp->on_used && !tmp->info.is_non_ref && - tmp->frm_cnt == ref_frm_cnt) { - ref = &dpb->frames[i]; - break; - } - } - - h264e_dpb_dbg_f("frm %d found dist %d refer frm %d at %d %p\n", - frm_cnt, ref_dist, ref_frm_cnt, i, ref); - - if (NULL == ref) - ref = &dpb->frames[dpb->curr_idx]; - - return ref; -} - -static int cmp_st_list(const void *p0, const void *p1) -{ - H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; - H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; - - if (frm0->frame_num == frm1->frame_num) - return 0; - if (frm0->frame_num < frm1->frame_num) - return 1; - else - return -1; -} - -static int cmp_lt_list(const void *p0, const void *p1) -{ - H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; - H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; - - if (frm0->lt_idx == frm1->lt_idx) - return 0; - if (frm0->lt_idx > frm1->lt_idx) - return 1; - else - return -1; -} - -/* - * Build list function - * - * This function should build the default list for current frame. - * Then check the reference frame is the default one or not. - * Reorder command is need if the reference frame is not match. - */ -void h264e_dpb_build_list(H264eDpb *dpb) -{ - RK_S32 i, j; - RK_S32 st_size = 0; - RK_S32 lt_size = 0; - - if (dpb->curr->info.is_intra) - return ; - - // init list - // 1. found all short term and long term ref - for (i = 0; i < dpb->curr_idx; i++) { - H264eDpbFrm *frm = &dpb->frames[i]; - - if (!frm->on_used) - continue; - - if (frm->info.is_non_ref) - continue; - - h264e_dpb_dbg_f("idx %d on_used %x ref_status %03x is_non_ref %d lt_ref %d\n", - i, frm->on_used, frm->ref_status, - frm->info.is_non_ref, frm->info.is_lt_ref); - - if (!frm->info.is_non_ref) { - if (!frm->info.is_lt_ref) { - dpb->stref[st_size] = frm; - st_size++; - h264e_dpb_dbg_f("found st %d st_size %d %p\n", i, st_size, frm); - } else { - dpb->ltref[lt_size] = frm; - lt_size++; - h264e_dpb_dbg_f("found lt %d lt_size %d %p\n", i, lt_size, frm); - } - } - } - - h264e_dpb_dbg_f("dpb_size %d st_size %d lt_size %d\n", dpb->dpb_size, st_size, lt_size); - - // sort st list - if (st_size > 1) { - if (hal_h264e_debug & H264E_DBG_DPB) { - mpp_log_f("dpb st list before sort\n"); - h264e_dpb_dump_listX(dpb->stref, st_size); - } - - qsort(dpb->stref, st_size, sizeof(dpb->stref[0]), cmp_st_list); - - if (hal_h264e_debug & H264E_DBG_DPB) { - mpp_log_f("dpb st list after sort\n"); - h264e_dpb_dump_listX(dpb->stref, st_size); - } - } - - if (lt_size > 1) { - if (hal_h264e_debug & H264E_DBG_DPB) { - mpp_log_f("dpb lt list before sort\n"); - h264e_dpb_dump_listX(dpb->ltref, lt_size); - } - - qsort(dpb->ltref, lt_size, sizeof(dpb->ltref[0]), cmp_lt_list); - - if (hal_h264e_debug & H264E_DBG_DPB) { - mpp_log_f("dpb lt list after sort\n"); - h264e_dpb_dump_listX(dpb->ltref, lt_size); - } - } - - // generate list before reorder - memset(dpb->list, 0, sizeof(dpb->list)); - j = 0; - for (i = 0; i < st_size; i++) - dpb->list[j++] = dpb->stref[i]; - - for (i = 0; i < lt_size; i++) - dpb->list[j++] = dpb->ltref[i]; - - dpb->st_size = st_size; - dpb->lt_size = lt_size; - - mpp_assert(dpb->dpb_size == st_size + lt_size); - - if (hal_h264e_debug & H264E_DBG_DPB) - h264e_dpb_dump_list(dpb); - - if (dpb->st_size + dpb->lt_size) { - H264eDpbFrm *curr = dpb->curr; - H264eDpbFrm *def_ref = dpb->list[0]; - - RK_S32 curr_frm_cnt = curr->frm_cnt; - RK_S32 def_ref_frm_cnt = def_ref->frm_cnt; - RK_S32 set_ref_frm_cnt = curr->frm_cnt + curr->ref_dist; - - dpb->need_reorder = (def_ref_frm_cnt != set_ref_frm_cnt) ? (1) : (0); - h264e_dpb_dbg_f("refer curr %d def %d set %d reorder %d\n", - curr_frm_cnt, def_ref_frm_cnt, set_ref_frm_cnt, - dpb->need_reorder); - } else { - h264e_dpb_dbg_f("refer NULL\n"); - } -} - -void h264e_dpb_build_marking(H264eDpb *dpb) -{ - RK_S32 i; - H264eDpbFrm *frm = dpb->curr; - H264eDpbFrm *ref = h264e_dpb_get_refr(frm); - - h264e_dpb_dbg_f("curr %d gop %d idx %d ref %d ready -> frm %d gop %d idx %d\n", - frm->frm_cnt, frm->gop_cnt, frm->gop_idx, !frm->info.is_non_ref, - ref->frm_cnt, ref->gop_cnt, ref->gop_cnt); - - // refernce frame can not mark itself as unreferenced. - // So do NOT clear RECN flag here - // clear the ref status and count once - if (frm != ref) { - ref->ref_status &= ~(REF_BY_REFR(frm->gop_idx)); - - if (ref->ref_count > 0) - ref->ref_count--; - - h264e_dpb_dbg_f("refr %d ref_status %03x count %d\n", - ref->gop_idx, ref->ref_status, ref->ref_count); - } - - if (!frm->info.is_non_ref && frm->info.is_lt_ref) { - h264e_dpb_dbg_f("found lt idx %d curr max %d\n", frm->lt_idx, dpb->curr_max_lt_idx); - if (frm->lt_idx > dpb->curr_max_lt_idx) { - dpb->next_max_lt_idx = frm->lt_idx; - } - } - - if (frm->info.is_idr) - return ; - - if (frm->info.is_non_ref) - return ; - - h264e_dpb_dbg_f("curr -- frm %d gop %d idx %d T%d\n", - frm->frm_cnt, frm->gop_cnt, frm->gop_idx, frm->info.temporal_id); - - // if we are reference frame scan the previous frame to mark - for (i = 0; i < dpb->curr_idx; i++) { - H264eDpbFrm *tmp = &dpb->frames[i]; - - if (!tmp->on_used) - continue; - - if (tmp->info.is_non_ref) - continue; - - h264e_dpb_dbg_f("slot %2d frm %3d gop %3d idx %2d T%d lt %d cnt %d\n", - i, tmp->frm_cnt, tmp->gop_cnt, tmp->gop_idx, - tmp->info.temporal_id, tmp->info.is_lt_ref, tmp->ref_count); - - if (tmp->info.is_lt_ref) { - if (frm->info.is_lt_ref && frm->lt_idx == tmp->lt_idx) { - h264e_dpb_dbg_f("frm %3d lt idx %d replace frm %d dpb size %d\n", - frm->frm_cnt, tmp->lt_idx, tmp->frm_cnt, - dpb->dpb_size); - } - - continue; - } - - if (!tmp->marked_unref && !tmp->ref_count && - tmp != frm && tmp != ref && - tmp->info.temporal_id == frm->info.temporal_id) { - /* - * NOTE: In ffmpeg we can not mark reference frame to be - * non-reference frame. But in JM it is valid for mmco execution - * is after frame decoding. So for compatibility consideration - * we do NOT remove current reference frame from dpb. - * That is the reason for frm->gop_index != ref_index - * - * There is a case for the first frame of a new gop which is not - * first frame of the whole sequeuce. On this case we need to - * remove frame in previous gop - * - * Tsvc temporal hierarchy dependency require the reference - * must be marked non-reference frame by the frame with same - * temporal layer id. - */ - - dpb->unref[dpb->unref_cnt] = tmp; - dpb->unref_cnt++; - - tmp->marked_unref = 1; - h264e_dpb_dbg_f("frm %d T%d mark frm %d gop %d idx %d to be unreference dpb size %d\n", - frm->frm_cnt, frm->info.temporal_id, tmp->frm_cnt, tmp->gop_cnt, - tmp->gop_idx, dpb->dpb_size); - } - } - - h264e_dpb_dbg_f("dpb size %d unref_cnt %d\n", dpb->dpb_size, dpb->unref_cnt); -} - -void h264e_dpb_curr_ready(H264eDpb *dpb) -{ - H264eDpbFrm *frm = dpb->curr; - H264eDpbFrm *ref = h264e_dpb_get_refr(frm); - - h264e_dpb_dbg_f("curr %d gop %d idx %d refr -> frm %d gop %d idx %d ready\n", - frm->frm_cnt, frm->gop_cnt, frm->gop_idx, - ref->frm_cnt, ref->gop_cnt, ref->gop_idx, frm->info.is_non_ref); - - if (!frm->info.is_non_ref) { - frm->ref_status &= ~(REF_BY_RECN(frm->gop_idx)); - frm->ref_count--; - } - - if (!dpb->curr->info.is_non_ref) { - RK_S32 i; - RK_S32 insert = -1; - - dpb->dpb_size++; - - if (dpb->curr->info.is_lt_ref) { - // long-term ref swap and replace - for (i = dpb->max_st_cnt; i < dpb->curr_idx; i++) { - H264eDpbFrm *tmp = &dpb->frames[i]; - - // try found the swap frame with same lt_idx - if (!tmp->on_used) { - insert = i; - break; - } else { - if (tmp->lt_idx == frm->lt_idx) { - tmp->on_used = 0; - dpb->dpb_size--; - insert = i; - break; - } - } - } - } else { - // normal gop position swap and decrease ref_cnt - for (i = 0; i < dpb->max_st_cnt; i++) { - H264eDpbFrm *tmp = &dpb->frames[i]; - - if (!tmp->on_used) { - insert = i; - break; - } - } - } - - mpp_assert(insert >= 0); - - h264e_dpb_dbg_f("frm %d lt %d swap from %d to pos %d\n", - frm->frm_cnt, frm->info.is_lt_ref, - dpb->curr_idx, insert); - - h264e_dpb_frm_swap(dpb, insert, dpb->curr_idx); - } else - dpb->curr->on_used = 0; - - if (hal_h264e_debug & H264E_DBG_DPB) - h264e_dpb_dump_frms(dpb); - - dpb->curr = NULL; -} - diff --git a/mpp/hal/common/h264/h264e_slice.c b/mpp/hal/common/h264/h264e_slice.c deleted file mode 100644 index 200e85ba..00000000 --- a/mpp/hal/common/h264/h264e_slice.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright 2015 Rockchip Electronics Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "h264e_slice" - -#include - -#include "mpp_mem.h" -#include "mpp_bitread.h" - -#include "hal_h264e_com.h" - -#include "h264e_dpb.h" -#include "h264e_slice.h" -#include "h264e_stream.h" - -#define RD_LOG(bit, log, val) \ - do { \ - h264e_dpb_slice("%4d bit rd %s %d\n", bit.used_bits, log, val); \ - } while (0) - -RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size) -{ - BitReadCtx_t bit; - RK_S32 ret = 0; - RK_S32 val = 0; - RK_S32 bit_cnt = 0; - - mpp_set_bitread_ctx(&bit, p, size); - - ret |= mpp_read_longbits(&bit, 32, (RK_U32 *)&val); - RD_LOG(bit, "start code", val); - - ret |= mpp_read_bits(&bit, 1, &slice->forbidden_bit); - RD_LOG(bit, "forbidden_zero_bit", slice->forbidden_bit); - - ret |= mpp_read_bits(&bit, 2, &slice->nal_reference_idc); - RD_LOG(bit, "nal_ref_idc", slice->nal_reference_idc); - - ret |= mpp_read_bits(&bit, 5, &slice->nalu_type); - RD_LOG(bit, "nal_unit_type", slice->nalu_type); - - ret = mpp_read_ue(&bit, &slice->start_mb_nr); - RD_LOG(bit, "first_mb_nr", slice->start_mb_nr); - - ret |= mpp_read_ue(&bit, &slice->slice_type); - RD_LOG(bit, "slice_type", slice->slice_type); - - ret |= mpp_read_ue(&bit, &slice->pic_parameter_set_id); - RD_LOG(bit, "pic_parameter_set_id", slice->pic_parameter_set_id); - - ret |= mpp_read_bits(&bit, 16, &slice->frame_num); - RD_LOG(bit, "frame_num", slice->frame_num); - - slice->idr_flag = (slice->nalu_type == 5); - if (slice->idr_flag) { - ret |= mpp_read_ue(&bit, &slice->idr_pic_id); - RD_LOG(bit, "idr_pic_id", slice->idr_pic_id); - } - - // pic_order_cnt_type here - // vpu hardware is always zero. Just ignore - - // NOTE: Only P slice has num_ref_idx_override flag and ref_pic_list_modification flag - if (slice->slice_type == 0) { - ret |= mpp_read_bits(&bit, 1, &slice->num_ref_idx_override); - RD_LOG(bit, "num_ref_idx_override", slice->num_ref_idx_override); - - ret |= mpp_read_bits(&bit, 1, &slice->ref_pic_list_modification_flag); - RD_LOG(bit, "ref_pic_list_modification_flag", - slice->ref_pic_list_modification_flag); - } - - // NOTE: hardware is always zero - slice->ref_pic_list_modification_flag = 0; - - if (slice->nal_reference_idc) { - if (slice->idr_flag) { - ret |= mpp_read_bits(&bit, 1, &slice->no_output_of_prior_pics); - RD_LOG(bit, "no_output_of_prior_pics", - slice->no_output_of_prior_pics); - - ret |= mpp_read_bits(&bit, 1, &slice->long_term_reference_flag); - RD_LOG(bit, "long_term_reference_flag", - slice->long_term_reference_flag); - } else { - ret |= mpp_read_bits(&bit, 1, &slice->adaptive_ref_pic_buffering); - RD_LOG(bit, "adaptive_ref_pic_buffering", - slice->adaptive_ref_pic_buffering); - - mpp_assert(slice->adaptive_ref_pic_buffering == 0); - } - } - - if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { - ret |= mpp_read_ue(&bit, &slice->cabac_init_idc); - RD_LOG(bit, "cabac_init_idc", slice->cabac_init_idc); - } - - ret |= mpp_read_se(&bit, &slice->qp_delta); - RD_LOG(bit, "qp_delta", slice->qp_delta); - - ret |= mpp_read_ue(&bit, &slice->disable_deblocking_filter_idc); - RD_LOG(bit, "disable_deblocking_filter_idc", - slice->disable_deblocking_filter_idc); - - ret |= mpp_read_se(&bit, &slice->slice_alpha_c0_offset_div2); - RD_LOG(bit, "slice_alpha_c0_offset_div2", - slice->slice_alpha_c0_offset_div2); - - ret |= mpp_read_se(&bit, &slice->slice_beta_offset_div2); - RD_LOG(bit, "slice_beta_offset_div2", slice->slice_beta_offset_div2); - - h264e_dpb_slice("non-aligned used bit %d\n", bit.used_bits); - - if (slice->entropy_coding_mode) { - if (bit.num_remaining_bits_in_curr_byte_) { - RK_U32 tmp = bit.num_remaining_bits_in_curr_byte_; - - ret |= mpp_read_bits(&bit, tmp, &val); - RD_LOG(bit, "cabac aligned bit", tmp); - } - } - bit_cnt = bit.used_bits; - - h264e_dpb_slice("total aligned used bit %d\n", bit_cnt); - - return bit_cnt; -} - -#define WR_LOG(log, val) \ - do { \ - h264e_dpb_slice("B %2d b %d val %08x - %s %d\n", \ - s->byte_cnt, s->buffered_bits, s->byte_buffer, \ - log, val); \ - } while (0) - -RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size) -{ - H264eStream stream; - H264eStream *s = &stream; - RK_S32 i; - RK_S32 bitCnt = 0; - - h264e_stream_init(s, p, size); - - RK_U8 *tmp = (RK_U8 *)s->buffer; - - /* nal header */ - h264e_stream_put_bits(s, 0, 24, "start_code_zero"); - h264e_stream_put_bits(s, 1, 8, "start_code_one"); - WR_LOG("start_code", 1); - - h264e_stream_put_bits(s, 0, 1, "forbidden_bit"); - WR_LOG("forbidden_bit", 0); - - h264e_stream_put_bits(s, slice->nal_reference_idc, 2, "nal_reference_idc"); - WR_LOG("nal_reference_idc", slice->nal_reference_idc); - - h264e_stream_put_bits(s, slice->nalu_type, 5, "nalu_type"); - WR_LOG("nalu_type", slice->nalu_type); - - /* slice header */ - h264e_stream_write_ue(s, slice->start_mb_nr, "start_mb_nr"); - WR_LOG("first_mb_nr", slice->start_mb_nr); - - h264e_stream_write_ue(s, slice->slice_type, "slice_type"); - WR_LOG("slice_type", slice->slice_type); - - h264e_stream_write_ue(s, slice->pic_parameter_set_id, "pic_parameter_set_id"); - WR_LOG("pic_parameter_set_id", slice->pic_parameter_set_id); - - h264e_stream_put_bits_with_detect(s, slice->frame_num, 16, "frame_num"); - WR_LOG("frame_num", slice->frame_num); - - slice->idr_flag = (slice->nalu_type == 5); - if (slice->idr_flag) { - h264e_stream_write_ue(s, slice->idr_pic_id, "idr_pic_id"); - WR_LOG("idr_pic_id", slice->idr_pic_id); - } - - // Force to use poc type 0 here - { - RK_S32 pic_order_cnt_lsb = slice->pic_order_cnt_lsb; - RK_S32 max_poc_lsb = (1 << slice->log2_max_poc_lsb) - 1; - - - if (pic_order_cnt_lsb >= max_poc_lsb) - pic_order_cnt_lsb -= max_poc_lsb; - - h264e_stream_put_bits_with_detect(s, pic_order_cnt_lsb, 16, "pic_order_cnt_lsb"); - WR_LOG("pic_order_cnt_lsb", pic_order_cnt_lsb); - } - - if (slice->slice_type == 0) { - h264e_stream_put_bits_with_detect(s, slice->num_ref_idx_override, 1, - "num_ref_idx_override"); - WR_LOG("num_ref_idx_override", slice->num_ref_idx_override); - - h264e_stream_put_bits_with_detect(s, slice->ref_pic_list_modification_flag, 1, - "ref_pic_list_reordering"); - WR_LOG("ref_pic_list_reordering", slice->ref_pic_list_modification_flag); - } - - if (slice->ref_pic_list_modification_flag) { - h264e_stream_write_ue(s, slice->modification_of_pic_nums_idc, - "modification_of_pic_nums_idc"); - WR_LOG("modification_of_pic_nums_idc", slice->modification_of_pic_nums_idc); - - switch (slice->modification_of_pic_nums_idc) { - case 0 : - case 1 : { - h264e_stream_write_ue(s, slice->abs_diff_pic_num_minus1, - "abs_diff_pic_num_minus1"); - WR_LOG("abs_diff_pic_num_minus1", slice->abs_diff_pic_num_minus1); - } break; - case 2 : { - h264e_stream_write_ue(s, slice->long_term_pic_idx, - "long_term_pic_idx"); - WR_LOG("long_term_pic_idx", slice->long_term_pic_idx); - } break; - default : { - mpp_err_f("invalid modification_of_pic_nums_idc %d\n", - slice->modification_of_pic_nums_idc); - } break; - } - - h264e_stream_write_ue(s, 3, - "modification_of_pic_nums_idc"); - WR_LOG("modification_of_pic_nums_idc", 3); - } - - // NOTE: ignore nal ref idc here - h264e_dpb_mmco("nal_reference_idc %d idr_flag %d\n", - slice->nal_reference_idc, slice->idr_flag); - - if (slice->nal_reference_idc) { - if (slice->idr_flag) { - h264e_stream_put_bits_with_detect(s, slice->no_output_of_prior_pics, 1, - "no_output_of_prior_pics_flag"); - WR_LOG("no_output_of_prior_pics_flag", slice->no_output_of_prior_pics); - - h264e_stream_put_bits_with_detect(s, slice->long_term_reference_flag, 1, - "long_term_reference_flag"); - WR_LOG("long_term_reference_flag", slice->long_term_reference_flag); - - // clear long_term_reference_flag flag - slice->long_term_reference_flag = 0; - } else { - h264e_dpb_mmco("mmco count %d\n", slice->mmco_cnt); - - if (!list_empty(&slice->mmco)) { - H264eMmco *mmco, *n; - - h264e_stream_put_bits_with_detect(s, 1, 1, - "adaptive_ref_pic_marking_mode_flag"); - WR_LOG("adaptive_ref_pic_marking_mode_flag", 1); - - list_for_each_entry_safe(mmco, n, &slice->mmco, H264eMmco, list) { - h264e_dpb_mmco("del mmco %p at %p list %p %p\n", - mmco, slice, mmco->list.prev, mmco->list.next); - - list_del_init(&mmco->list); - - h264e_stream_write_ue(s, mmco->mmco, - "memory_management_control_operation"); - WR_LOG("memory_management_control_operation", mmco->mmco); - - switch (mmco->mmco) { - case 1 : { - h264e_stream_write_ue(s, mmco->difference_of_pic_nums_minus1, - "difference_of_pic_nums_minus1"); - WR_LOG("difference_of_pic_nums_minus1", - mmco->difference_of_pic_nums_minus1); - } break; - case 2 : { - h264e_stream_write_ue(s, mmco->long_term_pic_num , - "long_term_pic_num"); - WR_LOG("long_term_pic_num", - mmco->long_term_pic_num); - } break; - case 3 : { - h264e_stream_write_ue(s, mmco->difference_of_pic_nums_minus1, - "difference_of_pic_nums_minus1"); - WR_LOG("difference_of_pic_nums_minus1", - mmco->difference_of_pic_nums_minus1); - - h264e_stream_write_ue(s, mmco->long_term_frame_idx , - "long_term_frame_idx"); - WR_LOG("long_term_frame_idx", mmco->long_term_frame_idx); - } break; - case 4 : { - h264e_stream_write_ue(s, mmco->max_long_term_frame_idx_plus1, - "max_long_term_frame_idx_plus1"); - WR_LOG("max_long_term_frame_idx_plus1", - mmco->max_long_term_frame_idx_plus1); - } break; - case 5 : { - } break; - case 6 : { - h264e_stream_write_ue(s, mmco->long_term_frame_idx, - "long_term_frame_idx"); - WR_LOG("long_term_frame_idx", mmco->long_term_frame_idx); - } break; - default : { - mpp_err_f("invalid mmco %d\n", mmco->mmco); - } break; - } - - h264e_dpb_mmco("free %p\n", mmco); - MPP_FREE(mmco); - - slice->mmco_cnt--; - } - - h264e_stream_write_ue(s, 0, - "memory_management_control_operation"); - } else { - h264e_stream_put_bits_with_detect(s, 0, 1, - "adaptive_ref_pic_marking_mode_flag"); - WR_LOG("adaptive_ref_pic_marking_mode_flag", 0); - } - - mpp_assert(slice->mmco_cnt == 0); - } - } - - if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { - h264e_stream_write_ue(s, slice->cabac_init_idc, "cabac_init_idc"); - WR_LOG("cabac_init_idc", slice->cabac_init_idc); - } - - h264e_stream_write_se(s, slice->qp_delta, "qp_delta"); - WR_LOG("qp_delta", slice->qp_delta); - - h264e_stream_write_ue(s, 0, "disable_deblocking_filter_idc"); - WR_LOG("disable_deblocking_filter_idc", slice->disable_deblocking_filter_idc); - - h264e_stream_write_se(s, 0, "slice_alpha_c0_offset_div2"); - WR_LOG("slice_alpha_c0_offset_div2", slice->slice_alpha_c0_offset_div2); - - h264e_stream_write_se(s, 0, "slice_beta_offset_div2"); - WR_LOG("slice_beta_offset_div2", slice->slice_beta_offset_div2); - - bitCnt = s->buffered_bits + s->byte_cnt * 8; - - if (s->buffered_bits) { - // NOTE: only have aligned bit on cabac mode but cavlc also need to write byte cache to memory - RK_S32 left = (8 - s->buffered_bits); - for (i = 0; i < left; i++) { - h264e_stream_put_bits_with_detect(s, 1, 1, "align_bit"); - WR_LOG("align_bit", 1); - } - } - - // update on cabac mode - if (slice->entropy_coding_mode) - bitCnt = s->buffered_bits + s->byte_cnt * 8; - - WR_LOG("all done", 0); - - RK_S32 pos = 0; - char log[256]; - - pos = sprintf(log + pos, "sw stream: "); - for (i = 0; i < 16; i ++) { - pos += sprintf(log + pos, "%02x ", tmp[i]); - } - pos += sprintf(log + pos, "\n"); - h264e_dpb_slice(log); - - return bitCnt; -} - -H264eMmco *h264e_slice_gen_mmco(RK_S32 id, RK_S32 arg0, RK_S32 arg1) -{ - H264eMmco *mmco = mpp_malloc(H264eMmco, 1); - if (NULL == mmco) { - mpp_err_f("failed to malloc mmco structure\n"); - return NULL; - } - mmco->mmco = id; - switch (id) { - case 0 : { - } break; - case 1 : { - mmco->difference_of_pic_nums_minus1 = arg0; - } break; - case 2 : { - mmco->long_term_pic_num = arg0; - } break; - case 3 : { - mmco->difference_of_pic_nums_minus1 = arg0; - mmco->long_term_pic_num = arg1; - } break; - case 4 : { - mmco->max_long_term_frame_idx_plus1 = arg0; - } break; - case 5 : { - } break; - case 6 : { - mmco->long_term_frame_idx = arg0; - } break; - default : { - mpp_err_f("invalid mmco %d\n", id); - } break; - } - - INIT_LIST_HEAD(&mmco->list); - - h264e_dpb_mmco("gen mmco %p\n", mmco); - - return mmco; -} - -MPP_RET h264e_slice_add_mmco(H264eSlice *slice, H264eMmco *mmco) -{ - list_add_tail(&mmco->list, &slice->mmco); - slice->mmco_cnt++; - - h264e_dpb_mmco("add mmco %p to %p list %p %p\n", - mmco, slice, mmco->list.prev, mmco->list.next); - - return MPP_OK; -} - -MPP_RET h264e_slice_update(H264eSlice *slice, void *p) -{ - H264eDpb *dpb = (H264eDpb *)p; - H264eDpbFrm *frm = &dpb->frames[dpb->curr_idx]; - - slice->nal_reference_idc = !frm->info.is_non_ref; - h264e_dpb_slice("gop %d nal_reference_idc %d is_non_ref %d\n", - frm->gop_idx, slice->nal_reference_idc, - frm->info.is_non_ref); - - // update reorder according to current dpb status - if (dpb->need_reorder) { - H264eDpbFrm *ref = h264e_dpb_get_refr(frm); - - h264e_dpb_slice("reorder to frm %d gop %d idx %d\n", - ref->frm_cnt, ref->gop_cnt, ref->gop_idx); - - slice->ref_pic_list_modification_flag = 1; - mpp_assert(!ref->info.is_non_ref); - - slice->modification_of_pic_nums_idc = (ref->info.is_lt_ref) ? (2) : (0); - if (ref->info.is_lt_ref) { - slice->modification_of_pic_nums_idc = 2; - slice->long_term_pic_idx = ref->lt_idx; - - h264e_dpb_slice("reorder lt idx %d \n", slice->long_term_pic_idx); - } else { - /* Only support ref pic num less than current pic num case */ - slice->modification_of_pic_nums_idc = 0; - slice->abs_diff_pic_num_minus1 = MPP_ABS(frm->frame_num - ref->frame_num) - 1; - - h264e_dpb_slice("reorder st cur %d ref %d diff - 1 %d\n", - frm->frame_num, ref->frame_num, - slice->abs_diff_pic_num_minus1); - } - - dpb->need_reorder = 0; - } - - // remove frame if they are not used any more - // NOTE: only add marking on reference frame - INIT_LIST_HEAD(&slice->mmco); - slice->mmco_cnt = 0; - - if (!frm->info.is_non_ref) { - H264eMmco *mmco = NULL; - - if (frm->info.is_lt_ref) { - if (frm->info.is_idr) { - // IDR long-term is directly flag - slice->long_term_reference_flag = 1; - } else { - if (dpb->next_max_lt_idx != dpb->curr_max_lt_idx) { - RK_S32 max_lt_idx_p1 = dpb->next_max_lt_idx + 1; - - mmco = h264e_slice_gen_mmco(4, max_lt_idx_p1, 0); - h264e_dpb_mmco("add mmco 4 %d\n", max_lt_idx_p1); - - h264e_slice_add_mmco(slice, mmco); - dpb->curr_max_lt_idx = dpb->next_max_lt_idx; - } - - mmco = h264e_slice_gen_mmco(6, frm->lt_idx, 0); - h264e_dpb_mmco("add mmco 6 %d\n", frm->lt_idx); - h264e_slice_add_mmco(slice, mmco); - } - } - - if (dpb->unref_cnt) { - RK_U32 i = 0; - RK_S32 cur_frm_num = frm->frame_num; - - for (i = 0; i < dpb->unref_cnt; i++) { - H264eDpbFrm *unref = dpb->unref[i]; - RK_S32 unref_frm_num = unref->frame_num; - - if (!unref->info.is_lt_ref) { - RK_S32 difference_of_pic_nums_minus1 = MPP_ABS(unref_frm_num - cur_frm_num) - 1; - - h264e_dpb_mmco("cur_frm_num %d unref_frm_num %d\n", cur_frm_num, unref_frm_num); - h264e_dpb_mmco("add mmco st 1 %d\n", difference_of_pic_nums_minus1); - - mmco = h264e_slice_gen_mmco(1, difference_of_pic_nums_minus1, 0); - } else { - h264e_dpb_mmco("add mmco lt 2 %d\n", unref->lt_idx); - - mmco = h264e_slice_gen_mmco(2, unref->lt_idx, 0); - } - h264e_slice_add_mmco(slice, mmco); - - /* update frame status here */ - unref->marked_unref = 0; - unref->info.is_non_ref = 1; - unref->on_used = 0; - - h264e_dpb_mmco("set frm %d gop %d idx %d to not used\n", - unref->frm_cnt, unref->gop_cnt, unref->gop_idx); - - // decrease dpb size here for sometime frame will be remove later - dpb->dpb_size--; - } - dpb->unref_cnt = 0; - } - - if (hal_h264e_debug & H264E_DBG_SLICE) - h264e_dpb_dump_frms(dpb); - } - - return MPP_OK; -} - -static RK_S32 frame_no = 0; - -RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, RK_S32 src_size) -{ - RK_S32 dst_byte = dst_bit / 8; - RK_S32 src_byte = src_bit / 8; - RK_S32 dst_bit_r = dst_bit & 7; - RK_S32 src_bit_r = src_bit & 7; - RK_S32 src_len = src_size - src_byte; - RK_S32 diff_len = 0; - - if (src_bit_r == 0 && dst_bit_r == 0) { - // direct copy - if (hal_h264e_debug & H264E_DBG_SLICE) - mpp_log_f("direct copy %p -> %p %d\n", src, dst, src_len); - - memcpy(dst + dst_byte, src + src_byte, src_len); - return diff_len; - } - - RK_U8 *psrc = src + src_byte; - RK_U8 *pdst = dst + dst_byte; - - RK_U16 tmp16a, tmp16b, tmp16c, last_tmp; - RK_U8 tmp0, tmp1; - RK_U32 loop = src_len; - RK_U32 i = 0; - RK_U32 src_zero_cnt = 0; - RK_U32 dst_zero_cnt = 0; - RK_U32 dst_len = 0; - - if (hal_h264e_debug & H264E_DBG_SLICE) - mpp_log("bit [%d %d] [%d %d] loop %d\n", src_bit, dst_bit, - src_bit_r, dst_bit_r, loop); - - last_tmp = pdst[0] >> (8 - dst_bit_r) << (8 - dst_bit_r); - - for (i = 0; i < loop; i++) { - if (psrc[0] == 0) { - src_zero_cnt++; - } else { - src_zero_cnt = 0; - } - - // tmp0 tmp1 is next two non-aligned bytes from src - tmp0 = psrc[0]; - tmp1 = (i < loop - 1) ? psrc[1] : 0; - - if (src_zero_cnt >= 2 && tmp1 == 3) { - if (hal_h264e_debug & H264E_DBG_SLICE) - mpp_log("found 03 at src pos %d %02x %02x %02x %02x %02x %02x %02x %02x\n", - i, psrc[-2], psrc[-1], psrc[0], psrc[1], psrc[2], - psrc[3], psrc[4], psrc[5]); - - psrc++; - i++; - tmp1 = psrc[1]; - src_zero_cnt = 0; - diff_len--; - } - // get U16 data - tmp16a = ((RK_U16)tmp0 << 8) | (RK_U16)tmp1; - - if (src_bit_r) { - tmp16b = tmp16a << src_bit_r; - } else { - tmp16b = tmp16a; - } - - if (dst_bit_r) - tmp16c = tmp16b >> dst_bit_r | (last_tmp >> (8 - dst_bit_r) << (16 - dst_bit_r)); - else - tmp16c = tmp16b; - - pdst[0] = (tmp16c >> 8) & 0xFF; - pdst[1] = tmp16c & 0xFF; - - if (hal_h264e_debug & H264E_DBG_SLICE) { - if (i < 10) { - mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); - } - if (i >= loop - 10) { - mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); - } - } - - if (dst_zero_cnt == 2 && pdst[0] <= 0x3) { - if (hal_h264e_debug & H264E_DBG_SLICE) - mpp_log("found 03 at dst frame %d pos %d\n", frame_no, dst_len); - - pdst[2] = pdst[1]; - pdst[1] = pdst[0]; - pdst[0] = 0x3; - pdst++; - diff_len++; - dst_len++; - dst_zero_cnt = 0; - } - - if (pdst[0] == 0) - dst_zero_cnt++; - else - dst_zero_cnt = 0; - - last_tmp = tmp16c; - - psrc++; - pdst++; - dst_len++; - } - - frame_no++; - - return diff_len; -} diff --git a/mpp/hal/common/h264/h264e_slice.h b/mpp/hal/common/h264/h264e_slice.h deleted file mode 100644 index feb62539..00000000 --- a/mpp/hal/common/h264/h264e_slice.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2015 Rockchip Electronics Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __H264E_SLICE_H__ -#define __H264E_SLICE_H__ - -#include "rk_type.h" -#include "mpp_err.h" -#include "mpp_list.h" - -/* - * For H.264 encoder slice header process. - * Remove some syntax that encoder not supported. - * Field, mbaff, B slice are not supported yet. - */ - -#define MAX_H264E_REFS_CNT 8 - -typedef struct H264eMmco_t H264eMmco; -typedef struct H264eSlice_t H264eSlice; - -typedef struct H264eMmco_t { - struct list_head list; - - /* - * mmco (Memory management control operation) value - * 0 - End memory_management_control_operation syntax element loop - * 1 - Mark a short-term reference picture as "unused for reference" - * 2 - Mark a long-term reference picture as "unused for reference" - * 3 - Mark a short-term reference picture as "used for long-term - * reference" and assign a long-term frame index to it - * 4 - Specify the maximum long-term frame index and mark all long-term - * reference pictures having long-term frame indices greater than - * the maximum value as "unused for reference" - * 5 - Mark all reference pictures as "unused for reference" and set the - * MaxLongTermFrameIdx variable to "no long-term frame indices" - * 6 - Mark the current picture as "used for long-term reference" and - * assign a long-term frame index to it - */ - RK_S32 mmco; - RK_S32 difference_of_pic_nums_minus1; // for MMCO 1 & 3 - RK_S32 long_term_pic_num; // for MMCO 2 - RK_S32 long_term_frame_idx; // for MMCO 3 & 6 - RK_S32 max_long_term_frame_idx_plus1; // for MMCO 4 -} H264eMmco; - -typedef struct H264eSlice_t { - /* Input parameter before reading */ - RK_U32 max_num_ref_frames; - RK_U32 entropy_coding_mode; - RK_S32 log2_max_poc_lsb; - - /* Nal parameters */ - RK_S32 forbidden_bit; - RK_S32 nal_reference_idc; - RK_S32 nalu_type; - - /* Unchanged parameters */ - RK_U32 start_mb_nr; - RK_U32 slice_type; - RK_U32 pic_parameter_set_id; - RK_S32 frame_num; - RK_S32 num_ref_idx_override; - RK_S32 qp_delta; - RK_U32 cabac_init_idc; - RK_U32 disable_deblocking_filter_idc; - RK_S32 slice_alpha_c0_offset_div2; - RK_S32 slice_beta_offset_div2; - - RK_S32 idr_flag; - RK_U32 idr_pic_id; - /* for poc mode 0 */ - RK_S32 pic_order_cnt_lsb; - RK_S32 num_ref_idx_active; - /* idr mmco flag */ - RK_S32 no_output_of_prior_pics; - RK_S32 long_term_reference_flag; - - /* Changable parameters */ - RK_S32 adaptive_ref_pic_buffering; - - /* reorder parameter */ - RK_S32 ref_pic_list_modification_flag; - RK_S32 modification_of_pic_nums_idc; - RK_S32 abs_diff_pic_num_minus1; - RK_S32 long_term_pic_idx; - RK_S32 abs_diff_view_idx_minus1; - - /* mmco parameter */ - struct list_head mmco; - RK_S32 mmco_cnt; - - /* slice modification infomation */ - void * hw_buf; - void * sw_buf; - RK_S32 hw_length; - RK_S32 sw_length; -} H264eSlice; - -#ifdef __cplusplus -extern "C" { -#endif - -RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size); -RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size); -RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, - RK_S32 src_size); -MPP_RET h264e_slice_update(H264eSlice *slice, void *p); - -H264eMmco *h264e_slice_gen_mmco(RK_S32 id, RK_S32 arg0, RK_S32 arg1); -MPP_RET h264e_slice_add_mmco(H264eSlice *slice, H264eMmco *mmco); - -#ifdef __cplusplus -} -#endif - -#endif /* __H264E_SLICE_H__ */