[LMCS] initial bitstream writing and LMCS structures

This commit is contained in:
Marko Viitanen 2021-04-30 10:04:41 +03:00
parent 3d9d1930d8
commit 38eafbbf78
6 changed files with 274 additions and 12 deletions

View file

@ -100,6 +100,8 @@ libkvazaar_la_SOURCES = \
rate_control.h \ rate_control.h \
rdo.c \ rdo.c \
rdo.h \ rdo.h \
reshape.c \
reshape.h \
sao.c \ sao.c \
sao.h \ sao.h \
scalinglist.c \ scalinglist.c \

View file

@ -11,6 +11,7 @@
#include "rdo.h" #include "rdo.h"
#include "strategies/strategies-sao.h" #include "strategies/strategies-sao.h"
#include "kvz_math.h" #include "kvz_math.h"
#include "reshape.h"
#if MAX_NUM_CC_ALF_FILTERS>1 #if MAX_NUM_CC_ALF_FILTERS>1
typedef struct filter_idx_count typedef struct filter_idx_count
@ -1574,6 +1575,42 @@ static void encode_alf_aps_flags(encoder_state_t * const state,
} }
} }
// ToDo: Fill in LMCS APS
static void encode_lmcs_aps(encoder_state_t* const state, lmcs_aps* aps)
{
bitstream_t* const stream = &state->stream;
//SliceReshapeInfo param = pcAPS->getReshaperAPSInfo();
WRITE_UE(stream, 0/*param.reshaperModelMinBinIdx*/, "lmcs_min_bin_idx");
WRITE_UE(stream, 16 - 1/*16 - 1 - param.reshaperModelMaxBinIdx*/, "lmcs_delta_max_bin_idx");
WRITE_UE(stream, 7/*param.maxNbitsNeededDeltaCW - 1*/, "lmcs_delta_cw_prec_minus1");
/*
for (int i = param.reshaperModelMinBinIdx; i <= param.reshaperModelMaxBinIdx; i++)
{
int deltaCW = param.reshaperModelBinCWDelta[i];
int signCW = (deltaCW < 0) ? 1 : 0;
int absCW = (deltaCW < 0) ? (-deltaCW) : deltaCW;
WRITE_CODE(absCW, param.maxNbitsNeededDeltaCW, "lmcs_delta_abs_cw[ i ]");
if (absCW > 0)
{
WRITE_FLAG(signCW, "lmcs_delta_sign_cw_flag[ i ]");
}
}
int deltaCRS = pcAPS->chromaPresentFlag ? param.chrResScalingOffset : 0;
int signCRS = (deltaCRS < 0) ? 1 : 0;
int absCRS = (deltaCRS < 0) ? (-deltaCRS) : deltaCRS;
if (pcAPS->chromaPresentFlag)
{
WRITE_CODE(absCRS, 3, "lmcs_delta_abs_crs");
}
if (absCRS > 0)
{
WRITE_FLAG(signCRS, "lmcs_delta_sign_crs_flag");
}
*/
}
static void encoder_state_write_adaptation_parameter_set(encoder_state_t * const state, alf_aps *aps) static void encoder_state_write_adaptation_parameter_set(encoder_state_t * const state, alf_aps *aps)
{ {
#ifdef KVZ_DEBUG #ifdef KVZ_DEBUG
@ -1590,10 +1627,10 @@ static void encoder_state_write_adaptation_parameter_set(encoder_state_t * const
{ {
encode_alf_aps_flags(state, aps); encode_alf_aps_flags(state, aps);
} }
/*else if (aps->aps_type == T_LMCS_APS) else if (aps->aps_type == T_LMCS_APS)
{ {
codeLmcsAps(pcAPS); //encode_lmcs_aps(state);
}*/ }
/*else if (aps->aps_type == T_SCALING_LIST_APS) /*else if (aps->aps_type == T_SCALING_LIST_APS)
{ {
codeScalingListAps(pcAPS); codeScalingListAps(pcAPS);
@ -1606,7 +1643,7 @@ static void encoder_state_write_adaptation_parameter_set(encoder_state_t * const
//For example, in RA, update is on intra slice, but intra slice may not use reshaper //For example, in RA, update is on intra slice, but intra slice may not use reshaper
static void encode_alf_aps_lmcs(encoder_state_t * const state) static void encode_alf_aps_lmcs(encoder_state_t * const state)
{ {
if (0 /*pcSlice->getSPS()->getUseLmcs()*/) if (state->encoder_control->cfg.lmcs_enable) // ToDo: do something with LMCS
{/* {/*
//only 1 LMCS data for 1 picture //only 1 LMCS data for 1 picture
int apsId = picHeader->getLmcsAPSId(); int apsId = picHeader->getLmcsAPSId();
@ -1670,18 +1707,11 @@ static void encode_alf_aps(encoder_state_t * const state)
if (write_aps) if (write_aps)
{ {
//actualTotalBits += xWriteAPS(accessUnit, aps);
kvz_nal_write(stream, NAL_UNIT_PREFIX_APS, 0, state->frame->first_nal); kvz_nal_write(stream, NAL_UNIT_PREFIX_APS, 0, state->frame->first_nal);
state->frame->first_nal = false; state->frame->first_nal = false;
encoder_state_write_adaptation_parameter_set(state, &aps); encoder_state_write_adaptation_parameter_set(state, &aps);
//apsMap->clearChangedFlag((apsId << NUM_APS_TYPE_LEN) + ALF_APS);
aps_map[aps_id + T_ALF_APS].b_changed = false; aps_map[aps_id + T_ALF_APS].b_changed = false;
//CHECK(aps != pcSlice->getAlfAPSs()[apsId] && apsId != pcSlice->getTileGroupCcAlfCbApsId() && apsId != pcSlice->getTileGroupCcAlfCrApsId(), "Wrong APS pointer in compressGOP");
/*assert(!(aps.aps_id != state->slice->apss[aps_id].aps_id
&& aps_id != state->slice->tile_group_cc_alf_cr_aps_id
&& aps_id != state->slice->tile_group_cc_alf_cr_aps_id)); //"Wrong APS id");*/
} }
} }
} }

View file

@ -631,7 +631,7 @@ static void encoder_state_write_bitstream_seq_parameter_set(bitstream_t* stream,
WRITE_U(stream, encoder->cfg.alf_type == KVZ_ALF_FULL, 1, "sps_ccalf_enabled_flag"); WRITE_U(stream, encoder->cfg.alf_type == KVZ_ALF_FULL, 1, "sps_ccalf_enabled_flag");
} }
WRITE_U(stream, 0, 1, "sps_lmcs_enable_flag"); WRITE_U(stream, encoder->cfg.lmcs_enable, 1, "sps_lmcs_enable_flag");
WRITE_U(stream, 0, 1, "sps_weighted_pred_flag"); // Use of Weighting Prediction (P_SLICE) WRITE_U(stream, 0, 1, "sps_weighted_pred_flag"); // Use of Weighting Prediction (P_SLICE)
WRITE_U(stream, 0, 1, "sps_weighted_bipred_flag"); // Use of Weighting Bi-Prediction (B_SLICE) WRITE_U(stream, 0, 1, "sps_weighted_bipred_flag"); // Use of Weighting Bi-Prediction (B_SLICE)
@ -1111,7 +1111,20 @@ static void kvz_encoder_state_write_bitstream_picture_header(
state->tile->frame->alf_cc_enable_flag[COMPONENT_Cb] = false; state->tile->frame->alf_cc_enable_flag[COMPONENT_Cb] = false;
state->tile->frame->alf_cc_enable_flag[COMPONENT_Cr] = false;*/ state->tile->frame->alf_cc_enable_flag[COMPONENT_Cr] = false;*/
} }
if (encoder->cfg.lmcs_enable)
{
WRITE_U(stream, 1, 1, "ph_lmcs_enabled_flag");
//if (picHeader->getLmcsEnabledFlag())
{
WRITE_U(stream, 0, 2, "ph_lmcs_aps_id");
if (encoder->chroma_format != KVZ_CSP_400)
{
WRITE_U(stream, 0, 1, "ph_chroma_residual_scale_flag"); // ToDo: LMCS Enable chroma scaling
}
}
}
// getDeblockingFilterControlPresentFlag // getDeblockingFilterControlPresentFlag
// END PICTURE HEADER // END PICTURE HEADER
@ -1494,6 +1507,15 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state)
// Adaptation parameter set (APS) // Adaptation parameter set (APS)
kvz_encode_alf_adaptive_parameter_set(state); kvz_encode_alf_adaptive_parameter_set(state);
if (state->encoder_control->cfg.lmcs_enable) {
// ToDo: Write LMCS APS NAL
/*
kvz_nal_write(stream, NAL_UNIT_PREFIX_APS, 0, state->frame->first_nal);
state->frame->first_nal = false;
encoder_state_write_adaptation_parameter_set(state, &aps);
*/
}
encoder_state_write_bitstream_children(state); encoder_state_write_bitstream_children(state);
if (state->encoder_control->cfg.hash != KVZ_HASH_NONE) { if (state->encoder_control->cfg.hash != KVZ_HASH_NONE) {

View file

@ -53,6 +53,12 @@
// VVC related definitions // VVC related definitions
#define ENABLE_WPP_PARALLELISM 0 #define ENABLE_WPP_PARALLELISM 0
//LMCS
#define PIC_CODE_CW_BINS 16
#define PIC_ANALYZE_CW_BINS 32
#define LMCS_SEG_NUM 32
#define FP_PREC 11
#define CSCALE_FP_PREC 11
/** /**
* \defgroup Bitstream * \defgroup Bitstream

97
src/reshape.c Normal file
View file

@ -0,0 +1,97 @@
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2021 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "reshape.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "cabac.h"
#include "rdo.h"
#include "strategies/strategies-sao.h"
#include "kvz_math.h"
void kvz_free_lmcs_aps(lmcs_aps* aps)
{
FREE_POINTER(aps->m_invLUT);
FREE_POINTER(aps->m_fwdLUT);
}
void kvz_init_lmcs_seq_stats(lmcs_seq_info* stats, int32_t m_binNum)
{
for (int i = 0; i < m_binNum; i++)
{
stats->binVar[i] = 0.0;
stats->binHist[i] = 0.0;
stats->normVar[i] = 0.0;
}
stats->nonZeroCnt = 0;
stats->weightVar = 0.0;
stats->weightNorm = 0.0;
stats->minBinVar = 0.0;
stats->maxBinVar = 0.0;
stats->meanBinVar = 0.0;
stats->ratioStdU = 0.0;
stats->ratioStdV = 0.0;
}
void kvz_init_lmcs_aps(lmcs_aps* aps, int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight, int bitDepth)
{
aps->m_lumaBD = bitDepth;
aps->m_reshapeLUTSize = 1 << aps->m_lumaBD;
aps->m_initCWAnalyze = aps->m_reshapeLUTSize / PIC_ANALYZE_CW_BINS;
aps->m_initCW = aps->m_reshapeLUTSize / PIC_CODE_CW_BINS;
aps->m_fwdLUT = calloc(1, sizeof(kvz_pixel) * aps->m_reshapeLUTSize);
aps->m_invLUT = calloc(1, sizeof(kvz_pixel) * aps->m_reshapeLUTSize);
memset(aps->m_binCW, 0, sizeof(uint16_t) * PIC_ANALYZE_CW_BINS);
memset(aps->m_binImportance, 0, sizeof(uint32_t) * PIC_ANALYZE_CW_BINS);
memset(aps->m_reshapePivot, 0, sizeof(kvz_pixel) * PIC_CODE_CW_BINS + 1);
memset(aps->m_inputPivot, 0, sizeof(kvz_pixel) * PIC_CODE_CW_BINS + 1);
for (int i = 0; i < PIC_CODE_CW_BINS; i++) {
aps->m_fwdScaleCoef[i] = 1 << FP_PREC;
}
for (int i = 0; i < PIC_CODE_CW_BINS; i++) {
aps->m_invScaleCoef[i] = 1 << FP_PREC;
}
for (int i = 0; i < PIC_CODE_CW_BINS; i++) {
aps->m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
}
aps->m_sliceReshapeInfo.sliceReshaperEnableFlag = true;
aps->m_sliceReshapeInfo.enableChromaAdj = true;
aps->m_sliceReshapeInfo.sliceReshaperModelPresentFlag = true;
aps->m_sliceReshapeInfo.reshaperModelMinBinIdx = 0;
aps->m_sliceReshapeInfo.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1;
memset(aps->m_sliceReshapeInfo.reshaperModelBinCWDelta, 0, (PIC_CODE_CW_BINS) * sizeof(int));
aps->m_sliceReshapeInfo.chrResScalingOffset = 0;
aps->m_binNum = PIC_CODE_CW_BINS;
kvz_init_lmcs_seq_stats(&aps->m_srcSeqStats, aps->m_binNum);
kvz_init_lmcs_seq_stats(&aps->m_rspSeqStats, aps->m_binNum);
}

105
src/reshape.h Normal file
View file

@ -0,0 +1,105 @@
#pragma once
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2021 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* \ingroup Reconstruction
* \file
* LMCS reshape.
*/
#include "checkpoint.h"
#include "cu.h"
#include "encoder.h"
#include "encoderstate.h"
#include "global.h" // IWYU pragma: keep
#include "kvazaar.h"
#include "videoframe.h"
#include "image.h"
#include "nal.h"
typedef struct lmcs_seq_info
{
double binVar[32];
double binHist[32];
double normVar[32];
int nonZeroCnt;
double weightVar;
double weightNorm;
double minBinVar;
double maxBinVar;
double meanBinVar;
double ratioStdU;
double ratioStdV;
} lmcs_seq_info;
typedef struct SliceReshapeInfo {
bool sliceReshaperEnableFlag;
bool sliceReshaperModelPresentFlag;
unsigned enableChromaAdj;
uint32_t reshaperModelMinBinIdx;
uint32_t reshaperModelMaxBinIdx;
int reshaperModelBinCWDelta[PIC_CODE_CW_BINS];
int maxNbitsNeededDeltaCW;
int chrResScalingOffset;
} SliceReshapeInfo;
typedef struct lmcs_aps {
SliceReshapeInfo m_sliceReshapeInfo;
bool m_CTUFlag;
bool m_recReshaped;
kvz_pixel* m_invLUT;
kvz_pixel* m_fwdLUT;
int32_t m_chromaAdjHelpLUT[PIC_CODE_CW_BINS];
uint16_t m_binCW[PIC_ANALYZE_CW_BINS];
uint16_t m_initCW;
bool m_reshape;
kvz_pixel m_reshapePivot[PIC_CODE_CW_BINS + 1];
kvz_pixel m_inputPivot[PIC_CODE_CW_BINS + 1];
int32_t m_fwdScaleCoef[PIC_CODE_CW_BINS];
int32_t m_invScaleCoef[PIC_CODE_CW_BINS];
int m_lumaBD;
int m_reshapeLUTSize;
int m_chromaScale;
int m_vpduX;
int m_vpduY;
bool m_exceedSTD;
uint32_t m_binImportance[PIC_ANALYZE_CW_BINS];
int m_tcase;
int m_rateAdpMode;
bool m_useAdpCW;
uint16_t m_initCWAnalyze;
//ReshapeCW m_reshapeCW;
kvz_pixel m_cwLumaWeight[PIC_CODE_CW_BINS];
double m_chromaWeight;
int m_chromaAdj;
int m_binNum;
lmcs_seq_info m_srcSeqStats;
lmcs_seq_info m_rspSeqStats;
} lmcs_aps;
void kvz_free_lmcs_aps(lmcs_aps* aps);
void kvz_init_lmcs_seq_stats(lmcs_seq_info* stats, int32_t m_binNum);
void kvz_init_lmcs_aps(lmcs_aps* aps, int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight, int bitDepth);