Path: blob/master/libs/jxr/image/encode/strPredQuantEnc.c
4393 views
//*@@@+++@@@@******************************************************************1//2// Copyright © Microsoft Corp.3// All rights reserved.4//5// Redistribution and use in source and binary forms, with or without6// modification, are permitted provided that the following conditions are met:7//8// • Redistributions of source code must retain the above copyright notice,9// this list of conditions and the following disclaimer.10// • Redistributions in binary form must reproduce the above copyright notice,11// this list of conditions and the following disclaimer in the documentation12// and/or other materials provided with the distribution.13//14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"15// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE18// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR19// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF20// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS21// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN22// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)23// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE24// POSSIBILITY OF SUCH DAMAGE.25//26//*@@@---@@@@******************************************************************2728#include "strcodec.h"29#include "encode.h"3031I32 QUANT_Mulless(PixelI v, PixelI o, I32 r)32{33const I32 m = v >> 31;3435assert(sizeof(PixelI) == sizeof(U32));36return ((((v ^ m) - m + o) >> r) ^ m) - m;37}3839I32 MUL32HR(U32 a, U32 b, U32 r)40{41return (I32)((U32)((U64)a * b >> 32) >> r);42}4344I32 QUANT(PixelI v, PixelI o, I32 man, I32 exp)45{46const I32 m = v >> 31;4748assert(sizeof(PixelI) == sizeof(U32));49return (MUL32HR((v ^ m) - m + o, man, exp) ^ m) - m;50}5152Int quantizeMacroblock(CWMImageStrCodec* pSC)53{54CWMITile * pTile = pSC->pTile + pSC->cTileColumn;55CWMIMBInfo * pMBInfo = &pSC->MBInfo;56const COLORFORMAT cf = pSC->m_param.cfColorFormat;57int iChannel, i, j;5859if(/*pSC->m_param.bScaledArith && */pSC->m_param.bTranscode == FALSE)60for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){61const Bool bUV = (iChannel > 0 && (cf == YUV_444 || cf == YUV_422 || cf == YUV_420));62const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16);63const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset));64CWMIQuantizer * pQPDC = pTile->pQuantizerDC[iChannel];65CWMIQuantizer * pQPLP = pTile->pQuantizerLP[iChannel] + pMBInfo->iQIndexLP;66CWMIQuantizer * pQPHP = pTile->pQuantizerHP[iChannel] + pMBInfo->iQIndexHP;6768for(j = 0; j < iNumBlock; j ++){69PixelI * pData = pSC->pPlane[iChannel] + pOffset[j];7071if(j == 0) // DC72pData[0] = (pQPDC->iMan == 0 ? QUANT_Mulless(pData[0], pQPDC->iOffset, pQPDC->iExp) : QUANT(pData[0], pQPDC->iOffset, pQPDC->iMan, pQPDC->iExp));73else if(pSC->WMISCP.sbSubband != SB_DC_ONLY) // LP74pData[0] = (pQPLP->iMan == 0 ? QUANT_Mulless(pData[0], pQPLP->iOffset, pQPLP->iExp) : QUANT(pData[0], pQPLP->iOffset, pQPLP->iMan, pQPLP->iExp));7576// quantize HP77if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)78for(i = 1; i < 16; i ++)79pData[i] = (pQPHP->iMan == 0 ? QUANT_Mulless(pData[i], pQPHP->iOffset, pQPHP->iExp) : QUANT(pData[i], pQPHP->iOffset, pQPHP->iMan, pQPHP->iExp));80}81}8283for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){84I32 * pDC = pSC->MBInfo.iBlockDC[iChannel];85PixelI * pData = pSC->pPlane[iChannel];8687if(iChannel > 0 && cf == YUV_422){88for(i = 0; i < 8; i ++){89pDC[i] = pData[blkOffsetUV_422[i]];90}91}92else if(iChannel > 0 && cf == YUV_420){93for(i = 0; i < 4; i ++){94pDC[i] = pData[blkOffsetUV[i]];95}96}97else{98for(i = 0; i < 16; i ++){99pDC[i] = pData[dctIndex[2][i]];100}101}102}103104return 0;105}106107/* frequency domain prediction */108Void predMacroblockEnc(CWMImageStrCodec * pSC)109{110const COLORFORMAT cf = pSC->m_param.cfColorFormat;111const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels;112size_t mbX = pSC->cColumn - 1;// mbY = pSC->cRow - 1;113CWMIMBInfo *pMBInfo = &(pSC->MBInfo);114Int iDCACPredMode = getDCACPredMode(pSC, mbX);115Int iDCPredMode = (iDCACPredMode & 0x3);116Int iADPredMode = (iDCACPredMode & 0xC);117Int iACPredMode = getACPredMode(pMBInfo, cf);118PixelI * pOrg, * pRef;119Int i, j, k;120121pMBInfo->iOrientation = 2 - iACPredMode;122123/* keep necessary info for future prediction */124updatePredInfo(pSC, pMBInfo, mbX, cf);125126for(i = 0; i < iChannels; i ++){127pOrg = pMBInfo->iBlockDC[i]; // current DC block128129/* DC prediction */130if(iDCPredMode == 1){ // predict DC from top131pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;132}133else if(iDCPredMode == 0){ // predict DC from left134pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;135}136else if(iDCPredMode == 2){// predict DC from top&left137pOrg[0] -= ((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC) >> 1;138}139140/* AD prediction */141if(iADPredMode == 4){// predict AD from top142pRef = (pSC->PredInfoPrevRow[i] + mbX)->piAD;143pOrg[4] -= pRef[3], pOrg[8] -= pRef[4], pOrg[12] -= pRef[5];144}145else if(iADPredMode == 0){// predict AD from left146pRef = (pSC->PredInfo[i] + mbX - 1)->piAD;147pOrg[1] -= pRef[0], pOrg[2] -= pRef[1], pOrg[3] -= pRef[2];148}149150pOrg = pSC->pPlane[i];151/* AC prediction */152if(iACPredMode == 1){ // predict from top153for(k = 0; k <= 192; k += 64){154/* inside macroblock, in reverse order */155for(j = 48; j > 0; j -= 16){156pOrg[k + j + 10] -= pOrg[k + j + 10 - 16];157pOrg[k + j + 2] -= pOrg[k + j + 2 - 16];158pOrg[k + j + 9] -= pOrg[k + j + 9 - 16];159}160}161}162else if(iACPredMode == 0){ // predict from left163for(k = 0; k < 64; k += 16){164/* inside macroblock, in reverse order */165for(j = 192; j > 0; j -= 64){166pOrg[k + j + 5] -= pOrg[k + j + 5 - 64];167pOrg[k + j + 1] -= pOrg[k + j + 1 - 64];168pOrg[k + j + 6] -= pOrg[k + j + 6 - 64];169}170}171}172}173174if(cf == YUV_420){175for(i = 1; i < 3; i ++){176pOrg = pMBInfo->iBlockDC[i]; // current DC block177178/* DC prediciton */179if(iDCPredMode == 1){ // predict DC from top180pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;181}182else if(iDCPredMode == 0){ // predict DC from left183pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;184}185else if(iDCPredMode == 2){ // predict DC from top&left186pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1);187}188189/* AD prediction */190if(iADPredMode == 4){// predict AD from top191pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[1];192}193else if(iADPredMode == 0){// predict AD from left194pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0];195}196197pOrg = pSC->pPlane[i];198/* AC prediction */199if(iACPredMode == 1){ // predict from top200for(j = 16; j <= 48; j += 32){201/* inside macroblock */202pOrg[j + 10] -= pOrg[j + 10 - 16];203pOrg[j + 2] -= pOrg[j + 2 - 16];204pOrg[j + 9] -= pOrg[j + 9 - 16];205}206}207else if(iACPredMode == 0){ // predict from left208for(j = 32; j <= 48; j += 16){209/* inside macroblock */210pOrg[j + 5] -= pOrg[j + 5 - 32];211pOrg[j + 1] -= pOrg[j + 1 - 32];212pOrg[j + 6] -= pOrg[j + 6 - 32];213}214}215}216}217else if(cf == YUV_422){218for(i = 1; i < 3; i ++){219pOrg = pMBInfo->iBlockDC[i]; // current DC block220221/* DC prediciton */222if(iDCPredMode == 1){ // predict DC from top223pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;224}225else if(iDCPredMode == 0){ // predict DC from left226pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;227}228else if(iDCPredMode == 2){ // predict DC from top&left229pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1);230}231232/* AD prediction */233if(iADPredMode == 4){// predict AD from top234pOrg[4] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[4]; // AC of HT !!!235pOrg[6] -= pOrg[2];236pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[3];237}238else if(iADPredMode == 0){// predict AD from left239pOrg[4] -= (pSC->PredInfo[i] + mbX - 1)->piAD[4]; // AC of HT !!!240pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0];241pOrg[5] -= (pSC->PredInfo[i] + mbX - 1)->piAD[2];242}243else if(iDCPredMode == 1){244pOrg[6] -= pOrg[2];245}246247pOrg = pSC->pPlane[i]; // current MB248/* AC prediction */249if(iACPredMode == 1){ // predict from top250for(j = 48; j > 0; j -= 16){251for(k = 0; k <= 64; k += 64){252/* inside macroblock */253pOrg[j + k + 10] -= pOrg[j + k + 10 - 16];254pOrg[j + k + 2] -= pOrg[j + k + 2 - 16];255pOrg[j + k + 9] -= pOrg[j + k + 9 - 16];256}257}258}259else if(iACPredMode == 0){ // predict from left260for(j = 64; j <= 112; j += 16){261/* inside macroblock */262pOrg[j + 5] -= pOrg[j + 5 - 64];263pOrg[j + 1] -= pOrg[j + 1 - 64];264pOrg[j + 6] -= pOrg[j + 6 - 64];265}266}267}268}269}270271272/* CBP prediction for 16 x 16 MB */273/* block index */274/* 0 1 4 5 */275/* 2 3 6 7 */276/* 8 9 12 13 */277/* 10 11 14 15 */278279static int NumOnes(int i)280{281int retval = 0;282static const int g_Count[] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 };283i = i & 0xffff;284while (i) {285retval += g_Count[i & 0xf];286i >>= 4;287}288return retval;289}290291#define SATURATE32(x) if((unsigned int)(x + 16) >= 32) { if (x < 0) x = -16; else x = 15; }292293static Int predCBPCEnc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)294{295Int iPredCBP = 0, iRetval = 0;296Int iNOrig = NumOnes(iCBP), iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);297298UNREFERENCED_PARAMETER( mbY );299300/* only top left block pattern is predicted from neighbour */301if(pSC->m_bCtxLeft) {302if (pSC->m_bCtxTop) {303iPredCBP = 1;304}305else {306Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;307iPredCBP = (iTopCBP >> 10) & 1; // left: top(10) => 0308}309}310else {311Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;312iPredCBP = ((iLeftCBP >> 5) & 1); // left(5) => 0313}314315iPredCBP |= (iCBP & 0x3300) << 2; // [8 9 12 13]->[10 11 14 15]316iPredCBP |= (iCBP & 0xcc) << 6; // [2 3 6 7]->[8 9 12 13]317iPredCBP |= (iCBP & 0x33) << 2; // [0 1 4 5]->[2 3 6 7]318iPredCBP |= (iCBP & 0x11) << 1; // [0 4]->[1 5]319iPredCBP |= (iCBP & 0x2) << 3; // [1]->[4]320321if (c) c = 1;322if (pModel->m_iState[c] == 0) {323iRetval = iPredCBP ^ iCBP;324}325else if (pModel->m_iState[c] == 1) {326iRetval = iCBP;327}328else {329iRetval = iCBP ^ 0xffff;330}331332pModel->m_iCount0[c] += iNOrig - iNDiff;333SATURATE32(pModel->m_iCount0[c]);334335pModel->m_iCount1[c] += 16 - iNOrig - iNDiff;336SATURATE32(pModel->m_iCount1[c]);337338if (pModel->m_iCount0[c] < 0) {339if (pModel->m_iCount0[c] < pModel->m_iCount1[c]) {340pModel->m_iState[c] = 1;341}342else {343pModel->m_iState[c] = 2;344}345}346else if (pModel->m_iCount1[c] < 0) {347pModel->m_iState[c] = 2;348}349else {350pModel->m_iState[c] = 0;351}352return iRetval;353}354355static Int predCBPC420Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)356{357Int iPredCBP = 0, iRetval = 0;358Int iNOrig = NumOnes(iCBP) * 4, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);359360UNREFERENCED_PARAMETER( mbY );361362/* only top left block pattern is predicted from neighbour */363if(pSC->m_bCtxLeft) {364if (pSC->m_bCtxTop) {365iPredCBP = 1;366}367else {368Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;369iPredCBP = (iTopCBP >> 2) & 1; // left: top(2) => 0370}371}372else {373Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;374iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0375}376377iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1]378iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3]379380if (pModel->m_iState[1] == 0) {381iRetval = iPredCBP ^ iCBP;382}383else if (pModel->m_iState[1] == 1) {384iRetval = iCBP;385}386else {387iRetval = iCBP ^ 0xf;388}389390pModel->m_iCount0[1] += iNOrig - iNDiff;391SATURATE32(pModel->m_iCount0[1]);392393pModel->m_iCount1[1] += 16 - iNOrig - iNDiff;394SATURATE32(pModel->m_iCount1[1]);395396if (pModel->m_iCount0[1] < 0) {397if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) {398pModel->m_iState[1] = 1;399}400else {401pModel->m_iState[1] = 2;402}403}404else if (pModel->m_iCount1[1] < 0) {405pModel->m_iState[1] = 2;406}407else {408pModel->m_iState[1] = 0;409}410return iRetval;411}412413static Int predCBPC422Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)414{415Int iPredCBP = 0, iRetval = 0;416Int iNOrig = NumOnes(iCBP) * 2, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);417418UNREFERENCED_PARAMETER( mbY );419420/* only top left block pattern is predicted from neighbour */421if(pSC->m_bCtxLeft) {422if (pSC->m_bCtxTop) {423iPredCBP = 1;424}425else {426Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;427iPredCBP = (iTopCBP >> 6) & 1; // left: top(6) => 0428}429}430else {431Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;432iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0433}434435iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1]436iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3]437iPredCBP |= (iCBP & 0xc) << 2; // [2 3]->[4 5]438iPredCBP |= (iCBP & 0x30) << 2; // [4 5]->[6 7]439440if (pModel->m_iState[1] == 0) {441iRetval = iPredCBP ^ iCBP;442}443else if (pModel->m_iState[1] == 1) {444iRetval = iCBP;445}446else {447iRetval = iCBP ^ 0xff;448}449450pModel->m_iCount0[1] += iNOrig - iNDiff;451SATURATE32(pModel->m_iCount0[1]);452453pModel->m_iCount1[1] += 16 - iNOrig - iNDiff;454SATURATE32(pModel->m_iCount1[1]);455456if (pModel->m_iCount0[1] < 0) {457if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) {458pModel->m_iState[1] = 1;459}460else {461pModel->m_iState[1] = 2;462}463}464else if (pModel->m_iCount1[1] < 0) {465pModel->m_iState[1] = 2;466}467else {468pModel->m_iState[1] = 0;469}470return iRetval;471}472473Void predCBPEnc(CWMImageStrCodec* pSC, CCodingContext *pContext)474{475size_t mbX = pSC->cColumn - 1, mbY = pSC->cRow - 1;476CWMIMBInfo * pMBInfo = &(pSC->MBInfo);477int iChannel, i, j;478479for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){480const COLORFORMAT cf = pSC->m_param.cfColorFormat;481const Bool bUV = (iChannel > 0);482const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16);483const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset));484const Int threshold = (1 << pContext->m_aModelAC.m_iFlcBits[bUV ? 1 : 0]) - 1, threshold2 = threshold * 2 + 1;485Int iCBP = 0;486487for(j = 0; j < iNumBlock; j ++){488PixelI * pData = pSC->pPlane[iChannel] + pOffset[j];489for(i = 1; i < 16; i ++){490if((unsigned int)(pData[i] + threshold) >= (unsigned int) threshold2){ // significant coeff491iCBP |= (1 << j); // update CBP492break;493}494}495}496497pMBInfo->iCBP[iChannel] = (pSC->PredInfo[iChannel] + mbX)->iCBP = iCBP;498499if(iNumBlock == 16){500pMBInfo->iDiffCBP[iChannel] = predCBPCEnc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);501}502else if(iNumBlock == 8){503pSC->MBInfo.iDiffCBP[iChannel] = predCBPC422Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);504}505else{506pSC->MBInfo.iDiffCBP[iChannel] = predCBPC420Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);507}508}509}510511512513