Path: blob/master/libs/jxr/image/decode/JXRTranscode.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 "windowsmediaphoto.h"29#include "strcodec.h"30#include "decode.h"3132EXTERN_C Void freePredInfo(CWMImageStrCodec *);3334EXTERN_C Int ReadWMIHeader(CWMImageInfo *, CWMIStrCodecParam *, CCoreParameters *);35EXTERN_C Int StrIODecInit(CWMImageStrCodec *);36EXTERN_C Int StrDecInit(CWMImageStrCodec *);37EXTERN_C Int readPackets(CWMImageStrCodec *);38EXTERN_C Int DecodeMacroblockDC(CWMImageStrCodec *, CCodingContext *, Int, Int);39EXTERN_C Int DecodeMacroblockLowpass(CWMImageStrCodec *, CCodingContext *, Int, Int);40EXTERN_C Int DecodeMacroblockHighpass(CWMImageStrCodec *, CCodingContext *, Int, Int);41EXTERN_C Void predDCACDec(CWMImageStrCodec *);42EXTERN_C Void predACDec(CWMImageStrCodec *);43EXTERN_C Void StrIODecTerm(CWMImageStrCodec *);44EXTERN_C Void FreeCodingContextDec(CWMImageStrCodec *);4546EXTERN_C Int StrEncInit(CWMImageStrCodec *);47EXTERN_C Void StrIOEncTerm(CWMImageStrCodec *);48EXTERN_C Void FreeCodingContextEnc(CWMImageStrCodec *);49EXTERN_C Int encodeMB(CWMImageStrCodec *, Int, Int);50EXTERN_C Int writeIndexTableNull(CWMImageStrCodec *);51EXTERN_C Void writePacketHeader(BitIOInfo *, U8, U8);5253EXTERN_C Int WriteWMIHeader(CWMImageStrCodec *);54EXTERN_C Int ReadImagePlaneHeader(CWMImageInfo *, CWMIStrCodecParam *, CCoreParameters *, SimpleBitIO *);55EXTERN_C Int WriteImagePlaneHeader(CWMImageStrCodec *);56EXTERN_C Int writeIndexTable(CWMImageStrCodec *);57EXTERN_C Int copyTo(struct WMPStream *, struct WMPStream *, size_t);5859const static Bool bFlipV[O_MAX] = {FALSE, TRUE , FALSE, TRUE, TRUE , TRUE, FALSE, FALSE};60const static Bool bFlipH[O_MAX] = {FALSE, FALSE, TRUE , TRUE, FALSE, TRUE, FALSE, TRUE};6162typedef struct CTileQPInfo63{64U8 dcMode;65U8 dcIndex[MAX_CHANNELS];6667Bool bUseDC;68U8 lpNum;69Bool bUseDCAlpha;70U8 lpNumAlpha;71U8 lpMode[16];72U8 lpIndex[16][MAX_CHANNELS];7374Bool bUseLP;75U8 hpNum;76Bool bUseLPAlpha;77U8 hpNumAlpha;78U8 hpMode[16];79U8 hpIndex[16][MAX_CHANNELS];80} CTileQPInfo;8182Void transcodeQuantizer(BitIOInfo * pIO, U8 cIndex[MAX_CHANNELS], U8 cChMode, size_t cChannel)83{84if(cChMode > 2)85cChMode = 2;8687if(cChannel > 1)88putBit16(pIO, cChMode, 2); // Channel mode89else90cChMode = 0;9192putBit16(pIO, cIndex[0], 8); // Y9394if(cChMode == 1) // MIXED95putBit16(pIO, cIndex[1], 8); // UV96else if(cChMode > 0){ // INDEPENDENT97size_t i;9899for(i = 1; i < cChannel; i ++)100putBit16(pIO, cIndex[i], 8); // UV101}102}103104Void transcodeQuantizers(BitIOInfo * pIO, U8 cIndex[16][MAX_CHANNELS], U8 cChMode[16], U32 cNum, size_t cChannel, Bool bCopy)105{106putBit16(pIO, bCopy == TRUE ? 1 : 0, 1);107if(bCopy == FALSE){108U32 i;109110putBit16(pIO, cNum - 1, 4);111112for(i = 0; i < cNum; i ++)113transcodeQuantizer(pIO, cIndex[i], cChMode[i], cChannel);114}115}116117Void transcodeQuantizersAlpha(BitIOInfo * pIO, U8 cIndex[16][MAX_CHANNELS], U32 cNum, size_t iChannel, Bool bCopy)118{119putBit16(pIO, bCopy == TRUE ? 1 : 0, 1);120if(bCopy == FALSE){121U32 i;122123putBit16(pIO, cNum - 1, 4);124125for(i = 0; i < cNum; i ++)126putBit16(pIO, cIndex[i][iChannel], 8);127}128}129130Void transcodeTileHeader(CWMImageStrCodec * pSC, CTileQPInfo * pTileQPInfo)131{132if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE){ // write packet headers133CCodingContext * pContext = &pSC->m_pCodingContext[pSC->cTileColumn];134CWMITile * pTile = pSC->pTile + pSC->cTileColumn;135U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + pSC->cTileColumn) & 0x1F);136CWMImageStrCodec * pSCAlpha = (pSC->m_param.bAlphaChannel ? pSC->m_pNextSC : NULL);137const size_t iAlphaPos = pSC->m_param.cNumChannels;138139writePacketHeader(pContext->m_pIODC, pSC->WMISCP.bfBitstreamFormat == SPATIAL ? 0 : 1, pID);140if (pSC->m_param.bTrimFlexbitsFlag && pSC->WMISCP.bfBitstreamFormat == SPATIAL)141putBit16(pContext->m_pIODC, pContext->m_iTrimFlexBits, 4);142143if((pSC->m_param.uQPMode & 1) != 0) // not DC uniform144transcodeQuantizer(pContext->m_pIODC, pTileQPInfo->dcIndex, pTileQPInfo->dcMode, pSC->WMISCP.cChannel);145if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 1) != 0) // not DC uniform146putBit16(pContext->m_pIODC, pTileQPInfo->dcIndex[iAlphaPos], 8);147148if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) {149if(pSC->WMISCP.sbSubband != SB_DC_ONLY){150if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform151transcodeQuantizers(pContext->m_pIODC, pTileQPInfo->lpIndex, pTileQPInfo->lpMode, pTileQPInfo->lpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseDC);152if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 2) != 0) // not LP uniform153transcodeQuantizersAlpha(pContext->m_pIODC, pTileQPInfo->lpIndex, pTileQPInfo->lpNumAlpha, iAlphaPos, pTileQPInfo->bUseDCAlpha);154if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){155if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform156transcodeQuantizers(pContext->m_pIODC, pTileQPInfo->hpIndex, pTileQPInfo->hpMode, pTileQPInfo->hpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseLP);157if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 4) != 0) // not HP uniform158transcodeQuantizersAlpha(pContext->m_pIODC, pTileQPInfo->hpIndex, pTileQPInfo->hpNumAlpha, iAlphaPos, pTileQPInfo->bUseLPAlpha);159}160}161}162else{163if(pSC->WMISCP.sbSubband != SB_DC_ONLY){164writePacketHeader(pContext->m_pIOLP, 2, pID);165if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform166transcodeQuantizers(pContext->m_pIOLP, pTileQPInfo->lpIndex, pTileQPInfo->lpMode, pTileQPInfo->lpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseDC);167if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 2) != 0) // not LP uniform168transcodeQuantizersAlpha(pContext->m_pIOLP, pTileQPInfo->lpIndex, pTileQPInfo->lpNumAlpha, iAlphaPos, pTileQPInfo->bUseDCAlpha);169170if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){171writePacketHeader(pContext->m_pIOAC, 3, pID);172if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform173transcodeQuantizers(pContext->m_pIOAC, pTileQPInfo->hpIndex, pTileQPInfo->hpMode, pTileQPInfo->hpNum, pSC->WMISCP.cChannel, pTileQPInfo->bUseLP);174if(pSCAlpha != NULL && (pSCAlpha->m_param.uQPMode & 4) != 0) // not HP uniform175transcodeQuantizersAlpha(pContext->m_pIOAC, pTileQPInfo->hpIndex, pTileQPInfo->hpNumAlpha, iAlphaPos, pTileQPInfo->bUseLPAlpha);176177if(pSC->WMISCP.sbSubband != SB_NO_FLEXBITS){178writePacketHeader(pContext->m_pIOFL, 4, pID);179if (pSC->m_param.bTrimFlexbitsFlag)180putBit16(pContext->m_pIOFL, pContext->m_iTrimFlexBits, 4);181}182}183}184}185pTile->cBitsLP = (pTileQPInfo->bUseDC ? 0 : dquantBits(pTileQPInfo->lpNum));186pTile->cBitsHP = (pTileQPInfo->bUseLP ? 0 : dquantBits(pTileQPInfo->hpNum));187if(pSCAlpha != NULL){188pTile = pSCAlpha->pTile + pSC->cTileColumn;189pTile->cBitsLP = (pTileQPInfo->bUseDCAlpha ? 0 : dquantBits(pTileQPInfo->lpNumAlpha));190pTile->cBitsHP = (pTileQPInfo->bUseLPAlpha ? 0 : dquantBits(pTileQPInfo->hpNumAlpha));191}192}193}194195Void transformDCBlock(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)196{197size_t i;198199if(bFlipV[oOrientation])200for(i = 0; i < 16; i += 4)201pOrg[i + 1] = -pOrg[i + 1], pOrg[i + 3] = -pOrg[i + 3];202203if(bFlipH[oOrientation])204for(i = 0; i < 4; i ++)205pOrg[i + 4] = -pOrg[i + 4], pOrg[i + 12] = -pOrg[i + 12];206207if(oOrientation < O_RCW)208memcpy(pDst, pOrg, 16 * sizeof(PixelI));209else210for(i = 0; i < 16; i ++)211pDst[i] = pOrg[(i >> 2) + ((i & 3) << 2)];212}213214Void transformDCBlock422(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)215{216assert(oOrientation < O_RCW);217218if(bFlipV[oOrientation])219pOrg[1] = -pOrg[1], pOrg[3] = -pOrg[3], pOrg[4] = -pOrg[4], pOrg[5] = -pOrg[5], pOrg[7] = -pOrg[7];220221if(bFlipH[oOrientation])222pOrg[2] = -pOrg[2], pOrg[3] = -pOrg[3], pOrg[6] = -pOrg[6], pOrg[7] = -pOrg[7];223224if(bFlipV[oOrientation])225pDst[0] = pOrg[0], pDst[1] = pOrg[5], pDst[2] = pOrg[6], pDst[3] = pOrg[7], pDst[4] = pOrg[4], pDst[5] = pOrg[1], pDst[6] = pOrg[2], pDst[7] = pOrg[3];226else227memcpy(pDst, pOrg, 8 * sizeof(PixelI));228}229230Void transformDCBlock420(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)231{232if(bFlipV[oOrientation])233pOrg[1] = -pOrg[1], pOrg[3] = -pOrg[3];234235if(bFlipH[oOrientation])236pOrg[2] = -pOrg[2], pOrg[3] = -pOrg[3];237238pDst[0] = pOrg[0], pDst[3] = pOrg[3];239if(oOrientation < O_RCW)240pDst[1] = pOrg[1], pDst[2] = pOrg[2];241else242pDst[1] = pOrg[2], pDst[2] = pOrg[1];243}244245Void transformACBlocks(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)246{247PixelI * pO, * pD;248const Int * pT = dctIndex[0];249size_t i, j, k;250251for(j = 0, pO = pOrg; j < 16; j ++, pO += 16){252if(bFlipV[oOrientation])253for(i = 0; i < 16; i += 4)254pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]];255256if(bFlipH[oOrientation])257for(i = 0; i < 4; i ++)258pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]];259}260261for(j = 0; j < 4; j ++)262for(i = 0; i < 4; i ++){263size_t ii = (bFlipV[oOrientation] ? 3 - i : i);264size_t jj = (bFlipH[oOrientation] ? 3 - j : j);265266if(oOrientation < O_RCW)267memcpy(pDst + (jj * 4 + ii) * 16, pOrg + (j * 4 + i) * 16, 16 * sizeof(PixelI));268else{269pO = pOrg + (j * 4 + i) * 16;270pD = pDst + (ii * 4 + jj) * 16;271for(k = 1; k < 16; k ++)272pD[pT[k]] = pO[pT[(k >> 2) + ((k & 3) << 2)]];273}274}275}276277Void transformACBlocks422(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)278{279PixelI * pO;280const Int * pT = dctIndex[0];281size_t i, j;282283assert(oOrientation < O_RCW);284285for(j = 0, pO = pOrg; j < 8; j ++, pO += 16){286if(bFlipV[oOrientation])287for(i = 0; i < 16; i += 4)288pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]];289290if(bFlipH[oOrientation])291for(i = 0; i < 4; i ++)292pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]];293}294295for(j = 0; j < 2; j ++)296for(i = 0; i < 4; i ++){297size_t ii = (bFlipV[oOrientation] ? 3 - i : i);298size_t jj = (bFlipH[oOrientation] ? 1 - j : j);299300memcpy(pDst + (jj * 4 + ii) * 16, pOrg + (j * 4 + i) * 16, 16 * sizeof(PixelI));301}302}303304Void transformACBlocks420(PixelI * pOrg, PixelI * pDst, ORIENTATION oOrientation)305{306PixelI * pO, * pD;307const Int * pT = dctIndex[0];308size_t i, j, k;309310for(j = 0, pO = pOrg; j < 4; j ++, pO += 16){311if(bFlipV[oOrientation])312for(i = 0; i < 16; i += 4)313pO[pT[i + 1]] = -pO[pT[i + 1]], pO[pT[i + 3]] = -pO[pT[i + 3]];314315if(bFlipH[oOrientation])316for(i = 0; i < 4; i ++)317pO[pT[i + 4]] = -pO[pT[i + 4]], pO[pT[i + 12]] = -pO[pT[i + 12]];318}319320for(j = 0; j < 2; j ++)321for(i = 0; i < 2; i ++){322size_t ii = (bFlipV[oOrientation] ? 1 - i : i);323size_t jj = (bFlipH[oOrientation] ? 1 - j : j);324325if(oOrientation < O_RCW)326memcpy(pDst + (jj * 2 + ii) * 16, pOrg + (j * 2 + i) * 16, 16 * sizeof(PixelI));327else{328pO = pOrg + (j * 2 + i) * 16;329pD = pDst + (ii * 2 + jj) * 16;330for(k = 1; k < 16; k ++)331pD[pT[k]] = pO[pT[(k >> 2) + ((k & 3) << 2)]];332}333}334}335336Int getROI(CWMImageInfo * pII, CCoreParameters * pCore, CWMIStrCodecParam * pSCP, CWMTranscodingParam * pParam)337{338const ORIENTATION oO = pParam->oOrientation;339size_t iLeft, iTop, cWidth, cHeight, i, j;340size_t mbLeft, mbRight, mbTop, mbBottom;341size_t * iTile = (size_t *)malloc(MAX_TILES * sizeof(size_t));342343if(iTile == NULL)344return ICERR_ERROR;345346if(pParam->cLeftX + pParam->cWidth > pII->cWidth || pParam->cTopY + pParam->cHeight > pII->cHeight) // invalid region347return ICERR_ERROR;348349cWidth = pParam->cWidth, cHeight = pParam->cHeight;350iLeft = pParam->cLeftX + pCore->cExtraPixelsLeft, iTop = pParam->cTopY + pCore->cExtraPixelsTop;351if(pSCP->olOverlap != OL_NONE && pParam->bIgnoreOverlap == FALSE){ // include pixels borrowed352size_t cBlurred = (pSCP->olOverlap == OL_TWO ? 10 : 2);353354if(iLeft > cBlurred)355iLeft -= cBlurred, cWidth += cBlurred;356else357cWidth += iLeft, iLeft = 0;358if(iTop > cBlurred)359iTop -= cBlurred, cHeight += cBlurred;360else361cHeight += iTop, iTop = 0;362cWidth += cBlurred, cHeight += cBlurred;363if(iLeft + cWidth > pII->cWidth + pCore->cExtraPixelsLeft + pCore->cExtraPixelsRight)364cWidth = pII->cWidth + pCore->cExtraPixelsLeft + pCore->cExtraPixelsRight - iLeft;365if(iTop + cHeight > pII->cHeight + pCore->cExtraPixelsTop + pCore->cExtraPixelsBottom)366cHeight = pII->cHeight + pCore->cExtraPixelsTop + pCore->cExtraPixelsBottom - iTop;367}368369mbTop = (iTop >> 4), mbLeft = (iLeft >> 4);370mbBottom = (iTop + cHeight + 15) >> 4, mbRight = (iLeft + cWidth + 15) >> 4;371pCore->cExtraPixelsLeft += pParam->cLeftX - (mbLeft << 4);372pCore->cExtraPixelsRight = ((mbRight - mbLeft) << 4) - pParam->cWidth - pCore->cExtraPixelsLeft;373pCore->cExtraPixelsTop += pParam->cTopY - (mbTop << 4);374pCore->cExtraPixelsBottom = ((mbBottom - mbTop) << 4) - pParam->cHeight - pCore->cExtraPixelsTop;375376pII->cWidth = ((mbRight - mbLeft) << 4) - pCore->cExtraPixelsLeft - pCore->cExtraPixelsRight;377pII->cHeight = ((mbBottom - mbTop) << 4) - pCore->cExtraPixelsTop - pCore->cExtraPixelsBottom;378pParam->cLeftX = iLeft, pParam->cTopY = iTop;379pParam->cWidth = cWidth, pParam->cHeight = cHeight;380381// extra pixels in transformed space382#define SWAP(a, b) i = a, a = b, b = i383if(oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH)384SWAP(pCore->cExtraPixelsLeft, pCore->cExtraPixelsRight);385if(oO == O_FLIPV || oO == O_FLIPVH || oO == O_RCW || oO == O_RCW_FLIPV)386SWAP(pCore->cExtraPixelsTop, pCore->cExtraPixelsBottom);387if(oO >= O_RCW){388SWAP(pCore->cExtraPixelsLeft, pCore->cExtraPixelsTop);389SWAP(pCore->cExtraPixelsRight, pCore->cExtraPixelsBottom);390}391392// adjust tiling393for(i = 0, j = 0, iTile[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++)394if((size_t)pSCP->uiTileX[i] >= mbLeft && (size_t)pSCP->uiTileX[i] < mbRight){395if(j >= MAX_TILES)396j = MAX_TILES - 1;397iTile[j] = (size_t)pSCP->uiTileX[i] - mbLeft, j ++;398}399if(iTile[0] == 0)400for(i = 0, pSCP->cNumOfSliceMinus1V = (j == 0 ? 0 : (U32)(j - 1)); i < j; i ++)401pSCP->uiTileX[i] = (U32)iTile[i];402else403for(i = 1, pSCP->uiTileX[0] = 0, pSCP->cNumOfSliceMinus1V = (U32)j; i <= j; i ++)404pSCP->uiTileX[i] = (U32)iTile[i - 1];405if(oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH){ // reverse order406for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++)407iTile[i] = mbRight - mbLeft - (size_t)pSCP->uiTileX[i];408for(i = 1, pSCP->uiTileX[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++)409pSCP->uiTileX[i] = (U32)(iTile[(size_t)pSCP->cNumOfSliceMinus1V - i + 1]);410}411for(i = 0, j = 0, iTile[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++)412if(pSCP->uiTileY[i] >= mbTop && pSCP->uiTileY[i] < mbBottom){413if(j >= MAX_TILES)414j = MAX_TILES - 1;415iTile[j] = (size_t)pSCP->uiTileY[i] - mbTop, j ++;416}417if(iTile[0] == 0)418for(i = 0, pSCP->cNumOfSliceMinus1H = (j == 0 ? 0 : (U32)(j - 1)); i < j; i ++)419pSCP->uiTileY[i] = (U32)iTile[i];420else421for(i = 1, pSCP->uiTileY[0] = 0, pSCP->cNumOfSliceMinus1H = (U32)j; i <= j; i ++)422pSCP->uiTileY[i] = (U32)iTile[i - 1];423if(oO == O_FLIPV || oO == O_FLIPVH || oO == O_RCW || oO == O_RCW_FLIPV){ // reverse order424for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++)425iTile[i] = mbBottom - mbTop - (size_t)pSCP->uiTileY[i];426for(i = 1, pSCP->uiTileY[0] = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++)427pSCP->uiTileY[i] = (U32)(iTile[(size_t)pSCP->cNumOfSliceMinus1H - i + 1]);428}429if(oO >= O_RCW){ // switch X & Y430for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++)431iTile[i] = (size_t)pSCP->uiTileX[i];432for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1H; i ++)433pSCP->uiTileX[i] = pSCP->uiTileY[i];434for(i = 0; i <= (size_t)pSCP->cNumOfSliceMinus1V; i ++)435pSCP->uiTileY[i] = (U32)iTile[i];436i = (size_t)pSCP->cNumOfSliceMinus1H, pSCP->cNumOfSliceMinus1H = pSCP->cNumOfSliceMinus1V, pSCP->cNumOfSliceMinus1V = (U32)i;437}438439free(iTile);440441return ICERR_OK;442}443444Bool isTileBoundary(U32 * pTilePos, U32 cTiles, U32 cMBs, U32 iPos)445{446U32 i;447448for(i = 0; i < cTiles; i ++)449if(iPos == pTilePos[i] * 16)450break;451452return ((i < cTiles || (iPos + 15) / 16 >= cMBs) ? TRUE : FALSE);453}454455Bool isTileExtraction(CWMImageStrCodec * pSC, CWMTranscodingParam * pParam)456{457if(pParam->bIgnoreOverlap == FALSE && pSC->WMISCP.olOverlap == OL_NONE)458pParam->bIgnoreOverlap = TRUE;459460if(pParam->bIgnoreOverlap == TRUE && pParam->oOrientation == O_NONE && pParam->bfBitstreamFormat == pSC->WMISCP.bfBitstreamFormat){461if(pParam->bfBitstreamFormat == SPATIAL && pParam->sbSubband != pSC->WMISCP.sbSubband)462return FALSE;463464return (isTileBoundary(pSC->WMISCP.uiTileX, pSC->WMISCP.cNumOfSliceMinus1V + 1, (U32)pSC->cmbWidth, (U32)(pParam->cLeftX + pSC->m_param.cExtraPixelsLeft)) &&465isTileBoundary(pSC->WMISCP.uiTileY, pSC->WMISCP.cNumOfSliceMinus1H + 1, (U32)pSC->cmbHeight, (U32)(pParam->cTopY + pSC->m_param.cExtraPixelsTop)) &&466isTileBoundary(pSC->WMISCP.uiTileX, pSC->WMISCP.cNumOfSliceMinus1V + 1, (U32)pSC->cmbWidth, (U32)(pParam->cLeftX + pParam->cWidth + pSC->m_param.cExtraPixelsLeft)) &&467isTileBoundary(pSC->WMISCP.uiTileY, pSC->WMISCP.cNumOfSliceMinus1H + 1, (U32)pSC->cmbHeight, (U32)(pParam->cTopY + pParam->cHeight + pSC->m_param.cExtraPixelsTop)));468}469470return FALSE;471}472473Int WMPhotoTranscode(struct WMPStream * pStreamIn, struct WMPStream * pStreamOut, CWMTranscodingParam * pParam)474{475PixelI * pMBBuf, MBBufAlpha[256]; // shared buffer, decoder <=> encoder bridge476PixelI * pFrameBuf = NULL, * pFrameBufAlpha = NULL;477CWMIMBInfo * pMBInfo = NULL, * pMBInfoAlpha = NULL;478CWMImageStrCodec * pSCDec, * pSCEnc, * pSC;479CWMDecoderParameters aDecoderParam = {0};480U8 * pIOHeaderDec, * pIOHeaderEnc;481CCodingContext * pContext;482CTileQPInfo * pTileQPInfo = NULL;483ORIENTATION oO = pParam->oOrientation;484size_t iAlphaPos = 0;485size_t cUnit;486size_t i, j, mbLeft, mbRight, mbTop, mbBottom, mbWidth, mbHeight;487488if(pStreamIn == NULL || pStreamOut == NULL || pParam == NULL)489return ICERR_ERROR;490491// initialize decoder492if((pSCDec = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL)493return ICERR_ERROR;494memset(pSCDec, 0, sizeof(CWMImageStrCodec));495496pSCDec->WMISCP.pWStream = pStreamIn;497if(ReadWMIHeader(&pSCDec->WMII, &pSCDec->WMISCP, &pSCDec->m_param) != ICERR_OK)498return ICERR_ERROR;499500if(pSCDec->WMISCP.cfColorFormat == YUV_422 && oO >= O_RCW)501pParam->oOrientation = oO = O_NONE; // Can not rotate 422 in compressed domain!502503pSCDec->cmbWidth = (pSCDec->WMII.cWidth + pSCDec->m_param.cExtraPixelsLeft + pSCDec->m_param.cExtraPixelsRight + 15) / 16;504pSCDec->cmbHeight = (pSCDec->WMII.cHeight + pSCDec->m_param.cExtraPixelsTop + pSCDec->m_param.cExtraPixelsBottom + 15) / 16;505pSCDec->m_param.cNumChannels = pSCDec->WMISCP.cChannel;506pSCDec->m_Dparam = &aDecoderParam;507pSCDec->m_Dparam->bSkipFlexbits = (pSCDec->WMISCP.sbSubband == SB_NO_FLEXBITS);508pSCDec->m_param.bTranscode = TRUE;509510pParam->bIgnoreOverlap = isTileExtraction(pSCDec, pParam);511512cUnit = (pSCDec->m_param.cfColorFormat == YUV_420 ? 384 : (pSCDec->m_param.cfColorFormat == YUV_422 ? 512 : 256 * pSCDec->m_param.cNumChannels));513if(cUnit > 256 * MAX_CHANNELS)514return ICERR_ERROR;515pSCDec->p1MBbuffer[0] = pMBBuf = (PixelI *)malloc(cUnit * sizeof(PixelI));516if(pMBBuf == NULL)517return ICERR_ERROR;518pSCDec->p1MBbuffer[1] = pSCDec->p1MBbuffer[0] + 256;519for(i = 2; i < pSCDec->m_param.cNumChannels; i ++)520pSCDec->p1MBbuffer[i] = pSCDec->p1MBbuffer[i - 1] + (pSCDec->m_param.cfColorFormat == YUV_420 ? 64 : (pSCDec->m_param.cfColorFormat == YUV_422 ? 128 : 256));521522if(pSCDec->m_param.bAlphaChannel){ // alpha channel523SimpleBitIO SB = {0};524525iAlphaPos = pSCDec->m_param.cNumChannels;526if((pSCDec->m_pNextSC = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL)527return ICERR_ERROR;528*pSCDec->m_pNextSC = *pSCDec;529pSCDec->m_pNextSC->p1MBbuffer[0] = MBBufAlpha;530pSCDec->m_pNextSC->WMISCP.cfColorFormat = pSCDec->m_pNextSC->WMII.cfColorFormat = pSCDec->m_pNextSC->m_param.cfColorFormat = Y_ONLY;531pSCDec->m_pNextSC->WMISCP.cChannel = pSCDec->m_pNextSC->m_param.cNumChannels = 1;532pSCDec->m_pNextSC->m_bSecondary = TRUE;533pSCDec->m_pNextSC->m_pNextSC = pSCDec;534535// read plane header of second image plane536if(attach_SB(&SB, pSCDec->WMISCP.pWStream) != ICERR_OK)537return ICERR_ERROR;538ReadImagePlaneHeader(&pSCDec->m_pNextSC->WMII, &pSCDec->m_pNextSC->WMISCP, &pSCDec->m_pNextSC->m_param, &SB);539detach_SB(&SB);540541if(StrDecInit(pSCDec->m_pNextSC) != ICERR_OK)542return ICERR_ERROR;543}544else545pParam->uAlphaMode = 0;546547pIOHeaderDec = (U8 *)malloc((PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo));548if(pIOHeaderDec == NULL)549return ICERR_ERROR;550memset(pIOHeaderDec, 0, (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo));551pSCDec->pIOHeader = (BitIOInfo *)((U8 *)ALIGNUP(pIOHeaderDec, PACKETLENGTH * 4) + PACKETLENGTH * 2);552553if(StrIODecInit(pSCDec) != ICERR_OK)554return ICERR_ERROR;555556if(StrDecInit(pSCDec) != ICERR_OK)557return ICERR_ERROR;558559if(pSCDec->m_param.bAlphaChannel){ // alpha channel560if(StrDecInit(pSCDec->m_pNextSC) != ICERR_OK)561return ICERR_ERROR;562}563564// initialize encoder565if((pSCEnc = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL)566return ICERR_ERROR;567memset(pSCEnc, 0, sizeof(CWMImageStrCodec));568569pSCEnc->WMII = pSCDec->WMII;570pSCEnc->WMISCP = pSCDec->WMISCP;571pSCEnc->m_param = pSCDec->m_param;572pSCEnc->WMISCP.pWStream = pStreamOut;573pSCEnc->WMISCP.bfBitstreamFormat = pParam->bfBitstreamFormat;574// pSCEnc->m_param.cfColorFormat = pSCEnc->WMISCP.cfColorFormat = pParam->cfColorFormat;575pSCEnc->m_param.cfColorFormat = pSCEnc->WMISCP.cfColorFormat;576pSCEnc->m_param.cNumChannels = (pSCEnc->WMISCP.cfColorFormat == Y_ONLY ? 1 : (pSCEnc->WMISCP.cfColorFormat == YUV_444 ? 3 : pSCEnc->WMISCP.cChannel));577pSCEnc->m_param.bAlphaChannel = (pParam->uAlphaMode > 0);578pSCEnc->m_param.bTranscode = TRUE;579if(pParam->sbSubband >= SB_MAX)580pParam->sbSubband = SB_ALL;581if(pParam->sbSubband > pSCEnc->WMISCP.sbSubband)582pSCEnc->WMISCP.sbSubband = pParam->sbSubband;583pSCEnc->m_bSecondary = FALSE;584585pIOHeaderEnc = (U8 *)malloc((PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo));586if(pIOHeaderEnc == NULL)587return ICERR_ERROR;588memset(pIOHeaderEnc, 0, (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 + sizeof(BitIOInfo));589pSCEnc->pIOHeader = (BitIOInfo *)((U8 *)ALIGNUP(pIOHeaderEnc, PACKETLENGTH * 4) + PACKETLENGTH * 2);590591for(i = 0; i < pSCEnc->m_param.cNumChannels; i ++)592pSCEnc->pPlane[i] = pSCDec->p1MBbuffer[i];593594for(i = 1; i < pSCDec->cNumBitIO * (pSCDec->WMISCP.cNumOfSliceMinus1H + 1); i ++){595if(pSCDec->pIndexTable[i] == 0 && i + 1 != pSCDec->cNumBitIO * (pSCDec->WMISCP.cNumOfSliceMinus1H + 1)) // empty packet596pSCDec->pIndexTable[i] = pSCDec->pIndexTable[i + 1];597if(pSCDec->pIndexTable[i] != 0 && pSCDec->pIndexTable[i] < pSCDec->pIndexTable[i - 1]) // out of order bitstream, can not do fast tile extraction!598pParam->bIgnoreOverlap = FALSE;599}600601if(getROI(&pSCEnc->WMII, &pSCEnc->m_param, &pSCEnc->WMISCP, pParam) != ICERR_OK)602return ICERR_ERROR;603604mbLeft = (pParam->cLeftX >> 4);605mbRight = ((pParam->cLeftX + pParam->cWidth + 15) >> 4);606mbTop = (pParam->cTopY >> 4);607mbBottom = ((pParam->cTopY + pParam->cHeight + 15) >> 4);608609if(pSCDec->WMISCP.uiTileX[pSCDec->WMISCP.cNumOfSliceMinus1V] >= mbLeft && pSCDec->WMISCP.uiTileX[pSCDec->WMISCP.cNumOfSliceMinus1V] <= mbRight &&610pSCDec->WMISCP.uiTileY[pSCDec->WMISCP.cNumOfSliceMinus1H] >= mbTop && pSCDec->WMISCP.uiTileY[pSCDec->WMISCP.cNumOfSliceMinus1H] <= mbBottom)611pParam->bIgnoreOverlap = FALSE;612613pSCEnc->bTileExtraction = pParam->bIgnoreOverlap;614615mbWidth = pSCEnc->cmbWidth = mbRight - mbLeft;616mbHeight = pSCEnc->cmbHeight = mbBottom - mbTop;617if(oO >= O_RCW){618SWAP(pSCEnc->WMII.cWidth, pSCEnc->WMII.cHeight);619SWAP(pSCEnc->cmbWidth, pSCEnc->cmbHeight);620}621622if(oO != O_NONE){623pFrameBuf = (PixelI *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit * sizeof(PixelI));624if(pFrameBuf == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit * sizeof(PixelI) < pSCEnc->cmbWidth * pSCEnc->cmbHeight * cUnit))625return ICERR_ERROR;626pMBInfo = (CWMIMBInfo *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo));627if(pMBInfo == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo) < pSCEnc->cmbWidth * pSCEnc->cmbHeight))628return ICERR_ERROR;629if(pParam->uAlphaMode > 0){ // alpha channel630pFrameBufAlpha = (PixelI *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256 * sizeof(PixelI));631if(pFrameBufAlpha == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256 * sizeof(PixelI) < pSCEnc->cmbWidth * pSCEnc->cmbHeight * 256))632return ICERR_ERROR;633pMBInfoAlpha = (CWMIMBInfo *)malloc(pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo));634if(pMBInfoAlpha == NULL || (pSCEnc->cmbWidth * pSCEnc->cmbHeight * sizeof(CWMIMBInfo) < pSCEnc->cmbWidth * pSCEnc->cmbHeight))635return ICERR_ERROR;636}637}638639if(oO < O_RCW && pSCEnc->WMII.oOrientation < O_RCW)640pSCEnc->WMII.oOrientation ^= oO;641else if(oO >= O_RCW && pSCEnc->WMII.oOrientation >= O_RCW){642pSCEnc->WMII.oOrientation ^= oO;643pSCEnc->WMII.oOrientation = (pSCEnc->WMII.oOrientation & 1) * 2 + (pSCEnc->WMII.oOrientation >> 1);644}645else if(oO >= O_RCW && pSCEnc->WMII.oOrientation < O_RCW)646pSCEnc->WMII.oOrientation = oO ^ ((pSCEnc->WMII.oOrientation & 1) * 2 + (pSCEnc->WMII.oOrientation >> 1));647else648pSCEnc->WMII.oOrientation ^= ((oO & 1) * 2 + (oO >> 1));649650// pSCEnc->WMISCP.nExpBias += 128;651652if(pParam->bIgnoreOverlap == TRUE){653attachISWrite(pSCEnc->pIOHeader, pSCEnc->WMISCP.pWStream);654pSCEnc->pTile = pSCDec->pTile;655if(pSCEnc->WMISCP.cNumOfSliceMinus1H + pSCEnc->WMISCP.cNumOfSliceMinus1V == 0 && pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL)656pSCEnc->m_param.bIndexTable = FALSE;657WriteWMIHeader(pSCEnc);658}659else{660pTileQPInfo = (CTileQPInfo *)malloc((oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1)) * sizeof( CTileQPInfo));661if(pTileQPInfo == NULL || ((oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1)) * sizeof( CTileQPInfo) < (oO == O_NONE ? 1 : (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1))))662return ICERR_ERROR;663664if(StrEncInit(pSCEnc) != ICERR_OK)665return ICERR_ERROR;666}667668if(pParam->uAlphaMode > 0){ // alpha channel669// pSCEnc->WMISCP.nExpBias -= 128;670if((pSCEnc->m_pNextSC = (CWMImageStrCodec *)malloc(sizeof(CWMImageStrCodec))) == NULL)671return ICERR_ERROR;672*pSCEnc->m_pNextSC = *pSCEnc;673pSCEnc->m_pNextSC->pPlane[0] = pSCDec->m_pNextSC->p1MBbuffer[0];674pSCEnc->m_pNextSC->WMISCP.cfColorFormat = pSCEnc->m_pNextSC->WMII.cfColorFormat = pSCEnc->m_pNextSC->m_param.cfColorFormat = Y_ONLY;675pSCEnc->m_pNextSC->WMISCP.cChannel = pSCEnc->m_pNextSC->m_param.cNumChannels = 1;676pSCEnc->m_pNextSC->m_bSecondary = TRUE;677pSCEnc->m_pNextSC->m_pNextSC = pSCEnc;678pSCEnc->m_pNextSC->m_param = pSCDec->m_pNextSC->m_param;679pSCEnc->m_param.bAlphaChannel = TRUE;680681if(pParam->bIgnoreOverlap == TRUE)682pSCEnc->m_pNextSC->pTile = pSCDec->m_pNextSC->pTile;683else if(StrEncInit(pSCEnc->m_pNextSC) != ICERR_OK)684return ICERR_ERROR;685686WriteImagePlaneHeader(pSCEnc->m_pNextSC);687}688689if(pParam->bIgnoreOverlap == TRUE){690SUBBAND sbEnc = pSCEnc->WMISCP.sbSubband, sbDec = pSCDec->WMISCP.sbSubband;691size_t cfEnc = ((pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL || sbEnc == SB_DC_ONLY) ? 1 : (sbEnc == SB_NO_HIGHPASS ? 2 : (sbEnc == SB_NO_FLEXBITS ? 3 : 4)));692size_t cfDec = ((pSCDec->WMISCP.bfBitstreamFormat == SPATIAL || sbDec == SB_DC_ONLY) ? 1 : (sbDec == SB_NO_HIGHPASS ? 2 : (sbDec == SB_NO_FLEXBITS ? 3 : 4)));693size_t k, l = 0;694695pSCEnc->pIndexTable = (size_t *)malloc(sizeof(size_t) * (pSCEnc->WMISCP.cNumOfSliceMinus1H + 1) * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) * cfEnc);696697if(pSCEnc->pIndexTable == NULL || cfEnc > cfDec)698return ICERR_ERROR;699700pSCEnc->cNumBitIO = cfEnc * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1);701702for(j = 0; j <= pSCDec->WMISCP.cNumOfSliceMinus1H; j ++){703for(i = 0; i <= pSCDec->WMISCP.cNumOfSliceMinus1V; i ++)704if(pSCDec->WMISCP.uiTileX[i] >= mbLeft && pSCDec->WMISCP.uiTileX[i] < mbRight &&705pSCDec->WMISCP.uiTileY[j] >= mbTop && pSCDec->WMISCP.uiTileY[j] < mbBottom){706for(k = 0; k < cfEnc; k ++, l ++)707pSCEnc->pIndexTable[l] = pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k + 1] - pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k];708}709}710711if(pSCEnc->WMISCP.cNumOfSliceMinus1H + pSCEnc->WMISCP.cNumOfSliceMinus1V == 0 && pSCEnc->WMISCP.bfBitstreamFormat == SPATIAL){712pSCEnc->m_param.bIndexTable = FALSE;713pSCEnc->cNumBitIO = 0;714writeIndexTableNull(pSCEnc);715}716else717writeIndexTable(pSCEnc);718719detachISWrite(pSCEnc, pSCEnc->pIOHeader);720721for(j = l = 0; j <= pSCDec->WMISCP.cNumOfSliceMinus1H; j ++){722for(i = 0; i <= pSCDec->WMISCP.cNumOfSliceMinus1V; i ++)723if(pSCDec->WMISCP.uiTileX[i] >= mbLeft && pSCDec->WMISCP.uiTileX[i] < mbRight &&724pSCDec->WMISCP.uiTileY[j] >= mbTop && pSCDec->WMISCP.uiTileY[j] < mbBottom){725for(k = 0; k < cfEnc; k ++){726pSCDec->WMISCP.pWStream->SetPos(pSCDec->WMISCP.pWStream, pSCDec->pIndexTable[(j * (pSCDec->WMISCP.cNumOfSliceMinus1V + 1) + i) * cfDec + k] + pSCDec->cHeaderSize);727copyTo(pSCDec->WMISCP.pWStream, pSCEnc->WMISCP.pWStream, pSCEnc->pIndexTable[l++]);728}729}730}731732free(pSCEnc->pIndexTable);733}734else735writeIndexTableNull(pSCEnc);736737for(pSCDec->cRow = 0; pSCDec->cRow < mbBottom && pParam->bIgnoreOverlap == FALSE; pSCDec->cRow ++){738for(pSCDec->cColumn = 0; pSCDec->cColumn < pSCDec->cmbWidth; pSCDec->cColumn ++){739Int cRow = (Int)pSCDec->cRow, cColumn = (Int)pSCDec->cColumn;740CWMITile * pTile;741742memset(pMBBuf, 0, sizeof(PixelI) * cUnit);743if(pSCDec->m_param.bAlphaChannel){ // alpha channel744memset(pSCDec->m_pNextSC->p1MBbuffer[0], 0, sizeof(PixelI) * 256);745pSCDec->m_pNextSC->cRow = pSCDec->cRow;746pSCDec->m_pNextSC->cColumn = pSCDec->cColumn;747}748749// decode750pSC = pSCDec;751for(i = (pSCDec->m_param.bAlphaChannel ? 2 : 1); i > 0; i --){752getTilePos(pSCDec, cColumn, cRow);753if(i == 2){754pSCDec->m_pNextSC->cTileColumn = pSCDec->cTileColumn;755pSCDec->m_pNextSC->cTileRow = pSCDec->cTileRow;756}757758if(readPackets(pSCDec) != ICERR_OK)759return ICERR_ERROR;760761pContext = &pSCDec->m_pCodingContext[pSCDec->cTileColumn];762763if(DecodeMacroblockDC(pSCDec, pContext, cColumn, cRow) != ICERR_OK)764return ICERR_ERROR;765766if(pSCDec->cSB > 1)767if(DecodeMacroblockLowpass(pSCDec, pContext, cColumn, cRow) != ICERR_OK)768return ICERR_ERROR;769770predDCACDec(pSCDec);771772if(pSCDec->cSB > 2)773if(DecodeMacroblockHighpass(pSCDec, pContext, cColumn, cRow) != ICERR_OK)774return ICERR_ERROR;775776predACDec(pSCDec);777778updatePredInfo(pSCDec, &pSCDec->MBInfo, cColumn, pSCDec->WMISCP.cfColorFormat);779780pSCDec = pSCDec->m_pNextSC;781}782pSCDec = pSC;783784if(pSCDec->cRow >= mbTop && pSCDec->cColumn >= mbLeft && pSCDec->cColumn < mbRight){785cRow = (Int)(pSCDec->cRow - mbTop);786if(bFlipV[oO])787cRow = (Int)mbHeight - cRow - 1;788cColumn = (Int)(pSCDec->cColumn - mbLeft);789if(bFlipH[oO])790cColumn = (Int)mbWidth - cColumn - 1;791792pSCEnc->m_bCtxLeft = pSCEnc->m_bCtxTop = FALSE;793for(i = 0; i <= pSCEnc->WMISCP.cNumOfSliceMinus1H; i ++)794if(pSCEnc->WMISCP.uiTileY[i] == (U32)(oO < O_RCW ? cRow : cColumn)){795pSCEnc->cTileRow = i;796pSCEnc->m_bCtxTop = TRUE;797break;798}799for(i = 0; i <= pSCEnc->WMISCP.cNumOfSliceMinus1V; i ++)800if(pSCEnc->WMISCP.uiTileX[i] == (U32)(oO < O_RCW ? cColumn : cRow)){801pSCEnc->cTileColumn = i;802pSCEnc->m_bCtxLeft = TRUE;803break;804}805806if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop){ // a new tile, buffer tile DQuant info807CTileQPInfo * pTmp = pTileQPInfo;808809pTile = pSCDec->pTile + pSCDec->cTileColumn;810811if(oO != O_NONE)812pTmp += pSCEnc->cTileRow * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) + pSCEnc->cTileColumn;813814pTmp->dcMode = pTile->cChModeDC;815for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++)816pTmp->dcIndex[i] = pTile->pQuantizerDC[i][0].iIndex;817818if(pSCEnc->WMISCP.sbSubband != SB_DC_ONLY){819pTmp->bUseDC = pTile->bUseDC;820pTmp->lpNum = pTile->cNumQPLP;821if(pTmp->bUseDC == FALSE)822for(j = 0; j < pTmp->lpNum; j ++){823pTmp->lpMode[j] = pTile->cChModeLP[j];824for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++)825pTmp->lpIndex[j][i] = pTile->pQuantizerLP[i][j].iIndex;826}827828if(pSCEnc->WMISCP.sbSubband != SB_NO_HIGHPASS){829pTmp->bUseLP = pTile->bUseLP;830pTmp->hpNum = pTile->cNumQPHP;831if(pTmp->bUseLP == FALSE)832for(j = 0; j < pTmp->hpNum; j ++){833pTmp->hpMode[j] = pTile->cChModeHP[j];834for(i = 0; i < pSCEnc->WMISCP.cChannel; i ++)835pTmp->hpIndex[j][i] = pTile->pQuantizerHP[i][j].iIndex;836}837}838}839840if(pParam->uAlphaMode > 0){841pTile = pSCDec->m_pNextSC->pTile + pSCDec->cTileColumn;842843pTmp->dcIndex[iAlphaPos] = pTile->pQuantizerDC[0][0].iIndex;844845if(pSCEnc->WMISCP.sbSubband != SB_DC_ONLY){846pTmp->bUseDCAlpha = pTile->bUseDC;847pTmp->lpNumAlpha = pTile->cNumQPLP;848if(pTmp->bUseDCAlpha == FALSE)849for(j = 0; j < pTmp->lpNumAlpha; j ++)850pTmp->lpIndex[j][iAlphaPos] = pTile->pQuantizerLP[0][j].iIndex;851if(pSCEnc->WMISCP.sbSubband != SB_NO_HIGHPASS){852pTmp->bUseLPAlpha = pTile->bUseLP;853pTmp->hpNumAlpha = pTile->cNumQPHP;854if(pTmp->bUseLPAlpha == FALSE)855for(j = 0; j < pTmp->hpNumAlpha; j ++)856pTmp->hpIndex[j][iAlphaPos] = pTile->pQuantizerHP[0][j].iIndex;857}858}859}860}861862if(oO == O_NONE){863// encode864pSCEnc->cColumn = pSCDec->cColumn - mbLeft + 1;865pSCEnc->cRow = pSCDec->cRow + 1 - mbTop;866pSCEnc->MBInfo = pSCDec->MBInfo;867868getTilePos(pSCEnc, cColumn, cRow);869870if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop)871transcodeTileHeader(pSCEnc, pTileQPInfo);872873if(encodeMB(pSCEnc, cColumn, cRow) != ICERR_OK)874return ICERR_ERROR;875if(pParam->uAlphaMode > 0){876pSCEnc->m_pNextSC->cColumn = pSCDec->cColumn - mbLeft + 1;877pSCEnc->m_pNextSC->cRow = pSCDec->cRow + 1 - mbTop;878getTilePos(pSCEnc->m_pNextSC, cColumn, cRow);879pSCEnc->m_pNextSC->MBInfo = pSCDec->m_pNextSC->MBInfo;880if(encodeMB(pSCEnc->m_pNextSC, cColumn, cRow) != ICERR_OK)881return ICERR_ERROR;882}883}884else{885size_t cOff = (oO < O_RCW ? (size_t)cRow * mbWidth + (size_t)cColumn : (size_t)cRow + mbHeight * (size_t)cColumn);886887pMBInfo[cOff] = pSCDec->MBInfo;888889memcpy(&pFrameBuf[cOff * cUnit], pMBBuf, cUnit * sizeof(PixelI));890891if(pParam->uAlphaMode > 0){892pMBInfoAlpha[cOff] = pSCDec->m_pNextSC->MBInfo;893894memcpy(&pFrameBufAlpha[cOff * 256], MBBufAlpha, 256 * sizeof(PixelI));895}896}897}898}899900advanceOneMBRow(pSCDec);901902if(oO == O_NONE)903advanceOneMBRow(pSCEnc);904}905906if(oO != O_NONE){907for(pSCEnc->cRow = 1; pSCEnc->cRow <= pSCEnc->cmbHeight; pSCEnc->cRow ++){908for(pSCEnc->cColumn = 1; pSCEnc->cColumn <= pSCEnc->cmbWidth; pSCEnc->cColumn ++){909Int cRow, cColumn;910size_t cOff = (pSCEnc->cRow - 1) * pSCEnc->cmbWidth + pSCEnc->cColumn - 1;911912for(i = 0; i < ((pSCEnc->m_param.cfColorFormat == YUV_420 || pSCEnc->m_param.cfColorFormat == YUV_422) ? 1 : pSCEnc->m_param.cNumChannels); i ++){913transformDCBlock(pMBInfo[cOff].iBlockDC[i], pSCEnc->MBInfo.iBlockDC[i], oO);914transformACBlocks(pFrameBuf + cOff * cUnit + i * 256, pMBBuf + 256 * i, oO);915}916if(pSCEnc->WMISCP.cfColorFormat == YUV_420)917for(i = 0; i < 2; i ++){918transformDCBlock420(pMBInfo[cOff].iBlockDC[i + 1], pSCEnc->MBInfo.iBlockDC[i + 1], oO);919transformACBlocks420(pFrameBuf + cOff * cUnit + 256 + i * 64, pMBBuf + 256 + i * 64, oO);920}921else if(pSCEnc->WMISCP.cfColorFormat == YUV_422)922for(i = 0; i < 2; i ++){923transformDCBlock422(pMBInfo[cOff].iBlockDC[i + 1], pSCEnc->MBInfo.iBlockDC[i + 1], oO);924transformACBlocks422(pFrameBuf + cOff * cUnit + 256 + i * 128, pMBBuf + 256 + i * 128, oO);925}926927pSCEnc->MBInfo.iQIndexLP = pMBInfo[cOff].iQIndexLP;928pSCEnc->MBInfo.iQIndexHP = pMBInfo[cOff].iQIndexHP;929930cRow = (Int)pSCEnc->cRow - 1;931cColumn = (Int)pSCEnc->cColumn - 1;932getTilePos(pSCEnc, cColumn, cRow);933934if(pSCEnc->m_bCtxLeft && pSCEnc->m_bCtxTop)935transcodeTileHeader(pSCEnc, pTileQPInfo + pSCEnc->cTileRow * (pSCEnc->WMISCP.cNumOfSliceMinus1V + 1) + pSCEnc->cTileColumn);936if(encodeMB(pSCEnc, cColumn, cRow) != ICERR_OK)937return ICERR_ERROR;938939if(pParam->uAlphaMode > 0){940pSCEnc->m_pNextSC->cColumn = pSCEnc->cColumn;941pSCEnc->m_pNextSC->cRow = pSCEnc->cRow;942getTilePos(pSCEnc->m_pNextSC, cColumn, cRow);943pSCEnc->m_pNextSC->MBInfo = pSCDec->m_pNextSC->MBInfo;944945transformDCBlock(pMBInfoAlpha[cOff].iBlockDC[0], pSCEnc->m_pNextSC->MBInfo.iBlockDC[0], oO);946transformACBlocks(pFrameBufAlpha + cOff * 256, MBBufAlpha, oO);947948pSCEnc->m_pNextSC->MBInfo.iQIndexLP = pMBInfoAlpha[cOff].iQIndexLP;949pSCEnc->m_pNextSC->MBInfo.iQIndexHP = pMBInfoAlpha[cOff].iQIndexHP;950951if(encodeMB(pSCEnc->m_pNextSC, cColumn, cRow) != ICERR_OK)952return ICERR_ERROR;953}954}955956advanceOneMBRow(pSCEnc);957}958}959960free(pMBBuf);961if(oO != O_NONE){962free(pFrameBuf);963free(pMBInfo);964if(pParam->uAlphaMode > 0){ // alpha channel965free(pFrameBufAlpha);966free(pMBInfoAlpha);967}968}969970freePredInfo(pSCDec);971freeTileInfo(pSCDec);972StrIODecTerm(pSCDec);973FreeCodingContextDec(pSCDec);974if(pSCDec->m_param.bAlphaChannel)975free(pSCDec->m_pNextSC);976free(pSCDec);977free(pIOHeaderDec);978979if(pParam->bIgnoreOverlap == FALSE){980freePredInfo(pSCEnc);981freeTileInfo(pSCEnc);982StrIOEncTerm(pSCEnc);983free(pTileQPInfo);984FreeCodingContextEnc(pSCEnc);985}986free(pSCEnc);987free(pIOHeaderEnc);988989return ICERR_OK;990}991992993