public void writeMBQpDelta(MEncoder encoder, MBType prevMbType, int mbQpDelta) { int ctx = 60; ctx += prevMbType == null || prevMbType == MBType.I_PCM || (prevMbType != MBType.I_16x16 && prevCBP == 0) || prevMbQpDelta == 0 ? 0 : 1; prevMbQpDelta = mbQpDelta; if (mbQpDelta-- == 0) { encoder.encodeBin(ctx, 0); } else { encoder.encodeBin(ctx, 1); if (mbQpDelta-- == 0) { encoder.encodeBin(62, 0); } else { while (mbQpDelta-- > 0) { encoder.encodeBin(63, 1); } encoder.encodeBin(63, 0); } } }
public void writeMBTypeI(MEncoder encoder, MBType left, MBType top, bool leftAvailable, bool topAvailable, int mbType) { int ctx = 3; ctx += !leftAvailable || left == MBType.I_NxN ? 0 : 1; ctx += !topAvailable || top == MBType.I_NxN ? 0 : 1; if (mbType == 0) { encoder.encodeBin(ctx, 0); } else { encoder.encodeBin(ctx, 1); if (mbType == 25) { encoder.encodeBinFinal(1); } else { encoder.encodeBinFinal(0); writeMBType16x16(encoder, mbType - 1); } } }
private void writeMBType16x16(MEncoder encoder, int mbType) { if (mbType < 12) { encoder.encodeBin(6, 0); } else { encoder.encodeBin(6, 1); mbType -= 12; } if (mbType < 4) { encoder.encodeBin(7, 0); encoder.encodeBin(9, mbType >> 1); encoder.encodeBin(10, mbType & 1); } else { mbType -= 4; encoder.encodeBin(7, 1); encoder.encodeBin(8, mbType >> 2); encoder.encodeBin(9, (mbType >> 1) & 1); encoder.encodeBin(10, mbType & 1); } }
public void writeIntraChromaPredMode(MEncoder encoder, int mbX, MBType left, MBType top, bool leftAvailable, bool topAvailable, int mode) { int ctx = 64; ctx += !leftAvailable || !left.isIntra() || chromaPredModeLeft == 0 ? 0 : 1; ctx += !topAvailable || !top.isIntra() || chromaPredModeTop[mbX] == 0 ? 0 : 1; encoder.encodeBin(ctx, mode-- == 0 ? 0 : 1); for (int i = 0; mode >= 0 && i < 2; i++) { encoder.encodeBin(67, mode-- == 0 ? 0 : 1); } chromaPredModeLeft = chromaPredModeTop[mbX] = mode; }
public void writeCoeffs(MEncoder encoder, BlockType blockType, int[] _out, int first, int num, int[] reorder) { for (int i = 0; i < num; i++) { tmp[i] = _out[reorder[first + i]]; } int numCoeff = 0; for (int i = 0; i < num; i++) { if (tmp[i] != 0) { numCoeff = i + 1; } } for (int i = 0; i < Math.Min(numCoeff, num - 1); i++) { if (tmp[i] != 0) { encoder.encodeBin(blockType.sigCoeffFlagCtxOff + i, 1); encoder.encodeBin(blockType.lastSigCoeffCtxOff + i, i == numCoeff - 1 ? 1 : 0); } else { encoder.encodeBin(blockType.sigCoeffFlagCtxOff + i, 0); } } int numGt1 = 0, numEq1 = 0; for (int j = numCoeff - 1; j >= 0; j--) { if (tmp[j] == 0) { continue; } int absLev = Math.Abs(tmp[j]) - 1; writeCoeffAbsLevel(encoder, blockType, numGt1, numEq1, absLev); if (absLev == 0) { ++numEq1; } else { ++numGt1; } encoder.encodeBinBypass(sign(tmp[j])); } }
private void writeCoeffAbsLevel(MEncoder encoder, BlockType blockType, int numDecodAbsLevelGt1, int numDecodAbsLevelEq1, int absLev) { int incB0 = ((numDecodAbsLevelGt1 != 0) ? 0 : Math.Min(4, 1 + numDecodAbsLevelEq1)); int incBN = 5 + Math.Min(4 - blockType.coeffAbsLevelAdjust, numDecodAbsLevelGt1); if (absLev == 0) { encoder.encodeBin(blockType.coeffAbsLevelCtxOff + incB0, 0); } else { encoder.encodeBin(blockType.coeffAbsLevelCtxOff + incB0, 1); if (absLev < 14) { for (int i = 1; i < absLev; i++) { encoder.encodeBin(blockType.coeffAbsLevelCtxOff + incBN, 1); } encoder.encodeBin(blockType.coeffAbsLevelCtxOff + incBN, 0); } else { for (int i = 1; i < 14; i++) { encoder.encodeBin(blockType.coeffAbsLevelCtxOff + incBN, 1); } absLev -= 14; int sufLen, pow; for (sufLen = 0, pow = 1; absLev >= pow; sufLen++, pow = (1 << sufLen)) { encoder.encodeBinBypass(1); absLev -= pow; } encoder.encodeBinBypass(0); for (sufLen--; sufLen >= 0; sufLen--) { encoder.encodeBinBypass((absLev >> sufLen) & 1); } } } }