mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-11-03 01:33:35 +08:00
[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:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
64
mpp/codec/enc/h265/h265e_context_table.h
Normal file
64
mpp/codec/enc/h265/h265e_context_table.h
Normal 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__ */
|
||||
@@ -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) {
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
353
mpp/codec/enc/h265/h265e_enctropy.c
Normal file
353
mpp/codec/enc/h265/h265e_enctropy.c
Normal 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");
|
||||
}
|
||||
55
mpp/codec/enc/h265/h265e_enctropy.h
Normal file
55
mpp/codec/enc/h265/h265e_enctropy.h
Normal 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
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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, <rpIndex, 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user