1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
|
/*****************************************************************************
* Copyright (C) 2013-2020 MulticoreWare, Inc
*
* Authors: Steve Borho <steve@borho.org>
* Min Chen <chenm003@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
*
* This program is also available under a commercial proprietary license.
* For more information, contact us at license @ x265.com.
*****************************************************************************/
#ifndef X265_ENTROPY_H
#define X265_ENTROPY_H
#include "common.h"
#include "bitstream.h"
#include "frame.h"
#include "cudata.h"
#include "contexts.h"
#include "slice.h"
namespace X265_NS {
// private namespace
struct SaoCtuParam;
struct EstBitsSbac;
class ScalingList;
enum SplitType
{
DONT_SPLIT = 0,
VERTICAL_SPLIT = 1,
QUAD_SPLIT = 2,
NUMBER_OF_SPLIT_MODES = 3
};
struct TURecurse
{
uint32_t section;
uint32_t splitMode;
uint32_t absPartIdxTURelCU;
uint32_t absPartIdxStep;
TURecurse(SplitType splitType, uint32_t _absPartIdxStep, uint32_t _absPartIdxTU)
{
static const uint32_t partIdxStepShift[NUMBER_OF_SPLIT_MODES] = { 0, 1, 2 };
section = 0;
absPartIdxTURelCU = _absPartIdxTU;
splitMode = (uint32_t)splitType;
absPartIdxStep = _absPartIdxStep >> partIdxStepShift[splitMode];
}
bool isNextSection()
{
if (splitMode == DONT_SPLIT)
{
section++;
return false;
}
else
{
absPartIdxTURelCU += absPartIdxStep;
section++;
return section < (uint32_t)(1 << splitMode);
}
}
bool isLastSection() const
{
return (section + 1) >= (uint32_t)(1 << splitMode);
}
};
struct EstBitsSbac
{
int significantCoeffGroupBits[NUM_SIG_CG_FLAG_CTX][2];
int significantBits[2][NUM_SIG_FLAG_CTX];
int lastBits[2][10];
int greaterOneBits[NUM_ONE_FLAG_CTX][2];
int levelAbsBits[NUM_ABS_FLAG_CTX][2];
int blockCbpBits[NUM_QT_CBF_CTX][2];
int blockRootCbpBits[2];
};
class Entropy : public SyntaxElementWriter
{
public:
uint64_t m_pad;
uint8_t m_contextState[160]; // MAX_OFF_CTX_MOD + padding
/* CABAC state */
uint32_t m_low;
uint32_t m_range;
uint32_t m_bufferedByte;
int m_numBufferedBytes;
int m_bitsLeft;
uint64_t m_fracBits;
EstBitsSbac m_estBitsSbac;
double m_meanQP;
Entropy();
void setBitstream(Bitstream* p) { m_bitIf = p; }
uint32_t getNumberOfWrittenBits()
{
X265_CHECK(!m_bitIf, "bit counting mode expected\n");
return (uint32_t)(m_fracBits >> 15);
}
#if CHECKED_BUILD || _DEBUG
bool m_valid;
void markInvalid() { m_valid = false; }
void markValid() { m_valid = true; }
#else
void markValid() { }
#endif
void zeroFract() { m_fracBits = 0; }
void resetBits();
void resetEntropy(const Slice& slice);
// SBAC RD
void load(const Entropy& src) { copyFrom(src); }
void store(Entropy& dest) const { dest.copyFrom(*this); }
void loadContexts(const Entropy& src) { copyContextsFrom(src); }
void loadIntraDirModeLuma(const Entropy& src);
void copyState(const Entropy& other);
#if ENABLE_ALPHA || ENABLE_MULTIVIEW
void codeVPS(const VPS& vps, const SPS& sps);
#else
void codeVPS(const VPS& vps);
#endif
void codeSPS(const SPS& sps, const ScalingList& scalingList, const ProfileTierLevel& ptl, int layer = 0);
void codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26, int layer = 0);
void codeVUI(const VUI& vui, int maxSubTLayers, bool bEmitVUITimingInfo, bool bEmitVUIHRDInfo, int layer = 0);
void codeAUD(const Slice& slice);
void codeHrdParameters(const HRDInfo& hrd, int maxSubTLayers);
void codeSliceHeader(const Slice& slice, FrameData& encData, uint32_t slice_addr, uint32_t slice_addr_bits, int sliceQp, int layer = 0);
void codeSliceHeaderWPPEntryPoints(const uint32_t *substreamSizes, uint32_t numSubStreams, uint32_t maxOffset);
void codeShortTermRefPicSet(const RPS& rps, int idx);
void finishSlice() { encodeBinTrm(1); finish(); dynamic_cast<Bitstream*>(m_bitIf)->writeByteAlignment(); }
void encodeCTU(const CUData& cu, const CUGeom& cuGeom);
void codeIntraDirLumaAng(const CUData& cu, uint32_t absPartIdx, bool isMultiple);
void codeIntraDirChroma(const CUData& cu, uint32_t absPartIdx, uint32_t *chromaDirMode);
void codeMergeIndex(const CUData& cu, uint32_t absPartIdx);
void codeMvd(const CUData& cu, uint32_t absPartIdx, int list);
void codePartSize(const CUData& cu, uint32_t absPartIdx, uint32_t depth);
void codePredInfo(const CUData& cu, uint32_t absPartIdx);
void codeQtCbfChroma(const CUData& cu, uint32_t absPartIdx, TextType ttype, uint32_t tuDepth, bool lowestLevel);
void codeCoeff(const CUData& cu, uint32_t absPartIdx, bool& bCodeDQP, const uint32_t depthRange[2]);
void codeCoeffNxN(const CUData& cu, const coeff_t* coef, uint32_t absPartIdx, uint32_t log2TrSize, TextType ttype);
inline void codeSaoMerge(uint32_t code) { encodeBin(code, m_contextState[OFF_SAO_MERGE_FLAG_CTX]); }
inline void codeSaoType(uint32_t code) { encodeBin(code, m_contextState[OFF_SAO_TYPE_IDX_CTX]); }
inline void codeMVPIdx(uint32_t symbol) { encodeBin(symbol, m_contextState[OFF_MVP_IDX_CTX]); }
inline void codeMergeFlag(const CUData& cu, uint32_t absPartIdx) { encodeBin(cu.m_mergeFlag[absPartIdx], m_contextState[OFF_MERGE_FLAG_EXT_CTX]); }
inline void codeSkipFlag(const CUData& cu, uint32_t absPartIdx) { encodeBin(cu.isSkipped(absPartIdx), m_contextState[OFF_SKIP_FLAG_CTX + cu.getCtxSkipFlag(absPartIdx)]); }
inline void codeSplitFlag(const CUData& cu, uint32_t absPartIdx, uint32_t depth) { encodeBin(cu.m_cuDepth[absPartIdx] > depth, m_contextState[OFF_SPLIT_FLAG_CTX + cu.getCtxSplitFlag(absPartIdx, depth)]); }
inline void codeTransformSubdivFlag(uint32_t symbol, uint32_t ctx) { encodeBin(symbol, m_contextState[OFF_TRANS_SUBDIV_FLAG_CTX + ctx]); }
inline void codePredMode(int predMode) { encodeBin(predMode == MODE_INTRA ? 1 : 0, m_contextState[OFF_PRED_MODE_CTX]); }
inline void codeCUTransquantBypassFlag(uint32_t symbol) { encodeBin(symbol, m_contextState[OFF_TQUANT_BYPASS_FLAG_CTX]); }
inline void codeQtCbfLuma(uint32_t cbf, uint32_t tuDepth) { encodeBin(cbf, m_contextState[OFF_QT_CBF_CTX + !tuDepth]); }
inline void codeQtCbfChroma(uint32_t cbf, uint32_t tuDepth) { encodeBin(cbf, m_contextState[OFF_QT_CBF_CTX + 2 + tuDepth]); }
inline void codeQtRootCbf(uint32_t cbf) { encodeBin(cbf, m_contextState[OFF_QT_ROOT_CBF_CTX]); }
inline void codeTransformSkipFlags(uint32_t transformSkip, TextType ttype) { encodeBin(transformSkip, m_contextState[OFF_TRANSFORMSKIP_FLAG_CTX + (ttype ? NUM_TRANSFORMSKIP_FLAG_CTX : 0)]); }
void codeDeltaQP(const CUData& cu, uint32_t absPartIdx);
void codeSaoOffset(const SaoCtuParam& ctuParam, int plane);
void codeSaoOffsetEO(int *offset, int typeIdx, int plane);
void codeSaoOffsetBO(int *offset, int bandPos, int plane);
/* RDO functions */
void estBit(EstBitsSbac& estBitsSbac, uint32_t log2TrSize, bool bIsLuma) const;
void estCBFBit(EstBitsSbac& estBitsSbac) const;
void estSignificantCoeffGroupMapBit(EstBitsSbac& estBitsSbac, bool bIsLuma) const;
void estSignificantMapBit(EstBitsSbac& estBitsSbac, uint32_t log2TrSize, bool bIsLuma) const;
void estSignificantCoefficientsBit(EstBitsSbac& estBitsSbac, bool bIsLuma) const;
inline uint32_t bitsIntraModeNonMPM() const { return bitsCodeBin(0, m_contextState[OFF_ADI_CTX]) + 5; }
inline uint32_t bitsIntraModeMPM(const uint32_t preds[3], uint32_t dir) const { return bitsCodeBin(1, m_contextState[OFF_ADI_CTX]) + (dir == preds[0] ? 1 : 2); }
inline uint32_t estimateCbfBits(uint32_t cbf, TextType ttype, uint32_t tuDepth) const { return bitsCodeBin(cbf, m_contextState[OFF_QT_CBF_CTX + ctxCbf[ttype][tuDepth]]); }
uint32_t bitsInterMode(const CUData& cu, uint32_t absPartIdx, uint32_t depth) const;
uint32_t bitsIntraMode(const CUData& cu, uint32_t absPartIdx) const
{
return bitsCodeBin(0, m_contextState[OFF_SKIP_FLAG_CTX + cu.getCtxSkipFlag(absPartIdx)]) + /* not skip */
bitsCodeBin(1, m_contextState[OFF_PRED_MODE_CTX]); /* intra */
}
/* these functions are only used to estimate the bits when cbf is 0 and will never be called when writing the bistream. */
inline void codeQtRootCbfZero() { encodeBin(0, m_contextState[OFF_QT_ROOT_CBF_CTX]); }
private:
/* CABAC private methods */
void start();
void finish();
void encodeBin(uint32_t binValue, uint8_t& ctxModel);
void encodeBinEP(uint32_t binValue);
void encodeBinsEP(uint32_t binValues, int numBins);
void encodeBinTrm(uint32_t binValue);
/* return the bits of encoding the context bin without updating */
inline uint32_t bitsCodeBin(uint32_t binValue, uint32_t ctxModel) const
{
uint64_t fracBits = (m_fracBits & 32767) + sbacGetEntropyBits(ctxModel, binValue);
return (uint32_t)(fracBits >> 15);
}
void encodeCU(const CUData& ctu, const CUGeom &cuGeom, uint32_t absPartIdx, uint32_t depth, bool& bEncodeDQP);
void finishCU(const CUData& ctu, uint32_t absPartIdx, uint32_t depth, bool bEncodeDQP);
void writeOut();
/* SBac private methods */
void writeUnaryMaxSymbol(uint32_t symbol, uint8_t* scmModel, int offset, uint32_t maxSymbol);
void writeEpExGolomb(uint32_t symbol, uint32_t count);
void writeCoefRemainExGolomb(uint32_t symbol, const uint32_t absGoRice);
void codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers, int layer = 0);
void codeScalingList(const ScalingList&);
void codeScalingList(const ScalingList& scalingList, uint32_t sizeId, uint32_t listId);
void codePredWeightTable(const Slice& slice);
void codeInterDir(const CUData& cu, uint32_t absPartIdx);
void codePUWise(const CUData& cu, uint32_t absPartIdx);
void codeRefFrmIdxPU(const CUData& cu, uint32_t absPartIdx, int list);
void codeRefFrmIdx(const CUData& cu, uint32_t absPartIdx, int list);
void codeSaoMaxUvlc(uint32_t code, uint32_t maxSymbol);
void codeLastSignificantXY(uint32_t posx, uint32_t posy, uint32_t log2TrSize, bool bIsLuma, uint32_t scanIdx);
void encodeTransform(const CUData& cu, uint32_t absPartIdx, uint32_t tuDepth, uint32_t log2TrSize,
bool& bCodeDQP, const uint32_t depthRange[2]);
void encodeTransformLuma(const CUData& cu, uint32_t absPartIdx, uint32_t tuDepth, uint32_t log2TrSize,
bool& bCodeDQP, const uint32_t depthRange[2]);
void copyFrom(const Entropy& src);
void copyContextsFrom(const Entropy& src);
};
}
#endif // ifndef X265_ENTROPY_H
|