123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- //*@@@+++@@@@******************************************************************
- //
- // Copyright © Microsoft Corp.
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // • Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // • Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- //
- //*@@@---@@@@******************************************************************
- #include "strcodec.h"
- #include "encode.h"
- I32 QUANT_Mulless(PixelI v, PixelI o, I32 r)
- {
- const I32 m = v >> 31;
- assert(sizeof(PixelI) == sizeof(U32));
- return ((((v ^ m) - m + o) >> r) ^ m) - m;
- }
- I32 MUL32HR(U32 a, U32 b, U32 r)
- {
- return (I32)((U32)((U64)a * b >> 32) >> r);
- }
- I32 QUANT(PixelI v, PixelI o, I32 man, I32 exp)
- {
- const I32 m = v >> 31;
- assert(sizeof(PixelI) == sizeof(U32));
- return (MUL32HR((v ^ m) - m + o, man, exp) ^ m) - m;
- }
- Int quantizeMacroblock(CWMImageStrCodec* pSC)
- {
- CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
- CWMIMBInfo * pMBInfo = &pSC->MBInfo;
- const COLORFORMAT cf = pSC->m_param.cfColorFormat;
- int iChannel, i, j;
- if(/*pSC->m_param.bScaledArith && */pSC->m_param.bTranscode == FALSE)
- for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){
- const Bool bUV = (iChannel > 0 && (cf == YUV_444 || cf == YUV_422 || cf == YUV_420));
- const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16);
- const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset));
- CWMIQuantizer * pQPDC = pTile->pQuantizerDC[iChannel];
- CWMIQuantizer * pQPLP = pTile->pQuantizerLP[iChannel] + pMBInfo->iQIndexLP;
- CWMIQuantizer * pQPHP = pTile->pQuantizerHP[iChannel] + pMBInfo->iQIndexHP;
- for(j = 0; j < iNumBlock; j ++){
- PixelI * pData = pSC->pPlane[iChannel] + pOffset[j];
- if(j == 0) // DC
- pData[0] = (pQPDC->iMan == 0 ? QUANT_Mulless(pData[0], pQPDC->iOffset, pQPDC->iExp) : QUANT(pData[0], pQPDC->iOffset, pQPDC->iMan, pQPDC->iExp));
- else if(pSC->WMISCP.sbSubband != SB_DC_ONLY) // LP
- pData[0] = (pQPLP->iMan == 0 ? QUANT_Mulless(pData[0], pQPLP->iOffset, pQPLP->iExp) : QUANT(pData[0], pQPLP->iOffset, pQPLP->iMan, pQPLP->iExp));
- // quantize HP
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
- for(i = 1; i < 16; i ++)
- pData[i] = (pQPHP->iMan == 0 ? QUANT_Mulless(pData[i], pQPHP->iOffset, pQPHP->iExp) : QUANT(pData[i], pQPHP->iOffset, pQPHP->iMan, pQPHP->iExp));
- }
- }
-
- for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){
- I32 * pDC = pSC->MBInfo.iBlockDC[iChannel];
- PixelI * pData = pSC->pPlane[iChannel];
- if(iChannel > 0 && cf == YUV_422){
- for(i = 0; i < 8; i ++){
- pDC[i] = pData[blkOffsetUV_422[i]];
- }
- }
- else if(iChannel > 0 && cf == YUV_420){
- for(i = 0; i < 4; i ++){
- pDC[i] = pData[blkOffsetUV[i]];
- }
- }
- else{
- for(i = 0; i < 16; i ++){
- pDC[i] = pData[dctIndex[2][i]];
- }
- }
- }
- return 0;
- }
- /* frequency domain prediction */
- Void predMacroblockEnc(CWMImageStrCodec * pSC)
- {
- const COLORFORMAT cf = pSC->m_param.cfColorFormat;
- const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels;
- size_t mbX = pSC->cColumn - 1;// mbY = pSC->cRow - 1;
- CWMIMBInfo *pMBInfo = &(pSC->MBInfo);
- Int iDCACPredMode = getDCACPredMode(pSC, mbX);
- Int iDCPredMode = (iDCACPredMode & 0x3);
- Int iADPredMode = (iDCACPredMode & 0xC);
- Int iACPredMode = getACPredMode(pMBInfo, cf);
- PixelI * pOrg, * pRef;
- Int i, j, k;
- pMBInfo->iOrientation = 2 - iACPredMode;
- /* keep necessary info for future prediction */
- updatePredInfo(pSC, pMBInfo, mbX, cf);
- for(i = 0; i < iChannels; i ++){
- pOrg = pMBInfo->iBlockDC[i]; // current DC block
-
- /* DC prediction */
- if(iDCPredMode == 1){ // predict DC from top
- pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;
- }
- else if(iDCPredMode == 0){ // predict DC from left
- pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;
- }
- else if(iDCPredMode == 2){// predict DC from top&left
- pOrg[0] -= ((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC) >> 1;
- }
- /* AD prediction */
- if(iADPredMode == 4){// predict AD from top
- pRef = (pSC->PredInfoPrevRow[i] + mbX)->piAD;
- pOrg[4] -= pRef[3], pOrg[8] -= pRef[4], pOrg[12] -= pRef[5];
- }
- else if(iADPredMode == 0){// predict AD from left
- pRef = (pSC->PredInfo[i] + mbX - 1)->piAD;
- pOrg[1] -= pRef[0], pOrg[2] -= pRef[1], pOrg[3] -= pRef[2];
- }
-
- pOrg = pSC->pPlane[i];
- /* AC prediction */
- if(iACPredMode == 1){ // predict from top
- for(k = 0; k <= 192; k += 64){
- /* inside macroblock, in reverse order */
- for(j = 48; j > 0; j -= 16){
- pOrg[k + j + 10] -= pOrg[k + j + 10 - 16];
- pOrg[k + j + 2] -= pOrg[k + j + 2 - 16];
- pOrg[k + j + 9] -= pOrg[k + j + 9 - 16];
- }
- }
- }
- else if(iACPredMode == 0){ // predict from left
- for(k = 0; k < 64; k += 16){
- /* inside macroblock, in reverse order */
- for(j = 192; j > 0; j -= 64){
- pOrg[k + j + 5] -= pOrg[k + j + 5 - 64];
- pOrg[k + j + 1] -= pOrg[k + j + 1 - 64];
- pOrg[k + j + 6] -= pOrg[k + j + 6 - 64];
- }
- }
- }
- }
- if(cf == YUV_420){
- for(i = 1; i < 3; i ++){
- pOrg = pMBInfo->iBlockDC[i]; // current DC block
- /* DC prediciton */
- if(iDCPredMode == 1){ // predict DC from top
- pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;
- }
- else if(iDCPredMode == 0){ // predict DC from left
- pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;
- }
- else if(iDCPredMode == 2){ // predict DC from top&left
- pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1);
- }
- /* AD prediction */
- if(iADPredMode == 4){// predict AD from top
- pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[1];
- }
- else if(iADPredMode == 0){// predict AD from left
- pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0];
- }
- pOrg = pSC->pPlane[i];
- /* AC prediction */
- if(iACPredMode == 1){ // predict from top
- for(j = 16; j <= 48; j += 32){
- /* inside macroblock */
- pOrg[j + 10] -= pOrg[j + 10 - 16];
- pOrg[j + 2] -= pOrg[j + 2 - 16];
- pOrg[j + 9] -= pOrg[j + 9 - 16];
- }
- }
- else if(iACPredMode == 0){ // predict from left
- for(j = 32; j <= 48; j += 16){
- /* inside macroblock */
- pOrg[j + 5] -= pOrg[j + 5 - 32];
- pOrg[j + 1] -= pOrg[j + 1 - 32];
- pOrg[j + 6] -= pOrg[j + 6 - 32];
- }
- }
- }
- }
- else if(cf == YUV_422){
- for(i = 1; i < 3; i ++){
- pOrg = pMBInfo->iBlockDC[i]; // current DC block
- /* DC prediciton */
- if(iDCPredMode == 1){ // predict DC from top
- pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;
- }
- else if(iDCPredMode == 0){ // predict DC from left
- pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;
- }
- else if(iDCPredMode == 2){ // predict DC from top&left
- pOrg[0] -= (((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC + 1) >> 1);
- }
- /* AD prediction */
- if(iADPredMode == 4){// predict AD from top
- pOrg[4] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[4]; // AC of HT !!!
- pOrg[6] -= pOrg[2];
- pOrg[2] -= (pSC->PredInfoPrevRow[i] + mbX)->piAD[3];
- }
- else if(iADPredMode == 0){// predict AD from left
- pOrg[4] -= (pSC->PredInfo[i] + mbX - 1)->piAD[4]; // AC of HT !!!
- pOrg[1] -= (pSC->PredInfo[i] + mbX - 1)->piAD[0];
- pOrg[5] -= (pSC->PredInfo[i] + mbX - 1)->piAD[2];
- }
- else if(iDCPredMode == 1){
- pOrg[6] -= pOrg[2];
- }
- pOrg = pSC->pPlane[i]; // current MB
- /* AC prediction */
- if(iACPredMode == 1){ // predict from top
- for(j = 48; j > 0; j -= 16){
- for(k = 0; k <= 64; k += 64){
- /* inside macroblock */
- pOrg[j + k + 10] -= pOrg[j + k + 10 - 16];
- pOrg[j + k + 2] -= pOrg[j + k + 2 - 16];
- pOrg[j + k + 9] -= pOrg[j + k + 9 - 16];
- }
- }
- }
- else if(iACPredMode == 0){ // predict from left
- for(j = 64; j <= 112; j += 16){
- /* inside macroblock */
- pOrg[j + 5] -= pOrg[j + 5 - 64];
- pOrg[j + 1] -= pOrg[j + 1 - 64];
- pOrg[j + 6] -= pOrg[j + 6 - 64];
- }
- }
- }
- }
- }
- /* CBP prediction for 16 x 16 MB */
- /* block index */
- /* 0 1 4 5 */
- /* 2 3 6 7 */
- /* 8 9 12 13 */
- /* 10 11 14 15 */
- static int NumOnes(int i)
- {
- int retval = 0;
- static const int g_Count[] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 };
- i = i & 0xffff;
- while (i) {
- retval += g_Count[i & 0xf];
- i >>= 4;
- }
- return retval;
- }
- #define SATURATE32(x) if((unsigned int)(x + 16) >= 32) { if (x < 0) x = -16; else x = 15; }
- static Int predCBPCEnc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)
- {
- Int iPredCBP = 0, iRetval = 0;
- Int iNOrig = NumOnes(iCBP), iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);
- UNREFERENCED_PARAMETER( mbY );
- /* only top left block pattern is predicted from neighbour */
- if(pSC->m_bCtxLeft) {
- if (pSC->m_bCtxTop) {
- iPredCBP = 1;
- }
- else {
- Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;
- iPredCBP = (iTopCBP >> 10) & 1; // left: top(10) => 0
- }
- }
- else {
- Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;
- iPredCBP = ((iLeftCBP >> 5) & 1); // left(5) => 0
- }
- iPredCBP |= (iCBP & 0x3300) << 2; // [8 9 12 13]->[10 11 14 15]
- iPredCBP |= (iCBP & 0xcc) << 6; // [2 3 6 7]->[8 9 12 13]
- iPredCBP |= (iCBP & 0x33) << 2; // [0 1 4 5]->[2 3 6 7]
- iPredCBP |= (iCBP & 0x11) << 1; // [0 4]->[1 5]
- iPredCBP |= (iCBP & 0x2) << 3; // [1]->[4]
- if (c) c = 1;
- if (pModel->m_iState[c] == 0) {
- iRetval = iPredCBP ^ iCBP;
- }
- else if (pModel->m_iState[c] == 1) {
- iRetval = iCBP;
- }
- else {
- iRetval = iCBP ^ 0xffff;
- }
- pModel->m_iCount0[c] += iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount0[c]);
- pModel->m_iCount1[c] += 16 - iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount1[c]);
- if (pModel->m_iCount0[c] < 0) {
- if (pModel->m_iCount0[c] < pModel->m_iCount1[c]) {
- pModel->m_iState[c] = 1;
- }
- else {
- pModel->m_iState[c] = 2;
- }
- }
- else if (pModel->m_iCount1[c] < 0) {
- pModel->m_iState[c] = 2;
- }
- else {
- pModel->m_iState[c] = 0;
- }
- return iRetval;
- }
- static Int predCBPC420Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)
- {
- Int iPredCBP = 0, iRetval = 0;
- Int iNOrig = NumOnes(iCBP) * 4, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);
- UNREFERENCED_PARAMETER( mbY );
- /* only top left block pattern is predicted from neighbour */
- if(pSC->m_bCtxLeft) {
- if (pSC->m_bCtxTop) {
- iPredCBP = 1;
- }
- else {
- Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;
- iPredCBP = (iTopCBP >> 2) & 1; // left: top(2) => 0
- }
- }
- else {
- Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;
- iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0
- }
- iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1]
- iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3]
- if (pModel->m_iState[1] == 0) {
- iRetval = iPredCBP ^ iCBP;
- }
- else if (pModel->m_iState[1] == 1) {
- iRetval = iCBP;
- }
- else {
- iRetval = iCBP ^ 0xf;
- }
- pModel->m_iCount0[1] += iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount0[1]);
- pModel->m_iCount1[1] += 16 - iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount1[1]);
- if (pModel->m_iCount0[1] < 0) {
- if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) {
- pModel->m_iState[1] = 1;
- }
- else {
- pModel->m_iState[1] = 2;
- }
- }
- else if (pModel->m_iCount1[1] < 0) {
- pModel->m_iState[1] = 2;
- }
- else {
- pModel->m_iState[1] = 0;
- }
- return iRetval;
- }
- static Int predCBPC422Enc(CWMImageStrCodec *pSC, Int iCBP, size_t mbX, size_t mbY, size_t c, CCBPModel *pModel)
- {
- Int iPredCBP = 0, iRetval = 0;
- Int iNOrig = NumOnes(iCBP) * 2, iNDiff = AVG_NDIFF;//NumOnes(iPredCBP ^ iCBP);
- UNREFERENCED_PARAMETER( mbY );
- /* only top left block pattern is predicted from neighbour */
- if(pSC->m_bCtxLeft) {
- if (pSC->m_bCtxTop) {
- iPredCBP = 1;
- }
- else {
- Int iTopCBP = (pSC->PredInfoPrevRow[c] + mbX)->iCBP;
- iPredCBP = (iTopCBP >> 6) & 1; // left: top(6) => 0
- }
- }
- else {
- Int iLeftCBP = (pSC->PredInfo[c] + mbX - 1)->iCBP;
- iPredCBP = ((iLeftCBP >> 1) & 1); // left(1) => 0
- }
- iPredCBP |= (iCBP & 0x1) << 1; // [0]->[1]
- iPredCBP |= (iCBP & 0x3) << 2; // [0 1]->[2 3]
- iPredCBP |= (iCBP & 0xc) << 2; // [2 3]->[4 5]
- iPredCBP |= (iCBP & 0x30) << 2; // [4 5]->[6 7]
- if (pModel->m_iState[1] == 0) {
- iRetval = iPredCBP ^ iCBP;
- }
- else if (pModel->m_iState[1] == 1) {
- iRetval = iCBP;
- }
- else {
- iRetval = iCBP ^ 0xff;
- }
- pModel->m_iCount0[1] += iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount0[1]);
- pModel->m_iCount1[1] += 16 - iNOrig - iNDiff;
- SATURATE32(pModel->m_iCount1[1]);
- if (pModel->m_iCount0[1] < 0) {
- if (pModel->m_iCount0[1] < pModel->m_iCount1[1]) {
- pModel->m_iState[1] = 1;
- }
- else {
- pModel->m_iState[1] = 2;
- }
- }
- else if (pModel->m_iCount1[1] < 0) {
- pModel->m_iState[1] = 2;
- }
- else {
- pModel->m_iState[1] = 0;
- }
- return iRetval;
- }
- Void predCBPEnc(CWMImageStrCodec* pSC, CCodingContext *pContext)
- {
- size_t mbX = pSC->cColumn - 1, mbY = pSC->cRow - 1;
- CWMIMBInfo * pMBInfo = &(pSC->MBInfo);
- int iChannel, i, j;
- for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){
- const COLORFORMAT cf = pSC->m_param.cfColorFormat;
- const Bool bUV = (iChannel > 0);
- const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16);
- const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset));
- const Int threshold = (1 << pContext->m_aModelAC.m_iFlcBits[bUV ? 1 : 0]) - 1, threshold2 = threshold * 2 + 1;
- Int iCBP = 0;
- for(j = 0; j < iNumBlock; j ++){
- PixelI * pData = pSC->pPlane[iChannel] + pOffset[j];
- for(i = 1; i < 16; i ++){
- if((unsigned int)(pData[i] + threshold) >= (unsigned int) threshold2){ // significant coeff
- iCBP |= (1 << j); // update CBP
- break;
- }
- }
- }
-
- pMBInfo->iCBP[iChannel] = (pSC->PredInfo[iChannel] + mbX)->iCBP = iCBP;
- if(iNumBlock == 16){
- pMBInfo->iDiffCBP[iChannel] = predCBPCEnc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);
- }
- else if(iNumBlock == 8){
- pSC->MBInfo.iDiffCBP[iChannel] = predCBPC422Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);
- }
- else{
- pSC->MBInfo.iDiffCBP[iChannel] = predCBPC420Enc(pSC, pMBInfo->iCBP[iChannel], mbX, mbY, iChannel, &pContext->m_aCBPModel);
- }
- }
- }
|