[h265e_v2]: Support sw encoder skip frame

Change-Id: Icc9735087028fad2ca28070de8fe829e795ccadb
Signed-off-by: sayon.chen <sayon.chen@rock-chips.com>
This commit is contained in:
sayon.chen
2020-09-15 19:43:54 +08:00
committed by Herman Chen
parent 4c625f0e3c
commit 4db63464e8
11 changed files with 1250 additions and 51 deletions

View File

@@ -10,6 +10,7 @@ add_library(${CODEC_H265E} STATIC
h265e_header_gen.c
h265e_stream.c
h265e_syntax.c
h265e_enctropy.c
)
target_link_libraries(${CODEC_H265E} mpp_base)

View File

@@ -222,11 +222,9 @@ static MPP_RET h265e_proc_dpb(void *ctx, HalEncTask *task)
EncRcTask *rc_task = task->rc_task;
EncCpbStatus *cpb = &task->rc_task->cpb;
h265e_dbg_func("enter\n");
h265e_dpb_bakup(p->dpb, &p->dpb_bak);
h265e_dpb_proc_cpb(p->dpb, cpb);
h265e_dpb_get_curr(p->dpb);
p->slice = p->dpb->curr->slice;
h265e_slice_init(ctx, p->slice, cpb->curr);
h265e_slice_init(ctx, cpb->curr);
h265e_dpb_build_list(p->dpb, cpb);
rc_task->frm = p->dpb->curr->status;
@@ -258,6 +256,27 @@ static MPP_RET h265e_proc_hal(void *ctx, HalEncTask *task)
return MPP_OK;
}
static MPP_RET h265e_proc_enc_skip(void *ctx, HalEncTask *task)
{
H265eCtx *p = (H265eCtx *)ctx;
MppPacket pkt = task->packet;
RK_U8 *ptr = mpp_packet_get_pos(pkt);
RK_U32 offset = mpp_packet_get_length(pkt);
RK_U32 len = mpp_packet_get_size(pkt) - offset;
RK_U32 new_length = 0;
h265e_dbg_func("enter\n");
ptr += offset;
p->slice->m_sliceQp = task->rc_task->info.quality_target;
new_length = h265e_code_slice_skip_frame(ctx, p->slice, ptr, len);
task->length = new_length;
task->rc_task->info.bit_real = 8 * new_length;
///mpp_packet_set_length(pkt, offset + new_length);
h265e_dbg_func("leave\n");
return MPP_OK;
}
static MPP_RET h265e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16],
const void *data, RK_S32 size)
{
@@ -619,5 +638,5 @@ const EncImplApi api_h265e = {
h265e_proc_dpb,
h265e_proc_hal,
h265e_add_sei,
NULL,
h265e_proc_enc_skip,
};

View File

@@ -37,6 +37,7 @@
#define H265E_DBG_SLICE (0x00000100)
#define H265E_DBG_HEADER (0x00000200)
#define H265E_DBG_API (0x00000400)
#define H265E_DBG_SKIP (0x00000800)
#define H265E_PS_BUF_SIZE 512
@@ -56,6 +57,8 @@ extern RK_U32 h265e_debug;
#define h265e_dbg_ps(fmt, ...) h265e_dbg(H265E_DBG_PS, fmt, ## __VA_ARGS__)
#define h265e_dbg_dpb(fmt, ...) h265e_dbg(H265E_DBG_DPB, fmt, ## __VA_ARGS__)
#define h265e_dbg_slice(fmt, ...) h265e_dbg(H265E_DBG_SLICE, fmt, ## __VA_ARGS__)
#define h265e_dbg_skip(fmt, ...) h265e_dbg(H265E_DBG_SKIP, fmt, ## __VA_ARGS__)
#define h265e_dbg_dpb_ref(fmt, ...) h265e_dbg(H265E_DBG_DPB_REF, fmt, ## __VA_ARGS__)
typedef struct H265eCtx_t {
@@ -71,7 +74,6 @@ typedef struct H265eCtx_t {
H265ePps pps;
H265eSlice *slice;
H265eDpb *dpb;
H265eDpb dpb_bak;
RK_U32 plt_flag;
void *extra_info;

View File

@@ -0,0 +1,64 @@
/*
* 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 __H265E_CONTEXT_TABLE_H__
#define __H265E_CONTEXT_TABLE_H__
#include "rk_type.h"
#define NUM_SPLIT_FLAG_CTX 3 ///< number of context models for split flag
#define NUM_SKIP_FLAG_CTX 3 ///< number of context models for skip flag
#define NUM_MERGE_FLAG_EXT_CTX 1 ///< number of context models for merge flag of merge extended
#define NUM_MERGE_IDX_EXT_CTX 1 ///< number of context models for merge index of merge extended
#define OFF_SPLIT_FLAG_CTX (0)
#define OFF_SKIP_FLAG_CTX (OFF_SPLIT_FLAG_CTX + NUM_SPLIT_FLAG_CTX)//3
#define OFF_MERGE_FLAG_EXT_CTX (OFF_SKIP_FLAG_CTX + NUM_SKIP_FLAG_CTX)//3
#define OFF_MERGE_IDX_EXT_CTX (OFF_MERGE_FLAG_EXT_CTX + NUM_MERGE_FLAG_EXT_CTX)//1
#define MAX_OFF_CTX_MOD (OFF_MERGE_IDX_EXT_CTX + NUM_MERGE_IDX_EXT_CTX)
#define CNU 154 ///< dummy initialization value for unused context models 'Context model Not Used'
extern const uint8_t g_nextState[128][2];
#define sbacGetMps(S) ((S) & 1)
#define sbacGetState(S) ((S) >> 1)
#define sbacNext(S, V) (g_nextState[(S)][(V)])
static const RK_U8 INIT_SPLIT_FLAG[3][NUM_SPLIT_FLAG_CTX] = {
{ 107, 139, 126, },
{ 107, 139, 126, },
{ 139, 141, 157, },
};
static const RK_U8 INIT_SKIP_FLAG[3][NUM_SKIP_FLAG_CTX] = {
{ 197, 185, 201, },
{ 197, 185, 201, },
{ CNU, CNU, CNU, },
};
static const RK_U8 INIT_MERGE_FLAG_EXT[3][NUM_MERGE_FLAG_EXT_CTX] = {
{ 154, },
{ 110, },
{ CNU, },
};
static const RK_U8 INIT_MERGE_IDX_EXT[3][NUM_MERGE_IDX_EXT_CTX] = {
{ 137, },
{ 122, },
{ CNU, },
};
#endif /* __H265E_CONTEXT_TABLE_H__ */

View File

@@ -89,18 +89,6 @@ MPP_RET h265e_dpb_init_curr(H265eDpb *dpb, H265eDpbFrm *frm)
return MPP_OK;
}
MPP_RET h265e_dpb_bakup(H265eDpb *dpb, H265eDpb *dpb_bak)
{
memcpy(dpb_bak, dpb, sizeof(H265eDpb));
return MPP_OK;
}
MPP_RET h265e_dpb_recover(H265eDpb *dpb, H265eDpb *dpb_bak)
{
memcpy(dpb, dpb_bak, sizeof(H265eDpb));
return MPP_OK;
}
MPP_RET h265e_dpb_get_curr(H265eDpb *dpb)
{
RK_U32 i;
@@ -190,7 +178,7 @@ MPP_RET h265e_dpb_deinit(H265eDpb *dpb)
return MPP_OK;
}
enum NALUnitType getNalUnitType(H265eDpb *dpb, int curPOC)
enum NALUnitType get_nal_unit_type(H265eDpb *dpb, int curPOC)
{
h265e_dbg_func("enter\n");
if (curPOC == 0) {
@@ -463,6 +451,31 @@ void h265e_dpb_arrange_lt_rps(H265eDpb *dpb, H265eSlice *slice)
h265e_dbg_func("leave\n");
}
static H265eDpbFrm *h265e_find_cpb_in_dpb(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm)
{
RK_S32 seq_idx = frm->seq_idx;
RK_S32 i;
if (!frm->valid)
return NULL;
h265e_dbg_dpb("frm %d start finding slot \n", frm->seq_idx);
for (i = 0; i < cnt; i++) {
if (!frms[i].inited) {
continue;
}
EncFrmStatus *p = &frms[i].status;
if (p->valid && p->seq_idx == seq_idx) {
h265e_dbg_dpb("frm %d match slot %d valid %d\n",
p->seq_idx, i, p->valid);
return &frms[i];
}
}
mpp_err_f("can not find match frm %d\n", seq_idx);
return NULL;
}
static H265eDpbFrm *h265e_find_cpb_frame(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm)
{
RK_S32 seq_idx = frm->seq_idx;
@@ -508,6 +521,7 @@ static MPP_RET h265e_check_frame_cpb(H265eDpbFrm *frm, RK_S32 cnt, EncFrmStatus
if (!frms[i].valid) {
continue;
}
if (frms[i].seq_idx == seq_idx) {
ret = MPP_OK;
}
@@ -561,24 +575,25 @@ void h265e_dpb_cpb2rps(H265eDpb *dpb, RK_S32 curPoc, H265eSlice *slice, EncCpbSt
i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref);
p = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, frm);
if (!frm->is_lt_ref) {
p->status.val = frm->val;
rps->delta_poc[idx_rps] = p->poc - curPoc;
rps->m_used[idx_rps] = 1;
idx_rps++;
st_size++;
h265e_dbg_dpb("found st %d st_size %d %p deat_poc %d\n", i, st_size,
frm, rps->delta_poc[idx_rps - 1]);
} else {
nLongTermRefPicPoc[lt_size] = p->gop_idx;
nLongTermRefPicRealPoc[lt_size] = p->poc;
nLongTermDealtPoc[lt_size] = p->poc - curPoc;
isMsbValid[lt_size] = p->gop_idx >= (RK_S32)(1 << p->slice->m_sps->m_bitsForPOC);
p->status.val = frm->val;
h265e_dbg_dpb("found lt %d lt_size %d %p dealt poc %d\n", i, lt_size,
frm, nLongTermDealtPoc[lt_size]);
lt_size++;
if (p) {
if (!frm->is_lt_ref) {
p->status.val = frm->val;
rps->delta_poc[idx_rps] = p->poc - curPoc;
rps->m_used[idx_rps] = 1;
idx_rps++;
st_size++;
h265e_dbg_dpb("found st %d st_size %d %p deat_poc %d\n", i, st_size,
frm, rps->delta_poc[idx_rps - 1]);
} else {
nLongTermRefPicPoc[lt_size] = p->gop_idx;
nLongTermRefPicRealPoc[lt_size] = p->poc;
nLongTermDealtPoc[lt_size] = p->poc - curPoc;
isMsbValid[lt_size] = p->gop_idx >= (RK_S32)(1 << p->slice->m_sps->m_bitsForPOC);
p->status.val = frm->val;
h265e_dbg_dpb("found lt %d lt_size %d %p dealt poc %d\n", i, lt_size,
frm, nLongTermDealtPoc[lt_size]);
lt_size++;
}
}
}
sort_delta_poc(rps);
@@ -624,8 +639,21 @@ void h265e_dpb_cpb2rps(H265eDpb *dpb, RK_S32 curPoc, H265eSlice *slice, EncCpbSt
void h265e_dpb_free_unsed(H265eDpb *dpb, EncCpbStatus *cpb)
{
h265e_dbg_func("enter\n");
RK_S32 i = 0;
h265e_dbg_func("enter\n");
if (cpb->curr.is_non_ref) {
H265eDpbFrm *frm = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, &cpb->curr);
if (frm) {
h265e_dbg_dpb("free curr unreference buf poc %d", frm->slice->poc);
frm->is_long_term = 0;
frm->used_by_cur = 0;
frm->on_used = 0;
frm->slice->is_referenced = 0;
}
}
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frame_list); i++) {
H265eDpbFrm *frm = &dpb->frame_list[i];
if (!frm->on_used)
@@ -635,13 +663,93 @@ void h265e_dpb_free_unsed(H265eDpb *dpb, EncCpbStatus *cpb)
frm->is_long_term = 0;
frm->used_by_cur = 0;
frm->on_used = 0;
frm->status.val = 0;
frm->slice->is_referenced = 0;
}
}
h265e_dbg_func("leave\n");
}
void h265e_dpb_proc_cpb(H265eDpb *dpb, EncCpbStatus *cpb)
{
EncFrmStatus *curr = &cpb->curr;
RK_U32 index = 0, i = 0;
H265eDpbFrm *p = NULL;
RK_U32 need_rebuild = 0;
RK_S32 max_gop_id = 0, max_poc = 0;
if (!dpb || !cpb)
return;
if (curr->is_idr) {
for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
H265eDpbFrm *frame = &dpb->frame_list[index];
if (frame->inited) {
frame->slice->is_referenced = 0;
frame->is_long_term = 0;
frame->used_by_cur = 0;
frame->on_used = 0;
frame->status.val = 0;
}
}
return;
}
for (i = 0; i < MAX_CPB_REFS; i++) {
EncFrmStatus *frm = &cpb->init[i];
if (!frm->valid)
continue;
mpp_assert(!frm->is_non_ref);
h265e_dbg_dpb("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n",
i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref);
p = h265e_find_cpb_in_dpb(dpb->frame_list, MAX_REFS, frm);
if (!p->on_used) {
p->on_used = 1;
p->status.val = frm->val;
p->slice->is_referenced = 1;
need_rebuild = 1;
}
}
if (need_rebuild) {
h265e_dbg_dpb("cpb roll back found");
for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
H265eDpbFrm *frame = &dpb->frame_list[index];
if (frame->on_used) {
if (max_poc < frame->slice->poc) {
max_poc = frame->slice->poc;
}
if (max_gop_id < frame->slice->gop_idx) {
max_gop_id = frame->slice->gop_idx;
}
}
}
H265eDpbFrm *frame = dpb->curr;
if (frame->inited) {
frame->slice->is_referenced = 0;
frame->is_long_term = 0;
frame->used_by_cur = 0;
frame->on_used = 0;
frame->status.val = 0;
}
dpb->seq_idx = max_poc;
dpb->gop_idx = max_gop_id;
}
for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
H265eDpbFrm *frame = &dpb->frame_list[index];
if (frame->inited && !frame->on_used) {
h265e_dbg_dpb("reset index %d frame->inited %d rame->on_used %d",
index, frame->inited, frame->on_used);
frame->status.val = 0;
}
}
}
void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb)
{
RK_S32 poc_cur = dpb->curr->slice->poc;
@@ -650,15 +758,15 @@ void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb)
RK_S32 i;
h265e_dbg_func("enter\n");
if (getNalUnitType(dpb, poc_cur) == NAL_IDR_W_RADL ||
getNalUnitType(dpb, poc_cur) == NAL_IDR_N_LP) {
if (get_nal_unit_type(dpb, poc_cur) == NAL_IDR_W_RADL ||
get_nal_unit_type(dpb, poc_cur) == NAL_IDR_N_LP) {
dpb->last_idr = poc_cur;
}
slice->last_idr = dpb->last_idr;
slice->m_temporalLayerNonReferenceFlag = !slice->is_referenced;
// Set the nal unit type
slice->m_nalUnitType = getNalUnitType(dpb, poc_cur);
slice->m_nalUnitType = get_nal_unit_type(dpb, poc_cur);
// If the slice is un-referenced, change from _R "referenced" to _N "non-referenced" NAL unit type
if (slice->m_temporalLayerNonReferenceFlag) {

View File

@@ -134,8 +134,7 @@ MPP_RET h265e_dpb_deinit(H265eDpb *dpb);
MPP_RET h265e_dpb_setup_buf_size(H265eDpb *dpb, RK_U32 size[], RK_U32 count);
MPP_RET h265e_dpb_get_curr(H265eDpb *dpb);
void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb);
MPP_RET h265e_dpb_bakup(H265eDpb *dpb, H265eDpb *dpb_bak);
MPP_RET h265e_dpb_recover(H265eDpb *dpb, H265eDpb *dpb_bak);
void h265e_dpb_proc_cpb(H265eDpb *dpb, EncCpbStatus *cpb);
#define h265e_dpb_dump_frms(dpb) h265e_dpb_dump_frm(dpb, __FUNCTION__)

View File

@@ -0,0 +1,353 @@
/*
* 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 "h265e_cabac"
#include "mpp_mem.h"
#include "mpp_common.h"
#include "h265e_slice.h"
#include "h265e_codec.h"
#include "h265e_enctropy.h"
#ifdef __GNUC__ /* GCCs builtin atomics */
#define CLZ32(id, x) id = (unsigned long)__builtin_clz(x) ^ 31
#elif defined(_MSC_VER) /* Windows atomic intrinsics */
#define CLZ32(id, x) _BitScanReverse(&id, x)
#endif
const RK_U8 g_lpsTable[64][4] = {
{ 128, 176, 208, 240 },
{ 128, 167, 197, 227 },
{ 128, 158, 187, 216 },
{ 123, 150, 178, 205 },
{ 116, 142, 169, 195 },
{ 111, 135, 160, 185 },
{ 105, 128, 152, 175 },
{ 100, 122, 144, 166 },
{ 95, 116, 137, 158 },
{ 90, 110, 130, 150 },
{ 85, 104, 123, 142 },
{ 81, 99, 117, 135 },
{ 77, 94, 111, 128 },
{ 73, 89, 105, 122 },
{ 69, 85, 100, 116 },
{ 66, 80, 95, 110 },
{ 62, 76, 90, 104 },
{ 59, 72, 86, 99 },
{ 56, 69, 81, 94 },
{ 53, 65, 77, 89 },
{ 51, 62, 73, 85 },
{ 48, 59, 69, 80 },
{ 46, 56, 66, 76 },
{ 43, 53, 63, 72 },
{ 41, 50, 59, 69 },
{ 39, 48, 56, 65 },
{ 37, 45, 54, 62 },
{ 35, 43, 51, 59 },
{ 33, 41, 48, 56 },
{ 32, 39, 46, 53 },
{ 30, 37, 43, 50 },
{ 29, 35, 41, 48 },
{ 27, 33, 39, 45 },
{ 26, 31, 37, 43 },
{ 24, 30, 35, 41 },
{ 23, 28, 33, 39 },
{ 22, 27, 32, 37 },
{ 21, 26, 30, 35 },
{ 20, 24, 29, 33 },
{ 19, 23, 27, 31 },
{ 18, 22, 26, 30 },
{ 17, 21, 25, 28 },
{ 16, 20, 23, 27 },
{ 15, 19, 22, 25 },
{ 14, 18, 21, 24 },
{ 14, 17, 20, 23 },
{ 13, 16, 19, 22 },
{ 12, 15, 18, 21 },
{ 12, 14, 17, 20 },
{ 11, 14, 16, 19 },
{ 11, 13, 15, 18 },
{ 10, 12, 15, 17 },
{ 10, 12, 14, 16 },
{ 9, 11, 13, 15 },
{ 9, 11, 12, 14 },
{ 8, 10, 12, 14 },
{ 8, 9, 11, 13 },
{ 7, 9, 11, 12 },
{ 7, 9, 10, 12 },
{ 7, 8, 10, 11 },
{ 6, 8, 9, 11 },
{ 6, 7, 9, 10 },
{ 6, 7, 8, 9 },
{ 2, 2, 2, 2 }
};
const RK_U8 g_nextState[128][2] = {
{ 2, 1 }, { 0, 3 }, { 4, 0 }, { 1, 5 }, { 6, 2 }, { 3, 7 }, { 8, 4 }, { 5, 9 },
{ 10, 4 }, { 5, 11 }, { 12, 8 }, { 9, 13 }, { 14, 8 }, { 9, 15 }, { 16, 10 }, { 11, 17 },
{ 18, 12 }, { 13, 19 }, { 20, 14 }, { 15, 21 }, { 22, 16 }, { 17, 23 }, { 24, 18 }, { 19, 25 },
{ 26, 18 }, { 19, 27 }, { 28, 22 }, { 23, 29 }, { 30, 22 }, { 23, 31 }, { 32, 24 }, { 25, 33 },
{ 34, 26 }, { 27, 35 }, { 36, 26 }, { 27, 37 }, { 38, 30 }, { 31, 39 }, { 40, 30 }, { 31, 41 },
{ 42, 32 }, { 33, 43 }, { 44, 32 }, { 33, 45 }, { 46, 36 }, { 37, 47 }, { 48, 36 }, { 37, 49 },
{ 50, 38 }, { 39, 51 }, { 52, 38 }, { 39, 53 }, { 54, 42 }, { 43, 55 }, { 56, 42 }, { 43, 57 },
{ 58, 44 }, { 45, 59 }, { 60, 44 }, { 45, 61 }, { 62, 46 }, { 47, 63 }, { 64, 48 }, { 49, 65 },
{ 66, 48 }, { 49, 67 }, { 68, 50 }, { 51, 69 }, { 70, 52 }, { 53, 71 }, { 72, 52 }, { 53, 73 },
{ 74, 54 }, { 55, 75 }, { 76, 54 }, { 55, 77 }, { 78, 56 }, { 57, 79 }, { 80, 58 }, { 59, 81 },
{ 82, 58 }, { 59, 83 }, { 84, 60 }, { 61, 85 }, { 86, 60 }, { 61, 87 }, { 88, 60 }, { 61, 89 },
{ 90, 62 }, { 63, 91 }, { 92, 64 }, { 65, 93 }, { 94, 64 }, { 65, 95 }, { 96, 66 }, { 67, 97 },
{ 98, 66 }, { 67, 99 }, { 100, 66 }, { 67, 101 }, { 102, 68 }, { 69, 103 }, { 104, 68 }, { 69, 105 },
{ 106, 70 }, { 71, 107 }, { 108, 70 }, { 71, 109 }, { 110, 70 }, { 71, 111 }, { 112, 72 }, { 73, 113 },
{ 114, 72 }, { 73, 115 }, { 116, 72 }, { 73, 117 }, { 118, 74 }, { 75, 119 }, { 120, 74 }, { 75, 121 },
{ 122, 74 }, { 75, 123 }, { 124, 76 }, { 77, 125 }, { 124, 76 }, { 77, 125 }, { 126, 126 }, { 127, 127 }
};
RK_U8 sbacInit(RK_S32 qp, RK_S32 initValue)
{
RK_S32 slope = (initValue >> 4) * 5 - 45;
RK_S32 offset = ((initValue & 15) << 3) - 16;
RK_S32 initState = MPP_MIN(MPP_MAX(1, (((slope * qp) >> 4) + offset)), 126);
RK_U32 mpState = (initState >= 64);
RK_U8 m_state = ((mpState ? (initState - 64) : (63 - initState)) << 1) + mpState;
return m_state;
}
static void initBuffer(H265eContextModel_t* contextModel, SliceType sliceType, RK_U8 cabacIntFlag, RK_S32 qp, RK_U8* ctxModel, RK_S32 size)
{
RK_S8 initType = 0;
RK_S32 n = 0;
h265e_dbg_skip("sliceType = %d", sliceType);
if (sliceType == I_SLICE)
initType = 0;
else if (sliceType == P_SLICE)
initType = cabacIntFlag ? 2 : 1;
else
initType = cabacIntFlag ? 1 : 2;
ctxModel += (2 - initType) * size;
for (n = 0; n < size; n++) {
contextModel[n].m_state = sbacInit(qp, ctxModel[n]);
//mpp_log("contextModel[%d].m_state = %d", n, contextModel[n].m_state);
contextModel[n].bBinsCoded = 0;
}
}
void h265e_reset_enctropy(void *slice_ctx)
{
H265eSlice *slice = (H265eSlice *)slice_ctx;
RK_U8 cabacInitFlag = slice->m_cabacInitFlag;
RK_S32 qp = slice->m_sliceQp;
SliceType sliceType = slice->m_sliceType;
h265e_dbg_func("enter\n");
initBuffer(&slice->m_contextModels[OFF_SPLIT_FLAG_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_SPLIT_FLAG, NUM_SPLIT_FLAG_CTX);
initBuffer(&slice->m_contextModels[OFF_SKIP_FLAG_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_SKIP_FLAG, NUM_SKIP_FLAG_CTX);
initBuffer(&slice->m_contextModels[OFF_MERGE_FLAG_EXT_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_MERGE_FLAG_EXT, NUM_MERGE_FLAG_EXT_CTX);
initBuffer(&slice->m_contextModels[OFF_MERGE_IDX_EXT_CTX], sliceType, cabacInitFlag, qp, (uint8_t*)INIT_MERGE_IDX_EXT, NUM_MERGE_IDX_EXT_CTX);
h265e_dbg_func("leave\n");
}
void h265e_cabac_resetBits(H265eCabacCtx *cabac_ctx)
{
h265e_dbg_func("enter\n");
cabac_ctx->m_low = 0;
cabac_ctx->m_bitsLeft = -12;
cabac_ctx->m_numBufferedBytes = 0;
cabac_ctx->m_bufferedByte = 0xff;
cabac_ctx->m_fracBits = 0;
h265e_dbg_func("leave\n");
}
void h265e_cabac_start(H265eCabacCtx *cabac_ctx)
{
h265e_dbg_func("enter\n");
cabac_ctx->m_low = 0;
cabac_ctx->m_range = 510;
cabac_ctx->m_bitsLeft = -12;
cabac_ctx->m_numBufferedBytes = 0;
cabac_ctx->m_bufferedByte = 0xff;
}
void h265e_cabac_init(H265eCabacCtx *cabac_ctx, MppWriteCtx * bitIf)
{
h265e_dbg_func("enter\n");
cabac_ctx->m_bitIf = bitIf;
h265e_cabac_start(cabac_ctx);
h265e_dbg_func("leave\n");
}
void h265e_cabac_writeOut(H265eCabacCtx *cabac_ctx)
{
MppWriteCtx* s = cabac_ctx->m_bitIf;
RK_U32 leadByte = cabac_ctx->m_low >> (13 + cabac_ctx->m_bitsLeft);
RK_U32 low_mask = (RK_U32)(~0) >> (11 + 8 - cabac_ctx->m_bitsLeft);
h265e_dbg_func("enter\n");
cabac_ctx->m_bitsLeft -= 8;
cabac_ctx->m_low &= low_mask;
if (leadByte == 0xff) {
cabac_ctx->m_numBufferedBytes++;
} else {
RK_U32 numBufferedBytes = cabac_ctx->m_numBufferedBytes;
if (numBufferedBytes > 0) {
RK_U32 carry = leadByte >> 8;
RK_U32 byteTowrite = cabac_ctx->m_bufferedByte + carry;
mpp_writer_put_bits(s, byteTowrite, 8);
h265e_dbg_skip("byteTowrite = %x", byteTowrite);
byteTowrite = (0xff + carry) & 0xff;
while (numBufferedBytes > 1) {
h265e_dbg_skip("byteTowrite = %x", byteTowrite);
mpp_writer_put_bits(s, byteTowrite, 8);
numBufferedBytes--;
}
}
cabac_ctx->m_numBufferedBytes = 1;
cabac_ctx->m_bufferedByte = (uint8_t)leadByte;
}
h265e_dbg_func("leave\n");
}
/**
* \brief Encode bin
*
* \param binValue bin value
* \param rcCtxModel context model
*/
void h265e_cabac_encodeBin(H265eCabacCtx *cabac_ctx, H265eContextModel_t *ctxModel, RK_U32 binValue)
{
RK_U32 mstate = ctxModel->m_state;
h265e_dbg_func("enter\n");
// mpp_log("before m_low %d ctxModel.m_state %d m_range %d \n", cabac_ctx->m_low, ctxModel->m_state,cabac_ctx->m_range);
ctxModel->m_state = sbacNext(mstate, binValue);
ctxModel->bBinsCoded = 1;
RK_U32 range = cabac_ctx->m_range;
RK_U32 state = sbacGetState(mstate);
RK_U32 lps = g_lpsTable[state][((uint8_t)range >> 6)];
range -= lps;
// mpp_log("ctxModel.m_state %d binValue %d \n", ctxModel->m_state, binValue);
// assert(lps >= 2);
RK_S32 numBits = (RK_U32)(range - 256) >> 31;
RK_U32 low = cabac_ctx->m_low;
// NOTE: MPS must be LOWEST bit in mstate
// assert(((binValue ^ mstate) & 1) == (binValue != sbacGetMps(mstate)));
if ((binValue ^ mstate) & 1) {
unsigned long idx;
CLZ32(idx, lps);
// assert(state != 63 || idx == 1);
numBits = 8 - idx;
if (state >= 63)
numBits = 6;
// assert(numBits <= 6);
low += range;
range = lps;
}
cabac_ctx->m_low = (low << numBits);
cabac_ctx->m_range = (range << numBits);
cabac_ctx->m_bitsLeft += numBits;
// mpp_log("after m_low %d ctxModel.m_state %d m_range %d \n", cabac_ctx->m_low, ctxModel->m_state,cabac_ctx->m_range);
if (cabac_ctx->m_bitsLeft >= 0) {
h265e_cabac_writeOut(cabac_ctx);
}
h265e_dbg_func("leave\n");
}
void h265e_cabac_encodeBinTrm(H265eCabacCtx *cabac_ctx, RK_U32 binValue)
{
h265e_dbg_func("enter\n");
// mpp_log("encodeBinTrm m_range %d binValue %d \n", cabac_ctx->m_range, binValue);
cabac_ctx->m_range -= 2;
if (binValue) {
cabac_ctx->m_low += cabac_ctx->m_range;
cabac_ctx->m_low <<= 7;
cabac_ctx->m_range = 2 << 7;
cabac_ctx->m_bitsLeft += 7;
} else if (cabac_ctx->m_range >= 256) {
return;
} else {
cabac_ctx->m_low <<= 1;
cabac_ctx->m_range <<= 1;
cabac_ctx->m_bitsLeft++;
}
if (cabac_ctx->m_bitsLeft >= 0) {
h265e_cabac_writeOut(cabac_ctx);
}
h265e_dbg_func("leave\n");
}
void h265e_cabac_finish(H265eCabacCtx *cabac_ctx)
{
MppWriteCtx* s = cabac_ctx->m_bitIf;
h265e_dbg_func("enter\n");
if (cabac_ctx->m_low >> (21 + cabac_ctx->m_bitsLeft)) {
mpp_writer_put_bits(s, cabac_ctx->m_bufferedByte + 1, 8);
while (cabac_ctx->m_numBufferedBytes > 1) {
mpp_writer_put_bits(s, 0, 8);
cabac_ctx->m_numBufferedBytes--;
}
cabac_ctx->m_low -= 1 << (21 + cabac_ctx->m_bitsLeft);
} else {
if (cabac_ctx->m_numBufferedBytes > 0) {
mpp_writer_put_bits(s, cabac_ctx->m_bufferedByte , 8);
}
while (cabac_ctx->m_numBufferedBytes > 1) {
mpp_writer_put_bits(s, 0xff , 8);
cabac_ctx->m_numBufferedBytes--;
}
}
mpp_writer_put_bits(s, cabac_ctx->m_low >> 8 , 13 + cabac_ctx->m_bitsLeft);
h265e_dbg_func("leave\n");
}
void h265e_cabac_flush(H265eCabacCtx *cabac_ctx)
{
MppWriteCtx* s = cabac_ctx->m_bitIf;
h265e_dbg_func("enter\n");
h265e_cabac_encodeBinTrm(cabac_ctx, 1);
h265e_cabac_finish(cabac_ctx);
mpp_writer_put_bits(s, 1, 1);
mpp_writer_align_zero(s);
h265e_cabac_start(cabac_ctx);
h265e_dbg_func("leave\n");
}

View File

@@ -0,0 +1,55 @@
/*
* 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 __H265E_ENCTROPY_H__
#define __H265E_ENCTROPY_H__
#include "mpp_bitwrite.h"
typedef struct H265eContextModel {
RK_U8 m_state; ///< internal state variable
RK_U8 bBinsCoded;
} H265eContextModel_t;
typedef struct H265eCabacCtx {
MppWriteCtx *m_bitIf;
RK_U32 m_low;
RK_U32 m_range;
RK_U32 m_bufferedByte;
RK_S32 m_numBufferedBytes;
RK_S32 m_bitsLeft;
RK_U64 m_fracBits;
RK_U8 m_bIsCounter;
} H265eCabacCtx;
#ifdef __cplusplus
extern "C" {
#endif
void h265e_cabac_init(H265eCabacCtx *cabac_ctx, MppWriteCtx * bitIf);
void h265e_reset_enctropy(void *slice_ctx);
void h265e_cabac_resetBits(H265eCabacCtx *cabac_ctx);
void h265e_cabac_encodeBin(H265eCabacCtx *cabac_ctx, H265eContextModel_t *ctxModel, RK_U32 binValue);
void h265e_cabac_encodeBinTrm(H265eCabacCtx *cabac_ctx, RK_U32 binValue);
void h265e_cabac_start(H265eCabacCtx *cabac_ctx);
void h265e_cabac_finish(H265eCabacCtx *cabac_ctx);
void h265e_cabac_flush(H265eCabacCtx *cabac_ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -54,6 +54,60 @@ H265levelspec levels[] = {
{ MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, 1, H265_LEVEL8_5, "8.5", 85 },
};
void init_zscan2raster(RK_S32 maxDepth, RK_S32 depth, RK_U32 startVal, RK_U32** curIdx)
{
RK_S32 stride = 1 << (maxDepth - 1);
if (depth == maxDepth) {
(*curIdx)[0] = startVal;
(*curIdx)++;
} else {
RK_S32 step = stride >> depth;
init_zscan2raster(maxDepth, depth + 1, startVal, curIdx);
init_zscan2raster(maxDepth, depth + 1, startVal + step, curIdx);
init_zscan2raster(maxDepth, depth + 1, startVal + step * stride, curIdx);
init_zscan2raster(maxDepth, depth + 1, startVal + step * stride + step, curIdx);
}
}
void init_raster2zscan(RK_U32 maxCUSize, RK_U32 maxDepth, RK_U32 *raster2zscan, RK_U32 *zscan2raster)
{
RK_U32 unitSize = maxCUSize >> (maxDepth - 1);
RK_U32 numPartInCUSize = (RK_U32)maxCUSize / unitSize;
RK_U32 i;
for ( i = 0; i < numPartInCUSize * numPartInCUSize; i++) {
raster2zscan[zscan2raster[i]] = i;
}
}
void init_raster2pelxy(RK_U32 maxCUSize, RK_U32 maxDepth, RK_U32 *raster2pelx, RK_U32 *raster2pely)
{
RK_U32 i;
RK_U32* tempx = &raster2pelx[0];
RK_U32* tempy = &raster2pely[0];
RK_U32 unitSize = maxCUSize >> (maxDepth - 1);
RK_U32 numPartInCUSize = maxCUSize / unitSize;
tempx[0] = 0;
tempx++;
for (i = 1; i < numPartInCUSize; i++) {
tempx[0] = tempx[-1] + unitSize;
tempy++;
}
for (i = 1; i < numPartInCUSize; i++) {
memcpy(tempx, tempx - numPartInCUSize, sizeof(RK_U32) * numPartInCUSize);
tempx += numPartInCUSize;
}
for (i = 1; i < numPartInCUSize * numPartInCUSize; i++) {
tempy[i] = (i / numPartInCUSize) * unitSize;
}
}
MPP_RET h265e_set_vps(H265eCtx *ctx, H265eVps *vps)
{
RK_S32 i;
@@ -121,6 +175,7 @@ MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps)
RK_S32 minCUSize, log2MinCUSize;
RK_S32 tuQTMinLog2Size = 2, tuQTMaxLog2Size;
MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg);
RK_U32 *tmp = &sps->zscan2raster[0];
memset(convertToBit, -1, sizeof(convertToBit));
c = 0;
@@ -142,6 +197,9 @@ MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps)
maxCUDepth += addCUDepth;
addCUDepth++;
init_zscan2raster(maxCUDepth + 1, 1, 0, &tmp );
init_raster2zscan(codec->max_cu_size, maxCUDepth + 1, &sps->raster2zscan[0], &sps->zscan2raster[0]);
init_raster2pelxy(codec->max_cu_size, maxCUDepth + 1, &sps->raster2pelx[0], &sps->raster2pely[0]);
if ((prep->width % minCUDepth) != 0) {
RK_U32 padsize = 0;
@@ -177,6 +235,7 @@ MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps)
sps->m_log2DiffMaxMinCodingBlockSize = 0 ;
sps->m_maxCUSize = codec->max_cu_size;
sps->m_maxCUDepth = maxCUDepth;
sps->m_addCUDepth = addCUDepth;
sps->m_RPSList.m_numberOfReferencePictureSets = 0;
sps->m_RPSList.m_referencePictureSets = NULL;

View File

@@ -22,7 +22,7 @@
#include "h265e_codec.h"
#include "h265e_slice.h"
H265eDpbFrm* get_ref_pic(H265eDpbFrm *frame_list, int poc)
H265eDpbFrm* get_ref_pic(H265eDpbFrm *frame_list, RK_S32 poc)
{
RK_S32 index = 0;
H265eDpbFrm *frame = NULL;
@@ -38,7 +38,7 @@ H265eDpbFrm* get_ref_pic(H265eDpbFrm *frame_list, int poc)
return frame;
}
H265eDpbFrm* get_lt_ref_pic(H265eDpbFrm *frame_list, H265eSlice *slice, int poc, RK_U32 pocHasMsb)
H265eDpbFrm* get_lt_ref_pic(H265eDpbFrm *frame_list, H265eSlice *slice, RK_S32 poc, RK_U32 pocHasMsb)
{
RK_S32 index = 0;
H265eDpbFrm *frame = NULL;
@@ -53,7 +53,7 @@ H265eDpbFrm* get_lt_ref_pic(H265eDpbFrm *frame_list, H265eSlice *slice, int poc,
for (index = MAX_REFS - 1 ; index >= 0; index--) {
frame = &frame_list[index];
if (frame->on_used && frame->poc != slice->poc && frame->slice->is_referenced) {
int picPoc = frame->poc;
RK_S32 picPoc = frame->poc;
if (!pocHasMsb) {
picPoc = picPoc % pocCycle;
}
@@ -203,7 +203,7 @@ void h265e_slice_set_ref_poc_list(H265eSlice *slice)
h265e_dbg_func("leave\n");
}
void h265e_slice_init(void *ctx, H265eSlice *slice, EncFrmStatus curr)
void h265e_slice_init(void *ctx, EncFrmStatus curr)
{
H265eCtx *p = (H265eCtx *)ctx;
H265eVps *vps = &p->vps;
@@ -211,7 +211,8 @@ void h265e_slice_init(void *ctx, H265eSlice *slice, EncFrmStatus curr)
H265ePps *pps = &p->pps;
MppEncCfgSet *cfg = p->cfg;
MppEncH265Cfg *codec = &cfg->codec.h265;
H265eSlice *slice = p->dpb->curr->slice;
p->slice = p->dpb->curr->slice;
h265e_dbg_func("enter\n");
memset(slice, 0, sizeof(H265eSlice));
slice->m_sps = sps;
@@ -276,3 +277,516 @@ void h265e_slice_init(void *ctx, H265eSlice *slice, EncFrmStatus curr)
slice->m_sliceType, slice->is_referenced);
h265e_dbg_func("leave\n");
}
void code_st_refpic_set(MppWriteCtx *bitIf, H265eReferencePictureSet* rps, RK_S32 idx)
{
if (idx > 0) {
mpp_writer_put_bits(bitIf, rps->m_interRPSPrediction, 1); // inter_RPS_prediction_flag
}
if (rps->m_interRPSPrediction) {
RK_S32 deltaRPS = rps->m_deltaRPS;
RK_S32 j;
mpp_writer_put_ue(bitIf, rps->m_deltaRIdxMinus1); // delta index of the Reference Picture Set used for prediction minus 1
mpp_writer_put_bits(bitIf, (deltaRPS >= 0 ? 0 : 1), 1); //delta_rps_sign
mpp_writer_put_ue(bitIf, abs(deltaRPS) - 1); // absolute delta RPS minus 1
for (j = 0; j < rps->m_numRefIdc; j++) {
RK_S32 refIdc = rps->m_refIdc[j];
mpp_writer_put_bits(bitIf, (refIdc == 1 ? 1 : 0), 1); //first bit is "1" if Idc is 1
if (refIdc != 1) {
mpp_writer_put_bits(bitIf, refIdc >> 1, 1); //second bit is "1" if Idc is 2, "0" otherwise.
}
}
} else {
mpp_writer_put_ue(bitIf, rps->num_negative_pic);
mpp_writer_put_ue(bitIf, rps->num_positive_pic);
RK_S32 prev = 0;
RK_S32 j;
for (j = 0; j < rps->num_negative_pic; j++) {
mpp_writer_put_ue(bitIf, prev - rps->delta_poc[j] - 1);
prev = rps->delta_poc[j];
mpp_writer_put_bits(bitIf, rps->m_used[j], 1);
}
prev = 0;
for (j = rps->num_negative_pic; j < rps->num_negative_pic + rps->num_positive_pic; j++) {
mpp_writer_put_ue(bitIf, rps->delta_poc[j] - prev - 1);
prev = rps->delta_poc[j];
mpp_writer_put_bits(bitIf, rps->m_used[j], 1);
}
}
}
RK_U8 find_matching_ltrp(H265eSlice* slice, RK_U32 *ltrpsIndex, RK_S32 ltrpPOC, RK_U32 usedFlag)
{
RK_U32 lsb = ltrpPOC % (1 << slice->m_sps->m_bitsForPOC);
RK_U32 k;
for (k = 0; k < slice->m_sps->m_numLongTermRefPicSPS; k++) {
if ((lsb == slice->m_sps->m_ltRefPicPocLsbSps[k]) && (usedFlag == slice->m_sps->m_usedByCurrPicLtSPSFlag[k])) {
*ltrpsIndex = k;
return 1;
}
}
return 0;
}
RK_S32 get_num_rps_cur_templist(H265eReferencePictureSet* rps)
{
RK_S32 numRpsCurrTempList = 0;
RK_S32 i;
for ( i = 0; i < rps->num_negative_pic + rps->num_positive_pic + rps->num_long_term_pic; i++) {
if (rps->m_used[i]) {
numRpsCurrTempList++;
}
}
return numRpsCurrTempList;
}
void h265e_code_slice_header(H265eSlice *slice, MppWriteCtx *bitIf)
{
RK_U32 i = 0;
mpp_writer_put_bits(bitIf, 1, 1); //first_slice_segment_in_pic_flag
mpp_writer_put_ue(bitIf, slice->m_ppsId);
H265eReferencePictureSet* rps = slice->m_rps;
slice->m_enableTMVPFlag = 0;
if (!slice->m_dependentSliceSegmentFlag) {
for (i = 0; i < (RK_U32)slice->m_pps->m_numExtraSliceHeaderBits; i++) {
mpp_writer_put_bits(bitIf, (slice->slice_reserved_flag >> i) & 0x1, 1);
}
mpp_writer_put_ue(bitIf, slice->m_sliceType);
if (slice->m_pps->m_outputFlagPresentFlag) {
mpp_writer_put_bits(bitIf, slice->m_picOutputFlag ? 1 : 0, 1);
}
if (slice->m_sliceType != I_SLICE) { // skip frame can't iDR
RK_S32 picOrderCntLSB = (slice->poc - slice->last_idr + (1 << slice->m_sps->m_bitsForPOC)) % (1 << slice->m_sps->m_bitsForPOC);
mpp_writer_put_bits(bitIf, picOrderCntLSB, slice->m_sps->m_bitsForPOC);
if (slice->m_bdIdx < 0) {
mpp_writer_put_bits(bitIf, 0, 1);
code_st_refpic_set(bitIf, rps, slice->m_sps->m_RPSList.m_numberOfReferencePictureSets);
} else {
mpp_writer_put_bits(bitIf, 1, 1);
RK_S32 numBits = 0;
while ((1 << numBits) < slice->m_sps->m_RPSList.m_numberOfReferencePictureSets) {
numBits++;
}
if (numBits > 0) {
mpp_writer_put_bits(bitIf, slice->m_bdIdx, numBits);
}
}
if (slice->m_sps->m_bLongTermRefsPresent) {
RK_S32 numLtrpInSH = rps->m_numberOfPictures;
RK_S32 ltrpInSPS[MAX_REFS];
RK_S32 numLtrpInSPS = 0;
RK_U32 ltrpIndex;
RK_S32 counter = 0;
RK_S32 k;
for (k = rps->m_numberOfPictures - 1; k > rps->m_numberOfPictures - rps->num_long_term_pic - 1; k--) {
if (find_matching_ltrp(slice, &ltrpIndex, rps->poc[k], rps->m_used[k])) {
ltrpInSPS[numLtrpInSPS] = ltrpIndex;
numLtrpInSPS++;
} else {
counter++;
}
}
numLtrpInSH -= numLtrpInSPS;
RK_S32 bitsForLtrpInSPS = 0;
while (slice->m_sps->m_numLongTermRefPicSPS > (RK_U32)(1 << bitsForLtrpInSPS)) {
bitsForLtrpInSPS++;
}
if (slice->m_sps->m_numLongTermRefPicSPS > 0) {
mpp_writer_put_ue(bitIf, numLtrpInSPS);
}
mpp_writer_put_ue(bitIf, numLtrpInSH);
// Note that the LSBs of the LT ref. pic. POCs must be sorted before.
// Not sorted here because LT ref indices will be used in setRefPicList()
RK_S32 prevDeltaMSB = 0;
RK_S32 offset = rps->num_negative_pic + rps->num_positive_pic;
for ( k = rps->m_numberOfPictures - 1; k > offset - 1; k--) {
if (counter < numLtrpInSPS) {
if (bitsForLtrpInSPS > 0) {
mpp_writer_put_bits(bitIf, ltrpInSPS[counter], bitsForLtrpInSPS);
}
} else {
mpp_writer_put_bits(bitIf, rps->m_pocLSBLT[k], slice->m_sps->m_bitsForPOC);
mpp_writer_put_bits(bitIf, rps->m_used[k], 1);
}
mpp_writer_put_bits(bitIf, rps->m_deltaPocMSBPresentFlag[k], 1);
if (rps->m_deltaPocMSBPresentFlag[k]) {
RK_U32 deltaFlag = 0;
if ((k == rps->m_numberOfPictures - 1) || (k == rps->m_numberOfPictures - 1 - numLtrpInSPS)) {
deltaFlag = 1;
}
if (deltaFlag) {
mpp_writer_put_ue(bitIf, rps->m_deltaPOCMSBCycleLT[k]);
} else {
RK_S32 differenceInDeltaMSB = rps->m_deltaPOCMSBCycleLT[k] - prevDeltaMSB;
mpp_writer_put_ue(bitIf, differenceInDeltaMSB);
}
prevDeltaMSB = rps->m_deltaPOCMSBCycleLT[k];
}
}
}
if (slice->m_sps->m_TMVPFlagsPresent) {
mpp_writer_put_bits(bitIf, slice->m_enableTMVPFlag ? 1 : 0, 1);
}
}
if (slice->m_sps->m_bUseSAO) { //skip frame close sao
mpp_writer_put_bits(bitIf, 0, 1);
mpp_writer_put_bits(bitIf, 0, 1);
}
//check if numrefidxes match the defaults. If not, override
if (slice->m_sliceType != I_SLICE) {
RK_U32 overrideFlag = (slice->m_numRefIdx[0] != (RK_S32)slice->m_pps->m_numRefIdxL0DefaultActive);
mpp_writer_put_bits(bitIf, overrideFlag ? 1 : 0, 1);
if (overrideFlag) {
mpp_writer_put_ue(bitIf, slice->m_numRefIdx[0] - 1);
slice->m_numRefIdx[1] = 0;
}
}
if (slice->m_pps->m_listsModificationPresentFlag && get_num_rps_cur_templist(rps) > 1) {
H265eRefPicListModification* refPicListModification = &slice->m_RefPicListModification;
mpp_writer_put_bits(bitIf, refPicListModification->m_refPicListModificationFlagL0 ? 1 : 0, 1);
if (refPicListModification->m_refPicListModificationFlagL0) {
RK_S32 numRpsCurrTempList0 = get_num_rps_cur_templist(rps);
if (numRpsCurrTempList0 > 1) {
RK_S32 length = 1;
numRpsCurrTempList0--;
while (numRpsCurrTempList0 >>= 1) {
length++;
}
for (i = 0; i < (RK_U32)slice->m_numRefIdx[0]; i++) {
mpp_writer_put_bits(bitIf, refPicListModification->m_RefPicSetIdxL0[i], length);
}
}
}
}
if (slice->m_pps->m_cabacInitPresentFlag) {
mpp_writer_put_bits(bitIf, slice->m_cabacInitFlag, 1);
}
if (slice->m_enableTMVPFlag) {
if (slice->m_sliceType != I_SLICE &&
((slice->m_colFromL0Flag == 1 && slice->m_numRefIdx[0] > 1) ||
(slice->m_colFromL0Flag == 0 && slice->m_numRefIdx[1] > 1))) {
mpp_writer_put_ue(bitIf, slice->m_colRefIdx);
}
}
if (slice->m_sliceType != I_SLICE) {
RK_S32 flag = MRG_MAX_NUM_CANDS - slice->m_maxNumMergeCand;
flag = flag == 5 ? 4 : flag;
mpp_writer_put_ue(bitIf, flag);
}
RK_S32 code = slice->m_sliceQp - (slice->m_pps->m_picInitQPMinus26 + 26);
mpp_writer_put_se(bitIf, code);
if (slice->m_pps->m_bSliceChromaQpFlag) {
code = slice->m_sliceQpDeltaCb;
mpp_writer_put_se(bitIf, code);
code = slice->m_sliceQpDeltaCr;
mpp_writer_put_se(bitIf, code);
}
if (slice->m_pps->m_deblockingFilterControlPresentFlag) {
if (slice->m_pps->m_deblockingFilterOverrideEnabledFlag) {
mpp_writer_put_bits(bitIf, slice->m_deblockingFilterOverrideFlag, 1);
}
if (slice->m_deblockingFilterOverrideFlag) {
mpp_writer_put_bits(bitIf, slice->m_deblockingFilterDisable, 1);
if (!slice->m_deblockingFilterDisable) {
mpp_writer_put_se(bitIf, slice->m_deblockingFilterBetaOffsetDiv2);
mpp_writer_put_se(bitIf, slice->m_deblockingFilterTcOffsetDiv2);
}
}
}
}
if (slice->m_pps->m_sliceHeaderExtensionPresentFlag) {
mpp_writer_put_ue(bitIf, slice->slice_header_extension_length);
for (i = 0; i < slice->slice_header_extension_length; i++) {
mpp_writer_put_bits(bitIf, 0, 8);
}
}
h265e_dbg_func("leave\n");
}
void code_skip_flag(H265eSlice *slice, RK_U32 abs_part_idx, DataCu *cu)
{
// get context function is here
H265eCabacCtx *cabac_ctx = &slice->m_cabac;
H265eSps *sps = slice->m_sps;
RK_U32 ctxSkip;
RK_U32 tpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]];
RK_U32 tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]];
//RK_U32 ctxSkip = cu->getCtxSkipFlag(abs_part_idx);
h265e_dbg_skip("tpelx = %d", tpelx);
if (cu->cur_addr == 0 ) {
ctxSkip = 0;
} else if ((tpely == 0) || (tpelx == 0)) {
ctxSkip = 1;
} else {
ctxSkip = 2;
}
h265e_dbg_skip("ctxSkip = %d", ctxSkip);
h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_SKIP_FLAG_CTX + ctxSkip], 1);
}
static void code_merge_index(H265eSlice *slice)
{
H265eCabacCtx *cabac_ctx = &slice->m_cabac;
h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_MERGE_IDX_EXT_CTX], 0);
}
static void code_split_flag(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, DataCu *cu)
{
H265eSps *sps = slice->m_sps;
if (depth == slice->m_sps->m_maxCUDepth - slice->m_sps->m_addCUDepth)
return;
h265e_dbg_skip("depth %d cu->m_cuDepth %d", depth, cu->m_cuDepth[sps->zscan2raster[abs_part_idx]]);
H265eCabacCtx *cabac_ctx = &slice->m_cabac;
RK_U32 currSplitFlag = (cu->m_cuDepth[sps->zscan2raster[abs_part_idx]] > depth) ? 1 : 0;
h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_SPLIT_FLAG_CTX], currSplitFlag);
}
static void encode_cu(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, DataCu *cu)
{
H265eSps *sps = slice->m_sps;
RK_U32 bBoundary = 0;
RK_U32 lpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]];
RK_U32 rpelx = lpelx + (sps->m_maxCUSize >> depth) - 1;
RK_U32 tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]];
RK_U32 bpely = tpely + (sps->m_maxCUSize >> depth) - 1;
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 {
h265e_dbg_skip("boundary flag found");
bBoundary = 1;
}
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 partUnitIdx = 0;
for (partUnitIdx = 0; partUnitIdx < 4; partUnitIdx++, abs_part_idx += qNumParts) {
h265e_dbg_skip("depth %d partUnitIdx = %d, qNumParts %d, abs_part_idx %d", depth, partUnitIdx, qNumParts, abs_part_idx);
lpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]];
tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]];
if ((lpelx < sps->m_picWidthInLumaSamples) && (tpely < sps->m_picHeightInLumaSamples)) {
encode_cu(slice, abs_part_idx, depth + 1, cu);
}
}
return;
}
h265e_dbg_skip("code_skip_flag in depth %d", depth);
code_skip_flag(slice, abs_part_idx, cu);
h265e_dbg_skip("code_merge_index in depth %d", depth);
code_merge_index(slice);
return;
}
static void proc_cu8(DataCu *cu, RK_U32 pos_x, RK_U32 pos_y)
{
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);
}
static void proc_cu16(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y)
{
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;
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);
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);
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);
}
}
static void proc_cu32(H265eSlice *slice, DataCu *cu, RK_U32 pos_x, RK_U32 pos_y)
{
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;
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);
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);
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);
}
}
static void proc_ctu(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 lpelx = cu->pixelX;
RK_U32 rpelx = lpelx + 63;
RK_U32 tpely = cu->pixelY;
RK_U32 bpely = tpely + 63;
for (k = 0; k < 256; k++) {
cu->m_cuDepth[k] = 0;
cu->m_cuSize[k] = 64;
}
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_cu32(slice, cu, cu_x_1, cu_y_1);
}
for (k = 0; k < 256; k++) {
switch (cu->m_cuDepth[k]) {
case 0: cu->m_cuSize[k] = 64; break;
case 1: cu->m_cuSize[k] = 32; break;
case 2: cu->m_cuSize[k] = 16; break;
case 3: cu->m_cuSize[k] = 8; break;
}
}
}
static void h265e_write_nal(MppWriteCtx *bitIf)
{
h265e_dbg_func("enter\n");
mpp_writer_put_raw_bits(bitIf, 0x0, 24);
mpp_writer_put_raw_bits(bitIf, 0x01, 8);
mpp_writer_put_bits(bitIf, 0, 1); // forbidden_zero_bit
mpp_writer_put_bits(bitIf, 1, 6); // nal_unit_type
mpp_writer_put_bits(bitIf, 0, 6); // nuh_reserved_zero_6bits
mpp_writer_put_bits(bitIf, 1, 3); // nuh_temporal_id_plus1
h265e_dbg_func("leave\n");
}
static void h265e_write_algin(MppWriteCtx *bitIf)
{
h265e_dbg_func("enter\n");
mpp_writer_put_bits(bitIf, 1, 1);
mpp_writer_align_zero(bitIf);
h265e_dbg_func("leave\n");
}
RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_S32 len)
{
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 i = 0, j = 0, cu_cnt = 0;
if (!buf || !len) {
mpp_err("buf or size no set");
return MPP_NOK;
}
mpp_writer_init(&bitIf, buf, len);
h265e_write_nal(&bitIf);
h265e_code_slice_header(slice, &bitIf);
h265e_write_algin(&bitIf);
h265e_reset_enctropy((void*)slice);
h265e_cabac_init(cabac_ctx, &bitIf);
DataCu cu;
cu.mb_w = mb_wd;
cu.mb_h = mb_h;
slice->is_referenced = 0;
for (i = 0; i < mb_h; i++) {
for ( j = 0; j < mb_wd; j++) {
cu.pixelX = j * 64;
cu.pixelY = i * 64;
cu.cur_addr = cu_cnt;
proc_ctu(slice, &cu);
encode_cu(slice, 0, 0, &cu);
h265e_cabac_encodeBinTrm(cabac_ctx, 0);
cu_cnt++;
}
}
h265e_cabac_finish(cabac_ctx);
h265e_write_algin(&bitIf);
h265e_dbg_func("leave\n");
return mpp_writer_bytes(&bitIf);
}

View File

@@ -22,6 +22,13 @@
#include "mpp_list.h"
#include "h265e_dpb.h"
#include "h265_syntax.h"
#include "h265e_enctropy.h"
#include "h265e_context_table.h"
#define MIN_PU_SIZE 4
#define MIN_TU_SIZE 4
#define MAX_NUM_SPU_W (64 / MIN_PU_SIZE) // maximum number of SPU in horizontal line
/*
* For H.265 encoder slice header process.
* Remove some syntax that encoder not supported.
@@ -29,6 +36,16 @@
*/
typedef struct H265eDpbFrm_t H265eDpbFrm;
typedef struct DataCu_t {
RK_U8 m_cuSize[256];
RK_U8 m_cuDepth[256];
RK_U32 pixelX;
RK_U32 pixelY;
RK_U32 mb_w;
RK_U32 mb_h;
RK_U32 cur_addr;
} DataCu;
typedef struct H265eReferencePictureSet_e {
RK_S32 m_deltaRIdxMinus1;
RK_S32 m_deltaRPS;
@@ -65,7 +82,6 @@ typedef struct H265eRefPicListModification_e {
RK_U32 m_RefPicSetIdxL1[REF_PIC_LIST_NUM_IDX];
} H265eRefPicListModification;
typedef struct ProfileTierLevel_e {
RK_S32 m_profileSpace;
RK_S32 m_tierFlag;
@@ -205,6 +221,7 @@ typedef struct H265eSps_e {
RK_S32 m_log2DiffMaxMinCodingBlockSize;
RK_U32 m_maxCUSize;
RK_U32 m_maxCUDepth;
RK_U32 m_addCUDepth;
H265eCropInfo m_conformanceWindow;
@@ -260,6 +277,10 @@ typedef struct H265eSps_e {
RK_S32 m_vuiParametersPresentFlag;
H265eVuiInfo vui;
H265ePTL *m_ptl;
RK_U32 zscan2raster[MAX_NUM_SPU_W * MAX_NUM_SPU_W];
RK_U32 raster2zscan[MAX_NUM_SPU_W * MAX_NUM_SPU_W];
RK_U32 raster2pelx[MAX_NUM_SPU_W * MAX_NUM_SPU_W];
RK_U32 raster2pely[MAX_NUM_SPU_W * MAX_NUM_SPU_W];
} H265eSps;
typedef struct H265ePps_e {
@@ -325,6 +346,9 @@ typedef struct H265eSlice_e {
H265eReferencePictureSet m_localRPS;
RK_S32 m_bdIdx;
H265eRefPicListModification m_RefPicListModification;
H265eContextModel_t m_contextModels[MAX_OFF_CTX_MOD];
H265eCabacCtx m_cabac;
enum NALUnitType m_nalUnitType; ///< Nal unit type for the slice
SliceType m_sliceType;
RK_U32 m_IsGenB;
@@ -393,7 +417,8 @@ extern "C" {
void h265e_slice_set_ref_list(H265eDpbFrm *frame_list, H265eSlice *slice);
void h265e_slice_set_ref_poc_list(H265eSlice *slice);
void h265e_slice_init(void *ctx, H265eSlice *slice, EncFrmStatus curr);
void h265e_slice_init(void *ctx, EncFrmStatus curr);
RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_S32 len);
#ifdef __cplusplus
}