From ff6032ed80c25ce636f8128e3b0948a764a6b425 Mon Sep 17 00:00:00 2001 From: "xiaoxu.chen" Date: Fri, 5 Jan 2024 10:17:41 +0800 Subject: [PATCH] fix[h265e]: Adapter RK3528 when encoding P frame skip 1.Correct encoding P skip frame on RK3528. For Rk3528, the maxCuSize is 32, which is different to other Chips that maxCUSize of them is 64. So we need to treat them differentlly. 2.The fixed parameters in the original process have been changed to vary based on maxCUSize. 3.Fix m_cuDepth problem, which value was incorrect. Change-Id: If4ba25d4d221af64d17c4991a708756ab5bc12d9 Signed-off-by: xiaoxu.chen --- mpp/codec/enc/h265/h265e_slice.c | 115 ++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/mpp/codec/enc/h265/h265e_slice.c b/mpp/codec/enc/h265/h265e_slice.c index 117ce614..44dc8643 100644 --- a/mpp/codec/enc/h265/h265e_slice.c +++ b/mpp/codec/enc/h265/h265e_slice.c @@ -584,7 +584,6 @@ static void encode_cu(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, Data h265e_dbg_skip("EncodeCU depth %d, abs_part_idx %d", depth, abs_part_idx); if ((rpelx < sps->m_picWidthInLumaSamples) && (bpely < sps->m_picHeightInLumaSamples)) { - h265e_dbg_skip("code_split_flag in depth %d", depth); code_split_flag(slice, abs_part_idx, depth, cu); } else { @@ -595,7 +594,8 @@ static void encode_cu(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, Data h265e_dbg_skip("m_cuDepth[%d] = %d maxCUDepth %d, m_addCUDepth %d", abs_part_idx, cu->m_cuDepth[sps->zscan2raster[abs_part_idx]], sps->m_maxCUDepth, sps->m_addCUDepth); if ((depth < cu->m_cuDepth[sps->zscan2raster[abs_part_idx]] && (depth < (sps->m_maxCUDepth - sps->m_addCUDepth))) || bBoundary) { - RK_U32 qNumParts = (256 >> (depth << 1)) >> 2; + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_U32 qNumParts = (numPartions >> (depth << 1)) >> 2; RK_U32 partUnitIdx = 0; for (partUnitIdx = 0; partUnitIdx < 4; partUnitIdx++, abs_part_idx += qNumParts) { @@ -616,93 +616,86 @@ static void encode_cu(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, Data return; } -static void proc_cu8(DataCu *cu, RK_U32 pos_x, RK_U32 pos_y) +static void proc_cu8(DataCu *cu, RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) { - RK_S32 nSize = 8; - RK_S32 nSubPart = nSize * nSize / 4 / 4; - RK_S32 puIdx = pos_x / 8 + pos_y / 8 * 8; - h265e_dbg_skip("8 ctu puIdx %d no need split", puIdx); - memset(cu->m_cuDepth + puIdx * nSubPart, 3, nSubPart); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); } -static void proc_cu16(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y) +static void proc_cu16(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y, RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) { RK_U32 m; H265eSps *sps = slice->m_sps; - RK_S32 nSize = 16; - RK_S32 nSubPart = nSize * nSize / 4 / 4; - RK_S32 puIdx = pos_x / 16 + pos_y / 16 * 4; - RK_U32 cu_x_1, cu_y_1; + RK_S32 newPuIdx; h265e_dbg_skip("cu 16 pos_x %d pos_y %d", pos_x, pos_y); if ((cu->pixelX + pos_x + 15 < sps->m_picWidthInLumaSamples) && (cu->pixelY + pos_y + 15 < sps->m_picHeightInLumaSamples)) { h265e_dbg_skip("16 ctu puIdx %d no need split", puIdx); - memset(cu->m_cuDepth + puIdx * nSubPart, 2, nSubPart); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); return; } else if ((cu->pixelX + pos_x >= sps->m_picWidthInLumaSamples) || (cu->pixelY + pos_y >= sps->m_picHeightInLumaSamples)) { h265e_dbg_skip("16 ctu puIdx %d out of pic", puIdx); - memset(cu->m_cuDepth + puIdx * nSubPart, 2, nSubPart); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); return; } for (m = 0; m < 4; m ++) { - cu_x_1 = pos_x + (m & 1) * (nSize >> 1); - cu_y_1 = pos_y + (m >> 1) * (nSize >> 1); - - proc_cu8(cu, cu_x_1, cu_y_1); + newPuIdx = puIdx * 4 + m; + proc_cu8(cu, nSubPart / 4, cuDepth + 1, newPuIdx); } } -static void proc_cu32(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y) +static void proc_cu32(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y, RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) { RK_U32 m; H265eSps *sps = slice->m_sps; RK_S32 nSize = 32; - RK_S32 nSubPart = nSize * nSize / 4 / 4; - RK_S32 puIdx = pos_x / 32 + pos_y / 32 * 2; RK_U32 cu_x_1, cu_y_1; + RK_S32 newPuIdx; h265e_dbg_skip("cu 32 pos_x %d pos_y %d", pos_x, pos_y); if ((cu->pixelX + pos_x + 31 < sps->m_picWidthInLumaSamples) && (cu->pixelY + pos_y + 31 < sps->m_picHeightInLumaSamples)) { h265e_dbg_skip("32 ctu puIdx %d no need split", puIdx); - memset(cu->m_cuDepth + puIdx * nSubPart, 1, nSubPart); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); return; } else if ((cu->pixelX + pos_x >= sps->m_picWidthInLumaSamples) || (cu->pixelY + pos_y >= sps->m_picHeightInLumaSamples)) { h265e_dbg_skip("32 ctu puIdx %d out of pic", puIdx); - memset(cu->m_cuDepth + puIdx * nSubPart, 1, nSubPart); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); return; } for (m = 0; m < 4; m ++) { cu_x_1 = pos_x + (m & 1) * (nSize >> 1); cu_y_1 = pos_y + (m >> 1) * (nSize >> 1); - - proc_cu16(slice, cu, cu_x_1, cu_y_1); + newPuIdx = puIdx * 4 + m; + proc_cu16(slice, cu, cu_x_1, cu_y_1, nSubPart / 4, cuDepth + 1, newPuIdx); } } -static void proc_ctu(H265eSlice *slice, DataCu *cu) +static void proc_ctu64(H265eSlice *slice, DataCu *cu) { H265eSps *sps = slice->m_sps; RK_U32 k, m; - RK_U32 cu_x_1, cu_y_1, m_nCtuSize = 64; + RK_U32 cu_x_1, cu_y_1; + RK_U32 m_nCtuSize = sps->m_maxCUSize; RK_U32 lpelx = cu->pixelX; - RK_U32 rpelx = lpelx + 63; + RK_U32 rpelx = lpelx + m_nCtuSize - 1; RK_U32 tpely = cu->pixelY; - RK_U32 bpely = tpely + 63; + RK_U32 bpely = tpely + m_nCtuSize - 1; + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_S32 cuDepth = 0; - for (k = 0; k < 256; k++) { + for (k = 0; k < numPartions; k++) { cu->m_cuDepth[k] = 0; - cu->m_cuSize[k] = 64; + cu->m_cuSize[k] = m_nCtuSize; } if ((rpelx < sps->m_picWidthInLumaSamples) && (bpely < sps->m_picHeightInLumaSamples)) return; @@ -710,10 +703,10 @@ static void proc_ctu(H265eSlice *slice, DataCu *cu) for (m = 0; m < 4; m ++) { cu_x_1 = (m & 1) * (m_nCtuSize >> 1); cu_y_1 = (m >> 1) * (m_nCtuSize >> 1); - proc_cu32(slice, cu, cu_x_1, cu_y_1); + proc_cu32(slice, cu, cu_x_1, cu_y_1, numPartions / 4, cuDepth + 1, m); } - for (k = 0; k < 256; k++) { + for (k = 0; k < numPartions; k++) { switch (cu->m_cuDepth[k]) { case 0: cu->m_cuSize[k] = 64; break; case 1: cu->m_cuSize[k] = 32; break; @@ -745,17 +738,51 @@ static void h265e_write_algin(MppWriteCtx *bitIf) h265e_dbg_func("leave\n"); } +static void proc_ctu32(H265eSlice *slice, DataCu *cu) +{ + H265eSps *sps = slice->m_sps; + RK_U32 k, m; + RK_U32 cu_x_1, cu_y_1; + RK_U32 m_nCtuSize = sps->m_maxCUSize; + RK_U32 lpelx = cu->pixelX; + RK_U32 rpelx = lpelx + m_nCtuSize - 1; + RK_U32 tpely = cu->pixelY; + RK_U32 bpely = tpely + m_nCtuSize - 1; + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_S32 cuDepth = 0; + + for (k = 0; k < numPartions; k++) { + cu->m_cuDepth[k] = 0; + cu->m_cuSize[k] = m_nCtuSize; + } + if ((rpelx < sps->m_picWidthInLumaSamples) && (bpely < sps->m_picHeightInLumaSamples)) + return; + + for (m = 0; m < 4; m ++) { + cu_x_1 = (m & 1) * (m_nCtuSize >> 1); + cu_y_1 = (m >> 1) * (m_nCtuSize >> 1); + proc_cu16(slice, cu, cu_x_1, cu_y_1, numPartions / 4, cuDepth + 1, m); + } + + for (k = 0; k < numPartions; k++) { + switch (cu->m_cuDepth[k]) { + case 0: cu->m_cuSize[k] = 32; break; + case 1: cu->m_cuSize[k] = 16; break; + case 2: cu->m_cuSize[k] = 8; break; + } + } +} RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_S32 len) { - + void (*proc_ctu)(H265eSlice *, DataCu *); MppWriteCtx bitIf; H265eCtx *p = (H265eCtx *)ctx; H265eSps *sps = &p->sps; H265eCabacCtx *cabac_ctx = &slice->m_cabac; h265e_dbg_func("enter\n"); - RK_U32 mb_wd = ((sps->m_picWidthInLumaSamples + 63) >> 6); - RK_U32 mb_h = ((sps->m_picHeightInLumaSamples + 63) >> 6); + RK_U32 mb_wd = (sps->m_picWidthInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; + RK_U32 mb_h = (sps->m_picHeightInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; RK_U32 cu_cnt; RK_U32 offset_x = 0; RK_U32 offset_y = 0; @@ -765,6 +792,14 @@ RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_ mpp_err("buf or size no set"); return MPP_NOK; } + + if (sps->m_maxCUSize == 32) + /* rk3528 maxCUSize[32] depth[3], other chips maxCUSize[64] depth[4], + So special handling is required */ + proc_ctu = proc_ctu32; + else + proc_ctu = proc_ctu64; + mpp_writer_init(&bitIf, buf, len); h265e_write_nal(&bitIf); h265e_code_slice_header(slice, &bitIf); @@ -782,10 +817,10 @@ RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_ proc_ctu(slice, &cu); encode_cu(slice, 0, 0, &cu); h265e_cabac_encodeBinTrm(cabac_ctx, 0); - offset_x += 64; + offset_x += sps->m_maxCUSize; if (offset_x >= sps->m_picWidthInLumaSamples) { offset_x = 0; - offset_y += 64; + offset_y += sps->m_maxCUSize; } } /* The last CTU handled independently, reducing the cost */ @@ -800,5 +835,3 @@ RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_ h265e_dbg_func("leave\n"); return mpp_writer_bytes(&bitIf); } - -